|
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, optional, 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 optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE; |
|
305 encode_kind &= ~DER_OPTIONAL; |
|
306 universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL) |
|
307 ? PR_TRUE : PR_FALSE; |
|
308 |
|
309 if (encode_kind & DER_POINTER) { |
|
310 if (contents_len) { |
|
311 src = *(void **)src; |
|
312 PORT_Assert (src != NULL); |
|
313 } |
|
314 if (dtemplate->sub != NULL) { |
|
315 dtemplate = dtemplate->sub; |
|
316 under_kind = dtemplate->kind; |
|
317 if (universal) { |
|
318 encode_kind = under_kind; |
|
319 } |
|
320 src = (void *)((char *)src + dtemplate->offset); |
|
321 } else if (universal) { |
|
322 under_kind = encode_kind & ~DER_POINTER; |
|
323 } else { |
|
324 under_kind = dtemplate->arg; |
|
325 } |
|
326 } else if (encode_kind & DER_INLINE) { |
|
327 dtemplate = dtemplate->sub; |
|
328 under_kind = dtemplate->kind; |
|
329 if (universal) { |
|
330 encode_kind = under_kind; |
|
331 } |
|
332 src = (void *)((char *)src + dtemplate->offset); |
|
333 } else if (universal) { |
|
334 under_kind = encode_kind; |
|
335 } else { |
|
336 under_kind = dtemplate->arg; |
|
337 } |
|
338 |
|
339 if (explicit) { |
|
340 buf = DER_StoreHeader (buf, encode_kind, |
|
341 (1 + DER_LengthLength(contents_len) |
|
342 + contents_len)); |
|
343 encode_kind = under_kind; |
|
344 } |
|
345 |
|
346 if ((encode_kind & DER_ANY) == 0) { /* DER_ANY already contains header */ |
|
347 buf = DER_StoreHeader (buf, encode_kind, contents_len); |
|
348 } |
|
349 |
|
350 /* If no real contents to encode, then we are done. */ |
|
351 if (contents_len == 0) |
|
352 return buf; |
|
353 |
|
354 if (under_kind & DER_INDEFINITE) { |
|
355 void **indp; |
|
356 |
|
357 indp = *(void ***)src; |
|
358 PORT_Assert (indp != NULL); |
|
359 |
|
360 under_kind &= ~DER_INDEFINITE; |
|
361 if (under_kind == DER_SET || under_kind == DER_SEQUENCE) { |
|
362 DERTemplate *tmpt = dtemplate->sub; |
|
363 PORT_Assert (tmpt != NULL); |
|
364 for (; *indp != NULL; indp++) { |
|
365 void *sub_src = (void *)((char *)(*indp) + tmpt->offset); |
|
366 buf = der_encode (buf, tmpt, sub_src); |
|
367 } |
|
368 } else { |
|
369 for (; *indp != NULL; indp++) { |
|
370 SECItem *item; |
|
371 int sub_len; |
|
372 |
|
373 item = (SECItem *)(*indp); |
|
374 sub_len = item->len; |
|
375 if (under_kind == DER_BIT_STRING) { |
|
376 if (sub_len) { |
|
377 int rem; |
|
378 |
|
379 sub_len = (sub_len + 7) >> 3; |
|
380 buf = DER_StoreHeader (buf, under_kind, sub_len + 1); |
|
381 rem = (sub_len << 3) - item->len; |
|
382 *buf++ = rem; /* remaining bits */ |
|
383 } else { |
|
384 buf = DER_StoreHeader (buf, under_kind, 0); |
|
385 } |
|
386 } else if (under_kind != DER_ANY) { |
|
387 buf = DER_StoreHeader (buf, under_kind, sub_len); |
|
388 } |
|
389 PORT_Memcpy (buf, item->data, sub_len); |
|
390 buf += sub_len; |
|
391 } |
|
392 } |
|
393 return buf; |
|
394 } |
|
395 |
|
396 switch (under_kind) { |
|
397 case DER_SEQUENCE: |
|
398 case DER_SET: |
|
399 { |
|
400 DERTemplate *tmpt; |
|
401 void *sub_src; |
|
402 |
|
403 for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) { |
|
404 sub_src = (void *)((char *)src + tmpt->offset); |
|
405 buf = der_encode (buf, tmpt, sub_src); |
|
406 } |
|
407 } |
|
408 break; |
|
409 |
|
410 case DER_BIT_STRING: |
|
411 { |
|
412 SECItem *item; |
|
413 int rem; |
|
414 |
|
415 /* |
|
416 * The contents length includes our extra octet; subtract |
|
417 * it off so we just have the real string length there. |
|
418 */ |
|
419 contents_len--; |
|
420 item = (SECItem *)src; |
|
421 PORT_Assert (contents_len == ((item->len + 7) >> 3)); |
|
422 rem = (contents_len << 3) - item->len; |
|
423 *buf++ = rem; /* remaining bits */ |
|
424 PORT_Memcpy (buf, item->data, contents_len); |
|
425 buf += contents_len; |
|
426 } |
|
427 break; |
|
428 |
|
429 default: |
|
430 { |
|
431 SECItem *item; |
|
432 |
|
433 item = (SECItem *)src; |
|
434 PORT_Assert (contents_len == item->len); |
|
435 PORT_Memcpy (buf, item->data, contents_len); |
|
436 buf += contents_len; |
|
437 } |
|
438 break; |
|
439 } |
|
440 |
|
441 return buf; |
|
442 } |
|
443 |
|
444 |
|
445 SECStatus |
|
446 DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src) |
|
447 { |
|
448 unsigned int contents_len, header_len; |
|
449 |
|
450 src = (void **)((char *)src + dtemplate->offset); |
|
451 |
|
452 /* |
|
453 * First figure out how long the encoding will be. Do this by |
|
454 * traversing the template from top to bottom and accumulating |
|
455 * the length of each leaf item. |
|
456 */ |
|
457 contents_len = contents_length (dtemplate, src); |
|
458 header_len = header_length (dtemplate, contents_len); |
|
459 |
|
460 dest->len = contents_len + header_len; |
|
461 |
|
462 /* Allocate storage to hold the encoding */ |
|
463 dest->data = (unsigned char*) PORT_ArenaAlloc(arena, dest->len); |
|
464 if (dest->data == NULL) { |
|
465 PORT_SetError(SEC_ERROR_NO_MEMORY); |
|
466 return SECFailure; |
|
467 } |
|
468 |
|
469 /* Now encode into the buffer */ |
|
470 (void) der_encode (dest->data, dtemplate, src); |
|
471 |
|
472 return SECSuccess; |
|
473 } |