security/nss/lib/util/dersubr.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "secder.h"
     6 #include <limits.h>
     7 #include "secerr.h"
     9 int
    10 DER_LengthLength(PRUint32 len)
    11 {
    12     if (len > 127) {
    13 	if (len > 255) {
    14 	    if (len > 65535L) {
    15 		if (len > 16777215L) {
    16 		    return 5;
    17 		} else {
    18 		    return 4;
    19 		}
    20 	    } else {
    21 		return 3;
    22 	    }
    23 	} else {
    24 	    return 2;
    25 	}
    26     } else {
    27 	return 1;
    28     }
    29 }
    31 unsigned char *
    32 DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len)
    33 {
    34     unsigned char b[4];
    36     b[0] = (unsigned char)(len >> 24);
    37     b[1] = (unsigned char)(len >> 16);
    38     b[2] = (unsigned char)(len >> 8);
    39     b[3] = (unsigned char)len;
    40     if ((code & DER_TAGNUM_MASK) == DER_SET
    41 	|| (code & DER_TAGNUM_MASK) == DER_SEQUENCE)
    42 	code |= DER_CONSTRUCTED;
    43     *buf++ = code;
    44     if (len > 127) {
    45 	if (len > 255) {
    46 	    if (len > 65535) {
    47 		if (len > 16777215) {
    48 		    *buf++ = 0x84;
    49 		    *buf++ = b[0];
    50 		    *buf++ = b[1];
    51 		    *buf++ = b[2];
    52 		    *buf++ = b[3];
    53 		} else {
    54 		    *buf++ = 0x83;
    55 		    *buf++ = b[1];
    56 		    *buf++ = b[2];
    57 		    *buf++ = b[3];
    58 		}
    59 	    } else {
    60 		*buf++ = 0x82;
    61 		*buf++ = b[2];
    62 		*buf++ = b[3];
    63 	    }
    64 	} else {
    65 	    *buf++ = 0x81;
    66 	    *buf++ = b[3];
    67 	}
    68     } else {
    69 	*buf++ = b[3];
    70     }
    71     return buf;
    72 }
    74 /*
    75  * XXX This should be rewritten, generalized, to take a long instead
    76  * of a PRInt32.
    77  */
    78 SECStatus
    79 DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i)
    80 {
    81     unsigned char bb[4];
    82     unsigned len;
    84     bb[0] = (unsigned char) (i >> 24);
    85     bb[1] = (unsigned char) (i >> 16);
    86     bb[2] = (unsigned char) (i >> 8);
    87     bb[3] = (unsigned char) (i);
    89     /*
    90     ** Small integers are encoded in a single byte. Larger integers
    91     ** require progressively more space.
    92     */
    93     if (i < -128) {
    94 	if (i < -32768L) {
    95 	    if (i < -8388608L) {
    96 		len = 4;
    97 	    } else {
    98 		len = 3;
    99 	    }
   100 	} else {
   101 	    len = 2;
   102 	}
   103     } else if (i > 127) {
   104 	if (i > 32767L) {
   105 	    if (i > 8388607L) {
   106 		len = 4;
   107 	    } else {
   108 		len = 3;
   109 	    }
   110 	} else {
   111 	    len = 2;
   112 	}
   113     } else {
   114 	len = 1;
   115     }
   116     it->data = (unsigned char*) PORT_ArenaAlloc(arena, len);
   117     if (!it->data) {
   118 	return SECFailure;
   119     }
   120     it->len = len;
   121     PORT_Memcpy(it->data, bb + (4 - len), len);
   122     return SECSuccess;
   123 }
   125 /*
   126  * XXX This should be rewritten, generalized, to take an unsigned long instead
   127  * of a PRUint32.
   128  */
   129 SECStatus
   130 DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui)
   131 {
   132     unsigned char bb[5];
   133     int len;
   135     bb[0] = 0;
   136     bb[1] = (unsigned char) (ui >> 24);
   137     bb[2] = (unsigned char) (ui >> 16);
   138     bb[3] = (unsigned char) (ui >> 8);
   139     bb[4] = (unsigned char) (ui);
   141     /*
   142     ** Small integers are encoded in a single byte. Larger integers
   143     ** require progressively more space.
   144     */
   145     if (ui > 0x7f) {
   146 	if (ui > 0x7fff) {
   147 	    if (ui > 0x7fffffL) {
   148 		if (ui >= 0x80000000L) {
   149 		    len = 5;
   150 		} else {
   151 		    len = 4;
   152 		}
   153 	    } else {
   154 		len = 3;
   155 	    }
   156 	} else {
   157 	    len = 2;
   158 	}
   159     } else {
   160 	len = 1;
   161     }
   163     it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
   164     if (it->data == NULL) {
   165 	return SECFailure;
   166     }
   168     it->len = len;
   169     PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
   171     return SECSuccess;
   172 }
   174 /*
   175 ** Convert a der encoded *signed* integer into a machine integral value.
   176 ** If an underflow/overflow occurs, sets error code and returns min/max.
   177 */
   178 long
   179 DER_GetInteger(const SECItem *it)
   180 {
   181     long ival = 0;
   182     unsigned len = it->len;
   183     unsigned char *cp = it->data;
   184     unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
   185     unsigned long ofloinit;
   187     PORT_Assert(len);
   188     if (!len) {
   189 	PORT_SetError(SEC_ERROR_INPUT_LEN);
   190 	return 0;
   191     }
   193     if (*cp & 0x80)
   194     	ival = -1L;
   195     ofloinit = ival & overflow;
   197     while (len) {
   198 	if ((ival & overflow) != ofloinit) {
   199 	    PORT_SetError(SEC_ERROR_BAD_DER);
   200 	    if (ival < 0) {
   201 		return LONG_MIN;
   202 	    }
   203 	    return LONG_MAX;
   204 	}
   205 	ival = ival << 8;
   206 	ival |= *cp++;
   207 	--len;
   208     }
   209     return ival;
   210 }
   212 /*
   213 ** Convert a der encoded *unsigned* integer into a machine integral value.
   214 ** If an overflow occurs, sets error code and returns max.
   215 */
   216 unsigned long
   217 DER_GetUInteger(SECItem *it)
   218 {
   219     unsigned long ival = 0;
   220     unsigned len = it->len;
   221     unsigned char *cp = it->data;
   222     unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8);
   224     PORT_Assert(len);
   225     if (!len) {
   226 	PORT_SetError(SEC_ERROR_INPUT_LEN);
   227 	return 0;
   228     }
   230     /* Cannot put a negative value into an unsigned container. */
   231     if (*cp & 0x80) {
   232 	PORT_SetError(SEC_ERROR_BAD_DER);
   233 	return 0;
   234     }
   236     while (len) {
   237 	if (ival & overflow) {
   238 	    PORT_SetError(SEC_ERROR_BAD_DER);
   239 	    return ULONG_MAX;
   240 	}
   241 	ival = ival << 8;
   242 	ival |= *cp++;
   243 	--len;
   244     }
   245     return ival;
   246 }

mercurial