|
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 /* |
|
6 * Utility routines to complement the ASN.1 encoding and decoding functions. |
|
7 */ |
|
8 |
|
9 #include "secasn1.h" |
|
10 |
|
11 |
|
12 /* |
|
13 * We have a length that needs to be encoded; how many bytes will the |
|
14 * encoding take? |
|
15 * |
|
16 * The rules are that 0 - 0x7f takes one byte (the length itself is the |
|
17 * entire encoding); everything else takes one plus the number of bytes |
|
18 * in the length. |
|
19 */ |
|
20 int |
|
21 SEC_ASN1LengthLength (unsigned long len) |
|
22 { |
|
23 int lenlen = 1; |
|
24 |
|
25 if (len > 0x7f) { |
|
26 do { |
|
27 lenlen++; |
|
28 len >>= 8; |
|
29 } while (len); |
|
30 } |
|
31 |
|
32 return lenlen; |
|
33 } |
|
34 |
|
35 |
|
36 /* |
|
37 * XXX Move over (and rewrite as appropriate) the rest of the |
|
38 * stuff in dersubr.c! |
|
39 */ |
|
40 |
|
41 |
|
42 /* |
|
43 * Find the appropriate subtemplate for the given template. |
|
44 * This may involve calling a "chooser" function, or it may just |
|
45 * be right there. In either case, it is expected to *have* a |
|
46 * subtemplate; this is asserted in debug builds (in non-debug |
|
47 * builds, NULL will be returned). |
|
48 * |
|
49 * "thing" is a pointer to the structure being encoded/decoded |
|
50 * "encoding", when true, means that we are in the process of encoding |
|
51 * (as opposed to in the process of decoding) |
|
52 */ |
|
53 const SEC_ASN1Template * |
|
54 SEC_ASN1GetSubtemplate (const SEC_ASN1Template *theTemplate, void *thing, |
|
55 PRBool encoding) |
|
56 { |
|
57 const SEC_ASN1Template *subt = NULL; |
|
58 |
|
59 PORT_Assert (theTemplate->sub != NULL); |
|
60 if (theTemplate->sub != NULL) { |
|
61 if (theTemplate->kind & SEC_ASN1_DYNAMIC) { |
|
62 SEC_ASN1TemplateChooserPtr chooserp; |
|
63 |
|
64 chooserp = *(SEC_ASN1TemplateChooserPtr *) theTemplate->sub; |
|
65 if (chooserp) { |
|
66 if (thing != NULL) |
|
67 thing = (char *)thing - theTemplate->offset; |
|
68 subt = (* chooserp)(thing, encoding); |
|
69 } |
|
70 } else { |
|
71 subt = (SEC_ASN1Template*)theTemplate->sub; |
|
72 } |
|
73 } |
|
74 return subt; |
|
75 } |
|
76 |
|
77 PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate) |
|
78 { |
|
79 if (!theTemplate) { |
|
80 return PR_TRUE; /* it doesn't get any simpler than NULL */ |
|
81 } |
|
82 /* only templates made of one primitive type or a choice of primitive |
|
83 types are considered simple */ |
|
84 if (! (theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK))) { |
|
85 return PR_TRUE; /* primitive type */ |
|
86 } |
|
87 if (!(theTemplate->kind & SEC_ASN1_CHOICE)) { |
|
88 return PR_FALSE; /* no choice means not simple */ |
|
89 } |
|
90 while (++theTemplate && theTemplate->kind) { |
|
91 if (theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK)) { |
|
92 return PR_FALSE; /* complex type */ |
|
93 } |
|
94 } |
|
95 return PR_TRUE; /* choice of primitive types */ |
|
96 } |
|
97 |