1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
40 * Generic templates for individual/simple items.
43 DERTemplate SECAnyTemplate
[] = {
45 0, NULL
, sizeof(SECItem
) }
48 DERTemplate SECBitStringTemplate
[] = {
50 0, NULL
, sizeof(SECItem
) }
53 DERTemplate SECBooleanTemplate
[] = {
55 0, NULL
, sizeof(SECItem
) }
58 DERTemplate SECIA5StringTemplate
[] = {
60 0, NULL
, sizeof(SECItem
) }
63 DERTemplate SECIntegerTemplate
[] = {
65 0, NULL
, sizeof(SECItem
) }
68 DERTemplate SECNullTemplate
[] = {
70 0, NULL
, sizeof(SECItem
) }
73 DERTemplate SECObjectIDTemplate
[] = {
75 0, NULL
, sizeof(SECItem
) }
78 DERTemplate SECOctetStringTemplate
[] = {
80 0, NULL
, sizeof(SECItem
) }
83 DERTemplate SECPrintableStringTemplate
[] = {
84 { DER_PRINTABLE_STRING
,
85 0, NULL
, sizeof(SECItem
) }
88 DERTemplate SECT61StringTemplate
[] = {
90 0, NULL
, sizeof(SECItem
) }
93 DERTemplate SECUTCTimeTemplate
[] = {
95 0, NULL
, sizeof(SECItem
) }
100 header_length(DERTemplate
*dtemplate
, uint32 contents_len
)
103 unsigned long encode_kind
, under_kind
;
104 PRBool
explicit, optional
, universal
;
106 encode_kind
= dtemplate
->kind
;
108 explicit = (encode_kind
& DER_EXPLICIT
) ? PR_TRUE
: PR_FALSE
;
109 optional
= (encode_kind
& DER_OPTIONAL
) ? PR_TRUE
: PR_FALSE
;
110 universal
= ((encode_kind
& DER_CLASS_MASK
) == DER_UNIVERSAL
)
111 ? PR_TRUE
: PR_FALSE
;
113 PORT_Assert (!(explicit && universal
)); /* bad templates */
115 if (encode_kind
& DER_POINTER
) {
116 if (dtemplate
->sub
!= NULL
) {
117 under_kind
= dtemplate
->sub
->kind
;
119 encode_kind
= under_kind
;
121 } else if (universal
) {
122 under_kind
= encode_kind
& ~DER_POINTER
;
124 under_kind
= dtemplate
->arg
;
126 } else if (encode_kind
& DER_INLINE
) {
127 PORT_Assert (dtemplate
->sub
!= NULL
);
128 under_kind
= dtemplate
->sub
->kind
;
130 encode_kind
= under_kind
;
132 } else if (universal
) {
133 under_kind
= encode_kind
;
135 under_kind
= dtemplate
->arg
;
138 /* This is only used in decoding; it plays no part in encoding. */
139 if (under_kind
& DER_DERPTR
)
142 /* No header at all for an "empty" optional. */
143 if ((contents_len
== 0) && optional
)
146 /* And no header for a full DER_ANY. */
147 if (encode_kind
& DER_ANY
)
151 * The common case: one octet for identifier and as many octets
152 * as necessary to hold the content length.
154 len
= 1 + DER_LengthLength(contents_len
);
156 /* Account for the explicit wrapper, if necessary. */
159 * Well, I was trying to do something useful, but these
160 * assertions are too restrictive on valid templates.
161 * I wanted to make sure that the top-level "kind" of
162 * a template does not also specify DER_EXPLICIT, which
163 * should only modify a component field. Maybe later
164 * I can figure out a better way to detect such a problem,
165 * but for now I must remove these checks altogether.
168 * This modifier applies only to components of a set or sequence;
169 * it should never be used on a set/sequence itself -- confirm.
171 PORT_Assert (under_kind
!= DER_SEQUENCE
);
172 PORT_Assert (under_kind
!= DER_SET
);
175 len
+= 1 + DER_LengthLength(len
+ contents_len
);
183 contents_length(DERTemplate
*dtemplate
, void *src
)
186 unsigned long encode_kind
, under_kind
;
190 PORT_Assert (src
!= NULL
);
192 encode_kind
= dtemplate
->kind
;
194 universal
= ((encode_kind
& DER_CLASS_MASK
) == DER_UNIVERSAL
)
195 ? PR_TRUE
: PR_FALSE
;
196 encode_kind
&= ~DER_OPTIONAL
;
198 if (encode_kind
& DER_POINTER
) {
203 if (dtemplate
->sub
!= NULL
) {
204 dtemplate
= dtemplate
->sub
;
205 under_kind
= dtemplate
->kind
;
206 src
= (void *)((char *)src
+ dtemplate
->offset
);
207 } else if (universal
) {
208 under_kind
= encode_kind
& ~DER_POINTER
;
210 under_kind
= dtemplate
->arg
;
212 } else if (encode_kind
& DER_INLINE
) {
213 PORT_Assert (dtemplate
->sub
!= NULL
);
214 dtemplate
= dtemplate
->sub
;
215 under_kind
= dtemplate
->kind
;
216 src
= (void *)((char *)src
+ dtemplate
->offset
);
217 } else if (universal
) {
218 under_kind
= encode_kind
;
220 under_kind
= dtemplate
->arg
;
223 /* Having any of these bits is not expected here... */
224 PORT_Assert ((under_kind
& (DER_EXPLICIT
| DER_INLINE
| DER_OPTIONAL
225 | DER_POINTER
| DER_SKIP
)) == 0);
227 /* This is only used in decoding; it plays no part in encoding. */
228 if (under_kind
& DER_DERPTR
)
231 if (under_kind
& DER_INDEFINITE
) {
233 void **indp
= *(void ***)src
;
239 under_kind
&= ~DER_INDEFINITE
;
241 if (under_kind
== DER_SET
|| under_kind
== DER_SEQUENCE
) {
242 DERTemplate
*tmpt
= dtemplate
->sub
;
243 PORT_Assert (tmpt
!= NULL
);
245 for (; *indp
!= NULL
; indp
++) {
246 void *sub_src
= (void *)((char *)(*indp
) + tmpt
->offset
);
247 sub_len
= contents_length (tmpt
, sub_src
);
248 len
+= sub_len
+ header_length (tmpt
, sub_len
);
252 * XXX Lisa is not sure this code (for handling, for example,
253 * DER_INDEFINITE | DER_OCTET_STRING) is right.
255 for (; *indp
!= NULL
; indp
++) {
256 SECItem
*item
= (SECItem
*)(*indp
);
258 if (under_kind
== DER_BIT_STRING
) {
259 sub_len
= (sub_len
+ 7) >> 3;
260 /* bit string contents involve an extra octet */
264 if (under_kind
!= DER_ANY
)
265 len
+= 1 + DER_LengthLength (sub_len
);
272 switch (under_kind
) {
281 for (tmpt
= dtemplate
+ 1; tmpt
->kind
; tmpt
++) {
282 sub_src
= (void *)((char *)src
+ tmpt
->offset
);
283 sub_len
= contents_length (tmpt
, sub_src
);
284 len
+= sub_len
+ header_length (tmpt
, sub_len
);
290 len
= (((SECItem
*)src
)->len
+ 7) >> 3;
291 /* bit string contents involve an extra octet */
297 len
= ((SECItem
*)src
)->len
;
305 static unsigned char *
306 der_encode(unsigned char *buf
, DERTemplate
*dtemplate
, void *src
)
310 unsigned long encode_kind
, under_kind
;
311 PRBool
explicit, optional
, universal
;
315 * First figure out how long the encoding will be. Do this by
316 * traversing the template from top to bottom and accumulating
317 * the length of each leaf item.
319 contents_len
= contents_length (dtemplate
, src
);
320 header_len
= header_length (dtemplate
, contents_len
);
323 * Enough smarts was involved already, so that if both the
324 * header and the contents have a length of zero, then we
325 * are not doing any encoding for this element.
327 if (header_len
== 0 && contents_len
== 0)
330 encode_kind
= dtemplate
->kind
;
332 explicit = (encode_kind
& DER_EXPLICIT
) ? PR_TRUE
: PR_FALSE
;
333 optional
= (encode_kind
& DER_OPTIONAL
) ? PR_TRUE
: PR_FALSE
;
334 encode_kind
&= ~DER_OPTIONAL
;
335 universal
= ((encode_kind
& DER_CLASS_MASK
) == DER_UNIVERSAL
)
336 ? PR_TRUE
: PR_FALSE
;
338 if (encode_kind
& DER_POINTER
) {
341 PORT_Assert (src
!= NULL
);
343 if (dtemplate
->sub
!= NULL
) {
344 dtemplate
= dtemplate
->sub
;
345 under_kind
= dtemplate
->kind
;
347 encode_kind
= under_kind
;
349 src
= (void *)((char *)src
+ dtemplate
->offset
);
350 } else if (universal
) {
351 under_kind
= encode_kind
& ~DER_POINTER
;
353 under_kind
= dtemplate
->arg
;
355 } else if (encode_kind
& DER_INLINE
) {
356 dtemplate
= dtemplate
->sub
;
357 under_kind
= dtemplate
->kind
;
359 encode_kind
= under_kind
;
361 src
= (void *)((char *)src
+ dtemplate
->offset
);
362 } else if (universal
) {
363 under_kind
= encode_kind
;
365 under_kind
= dtemplate
->arg
;
369 buf
= DER_StoreHeader (buf
, encode_kind
,
370 (1 + DER_LengthLength(contents_len
)
372 encode_kind
= under_kind
;
375 if ((encode_kind
& DER_ANY
) == 0) { /* DER_ANY already contains header */
376 buf
= DER_StoreHeader (buf
, encode_kind
, contents_len
);
379 /* If no real contents to encode, then we are done. */
380 if (contents_len
== 0)
383 if (under_kind
& DER_INDEFINITE
) {
386 indp
= *(void ***)src
;
387 PORT_Assert (indp
!= NULL
);
389 under_kind
&= ~DER_INDEFINITE
;
390 if (under_kind
== DER_SET
|| under_kind
== DER_SEQUENCE
) {
391 DERTemplate
*tmpt
= dtemplate
->sub
;
392 PORT_Assert (tmpt
!= NULL
);
393 for (; *indp
!= NULL
; indp
++) {
394 void *sub_src
= (void *)((char *)(*indp
) + tmpt
->offset
);
395 buf
= der_encode (buf
, tmpt
, sub_src
);
398 for (; *indp
!= NULL
; indp
++) {
402 item
= (SECItem
*)(*indp
);
404 if (under_kind
== DER_BIT_STRING
) {
408 sub_len
= (sub_len
+ 7) >> 3;
409 buf
= DER_StoreHeader (buf
, under_kind
, sub_len
+ 1);
410 rem
= (sub_len
<< 3) - item
->len
;
411 *buf
++ = rem
; /* remaining bits */
413 buf
= DER_StoreHeader (buf
, under_kind
, 0);
415 } else if (under_kind
!= DER_ANY
) {
416 buf
= DER_StoreHeader (buf
, under_kind
, sub_len
);
418 PORT_Memcpy (buf
, item
->data
, sub_len
);
425 switch (under_kind
) {
432 for (tmpt
= dtemplate
+ 1; tmpt
->kind
; tmpt
++) {
433 sub_src
= (void *)((char *)src
+ tmpt
->offset
);
434 buf
= der_encode (buf
, tmpt
, sub_src
);
445 * The contents length includes our extra octet; subtract
446 * it off so we just have the real string length there.
449 item
= (SECItem
*)src
;
450 PORT_Assert (contents_len
== ((item
->len
+ 7) >> 3));
451 rem
= (contents_len
<< 3) - item
->len
;
452 *buf
++ = rem
; /* remaining bits */
453 PORT_Memcpy (buf
, item
->data
, contents_len
);
462 item
= (SECItem
*)src
;
463 PORT_Assert (contents_len
== item
->len
);
464 PORT_Memcpy (buf
, item
->data
, contents_len
);
475 DER_Encode(PRArenaPool
*arena
, SECItem
*dest
, DERTemplate
*dtemplate
, void *src
)
477 unsigned int contents_len
, header_len
;
479 src
= (void **)((char *)src
+ dtemplate
->offset
);
482 * First figure out how long the encoding will be. Do this by
483 * traversing the template from top to bottom and accumulating
484 * the length of each leaf item.
486 contents_len
= contents_length (dtemplate
, src
);
487 header_len
= header_length (dtemplate
, contents_len
);
489 dest
->len
= contents_len
+ header_len
;
491 /* Allocate storage to hold the encoding */
492 dest
->data
= (unsigned char*) PORT_ArenaAlloc(arena
, dest
->len
);
493 if (dest
->data
== NULL
) {
494 PORT_SetError(SEC_ERROR_NO_MEMORY
);
498 /* Now encode into the buffer */
499 (void) der_encode (dest
->data
, dtemplate
, src
);