OLD | NEW |
1 /* | 1 /* |
2 * Signature stuff. | 2 * Signature stuff. |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 4 * This Source Code Form is subject to the terms of the Mozilla Public |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include "cryptohi.h" | 9 #include "cryptohi.h" |
10 #include "sechash.h" | 10 #include "sechash.h" |
11 #include "secder.h" | 11 #include "secder.h" |
12 #include "keyhi.h" | 12 #include "keyhi.h" |
13 #include "secoid.h" | 13 #include "secoid.h" |
14 #include "secdig.h" | 14 #include "secdig.h" |
15 #include "pk11func.h" | 15 #include "pk11func.h" |
16 #include "secerr.h" | 16 #include "secerr.h" |
17 #include "keyi.h" | 17 #include "keyi.h" |
18 | 18 |
19 struct SGNContextStr { | 19 struct SGNContextStr { |
20 SECOidTag signalg; | 20 SECOidTag signalg; |
21 SECOidTag hashalg; | 21 SECOidTag hashalg; |
22 void *hashcx; | 22 void *hashcx; |
23 const SECHashObject *hashobj; | 23 const SECHashObject *hashobj; |
24 SECKEYPrivateKey *key; | 24 SECKEYPrivateKey *key; |
25 }; | 25 }; |
26 | 26 |
27 SGNContext * | 27 SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key) { |
28 SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key) | 28 SGNContext *cx; |
29 { | 29 SECOidTag hashalg, signalg; |
30 SGNContext *cx; | 30 KeyType keyType; |
31 SECOidTag hashalg, signalg; | 31 SECStatus rv; |
32 KeyType keyType; | 32 |
33 SECStatus rv; | 33 /* OK, map a PKCS #7 hash and encrypt algorithm into |
34 | 34 * a standard hashing algorithm. Why did we pass in the whole |
35 /* OK, map a PKCS #7 hash and encrypt algorithm into | 35 * PKCS #7 algTag if we were just going to change here you might |
36 * a standard hashing algorithm. Why did we pass in the whole | 36 * ask. Well the answer is for some cards we may have to do the |
37 * PKCS #7 algTag if we were just going to change here you might | 37 * hashing on card. It may not support CKM_RSA_PKCS sign algorithm, |
38 * ask. Well the answer is for some cards we may have to do the | 38 * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS. |
39 * hashing on card. It may not support CKM_RSA_PKCS sign algorithm, | 39 */ |
40 * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS. | 40 /* we have a private key, not a public key, so don't pass it in */ |
41 */ | 41 rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg); |
42 /* we have a private key, not a public key, so don't pass it in */ | 42 if (rv != SECSuccess) { |
43 rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg); | 43 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
44 if (rv != SECSuccess) { | 44 return 0; |
45 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 45 } |
46 » return 0; | 46 keyType = seckey_GetKeyType(signalg); |
47 } | 47 |
48 keyType = seckey_GetKeyType(signalg); | 48 /* verify our key type */ |
49 | 49 if (key->keyType != keyType && |
50 /* verify our key type */ | 50 !((key->keyType == dsaKey) && (keyType == fortezzaKey))) { |
51 if (key->keyType != keyType && | 51 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
52 » !((key->keyType == dsaKey) && (keyType == fortezzaKey)) ) { | 52 return 0; |
53 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 53 } |
54 » return 0; | 54 |
55 } | 55 cx = (SGNContext *)PORT_ZAlloc(sizeof(SGNContext)); |
56 | 56 if (cx) { |
57 cx = (SGNContext*) PORT_ZAlloc(sizeof(SGNContext)); | 57 cx->hashalg = hashalg; |
58 if (cx) { | 58 cx->signalg = signalg; |
59 » cx->hashalg = hashalg; | 59 cx->key = key; |
60 » cx->signalg = signalg; | 60 } |
61 » cx->key = key; | 61 return cx; |
62 } | 62 } |
63 return cx; | 63 |
64 } | 64 void SGN_DestroyContext(SGNContext *cx, PRBool freeit) { |
65 | 65 if (cx) { |
66 void | |
67 SGN_DestroyContext(SGNContext *cx, PRBool freeit) | |
68 { | |
69 if (cx) { | |
70 » if (cx->hashcx != NULL) { | |
71 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | |
72 » cx->hashcx = NULL; | |
73 » } | |
74 » if (freeit) { | |
75 » PORT_ZFree(cx, sizeof(SGNContext)); | |
76 » } | |
77 } | |
78 } | |
79 | |
80 SECStatus | |
81 SGN_Begin(SGNContext *cx) | |
82 { | |
83 if (cx->hashcx != NULL) { | 66 if (cx->hashcx != NULL) { |
84 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | 67 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
85 » cx->hashcx = NULL; | 68 cx->hashcx = NULL; |
86 } | 69 } |
87 | 70 if (freeit) { |
88 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg); | 71 PORT_ZFree(cx, sizeof(SGNContext)); |
89 if (!cx->hashobj) | 72 } |
90 » return SECFailure;» /* error code is already set */ | 73 } |
91 | 74 } |
92 cx->hashcx = (*cx->hashobj->create)(); | 75 |
93 if (cx->hashcx == NULL) | 76 SECStatus SGN_Begin(SGNContext *cx) { |
94 » return SECFailure; | 77 if (cx->hashcx != NULL) { |
95 | 78 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
96 (*cx->hashobj->begin)(cx->hashcx); | 79 cx->hashcx = NULL; |
97 return SECSuccess; | 80 } |
98 } | 81 |
99 | 82 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg); |
100 SECStatus | 83 if (!cx->hashobj) return SECFailure; /* error code is already set */ |
101 SGN_Update(SGNContext *cx, const unsigned char *input, unsigned int inputLen) | 84 |
102 { | 85 cx->hashcx = (*cx->hashobj->create)(); |
103 if (cx->hashcx == NULL) { | 86 if (cx->hashcx == NULL) return SECFailure; |
104 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 87 |
105 » return SECFailure; | 88 (*cx->hashobj->begin)(cx->hashcx); |
106 } | 89 return SECSuccess; |
107 (*cx->hashobj->update)(cx->hashcx, input, inputLen); | 90 } |
108 return SECSuccess; | 91 |
| 92 SECStatus SGN_Update(SGNContext *cx, const unsigned char *input, |
| 93 unsigned int inputLen) { |
| 94 if (cx->hashcx == NULL) { |
| 95 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 96 return SECFailure; |
| 97 } |
| 98 (*cx->hashobj->update)(cx->hashcx, input, inputLen); |
| 99 return SECSuccess; |
109 } | 100 } |
110 | 101 |
111 /* XXX Old template; want to expunge it eventually. */ | 102 /* XXX Old template; want to expunge it eventually. */ |
112 static DERTemplate SECAlgorithmIDTemplate[] = { | 103 static DERTemplate SECAlgorithmIDTemplate[] = { |
113 { DER_SEQUENCE, | 104 {DER_SEQUENCE, 0, NULL, sizeof(SECAlgorithmID)}, |
114 » 0, NULL, sizeof(SECAlgorithmID) }, | 105 {DER_OBJECT_ID, offsetof(SECAlgorithmID, algorithm), }, |
115 { DER_OBJECT_ID, | 106 {DER_OPTIONAL | DER_ANY, offsetof(SECAlgorithmID, parameters), }, |
116 » offsetof(SECAlgorithmID,algorithm), }, | 107 {0, }}; |
117 { DER_OPTIONAL | DER_ANY, | |
118 » offsetof(SECAlgorithmID,parameters), }, | |
119 { 0, } | |
120 }; | |
121 | 108 |
122 /* | 109 /* |
123 * XXX OLD Template. Once all uses have been switched over to new one, | 110 * XXX OLD Template. Once all uses have been switched over to new one, |
124 * remove this. | 111 * remove this. |
125 */ | 112 */ |
126 static DERTemplate SGNDigestInfoTemplate[] = { | 113 static DERTemplate SGNDigestInfoTemplate[] = { |
127 { DER_SEQUENCE, | 114 {DER_SEQUENCE, 0, NULL, sizeof(SGNDigestInfo)}, |
128 » 0, NULL, sizeof(SGNDigestInfo) }, | 115 {DER_INLINE, offsetof(SGNDigestInfo, digestAlgorithm), |
129 { DER_INLINE, | 116 SECAlgorithmIDTemplate, }, |
130 » offsetof(SGNDigestInfo,digestAlgorithm), | 117 {DER_OCTET_STRING, offsetof(SGNDigestInfo, digest), }, {0, }}; |
131 » SECAlgorithmIDTemplate, }, | 118 |
132 { DER_OCTET_STRING, | 119 SECStatus SGN_End(SGNContext *cx, SECItem *result) { |
133 » offsetof(SGNDigestInfo,digest), }, | 120 unsigned char digest[HASH_LENGTH_MAX]; |
134 { 0, } | 121 unsigned part1; |
135 }; | 122 int signatureLen; |
136 | 123 SECStatus rv; |
137 SECStatus | 124 SECItem digder, sigitem; |
138 SGN_End(SGNContext *cx, SECItem *result) | 125 PLArenaPool *arena = 0; |
139 { | 126 SECKEYPrivateKey *privKey = cx->key; |
140 unsigned char digest[HASH_LENGTH_MAX]; | 127 SGNDigestInfo *di = 0; |
141 unsigned part1; | 128 |
142 int signatureLen; | 129 result->data = 0; |
143 SECStatus rv; | 130 digder.data = 0; |
144 SECItem digder, sigitem; | 131 |
145 PLArenaPool *arena = 0; | 132 /* Finish up digest function */ |
146 SECKEYPrivateKey *privKey = cx->key; | 133 if (cx->hashcx == NULL) { |
147 SGNDigestInfo *di = 0; | 134 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
148 | 135 return SECFailure; |
149 result->data = 0; | 136 } |
150 digder.data = 0; | 137 (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); |
151 | 138 |
152 /* Finish up digest function */ | 139 if (privKey->keyType == rsaKey) { |
153 if (cx->hashcx == NULL) { | 140 |
154 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 141 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
155 » return SECFailure; | 142 if (!arena) { |
156 } | 143 rv = SECFailure; |
157 (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); | 144 goto loser; |
158 | 145 } |
159 | 146 |
160 if (privKey->keyType == rsaKey) { | 147 /* Construct digest info */ |
161 | 148 di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); |
162 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 149 if (!di) { |
163 » if ( !arena ) { | 150 rv = SECFailure; |
164 » rv = SECFailure; | 151 goto loser; |
165 » goto loser; | 152 } |
166 » } | 153 |
167 ···· | 154 /* Der encode the digest as a DigestInfo */ |
168 » /* Construct digest info */ | 155 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
169 » di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); | |
170 » if (!di) { | |
171 » rv = SECFailure; | |
172 » goto loser; | |
173 » } | |
174 | |
175 » /* Der encode the digest as a DigestInfo */ | |
176 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, | |
177 di); | |
178 » if (rv != SECSuccess) { | |
179 » goto loser; | |
180 » } | |
181 } else { | |
182 » digder.data = digest; | |
183 » digder.len = part1; | |
184 } | |
185 | |
186 /* | |
187 ** Encrypt signature after constructing appropriate PKCS#1 signature | |
188 ** block | |
189 */ | |
190 signatureLen = PK11_SignatureLen(privKey); | |
191 if (signatureLen <= 0) { | |
192 » PORT_SetError(SEC_ERROR_INVALID_KEY); | |
193 » rv = SECFailure; | |
194 » goto loser; | |
195 } | |
196 sigitem.len = signatureLen; | |
197 sigitem.data = (unsigned char*) PORT_Alloc(signatureLen); | |
198 | |
199 if (sigitem.data == NULL) { | |
200 » rv = SECFailure; | |
201 » goto loser; | |
202 } | |
203 | |
204 rv = PK11_Sign(privKey, &sigitem, &digder); | |
205 if (rv != SECSuccess) { | 156 if (rv != SECSuccess) { |
206 » PORT_Free(sigitem.data); | 157 goto loser; |
207 » sigitem.data = NULL; | 158 } |
208 » goto loser; | 159 } else { |
209 } | 160 digder.data = digest; |
210 | 161 digder.len = part1; |
211 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || | 162 } |
212 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { | 163 |
213 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ | 164 /* |
214 » rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);· | 165 ** Encrypt signature after constructing appropriate PKCS#1 signature |
215 » PORT_Free(sigitem.data); | 166 ** block |
216 » if (rv != SECSuccess) | 167 */ |
217 » goto loser; | 168 signatureLen = PK11_SignatureLen(privKey); |
218 } else { | 169 if (signatureLen <= 0) { |
219 » result->len = sigitem.len; | 170 PORT_SetError(SEC_ERROR_INVALID_KEY); |
220 » result->data = sigitem.data; | 171 rv = SECFailure; |
221 } | 172 goto loser; |
222 | 173 } |
223 loser: | 174 sigitem.len = signatureLen; |
224 SGN_DestroyDigestInfo(di); | 175 sigitem.data = (unsigned char *)PORT_Alloc(signatureLen); |
225 if (arena != NULL) { | 176 |
226 » PORT_FreeArena(arena, PR_FALSE); | 177 if (sigitem.data == NULL) { |
227 } | 178 rv = SECFailure; |
228 return rv; | 179 goto loser; |
| 180 } |
| 181 |
| 182 rv = PK11_Sign(privKey, &sigitem, &digder); |
| 183 if (rv != SECSuccess) { |
| 184 PORT_Free(sigitem.data); |
| 185 sigitem.data = NULL; |
| 186 goto loser; |
| 187 } |
| 188 |
| 189 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || |
| 190 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { |
| 191 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ |
| 192 rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); |
| 193 PORT_Free(sigitem.data); |
| 194 if (rv != SECSuccess) goto loser; |
| 195 } else { |
| 196 result->len = sigitem.len; |
| 197 result->data = sigitem.data; |
| 198 } |
| 199 |
| 200 loser: |
| 201 SGN_DestroyDigestInfo(di); |
| 202 if (arena != NULL) { |
| 203 PORT_FreeArena(arena, PR_FALSE); |
| 204 } |
| 205 return rv; |
229 } | 206 } |
230 | 207 |
231 /************************************************************************/ | 208 /************************************************************************/ |
232 | 209 |
233 /* | 210 /* |
234 ** Sign a block of data returning in result a bunch of bytes that are the | 211 ** Sign a block of data returning in result a bunch of bytes that are the |
235 ** signature. Returns zero on success, an error code on failure. | 212 ** signature. Returns zero on success, an error code on failure. |
236 */ | 213 */ |
237 SECStatus | 214 SECStatus SEC_SignData(SECItem *res, const unsigned char *buf, int len, |
238 SEC_SignData(SECItem *res, const unsigned char *buf, int len, | 215 SECKEYPrivateKey *pk, SECOidTag algid) { |
239 » SECKEYPrivateKey *pk, SECOidTag algid) | 216 SECStatus rv; |
240 { | 217 SGNContext *sgn; |
241 SECStatus rv; | 218 |
242 SGNContext *sgn; | 219 sgn = SGN_NewContext(algid, pk); |
243 | 220 |
244 | 221 if (sgn == NULL) return SECFailure; |
245 sgn = SGN_NewContext(algid, pk); | 222 |
246 | 223 rv = SGN_Begin(sgn); |
247 if (sgn == NULL) | 224 if (rv != SECSuccess) goto loser; |
248 » return SECFailure; | 225 |
249 | 226 rv = SGN_Update(sgn, buf, len); |
250 rv = SGN_Begin(sgn); | 227 if (rv != SECSuccess) goto loser; |
251 if (rv != SECSuccess) | 228 |
252 » goto loser; | 229 rv = SGN_End(sgn, res); |
253 | 230 |
254 rv = SGN_Update(sgn, buf, len); | 231 loser: |
255 if (rv != SECSuccess) | 232 SGN_DestroyContext(sgn, PR_TRUE); |
256 » goto loser; | 233 return rv; |
257 | |
258 rv = SGN_End(sgn, res); | |
259 | |
260 loser: | |
261 SGN_DestroyContext(sgn, PR_TRUE); | |
262 return rv; | |
263 } | 234 } |
264 | 235 |
265 /************************************************************************/ | 236 /************************************************************************/ |
266 | 237 |
267 DERTemplate CERTSignedDataTemplate[] = | 238 DERTemplate CERTSignedDataTemplate[] = { |
268 { | 239 {DER_SEQUENCE, 0, NULL, sizeof(CERTSignedData)}, |
269 { DER_SEQUENCE, | 240 {DER_ANY, offsetof(CERTSignedData, data), }, |
270 » 0, NULL, sizeof(CERTSignedData) }, | 241 {DER_INLINE, offsetof(CERTSignedData, signatureAlgorithm), |
271 { DER_ANY, | 242 SECAlgorithmIDTemplate, }, |
272 » offsetof(CERTSignedData,data), }, | 243 {DER_BIT_STRING, offsetof(CERTSignedData, signature), }, {0, }}; |
273 { DER_INLINE, | |
274 » offsetof(CERTSignedData,signatureAlgorithm), | |
275 » SECAlgorithmIDTemplate, }, | |
276 { DER_BIT_STRING, | |
277 » offsetof(CERTSignedData,signature), }, | |
278 { 0, } | |
279 }; | |
280 | 244 |
281 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | 245 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
282 | 246 |
283 const SEC_ASN1Template CERT_SignedDataTemplate[] = | 247 const SEC_ASN1Template CERT_SignedDataTemplate[] = { |
284 { | 248 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTSignedData)}, |
285 { SEC_ASN1_SEQUENCE, | 249 {SEC_ASN1_ANY, offsetof(CERTSignedData, data), }, |
286 » 0, NULL, sizeof(CERTSignedData) }, | 250 {SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
287 { SEC_ASN1_ANY, | 251 offsetof(CERTSignedData, signatureAlgorithm), |
288 » offsetof(CERTSignedData,data), }, | 252 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), }, |
289 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 253 {SEC_ASN1_BIT_STRING, offsetof(CERTSignedData, signature), }, {0, }}; |
290 » offsetof(CERTSignedData,signatureAlgorithm), | |
291 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), }, | |
292 { SEC_ASN1_BIT_STRING, | |
293 » offsetof(CERTSignedData,signature), }, | |
294 { 0, } | |
295 }; | |
296 | 254 |
297 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate) | 255 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate) |
298 | 256 |
299 | 257 SECStatus SEC_DerSignData(PLArenaPool *arena, SECItem *result, |
300 SECStatus | 258 const unsigned char *buf, int len, |
301 SEC_DerSignData(PLArenaPool *arena, SECItem *result, | 259 SECKEYPrivateKey *pk, SECOidTag algID) { |
302 » const unsigned char *buf, int len, SECKEYPrivateKey *pk, | 260 SECItem it; |
303 » SECOidTag algID) | 261 CERTSignedData sd; |
304 { | 262 SECStatus rv; |
305 SECItem it; | 263 |
306 CERTSignedData sd; | 264 it.data = 0; |
307 SECStatus rv; | 265 |
308 | 266 /* XXX We should probably have some asserts here to make sure the key type |
309 it.data = 0; | 267 * and algID match |
310 | 268 */ |
311 /* XXX We should probably have some asserts here to make sure the key type | 269 |
312 * and algID match | 270 if (algID == SEC_OID_UNKNOWN) { |
313 */ | 271 switch (pk->keyType) { |
314 | 272 case rsaKey: |
315 if (algID == SEC_OID_UNKNOWN) { | 273 algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
316 » switch(pk->keyType) { | 274 break; |
317 » case rsaKey: | 275 case dsaKey: |
318 » algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 276 /* get Signature length (= q_len*2) and work from there */ |
319 » break; | 277 switch (PK11_SignatureLen(pk)) { |
320 » case dsaKey: | 278 case 448: |
321 » /* get Signature length (= q_len*2) and work from there */ | 279 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; |
322 » switch (PK11_SignatureLen(pk)) { | 280 break; |
323 » » case 448: | 281 case 512: |
324 » » algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; | 282 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; |
325 » » break; | 283 break; |
326 » » case 512: | 284 default: |
327 » » algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; | 285 algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; |
328 » » break; | 286 break; |
329 » » default: | 287 } |
330 » » algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; | 288 break; |
331 » » break; | 289 case ecKey: |
332 » } | 290 algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; |
333 » break; | 291 break; |
334 » case ecKey: | 292 default: |
335 » algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; | 293 PORT_SetError(SEC_ERROR_INVALID_KEY); |
336 » break; | 294 return SECFailure; |
337 » default: | 295 } |
338 » PORT_SetError(SEC_ERROR_INVALID_KEY); | 296 } |
339 » return SECFailure; | 297 |
340 » } | 298 /* Sign input buffer */ |
341 } | 299 rv = SEC_SignData(&it, buf, len, pk, algID); |
342 | 300 if (rv) goto loser; |
343 /* Sign input buffer */ | 301 |
344 rv = SEC_SignData(&it, buf, len, pk, algID); | 302 /* Fill out SignedData object */ |
345 if (rv) goto loser; | 303 PORT_Memset(&sd, 0, sizeof(sd)); |
346 | 304 sd.data.data = (unsigned char *)buf; |
347 /* Fill out SignedData object */ | 305 sd.data.len = len; |
348 PORT_Memset(&sd, 0, sizeof(sd)); | 306 sd.signature.data = it.data; |
349 sd.data.data = (unsigned char*) buf; | 307 sd.signature.len = it.len << 3; /* convert to bit string */ |
350 sd.data.len = len; | 308 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); |
351 sd.signature.data = it.data; | 309 if (rv) goto loser; |
352 sd.signature.len = it.len << 3;» » /* convert to bit string */ | 310 |
353 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); | 311 /* DER encode the signed data object */ |
354 if (rv) goto loser; | 312 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd); |
355 | 313 /* FALL THROUGH */ |
356 /* DER encode the signed data object */ | 314 |
357 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd); | 315 loser: |
358 /* FALL THROUGH */ | 316 PORT_Free(it.data); |
359 | 317 return rv; |
360 loser: | 318 } |
361 PORT_Free(it.data); | 319 |
362 return rv; | 320 SECStatus SGN_Digest(SECKEYPrivateKey *privKey, SECOidTag algtag, |
363 } | 321 SECItem *result, SECItem *digest) { |
364 | 322 int modulusLen; |
365 SECStatus | 323 SECStatus rv; |
366 SGN_Digest(SECKEYPrivateKey *privKey, | 324 SECItem digder; |
367 » » SECOidTag algtag, SECItem *result, SECItem *digest) | 325 PLArenaPool *arena = 0; |
368 { | 326 SGNDigestInfo *di = 0; |
369 int modulusLen; | 327 |
370 SECStatus rv; | 328 result->data = 0; |
371 SECItem digder; | 329 |
372 PLArenaPool *arena = 0; | 330 if (privKey->keyType == rsaKey) { |
373 SGNDigestInfo *di = 0; | 331 |
374 | 332 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
375 | 333 if (!arena) { |
376 result->data = 0; | 334 rv = SECFailure; |
377 | 335 goto loser; |
378 if (privKey->keyType == rsaKey) { | 336 } |
379 | 337 |
380 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 338 /* Construct digest info */ |
381 » if ( !arena ) { | 339 di = SGN_CreateDigestInfo(algtag, digest->data, digest->len); |
382 » rv = SECFailure; | 340 if (!di) { |
383 » goto loser; | 341 rv = SECFailure; |
384 » } | 342 goto loser; |
385 ···· | 343 } |
386 » /* Construct digest info */ | 344 |
387 » di = SGN_CreateDigestInfo(algtag, digest->data, digest->len); | 345 /* Der encode the digest as a DigestInfo */ |
388 » if (!di) { | 346 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
389 » rv = SECFailure; | |
390 » goto loser; | |
391 » } | |
392 | |
393 » /* Der encode the digest as a DigestInfo */ | |
394 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, | |
395 di); | |
396 » if (rv != SECSuccess) { | |
397 » goto loser; | |
398 » } | |
399 } else { | |
400 » digder.data = digest->data; | |
401 » digder.len = digest->len; | |
402 } | |
403 | |
404 /* | |
405 ** Encrypt signature after constructing appropriate PKCS#1 signature | |
406 ** block | |
407 */ | |
408 modulusLen = PK11_SignatureLen(privKey); | |
409 if (modulusLen <= 0) { | |
410 » PORT_SetError(SEC_ERROR_INVALID_KEY); | |
411 » rv = SECFailure; | |
412 » goto loser; | |
413 } | |
414 result->len = modulusLen; | |
415 result->data = (unsigned char*) PORT_Alloc(modulusLen); | |
416 | |
417 if (result->data == NULL) { | |
418 » rv = SECFailure; | |
419 » goto loser; | |
420 } | |
421 | |
422 rv = PK11_Sign(privKey, result, &digder); | |
423 if (rv != SECSuccess) { | 347 if (rv != SECSuccess) { |
424 » PORT_Free(result->data); | 348 goto loser; |
425 » result->data = NULL; | 349 } |
426 } | 350 } else { |
427 | 351 digder.data = digest->data; |
428 loser: | 352 digder.len = digest->len; |
429 SGN_DestroyDigestInfo(di); | 353 } |
430 if (arena != NULL) { | 354 |
431 » PORT_FreeArena(arena, PR_FALSE); | 355 /* |
432 } | 356 ** Encrypt signature after constructing appropriate PKCS#1 signature |
433 return rv; | 357 ** block |
434 } | 358 */ |
435 | 359 modulusLen = PK11_SignatureLen(privKey); |
436 SECOidTag | 360 if (modulusLen <= 0) { |
437 SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag) | 361 PORT_SetError(SEC_ERROR_INVALID_KEY); |
438 { | 362 rv = SECFailure; |
439 SECOidTag sigTag = SEC_OID_UNKNOWN; | 363 goto loser; |
440 | 364 } |
441 switch (keyType) { | 365 result->len = modulusLen; |
| 366 result->data = (unsigned char *)PORT_Alloc(modulusLen); |
| 367 |
| 368 if (result->data == NULL) { |
| 369 rv = SECFailure; |
| 370 goto loser; |
| 371 } |
| 372 |
| 373 rv = PK11_Sign(privKey, result, &digder); |
| 374 if (rv != SECSuccess) { |
| 375 PORT_Free(result->data); |
| 376 result->data = NULL; |
| 377 } |
| 378 |
| 379 loser: |
| 380 SGN_DestroyDigestInfo(di); |
| 381 if (arena != NULL) { |
| 382 PORT_FreeArena(arena, PR_FALSE); |
| 383 } |
| 384 return rv; |
| 385 } |
| 386 |
| 387 SECOidTag SEC_GetSignatureAlgorithmOidTag(KeyType keyType, |
| 388 SECOidTag hashAlgTag) { |
| 389 SECOidTag sigTag = SEC_OID_UNKNOWN; |
| 390 |
| 391 switch (keyType) { |
442 case rsaKey: | 392 case rsaKey: |
443 » switch (hashAlgTag) { | 393 switch (hashAlgTag) { |
444 » case SEC_OID_MD2: | 394 case SEC_OID_MD2: |
445 » sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;» break; | 395 sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; |
446 » case SEC_OID_MD5: | 396 break; |
447 » sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;» break; | 397 case SEC_OID_MD5: |
448 » case SEC_OID_SHA1: | 398 sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; |
449 » sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;» break; | 399 break; |
450 » case SEC_OID_SHA224: | 400 case SEC_OID_SHA1: |
451 » sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;» break; | 401 sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
452 » case SEC_OID_UNKNOWN:» /* default for RSA if not specified */ | 402 break; |
453 » case SEC_OID_SHA256: | 403 case SEC_OID_SHA224: |
454 » sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;» break; | 404 sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; |
455 » case SEC_OID_SHA384: | 405 break; |
456 » sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;» break; | 406 case SEC_OID_UNKNOWN: /* default for RSA if not specified */ |
457 » case SEC_OID_SHA512: | 407 case SEC_OID_SHA256: |
458 » sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;» break; | 408 sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
459 » default: | 409 break; |
460 » break; | 410 case SEC_OID_SHA384: |
461 » } | 411 sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
462 » break; | 412 break; |
| 413 case SEC_OID_SHA512: |
| 414 sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
| 415 break; |
| 416 default: |
| 417 break; |
| 418 } |
| 419 break; |
463 case dsaKey: | 420 case dsaKey: |
464 » switch (hashAlgTag) { | 421 switch (hashAlgTag) { |
465 » case SEC_OID_UNKNOWN:» /* default for DSA if not specified */ | 422 case SEC_OID_UNKNOWN: /* default for DSA if not specified */ |
466 » case SEC_OID_SHA1: | 423 case SEC_OID_SHA1: |
467 » sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; | 424 sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; |
468 » case SEC_OID_SHA224: | 425 break; |
469 » sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; break; | 426 case SEC_OID_SHA224: |
470 » case SEC_OID_SHA256: | 427 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; |
471 » sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; break; | 428 break; |
472 » default: | 429 case SEC_OID_SHA256: |
473 » break; | 430 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; |
474 » } | 431 break; |
475 » break; | 432 default: |
| 433 break; |
| 434 } |
| 435 break; |
476 case ecKey: | 436 case ecKey: |
477 » switch (hashAlgTag) { | 437 switch (hashAlgTag) { |
478 » case SEC_OID_UNKNOWN:» /* default for ECDSA if not specified */ | 438 case SEC_OID_UNKNOWN: /* default for ECDSA if not specified */ |
479 » case SEC_OID_SHA1: | 439 case SEC_OID_SHA1: |
480 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; break; | 440 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; |
481 » case SEC_OID_SHA224: | 441 break; |
482 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE; break; | 442 case SEC_OID_SHA224: |
483 » case SEC_OID_SHA256: | 443 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE; |
484 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; break; | 444 break; |
485 » case SEC_OID_SHA384: | 445 case SEC_OID_SHA256: |
486 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; break; | 446 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; |
487 » case SEC_OID_SHA512: | 447 break; |
488 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; break; | 448 case SEC_OID_SHA384: |
489 » default: | 449 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; |
490 » break; | 450 break; |
491 » } | 451 case SEC_OID_SHA512: |
| 452 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; |
| 453 break; |
| 454 default: |
| 455 break; |
| 456 } |
492 default: | 457 default: |
493 » break; | 458 break; |
494 } | 459 } |
495 return sigTag; | 460 return sigTag; |
496 } | 461 } |
OLD | NEW |