OLD | NEW |
| (Empty) |
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 : PR_FALSE; | |
83 | |
84 PORT_Assert (!(explicit && universal)); /* bad templates */ | |
85 | |
86 if (encode_kind & DER_POINTER) { | |
87 if (dtemplate->sub != NULL) { | |
88 under_kind = dtemplate->sub->kind; | |
89 if (universal) { | |
90 encode_kind = under_kind; | |
91 } | |
92 } else if (universal) { | |
93 under_kind = encode_kind & ~DER_POINTER; | |
94 } else { | |
95 under_kind = dtemplate->arg; | |
96 } | |
97 } else if (encode_kind & DER_INLINE) { | |
98 PORT_Assert (dtemplate->sub != NULL); | |
99 under_kind = dtemplate->sub->kind; | |
100 if (universal) { | |
101 encode_kind = under_kind; | |
102 } | |
103 } else if (universal) { | |
104 under_kind = encode_kind; | |
105 } else { | |
106 under_kind = dtemplate->arg; | |
107 } | |
108 | |
109 /* This is only used in decoding; it plays no part in encoding. */ | |
110 if (under_kind & DER_DERPTR) | |
111 return 0; | |
112 | |
113 /* No header at all for an "empty" optional. */ | |
114 if ((contents_len == 0) && optional) | |
115 return 0; | |
116 | |
117 /* And no header for a full DER_ANY. */ | |
118 if (encode_kind & DER_ANY) | |
119 return 0; | |
120 | |
121 /* | |
122 * The common case: one octet for identifier and as many octets | |
123 * as necessary to hold the content length. | |
124 */ | |
125 len = 1 + DER_LengthLength(contents_len); | |
126 | |
127 /* Account for the explicit wrapper, if necessary. */ | |
128 if (explicit) { | |
129 #if 0 /* | |
130 * Well, I was trying to do something useful, but these | |
131 * assertions are too restrictive on valid templates. | |
132 * I wanted to make sure that the top-level "kind" of | |
133 * a template does not also specify DER_EXPLICIT, which | |
134 * should only modify a component field. Maybe later | |
135 * I can figure out a better way to detect such a problem, | |
136 * but for now I must remove these checks altogether. | |
137 */ | |
138 /* | |
139 * This modifier applies only to components of a set or sequence; | |
140 * it should never be used on a set/sequence itself -- confirm. | |
141 */ | |
142 PORT_Assert (under_kind != DER_SEQUENCE); | |
143 PORT_Assert (under_kind != DER_SET); | |
144 #endif | |
145 | |
146 len += 1 + DER_LengthLength(len + contents_len); | |
147 } | |
148 | |
149 return len; | |
150 } | |
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 | |
161 PORT_Assert (src != NULL); | |
162 | |
163 encode_kind = dtemplate->kind; | |
164 | |
165 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) | |
166 ? PR_TRUE : 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 | |
196 | DER_POINTER | DER_SKIP)) == 0); | |
197 | |
198 /* This is only used in decoding; it plays no part in encoding. */ | |
199 if (under_kind & DER_DERPTR) | |
200 return 0; | |
201 | |
202 if (under_kind & DER_INDEFINITE) { | |
203 PRUint32 sub_len; | |
204 void **indp = *(void ***)src; | |
205 | |
206 if (indp == NULL) | |
207 return 0; | |
208 | |
209 len = 0; | |
210 under_kind &= ~DER_INDEFINITE; | |
211 | |
212 if (under_kind == DER_SET || under_kind == DER_SEQUENCE) { | |
213 DERTemplate *tmpt = dtemplate->sub; | |
214 PORT_Assert (tmpt != NULL); | |
215 | |
216 for (; *indp != NULL; indp++) { | |
217 void *sub_src = (void *)((char *)(*indp) + tmpt->offset); | |
218 sub_len = contents_length (tmpt, sub_src); | |
219 len += sub_len + header_length (tmpt, sub_len); | |
220 } | |
221 } else { | |
222 /* | |
223 * XXX Lisa is not sure this code (for handling, for example, | |
224 * DER_INDEFINITE | DER_OCTET_STRING) is right. | |
225 */ | |
226 for (; *indp != NULL; indp++) { | |
227 SECItem *item = (SECItem *)(*indp); | |
228 sub_len = item->len; | |
229 if (under_kind == DER_BIT_STRING) { | |
230 sub_len = (sub_len + 7) >> 3; | |
231 /* bit string contents involve an extra octet */ | |
232 if (sub_len) | |
233 sub_len++; | |
234 } | |
235 if (under_kind != DER_ANY) | |
236 len += 1 + DER_LengthLength (sub_len); | |
237 } | |
238 } | |
239 | |
240 return len; | |
241 } | |
242 | |
243 switch (under_kind) { | |
244 case DER_SEQUENCE: | |
245 case DER_SET: | |
246 { | |
247 DERTemplate *tmpt; | |
248 void *sub_src; | |
249 PRUint32 sub_len; | |
250 | |
251 len = 0; | |
252 for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) { | |
253 sub_src = (void *)((char *)src + tmpt->offset); | |
254 sub_len = contents_length (tmpt, sub_src); | |
255 len += sub_len + header_length (tmpt, sub_len); | |
256 } | |
257 } | |
258 break; | |
259 | |
260 case DER_BIT_STRING: | |
261 len = (((SECItem *)src)->len + 7) >> 3; | |
262 /* bit string contents involve an extra octet */ | |
263 if (len) | |
264 len++; | |
265 break; | |
266 | |
267 default: | |
268 len = ((SECItem *)src)->len; | |
269 break; | |
270 } | |
271 | |
272 return len; | |
273 } | |
274 | |
275 | |
276 static unsigned char * | |
277 der_encode(unsigned char *buf, DERTemplate *dtemplate, void *src) | |
278 { | |
279 int header_len; | |
280 PRUint32 contents_len; | |
281 unsigned long encode_kind, under_kind; | |
282 PRBool explicit, universal; | |
283 | |
284 | |
285 /* | |
286 * First figure out how long the encoding will be. Do this by | |
287 * traversing the template from top to bottom and accumulating | |
288 * the length of each leaf item. | |
289 */ | |
290 contents_len = contents_length (dtemplate, src); | |
291 header_len = header_length (dtemplate, contents_len); | |
292 | |
293 /* | |
294 * Enough smarts was involved already, so that if both the | |
295 * header and the contents have a length of zero, then we | |
296 * are not doing any encoding for this element. | |
297 */ | |
298 if (header_len == 0 && contents_len == 0) | |
299 return buf; | |
300 | |
301 encode_kind = dtemplate->kind; | |
302 | |
303 explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE; | |
304 encode_kind &= ~DER_OPTIONAL; | |
305 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) | |
306 ? PR_TRUE : PR_FALSE; | |
307 | |
308 if (encode_kind & DER_POINTER) { | |
309 if (contents_len) { | |
310 src = *(void **)src; | |
311 PORT_Assert (src != NULL); | |
312 } | |
313 if (dtemplate->sub != NULL) { | |
314 dtemplate = dtemplate->sub; | |
315 under_kind = dtemplate->kind; | |
316 if (universal) { | |
317 encode_kind = under_kind; | |
318 } | |
319 src = (void *)((char *)src + dtemplate->offset); | |
320 } else if (universal) { | |
321 under_kind = encode_kind & ~DER_POINTER; | |
322 } else { | |
323 under_kind = dtemplate->arg; | |
324 } | |
325 } else if (encode_kind & DER_INLINE) { | |
326 dtemplate = dtemplate->sub; | |
327 under_kind = dtemplate->kind; | |
328 if (universal) { | |
329 encode_kind = under_kind; | |
330 } | |
331 src = (void *)((char *)src + dtemplate->offset); | |
332 } else if (universal) { | |
333 under_kind = encode_kind; | |
334 } else { | |
335 under_kind = dtemplate->arg; | |
336 } | |
337 | |
338 if (explicit) { | |
339 buf = DER_StoreHeader (buf, encode_kind, | |
340 (1 + DER_LengthLength(contents_len) | |
341 + contents_len)); | |
342 encode_kind = under_kind; | |
343 } | |
344 | |
345 if ((encode_kind & DER_ANY) == 0) { /* DER_ANY already contains header */ | |
346 buf = DER_StoreHeader (buf, encode_kind, contents_len); | |
347 } | |
348 | |
349 /* If no real contents to encode, then we are done. */ | |
350 if (contents_len == 0) | |
351 return buf; | |
352 | |
353 if (under_kind & DER_INDEFINITE) { | |
354 void **indp; | |
355 | |
356 indp = *(void ***)src; | |
357 PORT_Assert (indp != NULL); | |
358 | |
359 under_kind &= ~DER_INDEFINITE; | |
360 if (under_kind == DER_SET || under_kind == DER_SEQUENCE) { | |
361 DERTemplate *tmpt = dtemplate->sub; | |
362 PORT_Assert (tmpt != NULL); | |
363 for (; *indp != NULL; indp++) { | |
364 void *sub_src = (void *)((char *)(*indp) + tmpt->offset); | |
365 buf = der_encode (buf, tmpt, sub_src); | |
366 } | |
367 } else { | |
368 for (; *indp != NULL; indp++) { | |
369 SECItem *item; | |
370 int sub_len; | |
371 | |
372 item = (SECItem *)(*indp); | |
373 sub_len = item->len; | |
374 if (under_kind == DER_BIT_STRING) { | |
375 if (sub_len) { | |
376 int rem; | |
377 | |
378 sub_len = (sub_len + 7) >> 3; | |
379 buf = DER_StoreHeader (buf, under_kind, sub_len + 1); | |
380 rem = (sub_len << 3) - item->len; | |
381 *buf++ = rem; /* remaining bits */ | |
382 } else { | |
383 buf = DER_StoreHeader (buf, under_kind, 0); | |
384 } | |
385 } else if (under_kind != DER_ANY) { | |
386 buf = DER_StoreHeader (buf, under_kind, sub_len); | |
387 } | |
388 PORT_Memcpy (buf, item->data, sub_len); | |
389 buf += sub_len; | |
390 } | |
391 } | |
392 return buf; | |
393 } | |
394 | |
395 switch (under_kind) { | |
396 case DER_SEQUENCE: | |
397 case DER_SET: | |
398 { | |
399 DERTemplate *tmpt; | |
400 void *sub_src; | |
401 | |
402 for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) { | |
403 sub_src = (void *)((char *)src + tmpt->offset); | |
404 buf = der_encode (buf, tmpt, sub_src); | |
405 } | |
406 } | |
407 break; | |
408 | |
409 case DER_BIT_STRING: | |
410 { | |
411 SECItem *item; | |
412 int rem; | |
413 | |
414 /* | |
415 * The contents length includes our extra octet; subtract | |
416 * it off so we just have the real string length there. | |
417 */ | |
418 contents_len--; | |
419 item = (SECItem *)src; | |
420 PORT_Assert (contents_len == ((item->len + 7) >> 3)); | |
421 rem = (contents_len << 3) - item->len; | |
422 *buf++ = rem; /* remaining bits */ | |
423 PORT_Memcpy (buf, item->data, contents_len); | |
424 buf += contents_len; | |
425 } | |
426 break; | |
427 | |
428 default: | |
429 { | |
430 SECItem *item; | |
431 | |
432 item = (SECItem *)src; | |
433 PORT_Assert (contents_len == item->len); | |
434 PORT_Memcpy (buf, item->data, contents_len); | |
435 buf += contents_len; | |
436 } | |
437 break; | |
438 } | |
439 | |
440 return buf; | |
441 } | |
442 | |
443 | |
444 SECStatus | |
445 DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src) | |
446 { | |
447 unsigned int contents_len, header_len; | |
448 | |
449 src = (void **)((char *)src + dtemplate->offset); | |
450 | |
451 /* | |
452 * First figure out how long the encoding will be. Do this by | |
453 * traversing the template from top to bottom and accumulating | |
454 * the length of each leaf item. | |
455 */ | |
456 contents_len = contents_length (dtemplate, src); | |
457 header_len = header_length (dtemplate, contents_len); | |
458 | |
459 dest->len = contents_len + header_len; | |
460 | |
461 /* Allocate storage to hold the encoding */ | |
462 dest->data = (unsigned char*) PORT_ArenaAlloc(arena, dest->len); | |
463 if (dest->data == NULL) { | |
464 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
465 return SECFailure; | |
466 } | |
467 | |
468 /* Now encode into the buffer */ | |
469 (void) der_encode (dest->data, dtemplate, src); | |
470 | |
471 return SECSuccess; | |
472 } | |
OLD | NEW |