Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/util/derenc.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 } |