dersubr.c (5824B)
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/. */ 4 5 #include "secder.h" 6 #include <limits.h> 7 #include "secerr.h" 8 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 } 30 31 unsigned char * 32 DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len) 33 { 34 unsigned char b[4]; 35 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 || (code & DER_TAGNUM_MASK) == DER_SEQUENCE) 41 code |= DER_CONSTRUCTED; 42 *buf++ = code; 43 if (len > 127) { 44 if (len > 255) { 45 if (len > 65535) { 46 if (len > 16777215) { 47 *buf++ = 0x84; 48 *buf++ = b[0]; 49 *buf++ = b[1]; 50 *buf++ = b[2]; 51 *buf++ = b[3]; 52 } else { 53 *buf++ = 0x83; 54 *buf++ = b[1]; 55 *buf++ = b[2]; 56 *buf++ = b[3]; 57 } 58 } else { 59 *buf++ = 0x82; 60 *buf++ = b[2]; 61 *buf++ = b[3]; 62 } 63 } else { 64 *buf++ = 0x81; 65 *buf++ = b[3]; 66 } 67 } else { 68 *buf++ = b[3]; 69 } 70 return buf; 71 } 72 73 /* 74 * XXX This should be rewritten, generalized, to take a long instead 75 * of a PRInt32. 76 */ 77 SECStatus 78 DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i) 79 { 80 unsigned char bb[4]; 81 unsigned len; 82 83 bb[0] = (unsigned char)(i >> 24); 84 bb[1] = (unsigned char)(i >> 16); 85 bb[2] = (unsigned char)(i >> 8); 86 bb[3] = (unsigned char)(i); 87 88 /* 89 ** Small integers are encoded in a single byte. Larger integers 90 ** require progressively more space. 91 */ 92 if (i < -128) { 93 if (i < -32768L) { 94 if (i < -8388608L) { 95 len = 4; 96 } else { 97 len = 3; 98 } 99 } else { 100 len = 2; 101 } 102 } else if (i > 127) { 103 if (i > 32767L) { 104 if (i > 8388607L) { 105 len = 4; 106 } else { 107 len = 3; 108 } 109 } else { 110 len = 2; 111 } 112 } else { 113 len = 1; 114 } 115 it->data = (unsigned char *)PORT_ArenaAlloc(arena, len); 116 if (!it->data) { 117 return SECFailure; 118 } 119 it->len = len; 120 PORT_Memcpy(it->data, bb + (4 - len), len); 121 return SECSuccess; 122 } 123 124 /* 125 * XXX This should be rewritten, generalized, to take an unsigned long instead 126 * of a PRUint32. 127 */ 128 SECStatus 129 DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui) 130 { 131 unsigned char bb[5]; 132 int len; 133 134 bb[0] = 0; 135 bb[1] = (unsigned char)(ui >> 24); 136 bb[2] = (unsigned char)(ui >> 16); 137 bb[3] = (unsigned char)(ui >> 8); 138 bb[4] = (unsigned char)(ui); 139 140 /* 141 ** Small integers are encoded in a single byte. Larger integers 142 ** require progressively more space. 143 */ 144 if (ui > 0x7f) { 145 if (ui > 0x7fff) { 146 if (ui > 0x7fffffL) { 147 if (ui >= 0x80000000L) { 148 len = 5; 149 } else { 150 len = 4; 151 } 152 } else { 153 len = 3; 154 } 155 } else { 156 len = 2; 157 } 158 } else { 159 len = 1; 160 } 161 162 it->data = (unsigned char *)PORT_ArenaAlloc(arena, len); 163 if (it->data == NULL) { 164 return SECFailure; 165 } 166 167 it->len = len; 168 PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len); 169 170 return SECSuccess; 171 } 172 173 /* 174 ** Convert a der encoded *signed* integer into a machine integral value. 175 ** If an underflow/overflow occurs, sets error code and returns min/max. 176 */ 177 long 178 DER_GetInteger(const SECItem *it) 179 { 180 unsigned long ival; 181 PRBool negative; 182 unsigned int len = it->len; 183 unsigned char *cp = it->data; 184 size_t lsize = sizeof(ival); 185 186 PORT_Assert(len); 187 if (!len) { 188 PORT_SetError(SEC_ERROR_INPUT_LEN); 189 return 0; 190 } 191 192 negative = (PRBool)(*cp & 0x80); 193 ival = negative ? ~0 : 0; 194 195 /* Ignore leading zeros/ones. */ 196 while (len && *cp == (unsigned char)ival) { 197 len--; 198 cp++; 199 } 200 201 /* Check for overflow/underflow. */ 202 if (len > lsize || (len == lsize && (*cp & 0x80) != negative)) { 203 PORT_SetError(SEC_ERROR_BAD_DER); 204 return negative ? LONG_MIN : LONG_MAX; 205 } 206 207 while (len--) { 208 ival <<= 8; 209 ival |= *cp++; 210 } 211 212 return ival; 213 } 214 215 /* 216 ** Convert a der encoded *unsigned* integer into a machine integral value. 217 ** If an overflow occurs, sets error code and returns max. 218 */ 219 unsigned long 220 DER_GetUInteger(SECItem *it) 221 { 222 unsigned long ival = 0; 223 unsigned len = it->len; 224 unsigned char *cp = it->data; 225 unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8); 226 227 PORT_Assert(len); 228 if (!len) { 229 PORT_SetError(SEC_ERROR_INPUT_LEN); 230 return 0; 231 } 232 233 /* Cannot put a negative value into an unsigned container. */ 234 if (*cp & 0x80) { 235 PORT_SetError(SEC_ERROR_BAD_DER); 236 return 0; 237 } 238 239 while (len) { 240 if (ival & overflow) { 241 PORT_SetError(SEC_ERROR_BAD_DER); 242 return ULONG_MAX; 243 } 244 ival = ival << 8; 245 ival |= *cp++; 246 --len; 247 } 248 return ival; 249 }