|
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 #include "secdig.h" |
|
5 |
|
6 #include "secoid.h" |
|
7 #include "secasn1.h" |
|
8 #include "secerr.h" |
|
9 |
|
10 /* |
|
11 * XXX Want to have a SGN_DecodeDigestInfo, like: |
|
12 * SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata); |
|
13 * that creates a pool and allocates from it and decodes didata into |
|
14 * the newly allocated DigestInfo structure. Then fix secvfy.c (it |
|
15 * will no longer need an arena itself) to call this and then call |
|
16 * DestroyDigestInfo when it is done, then can remove the old template |
|
17 * above and keep our new template static and "hidden". |
|
18 */ |
|
19 |
|
20 /* |
|
21 * XXX It might be nice to combine the following two functions (create |
|
22 * and encode). I think that is all anybody ever wants to do anyway. |
|
23 */ |
|
24 |
|
25 SECItem * |
|
26 SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo) |
|
27 { |
|
28 return SEC_ASN1EncodeItem (poolp, dest, diginfo, sgn_DigestInfoTemplate); |
|
29 } |
|
30 |
|
31 SGNDigestInfo * |
|
32 SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig, |
|
33 unsigned len) |
|
34 { |
|
35 SGNDigestInfo *di; |
|
36 SECStatus rv; |
|
37 PLArenaPool *arena; |
|
38 SECItem *null_param; |
|
39 SECItem dummy_value; |
|
40 |
|
41 switch (algorithm) { |
|
42 case SEC_OID_MD2: |
|
43 case SEC_OID_MD5: |
|
44 case SEC_OID_SHA1: |
|
45 case SEC_OID_SHA224: |
|
46 case SEC_OID_SHA256: |
|
47 case SEC_OID_SHA384: |
|
48 case SEC_OID_SHA512: |
|
49 break; |
|
50 default: |
|
51 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
|
52 return NULL; |
|
53 } |
|
54 |
|
55 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
56 if (arena == NULL) { |
|
57 return NULL; |
|
58 } |
|
59 |
|
60 di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo)); |
|
61 if (di == NULL) { |
|
62 PORT_FreeArena(arena, PR_FALSE); |
|
63 return NULL; |
|
64 } |
|
65 |
|
66 di->arena = arena; |
|
67 |
|
68 /* |
|
69 * PKCS #1 specifies that the AlgorithmID must have a NULL parameter |
|
70 * (as opposed to no parameter at all). |
|
71 */ |
|
72 dummy_value.data = NULL; |
|
73 dummy_value.len = 0; |
|
74 null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate); |
|
75 if (null_param == NULL) { |
|
76 goto loser; |
|
77 } |
|
78 |
|
79 rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm, |
|
80 null_param); |
|
81 |
|
82 SECITEM_FreeItem(null_param, PR_TRUE); |
|
83 |
|
84 if (rv != SECSuccess) { |
|
85 goto loser; |
|
86 } |
|
87 |
|
88 di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len); |
|
89 if (di->digest.data == NULL) { |
|
90 goto loser; |
|
91 } |
|
92 |
|
93 di->digest.len = len; |
|
94 PORT_Memcpy(di->digest.data, sig, len); |
|
95 return di; |
|
96 |
|
97 loser: |
|
98 SGN_DestroyDigestInfo(di); |
|
99 return NULL; |
|
100 } |
|
101 |
|
102 SGNDigestInfo * |
|
103 SGN_DecodeDigestInfo(SECItem *didata) |
|
104 { |
|
105 PLArenaPool *arena; |
|
106 SGNDigestInfo *di; |
|
107 SECStatus rv = SECFailure; |
|
108 SECItem diCopy = {siBuffer, NULL, 0}; |
|
109 |
|
110 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
|
111 if(arena == NULL) |
|
112 return NULL; |
|
113 |
|
114 rv = SECITEM_CopyItem(arena, &diCopy, didata); |
|
115 if (rv != SECSuccess) { |
|
116 PORT_FreeArena(arena, PR_FALSE); |
|
117 return NULL; |
|
118 } |
|
119 |
|
120 di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo)); |
|
121 if (di != NULL) { |
|
122 di->arena = arena; |
|
123 rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy); |
|
124 } |
|
125 |
|
126 if ((di == NULL) || (rv != SECSuccess)) { |
|
127 PORT_FreeArena(arena, PR_FALSE); |
|
128 di = NULL; |
|
129 } |
|
130 |
|
131 return di; |
|
132 } |
|
133 |
|
134 void |
|
135 SGN_DestroyDigestInfo(SGNDigestInfo *di) |
|
136 { |
|
137 if (di && di->arena) { |
|
138 PORT_FreeArena(di->arena, PR_FALSE); |
|
139 } |
|
140 |
|
141 return; |
|
142 } |
|
143 |
|
144 SECStatus |
|
145 SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b) |
|
146 { |
|
147 SECStatus rv; |
|
148 void *mark; |
|
149 |
|
150 if((poolp == NULL) || (a == NULL) || (b == NULL)) |
|
151 return SECFailure; |
|
152 |
|
153 mark = PORT_ArenaMark(poolp); |
|
154 a->arena = poolp; |
|
155 rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm, |
|
156 &b->digestAlgorithm); |
|
157 if (rv == SECSuccess) |
|
158 rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest); |
|
159 |
|
160 if (rv != SECSuccess) { |
|
161 PORT_ArenaRelease(poolp, mark); |
|
162 } else { |
|
163 PORT_ArenaUnmark(poolp, mark); |
|
164 } |
|
165 |
|
166 return rv; |
|
167 } |
|
168 |
|
169 SECComparison |
|
170 SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b) |
|
171 { |
|
172 SECComparison rv; |
|
173 |
|
174 /* Check signature algorithm's */ |
|
175 rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm); |
|
176 if (rv) return rv; |
|
177 |
|
178 /* Compare signature block length's */ |
|
179 rv = SECITEM_CompareItem(&a->digest, &b->digest); |
|
180 return rv; |
|
181 } |