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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)