derenc.c (13549B)
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 "secerr.h" 7 8 #if 0 9 /* 10 * Generic templates for individual/simple items. 11 */ 12 13 DERTemplate SECAnyTemplate[] = { 14 { DER_ANY, 15 0, NULL, sizeof(SECItem) } 16 }; 17 18 DERTemplate SECBitStringTemplate[] = { 19 { DER_BIT_STRING, 20 0, NULL, sizeof(SECItem) } 21 }; 22 23 DERTemplate SECBooleanTemplate[] = { 24 { DER_BOOLEAN, 25 0, NULL, sizeof(SECItem) } 26 }; 27 28 DERTemplate SECIA5StringTemplate[] = { 29 { DER_IA5_STRING, 30 0, NULL, sizeof(SECItem) } 31 }; 32 33 DERTemplate SECIntegerTemplate[] = { 34 { DER_INTEGER, 35 0, NULL, sizeof(SECItem) } 36 }; 37 38 DERTemplate SECNullTemplate[] = { 39 { DER_NULL, 40 0, NULL, sizeof(SECItem) } 41 }; 42 43 DERTemplate SECObjectIDTemplate[] = { 44 { DER_OBJECT_ID, 45 0, NULL, sizeof(SECItem) } 46 }; 47 48 DERTemplate SECOctetStringTemplate[] = { 49 { DER_OCTET_STRING, 50 0, NULL, sizeof(SECItem) } 51 }; 52 53 DERTemplate SECPrintableStringTemplate[] = { 54 { DER_PRINTABLE_STRING, 55 0, NULL, sizeof(SECItem) } 56 }; 57 58 DERTemplate SECT61StringTemplate[] = { 59 { DER_T61_STRING, 60 0, NULL, sizeof(SECItem) } 61 }; 62 63 DERTemplate SECUTCTimeTemplate[] = { 64 { DER_UTC_TIME, 65 0, NULL, sizeof(SECItem) } 66 }; 67 68 #endif 69 70 static int 71 header_length(DERTemplate *dtemplate, PRUint32 contents_len) 72 { 73 PRUint32 len; 74 unsigned long encode_kind, under_kind; 75 PRBool explicit, optional, universal; 76 77 encode_kind = dtemplate->kind; 78 79 explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE; 80 optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE; 81 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) 82 ? PR_TRUE 83 : PR_FALSE; 84 85 PORT_Assert(!(explicit && universal)); /* bad templates */ 86 87 if (encode_kind & DER_POINTER) { 88 if (dtemplate->sub != NULL) { 89 under_kind = dtemplate->sub->kind; 90 if (universal) { 91 encode_kind = under_kind; 92 } 93 } else if (universal) { 94 under_kind = encode_kind & ~DER_POINTER; 95 } else { 96 under_kind = dtemplate->arg; 97 } 98 } else if (encode_kind & DER_INLINE) { 99 PORT_Assert(dtemplate->sub != NULL); 100 under_kind = dtemplate->sub->kind; 101 if (universal) { 102 encode_kind = under_kind; 103 } 104 } else if (universal) { 105 under_kind = encode_kind; 106 } else { 107 under_kind = dtemplate->arg; 108 } 109 110 /* This is only used in decoding; it plays no part in encoding. */ 111 if (under_kind & DER_DERPTR) 112 return 0; 113 114 /* No header at all for an "empty" optional. */ 115 if ((contents_len == 0) && optional) 116 return 0; 117 118 /* And no header for a full DER_ANY. */ 119 if (encode_kind & DER_ANY) 120 return 0; 121 122 /* 123 * The common case: one octet for identifier and as many octets 124 * as necessary to hold the content length. 125 */ 126 len = 1 + DER_LengthLength(contents_len); 127 128 /* Account for the explicit wrapper, if necessary. */ 129 if (explicit) { 130 #if 0 /* \ 131 * Well, I was trying to do something useful, but these \ 132 * assertions are too restrictive on valid templates. \ 133 * I wanted to make sure that the top-level "kind" of \ 134 * a template does not also specify DER_EXPLICIT, which \ 135 * should only modify a component field. Maybe later \ 136 * I can figure out a better way to detect such a problem, \ 137 * but for now I must remove these checks altogether. \ 138 */ 139 /* 140 * This modifier applies only to components of a set or sequence; 141 * it should never be used on a set/sequence itself -- confirm. 142 */ 143 PORT_Assert (under_kind != DER_SEQUENCE); 144 PORT_Assert (under_kind != DER_SET); 145 #endif 146 147 len += 1 + DER_LengthLength(len + contents_len); 148 } 149 150 return len; 151 } 152 153 static PRUint32 154 contents_length(DERTemplate *dtemplate, void *src) 155 { 156 PRUint32 len; 157 unsigned long encode_kind, under_kind; 158 PRBool universal; 159 160 PORT_Assert(src != NULL); 161 162 encode_kind = dtemplate->kind; 163 164 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) 165 ? PR_TRUE 166 : PR_FALSE; 167 encode_kind &= ~DER_OPTIONAL; 168 169 if (encode_kind & DER_POINTER) { 170 src = *(void **)src; 171 if (src == NULL) { 172 return 0; 173 } 174 if (dtemplate->sub != NULL) { 175 dtemplate = dtemplate->sub; 176 under_kind = dtemplate->kind; 177 src = (void *)((char *)src + dtemplate->offset); 178 } else if (universal) { 179 under_kind = encode_kind & ~DER_POINTER; 180 } else { 181 under_kind = dtemplate->arg; 182 } 183 } else if (encode_kind & DER_INLINE) { 184 PORT_Assert(dtemplate->sub != NULL); 185 dtemplate = dtemplate->sub; 186 under_kind = dtemplate->kind; 187 src = (void *)((char *)src + dtemplate->offset); 188 } else if (universal) { 189 under_kind = encode_kind; 190 } else { 191 under_kind = dtemplate->arg; 192 } 193 194 /* Having any of these bits is not expected here... */ 195 PORT_Assert((under_kind & (DER_EXPLICIT | DER_INLINE | DER_OPTIONAL | DER_POINTER | DER_SKIP)) == 0); 196 197 /* This is only used in decoding; it plays no part in encoding. */ 198 if (under_kind & DER_DERPTR) 199 return 0; 200 201 if (under_kind & DER_INDEFINITE) { 202 PRUint32 sub_len; 203 void **indp = *(void ***)src; 204 205 if (indp == NULL) 206 return 0; 207 208 len = 0; 209 under_kind &= ~DER_INDEFINITE; 210 211 if (under_kind == DER_SET || under_kind == DER_SEQUENCE) { 212 DERTemplate *tmpt = dtemplate->sub; 213 PORT_Assert(tmpt != NULL); 214 215 for (; *indp != NULL; indp++) { 216 void *sub_src = (void *)((char *)(*indp) + tmpt->offset); 217 sub_len = contents_length(tmpt, sub_src); 218 len += sub_len + header_length(tmpt, sub_len); 219 } 220 } else { 221 /* 222 * XXX Lisa is not sure this code (for handling, for example, 223 * DER_INDEFINITE | DER_OCTET_STRING) is right. 224 */ 225 for (; *indp != NULL; indp++) { 226 SECItem *item = (SECItem *)(*indp); 227 sub_len = item->len; 228 if (under_kind == DER_BIT_STRING) { 229 sub_len = (sub_len + 7) >> 3; 230 /* bit string contents involve an extra octet */ 231 if (sub_len) 232 sub_len++; 233 } 234 if (under_kind != DER_ANY) 235 len += 1 + DER_LengthLength(sub_len); 236 } 237 } 238 239 return len; 240 } 241 242 switch (under_kind) { 243 case DER_SEQUENCE: 244 case DER_SET: { 245 DERTemplate *tmpt; 246 void *sub_src; 247 PRUint32 sub_len; 248 249 len = 0; 250 for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) { 251 sub_src = (void *)((char *)src + tmpt->offset); 252 sub_len = contents_length(tmpt, sub_src); 253 len += sub_len + header_length(tmpt, sub_len); 254 } 255 } break; 256 257 case DER_BIT_STRING: 258 len = (((SECItem *)src)->len + 7) >> 3; 259 /* bit string contents involve an extra octet */ 260 if (len) 261 len++; 262 break; 263 264 default: 265 len = ((SECItem *)src)->len; 266 break; 267 } 268 269 return len; 270 } 271 272 static unsigned char * 273 der_encode(unsigned char *buf, DERTemplate *dtemplate, void *src) 274 { 275 int header_len; 276 PRUint32 contents_len; 277 unsigned long encode_kind, under_kind; 278 PRBool explicit, universal; 279 280 /* 281 * First figure out how long the encoding will be. Do this by 282 * traversing the template from top to bottom and accumulating 283 * the length of each leaf item. 284 */ 285 contents_len = contents_length(dtemplate, src); 286 header_len = header_length(dtemplate, contents_len); 287 288 /* 289 * Enough smarts was involved already, so that if both the 290 * header and the contents have a length of zero, then we 291 * are not doing any encoding for this element. 292 */ 293 if (header_len == 0 && contents_len == 0) 294 return buf; 295 296 encode_kind = dtemplate->kind; 297 298 explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE; 299 encode_kind &= ~DER_OPTIONAL; 300 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) 301 ? PR_TRUE 302 : PR_FALSE; 303 304 if (encode_kind & DER_POINTER) { 305 if (contents_len) { 306 src = *(void **)src; 307 PORT_Assert(src != NULL); 308 } 309 if (dtemplate->sub != NULL) { 310 dtemplate = dtemplate->sub; 311 under_kind = dtemplate->kind; 312 if (universal) { 313 encode_kind = under_kind; 314 } 315 src = (void *)((char *)src + dtemplate->offset); 316 } else if (universal) { 317 under_kind = encode_kind & ~DER_POINTER; 318 } else { 319 under_kind = dtemplate->arg; 320 } 321 } else if (encode_kind & DER_INLINE) { 322 dtemplate = dtemplate->sub; 323 under_kind = dtemplate->kind; 324 if (universal) { 325 encode_kind = under_kind; 326 } 327 src = (void *)((char *)src + dtemplate->offset); 328 } else if (universal) { 329 under_kind = encode_kind; 330 } else { 331 under_kind = dtemplate->arg; 332 } 333 334 if (explicit) { 335 buf = DER_StoreHeader(buf, encode_kind, 336 (1 + DER_LengthLength(contents_len) + contents_len)); 337 encode_kind = under_kind; 338 } 339 340 if ((encode_kind & DER_ANY) == 0) { /* DER_ANY already contains header */ 341 buf = DER_StoreHeader(buf, encode_kind, contents_len); 342 } 343 344 /* If no real contents to encode, then we are done. */ 345 if (contents_len == 0) 346 return buf; 347 348 if (under_kind & DER_INDEFINITE) { 349 void **indp; 350 351 indp = *(void ***)src; 352 PORT_Assert(indp != NULL); 353 354 under_kind &= ~DER_INDEFINITE; 355 if (under_kind == DER_SET || under_kind == DER_SEQUENCE) { 356 DERTemplate *tmpt = dtemplate->sub; 357 PORT_Assert(tmpt != NULL); 358 for (; *indp != NULL; indp++) { 359 void *sub_src = (void *)((char *)(*indp) + tmpt->offset); 360 buf = der_encode(buf, tmpt, sub_src); 361 } 362 } else { 363 for (; *indp != NULL; indp++) { 364 SECItem *item; 365 int sub_len; 366 367 item = (SECItem *)(*indp); 368 sub_len = item->len; 369 if (under_kind == DER_BIT_STRING) { 370 if (sub_len) { 371 int rem; 372 373 sub_len = (sub_len + 7) >> 3; 374 buf = DER_StoreHeader(buf, under_kind, sub_len + 1); 375 rem = (sub_len << 3) - item->len; 376 *buf++ = rem; /* remaining bits */ 377 } else { 378 buf = DER_StoreHeader(buf, under_kind, 0); 379 } 380 } else if (under_kind != DER_ANY) { 381 buf = DER_StoreHeader(buf, under_kind, sub_len); 382 } 383 PORT_Memcpy(buf, item->data, sub_len); 384 buf += sub_len; 385 } 386 } 387 return buf; 388 } 389 390 switch (under_kind) { 391 case DER_SEQUENCE: 392 case DER_SET: { 393 DERTemplate *tmpt; 394 void *sub_src; 395 396 for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) { 397 sub_src = (void *)((char *)src + tmpt->offset); 398 buf = der_encode(buf, tmpt, sub_src); 399 } 400 } break; 401 402 case DER_BIT_STRING: { 403 SECItem *item; 404 int rem; 405 406 /* 407 * The contents length includes our extra octet; subtract 408 * it off so we just have the real string length there. 409 */ 410 contents_len--; 411 item = (SECItem *)src; 412 PORT_Assert(contents_len == ((item->len + 7) >> 3)); 413 rem = (contents_len << 3) - item->len; 414 *buf++ = rem; /* remaining bits */ 415 PORT_Memcpy(buf, item->data, contents_len); 416 buf += contents_len; 417 } break; 418 419 default: { 420 SECItem *item; 421 422 item = (SECItem *)src; 423 PORT_Assert(contents_len == item->len); 424 PORT_Memcpy(buf, item->data, contents_len); 425 buf += contents_len; 426 } break; 427 } 428 429 return buf; 430 } 431 432 SECStatus 433 DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src) 434 { 435 unsigned int contents_len, header_len; 436 437 src = (void **)((char *)src + dtemplate->offset); 438 439 /* 440 * First figure out how long the encoding will be. Do this by 441 * traversing the template from top to bottom and accumulating 442 * the length of each leaf item. 443 */ 444 contents_len = contents_length(dtemplate, src); 445 header_len = header_length(dtemplate, contents_len); 446 447 dest->len = contents_len + header_len; 448 449 /* Allocate storage to hold the encoding */ 450 dest->data = (unsigned char *)PORT_ArenaAlloc(arena, dest->len); 451 if (dest->data == NULL) { 452 PORT_SetError(SEC_ERROR_NO_MEMORY); 453 return SECFailure; 454 } 455 456 /* Now encode into the buffer */ 457 (void)der_encode(dest->data, dtemplate, src); 458 459 return SECSuccess; 460 }