Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/cryptohi/seckey.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 #include "cryptohi.h" | |
5 #include "keyhi.h" | |
6 #include "secoid.h" | |
7 #include "secitem.h" | |
8 #include "secder.h" | |
9 #include "base64.h" | |
10 #include "secasn1.h" | |
11 #include "cert.h" | |
12 #include "pk11func.h" | |
13 #include "secerr.h" | |
14 #include "secdig.h" | |
15 #include "prtime.h" | |
16 #include "keyi.h" | |
17 | |
18 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
19 SEC_ASN1_MKSUB(SEC_IntegerTemplate) | |
20 | |
21 const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = { | |
22 { SEC_ASN1_SEQUENCE, | |
23 0, NULL, sizeof(CERTSubjectPublicKeyInfo) }, | |
24 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
25 offsetof(CERTSubjectPublicKeyInfo,algorithm), | |
26 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
27 { SEC_ASN1_BIT_STRING, | |
28 offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), }, | |
29 { 0, } | |
30 }; | |
31 | |
32 const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] = | |
33 { | |
34 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) }, | |
35 { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) }, | |
36 { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) }, | |
37 { 0 } | |
38 }; | |
39 | |
40 const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = { | |
41 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, | |
42 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), }, | |
43 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), }, | |
44 { 0, } | |
45 }; | |
46 | |
47 static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = { | |
48 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0, | |
49 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) } | |
50 }; | |
51 | |
52 /* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */ | |
53 const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] = | |
54 { | |
55 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) }, | |
56 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
57 SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
58 offsetof(SECKEYRSAPSSParams, hashAlg), | |
59 seckey_PointerToAlgorithmIDTemplate }, | |
60 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
61 SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
62 offsetof(SECKEYRSAPSSParams, maskAlg), | |
63 seckey_PointerToAlgorithmIDTemplate }, | |
64 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
65 SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2, | |
66 offsetof(SECKEYRSAPSSParams, saltLength), | |
67 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
68 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
69 SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3, | |
70 offsetof(SECKEYRSAPSSParams, trailerField), | |
71 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
72 { 0 } | |
73 }; | |
74 | |
75 const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = { | |
76 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), }, | |
77 { 0, } | |
78 }; | |
79 | |
80 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { | |
81 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, | |
82 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, | |
83 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, | |
84 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, | |
85 { 0, } | |
86 }; | |
87 | |
88 const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = { | |
89 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), }, | |
90 { 0, } | |
91 }; | |
92 | |
93 const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = { | |
94 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, | |
95 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), }, | |
96 { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), }, | |
97 /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */ | |
98 { SEC_ASN1_SKIP_REST }, | |
99 { 0, } | |
100 }; | |
101 | |
102 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate) | |
103 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate) | |
104 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate) | |
105 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate) | |
106 | |
107 /* | |
108 * See bugzilla bug 125359 | |
109 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, | |
110 * all of the templates above that en/decode into integers must be converted | |
111 * from ASN.1's signed integer type. This is done by marking either the | |
112 * source or destination (encoding or decoding, respectively) type as | |
113 * siUnsignedInteger. | |
114 */ | |
115 static void | |
116 prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk) | |
117 { | |
118 pubk->u.rsa.modulus.type = siUnsignedInteger; | |
119 pubk->u.rsa.publicExponent.type = siUnsignedInteger; | |
120 } | |
121 | |
122 static void | |
123 prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk) | |
124 { | |
125 pubk->u.dsa.publicValue.type = siUnsignedInteger; | |
126 } | |
127 | |
128 static void | |
129 prepare_pqg_params_for_asn1(SECKEYPQGParams *params) | |
130 { | |
131 params->prime.type = siUnsignedInteger; | |
132 params->subPrime.type = siUnsignedInteger; | |
133 params->base.type = siUnsignedInteger; | |
134 } | |
135 | |
136 static void | |
137 prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk) | |
138 { | |
139 pubk->u.dh.prime.type = siUnsignedInteger; | |
140 pubk->u.dh.base.type = siUnsignedInteger; | |
141 pubk->u.dh.publicValue.type = siUnsignedInteger; | |
142 } | |
143 | |
144 /* Create an RSA key pair is any slot able to do so. | |
145 ** The created keys are "session" (temporary), not "token" (permanent), | |
146 ** and they are "sensitive", which makes them costly to move to another token. | |
147 */ | |
148 SECKEYPrivateKey * | |
149 SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx) | |
150 { | |
151 SECKEYPrivateKey *privk; | |
152 PK11RSAGenParams param; | |
153 PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx); | |
154 if (!slot) { | |
155 return NULL; | |
156 } | |
157 | |
158 param.keySizeInBits = keySizeInBits; | |
159 param.pe = 65537L; | |
160 | |
161 privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,¶m,pubk, | |
162 PR_FALSE, PR_TRUE, cx); | |
163 PK11_FreeSlot(slot); | |
164 return(privk); | |
165 } | |
166 | |
167 /* Create a DH key pair in any slot able to do so, | |
168 ** This is a "session" (temporary), not "token" (permanent) key. | |
169 ** Because of the high probability that this key will need to be moved to | |
170 ** another token, and the high cost of moving "sensitive" keys, we attempt | |
171 ** to create this key pair without the "sensitive" attribute, but revert to | |
172 ** creating a "sensitive" key if necessary. | |
173 */ | |
174 SECKEYPrivateKey * | |
175 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx) | |
176 { | |
177 SECKEYPrivateKey *privk; | |
178 PK11SlotInfo *slot; | |
179 | |
180 if (!param || !param->base.data || !param->prime.data || | |
181 param->prime.len < 512/8 || param->base.len == 0 || | |
182 param->base.len > param->prime.len + 1 || | |
183 (param->base.len == 1 && param->base.data[0] == 0)) { | |
184 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
185 return NULL; | |
186 } | |
187 | |
188 slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx); | |
189 if (!slot) { | |
190 return NULL; | |
191 } | |
192 | |
193 privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, | |
194 pubk, PR_FALSE, PR_FALSE, cx); | |
195 if (!privk) | |
196 privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, | |
197 pubk, PR_FALSE, PR_TRUE, cx); | |
198 | |
199 PK11_FreeSlot(slot); | |
200 return(privk); | |
201 } | |
202 | |
203 /* Create an EC key pair in any slot able to do so, | |
204 ** This is a "session" (temporary), not "token" (permanent) key. | |
205 ** Because of the high probability that this key will need to be moved to | |
206 ** another token, and the high cost of moving "sensitive" keys, we attempt | |
207 ** to create this key pair without the "sensitive" attribute, but revert to | |
208 ** creating a "sensitive" key if necessary. | |
209 */ | |
210 SECKEYPrivateKey * | |
211 SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx) | |
212 { | |
213 SECKEYPrivateKey *privk; | |
214 PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx); | |
215 if (!slot) { | |
216 return NULL; | |
217 } | |
218 | |
219 privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, | |
220 param, pubk, | |
221 PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE | | |
222 PK11_ATTR_PUBLIC, | |
223 CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); | |
224 if (!privk) | |
225 privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, | |
226 param, pubk, | |
227 PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE | | |
228 PK11_ATTR_PRIVATE, | |
229 CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); | |
230 | |
231 PK11_FreeSlot(slot); | |
232 return(privk); | |
233 } | |
234 | |
235 void | |
236 SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk) | |
237 { | |
238 if (privk) { | |
239 if (privk->pkcs11Slot) { | |
240 if (privk->pkcs11IsTemp) { | |
241 PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID); | |
242 } | |
243 PK11_FreeSlot(privk->pkcs11Slot); | |
244 | |
245 } | |
246 if (privk->arena) { | |
247 PORT_FreeArena(privk->arena, PR_TRUE); | |
248 } | |
249 } | |
250 } | |
251 | |
252 void | |
253 SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk) | |
254 { | |
255 if (pubk) { | |
256 if (pubk->pkcs11Slot) { | |
257 if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { | |
258 PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID); | |
259 } | |
260 PK11_FreeSlot(pubk->pkcs11Slot); | |
261 } | |
262 if (pubk->arena) { | |
263 PORT_FreeArena(pubk->arena, PR_FALSE); | |
264 } | |
265 } | |
266 } | |
267 | |
268 SECStatus | |
269 SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena, | |
270 CERTSubjectPublicKeyInfo *to, | |
271 CERTSubjectPublicKeyInfo *from) | |
272 { | |
273 SECStatus rv; | |
274 SECItem spk; | |
275 | |
276 rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm); | |
277 if (rv == SECSuccess) { | |
278 /* | |
279 * subjectPublicKey is a bit string, whose length is in bits. | |
280 * Convert the length from bits to bytes for SECITEM_CopyItem. | |
281 */ | |
282 spk = from->subjectPublicKey; | |
283 DER_ConvertBitString(&spk); | |
284 rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk); | |
285 /* Set the length back to bits. */ | |
286 if (rv == SECSuccess) { | |
287 to->subjectPublicKey.len = from->subjectPublicKey.len; | |
288 } | |
289 } | |
290 | |
291 return rv; | |
292 } | |
293 | |
294 /* Procedure to update the pqg parameters for a cert's public key. | |
295 * pqg parameters only need to be updated for DSA certificates. | |
296 * The procedure uses calls to itself recursively to update a certificate | |
297 * issuer's pqg parameters. Some important rules are: | |
298 * - Do nothing if the cert already has PQG parameters. | |
299 * - If the cert does not have PQG parameters, obtain them from the issuer. | |
300 * - A valid cert chain cannot have a DSA cert without | |
301 * pqg parameters that has a parent that is not a DSA cert. */ | |
302 | |
303 static SECStatus | |
304 seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count) | |
305 { | |
306 SECStatus rv; | |
307 SECOidData *oid=NULL; | |
308 int tag; | |
309 CERTSubjectPublicKeyInfo * subjectSpki=NULL; | |
310 CERTSubjectPublicKeyInfo * issuerSpki=NULL; | |
311 CERTCertificate *issuerCert = NULL; | |
312 | |
313 rv = SECSuccess; | |
314 | |
315 /* increment cert chain length counter*/ | |
316 count++; | |
317 | |
318 /* check if cert chain length exceeds the maximum length*/ | |
319 if (count > CERT_MAX_CERT_CHAIN) { | |
320 return SECFailure; | |
321 } | |
322 | |
323 oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm); | |
324 if (oid != NULL) { | |
325 tag = oid->offset; | |
326 | |
327 /* Check if cert has a DSA or EC public key. If not, return | |
328 * success since no PQG params need to be updated. | |
329 * | |
330 * Question: do we really need to do this for EC keys. They don't have | |
331 * PQG parameters, but they do have parameters. The question is does | |
332 * the child cert inherit thost parameters for EC from the parent, or | |
333 * do we always include those parameters in each cert. | |
334 */ | |
335 | |
336 if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && | |
337 (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && | |
338 (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && | |
339 (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && | |
340 (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && | |
341 (tag != SEC_OID_SDN702_DSA_SIGNATURE) && | |
342 (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { | |
343 | |
344 return SECSuccess; | |
345 } | |
346 } else { | |
347 return SECFailure; /* return failure if oid is NULL */ | |
348 } | |
349 | |
350 /* if cert has PQG parameters, return success */ | |
351 | |
352 subjectSpki=&subjectCert->subjectPublicKeyInfo; | |
353 | |
354 if (subjectSpki->algorithm.parameters.len != 0) { | |
355 return SECSuccess; | |
356 } | |
357 | |
358 /* check if the cert is self-signed */ | |
359 if (subjectCert->isRoot) { | |
360 /* fail since cert is self-signed and has no pqg params. */ | |
361 return SECFailure; | |
362 } | |
363 | |
364 /* get issuer cert */ | |
365 issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA); | |
366 if ( ! issuerCert ) { | |
367 return SECFailure; | |
368 } | |
369 | |
370 /* if parent is not DSA, return failure since | |
371 we don't allow this case. */ | |
372 | |
373 oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm); | |
374 if (oid != NULL) { | |
375 tag = oid->offset; | |
376 | |
377 /* Check if issuer cert has a DSA public key. If not, | |
378 * return failure. */ | |
379 | |
380 if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && | |
381 (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && | |
382 (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && | |
383 (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && | |
384 (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && | |
385 (tag != SEC_OID_SDN702_DSA_SIGNATURE) && | |
386 (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { | |
387 rv = SECFailure; | |
388 goto loser; | |
389 } | |
390 } else { | |
391 rv = SECFailure; /* return failure if oid is NULL */ | |
392 goto loser; | |
393 } | |
394 | |
395 | |
396 /* at this point the subject cert has no pqg parameters and the | |
397 * issuer cert has a DSA public key. Update the issuer's | |
398 * pqg parameters with a recursive call to this same function. */ | |
399 | |
400 rv = seckey_UpdateCertPQGChain(issuerCert, count); | |
401 if (rv != SECSuccess) { | |
402 rv = SECFailure; | |
403 goto loser; | |
404 } | |
405 | |
406 /* ensure issuer has pqg parameters */ | |
407 | |
408 issuerSpki=&issuerCert->subjectPublicKeyInfo; | |
409 if (issuerSpki->algorithm.parameters.len == 0) { | |
410 rv = SECFailure; | |
411 } | |
412 | |
413 /* if update was successful and pqg params present, then copy the | |
414 * parameters to the subject cert's key. */ | |
415 | |
416 if (rv == SECSuccess) { | |
417 rv = SECITEM_CopyItem(subjectCert->arena, | |
418 &subjectSpki->algorithm.parameters, | |
419 &issuerSpki->algorithm.parameters); | |
420 } | |
421 | |
422 loser: | |
423 if (issuerCert) { | |
424 CERT_DestroyCertificate(issuerCert); | |
425 } | |
426 return rv; | |
427 | |
428 } | |
429 | |
430 | |
431 SECStatus | |
432 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert) | |
433 { | |
434 if (!subjectCert) { | |
435 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
436 return SECFailure; | |
437 } | |
438 return seckey_UpdateCertPQGChain(subjectCert,0); | |
439 } | |
440 | |
441 | |
442 /* Decode the DSA PQG parameters. The params could be stored in two | |
443 * possible formats, the old fortezza-only wrapped format or | |
444 * the normal standard format. Store the decoded parameters in | |
445 * a V3 certificate data structure. */ | |
446 | |
447 static SECStatus | |
448 seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk, | |
449 const SECItem *params) { | |
450 SECStatus rv; | |
451 SECItem newparams; | |
452 | |
453 if (params == NULL) return SECFailure; | |
454 | |
455 if (params->data == NULL) return SECFailure; | |
456 | |
457 PORT_Assert(arena); | |
458 | |
459 /* make a copy of the data into the arena so QuickDER output is valid */ | |
460 rv = SECITEM_CopyItem(arena, &newparams, params); | |
461 | |
462 /* Check if params use the standard format. | |
463 * The value 0xa1 will appear in the first byte of the parameter data | |
464 * if the PQG parameters are not using the standard format. This | |
465 * code should be changed to use a better method to detect non-standard | |
466 * parameters. */ | |
467 | |
468 if ((newparams.data[0] != 0xa1) && | |
469 (newparams.data[0] != 0xa0)) { | |
470 | |
471 if (SECSuccess == rv) { | |
472 /* PQG params are in the standard format */ | |
473 prepare_pqg_params_for_asn1(&pubk->u.dsa.params); | |
474 rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params, | |
475 SECKEY_PQGParamsTemplate, | |
476 &newparams); | |
477 } | |
478 } else { | |
479 | |
480 if (SECSuccess == rv) { | |
481 /* else the old fortezza-only wrapped format is used. */ | |
482 PORT_SetError(SEC_ERROR_BAD_DER); | |
483 rv = SECFailure; | |
484 } | |
485 } | |
486 return rv; | |
487 } | |
488 | |
489 | |
490 /* Function used to make an oid tag to a key type */ | |
491 KeyType | |
492 seckey_GetKeyType (SECOidTag tag) { | |
493 KeyType keyType; | |
494 | |
495 switch (tag) { | |
496 case SEC_OID_X500_RSA_ENCRYPTION: | |
497 case SEC_OID_PKCS1_RSA_ENCRYPTION: | |
498 keyType = rsaKey; | |
499 break; | |
500 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: | |
501 keyType = rsaPssKey; | |
502 break; | |
503 case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION: | |
504 keyType = rsaOaepKey; | |
505 break; | |
506 case SEC_OID_ANSIX9_DSA_SIGNATURE: | |
507 keyType = dsaKey; | |
508 break; | |
509 case SEC_OID_MISSI_KEA_DSS_OLD: | |
510 case SEC_OID_MISSI_KEA_DSS: | |
511 case SEC_OID_MISSI_DSS_OLD: | |
512 case SEC_OID_MISSI_DSS: | |
513 keyType = fortezzaKey; | |
514 break; | |
515 case SEC_OID_MISSI_KEA: | |
516 case SEC_OID_MISSI_ALT_KEA: | |
517 keyType = keaKey; | |
518 break; | |
519 case SEC_OID_X942_DIFFIE_HELMAN_KEY: | |
520 keyType = dhKey; | |
521 break; | |
522 case SEC_OID_ANSIX962_EC_PUBLIC_KEY: | |
523 keyType = ecKey; | |
524 break; | |
525 /* accommodate applications that hand us a signature type when they | |
526 * should be handing us a cipher type */ | |
527 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | |
528 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: | |
529 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: | |
530 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: | |
531 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: | |
532 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: | |
533 keyType = rsaKey; | |
534 break; | |
535 default: | |
536 keyType = nullKey; | |
537 } | |
538 return keyType; | |
539 } | |
540 | |
541 /* Function used to determine what kind of cert we are dealing with. */ | |
542 KeyType | |
543 CERT_GetCertKeyType (const CERTSubjectPublicKeyInfo *spki) | |
544 { | |
545 return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm)); | |
546 } | |
547 | |
548 static SECKEYPublicKey * | |
549 seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) | |
550 { | |
551 SECKEYPublicKey *pubk; | |
552 SECItem os, newOs, newParms; | |
553 SECStatus rv; | |
554 PLArenaPool *arena; | |
555 SECOidTag tag; | |
556 | |
557 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); | |
558 if (arena == NULL) | |
559 return NULL; | |
560 | |
561 pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); | |
562 if (pubk == NULL) { | |
563 PORT_FreeArena (arena, PR_FALSE); | |
564 return NULL; | |
565 } | |
566 | |
567 pubk->arena = arena; | |
568 pubk->pkcs11Slot = 0; | |
569 pubk->pkcs11ID = CK_INVALID_HANDLE; | |
570 | |
571 | |
572 /* Convert bit string length from bits to bytes */ | |
573 os = spki->subjectPublicKey; | |
574 DER_ConvertBitString (&os); | |
575 | |
576 tag = SECOID_GetAlgorithmTag(&spki->algorithm); | |
577 | |
578 /* copy the DER into the arena, since Quick DER returns data that points | |
579 into the DER input, which may get freed by the caller */ | |
580 rv = SECITEM_CopyItem(arena, &newOs, &os); | |
581 if ( rv == SECSuccess ) | |
582 switch ( tag ) { | |
583 case SEC_OID_X500_RSA_ENCRYPTION: | |
584 case SEC_OID_PKCS1_RSA_ENCRYPTION: | |
585 pubk->keyType = rsaKey; | |
586 prepare_rsa_pub_key_for_asn1(pubk); | |
587 rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs); | |
588 if (rv == SECSuccess) | |
589 return pubk; | |
590 break; | |
591 case SEC_OID_ANSIX9_DSA_SIGNATURE: | |
592 case SEC_OID_SDN702_DSA_SIGNATURE: | |
593 pubk->keyType = dsaKey; | |
594 prepare_dsa_pub_key_for_asn1(pubk); | |
595 rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs); | |
596 if (rv != SECSuccess) break; | |
597 | |
598 rv = seckey_DSADecodePQG(arena, pubk, | |
599 &spki->algorithm.parameters); | |
600 | |
601 if (rv == SECSuccess) return pubk; | |
602 break; | |
603 case SEC_OID_X942_DIFFIE_HELMAN_KEY: | |
604 pubk->keyType = dhKey; | |
605 prepare_dh_pub_key_for_asn1(pubk); | |
606 rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs); | |
607 if (rv != SECSuccess) break; | |
608 | |
609 /* copy the DER into the arena, since Quick DER returns data that points | |
610 into the DER input, which may get freed by the caller */ | |
611 rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters); | |
612 if ( rv != SECSuccess ) | |
613 break; | |
614 | |
615 rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate, | |
616 &newParms); | |
617 | |
618 if (rv == SECSuccess) return pubk; | |
619 break; | |
620 case SEC_OID_ANSIX962_EC_PUBLIC_KEY: | |
621 pubk->keyType = ecKey; | |
622 pubk->u.ec.size = 0; | |
623 | |
624 /* Since PKCS#11 directly takes the DER encoding of EC params | |
625 * and public value, we don't need any decoding here. | |
626 */ | |
627 rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, | |
628 &spki->algorithm.parameters); | |
629 if ( rv != SECSuccess ) | |
630 break; | |
631 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs); | |
632 if (rv == SECSuccess) return pubk; | |
633 break; | |
634 | |
635 default: | |
636 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); | |
637 rv = SECFailure; | |
638 break; | |
639 } | |
640 | |
641 SECKEY_DestroyPublicKey (pubk); | |
642 return NULL; | |
643 } | |
644 | |
645 | |
646 /* required for JSS */ | |
647 SECKEYPublicKey * | |
648 SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) | |
649 { | |
650 return seckey_ExtractPublicKey(spki); | |
651 } | |
652 | |
653 SECKEYPublicKey * | |
654 CERT_ExtractPublicKey(CERTCertificate *cert) | |
655 { | |
656 SECStatus rv; | |
657 | |
658 if (!cert) { | |
659 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
660 return NULL; | |
661 } | |
662 rv = SECKEY_UpdateCertPQG(cert); | |
663 if (rv != SECSuccess) return NULL; | |
664 | |
665 return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo); | |
666 } | |
667 | |
668 int | |
669 SECKEY_ECParamsToKeySize(const SECItem *encodedParams) | |
670 { | |
671 SECOidTag tag; | |
672 SECItem oid = { siBuffer, NULL, 0}; | |
673 | |
674 /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), | |
675 * followed by the length of the curve oid and the curve oid. | |
676 */ | |
677 oid.len = encodedParams->data[1]; | |
678 oid.data = encodedParams->data + 2; | |
679 if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) | |
680 return 0; | |
681 | |
682 switch (tag) { | |
683 case SEC_OID_SECG_EC_SECP112R1: | |
684 case SEC_OID_SECG_EC_SECP112R2: | |
685 return 112; | |
686 | |
687 case SEC_OID_SECG_EC_SECT113R1: | |
688 case SEC_OID_SECG_EC_SECT113R2: | |
689 return 113; | |
690 | |
691 case SEC_OID_SECG_EC_SECP128R1: | |
692 case SEC_OID_SECG_EC_SECP128R2: | |
693 return 128; | |
694 | |
695 case SEC_OID_SECG_EC_SECT131R1: | |
696 case SEC_OID_SECG_EC_SECT131R2: | |
697 return 131; | |
698 | |
699 case SEC_OID_SECG_EC_SECP160K1: | |
700 case SEC_OID_SECG_EC_SECP160R1: | |
701 case SEC_OID_SECG_EC_SECP160R2: | |
702 return 160; | |
703 | |
704 case SEC_OID_SECG_EC_SECT163K1: | |
705 case SEC_OID_SECG_EC_SECT163R1: | |
706 case SEC_OID_SECG_EC_SECT163R2: | |
707 case SEC_OID_ANSIX962_EC_C2PNB163V1: | |
708 case SEC_OID_ANSIX962_EC_C2PNB163V2: | |
709 case SEC_OID_ANSIX962_EC_C2PNB163V3: | |
710 return 163; | |
711 | |
712 case SEC_OID_ANSIX962_EC_C2PNB176V1: | |
713 return 176; | |
714 | |
715 case SEC_OID_ANSIX962_EC_C2TNB191V1: | |
716 case SEC_OID_ANSIX962_EC_C2TNB191V2: | |
717 case SEC_OID_ANSIX962_EC_C2TNB191V3: | |
718 case SEC_OID_ANSIX962_EC_C2ONB191V4: | |
719 case SEC_OID_ANSIX962_EC_C2ONB191V5: | |
720 return 191; | |
721 | |
722 case SEC_OID_SECG_EC_SECP192K1: | |
723 case SEC_OID_ANSIX962_EC_PRIME192V1: | |
724 case SEC_OID_ANSIX962_EC_PRIME192V2: | |
725 case SEC_OID_ANSIX962_EC_PRIME192V3: | |
726 return 192; | |
727 | |
728 case SEC_OID_SECG_EC_SECT193R1: | |
729 case SEC_OID_SECG_EC_SECT193R2: | |
730 return 193; | |
731 | |
732 case SEC_OID_ANSIX962_EC_C2PNB208W1: | |
733 return 208; | |
734 | |
735 case SEC_OID_SECG_EC_SECP224K1: | |
736 case SEC_OID_SECG_EC_SECP224R1: | |
737 return 224; | |
738 | |
739 case SEC_OID_SECG_EC_SECT233K1: | |
740 case SEC_OID_SECG_EC_SECT233R1: | |
741 return 233; | |
742 | |
743 case SEC_OID_SECG_EC_SECT239K1: | |
744 case SEC_OID_ANSIX962_EC_C2TNB239V1: | |
745 case SEC_OID_ANSIX962_EC_C2TNB239V2: | |
746 case SEC_OID_ANSIX962_EC_C2TNB239V3: | |
747 case SEC_OID_ANSIX962_EC_C2ONB239V4: | |
748 case SEC_OID_ANSIX962_EC_C2ONB239V5: | |
749 case SEC_OID_ANSIX962_EC_PRIME239V1: | |
750 case SEC_OID_ANSIX962_EC_PRIME239V2: | |
751 case SEC_OID_ANSIX962_EC_PRIME239V3: | |
752 return 239; | |
753 | |
754 case SEC_OID_SECG_EC_SECP256K1: | |
755 case SEC_OID_ANSIX962_EC_PRIME256V1: | |
756 return 256; | |
757 | |
758 case SEC_OID_ANSIX962_EC_C2PNB272W1: | |
759 return 272; | |
760 | |
761 case SEC_OID_SECG_EC_SECT283K1: | |
762 case SEC_OID_SECG_EC_SECT283R1: | |
763 return 283; | |
764 | |
765 case SEC_OID_ANSIX962_EC_C2PNB304W1: | |
766 return 304; | |
767 | |
768 case SEC_OID_ANSIX962_EC_C2TNB359V1: | |
769 return 359; | |
770 | |
771 case SEC_OID_ANSIX962_EC_C2PNB368W1: | |
772 return 368; | |
773 | |
774 case SEC_OID_SECG_EC_SECP384R1: | |
775 return 384; | |
776 | |
777 case SEC_OID_SECG_EC_SECT409K1: | |
778 case SEC_OID_SECG_EC_SECT409R1: | |
779 return 409; | |
780 | |
781 case SEC_OID_ANSIX962_EC_C2TNB431R1: | |
782 return 431; | |
783 | |
784 case SEC_OID_SECG_EC_SECP521R1: | |
785 return 521; | |
786 | |
787 case SEC_OID_SECG_EC_SECT571K1: | |
788 case SEC_OID_SECG_EC_SECT571R1: | |
789 return 571; | |
790 | |
791 default: | |
792 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |
793 return 0; | |
794 } | |
795 } | |
796 | |
797 int | |
798 SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams) | |
799 { | |
800 SECOidTag tag; | |
801 SECItem oid = { siBuffer, NULL, 0}; | |
802 | |
803 /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), | |
804 * followed by the length of the curve oid and the curve oid. | |
805 */ | |
806 oid.len = encodedParams->data[1]; | |
807 oid.data = encodedParams->data + 2; | |
808 if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) | |
809 return 0; | |
810 | |
811 switch (tag) { | |
812 case SEC_OID_SECG_EC_SECP112R1: | |
813 return 112; | |
814 case SEC_OID_SECG_EC_SECP112R2: | |
815 return 110; | |
816 | |
817 case SEC_OID_SECG_EC_SECT113R1: | |
818 case SEC_OID_SECG_EC_SECT113R2: | |
819 return 113; | |
820 | |
821 case SEC_OID_SECG_EC_SECP128R1: | |
822 return 128; | |
823 case SEC_OID_SECG_EC_SECP128R2: | |
824 return 126; | |
825 | |
826 case SEC_OID_SECG_EC_SECT131R1: | |
827 case SEC_OID_SECG_EC_SECT131R2: | |
828 return 131; | |
829 | |
830 case SEC_OID_SECG_EC_SECP160K1: | |
831 case SEC_OID_SECG_EC_SECP160R1: | |
832 case SEC_OID_SECG_EC_SECP160R2: | |
833 return 161; | |
834 | |
835 case SEC_OID_SECG_EC_SECT163K1: | |
836 return 163; | |
837 case SEC_OID_SECG_EC_SECT163R1: | |
838 return 162; | |
839 case SEC_OID_SECG_EC_SECT163R2: | |
840 case SEC_OID_ANSIX962_EC_C2PNB163V1: | |
841 return 163; | |
842 case SEC_OID_ANSIX962_EC_C2PNB163V2: | |
843 case SEC_OID_ANSIX962_EC_C2PNB163V3: | |
844 return 162; | |
845 | |
846 case SEC_OID_ANSIX962_EC_C2PNB176V1: | |
847 return 161; | |
848 | |
849 case SEC_OID_ANSIX962_EC_C2TNB191V1: | |
850 return 191; | |
851 case SEC_OID_ANSIX962_EC_C2TNB191V2: | |
852 return 190; | |
853 case SEC_OID_ANSIX962_EC_C2TNB191V3: | |
854 return 189; | |
855 case SEC_OID_ANSIX962_EC_C2ONB191V4: | |
856 return 191; | |
857 case SEC_OID_ANSIX962_EC_C2ONB191V5: | |
858 return 188; | |
859 | |
860 case SEC_OID_SECG_EC_SECP192K1: | |
861 case SEC_OID_ANSIX962_EC_PRIME192V1: | |
862 case SEC_OID_ANSIX962_EC_PRIME192V2: | |
863 case SEC_OID_ANSIX962_EC_PRIME192V3: | |
864 return 192; | |
865 | |
866 case SEC_OID_SECG_EC_SECT193R1: | |
867 case SEC_OID_SECG_EC_SECT193R2: | |
868 return 193; | |
869 | |
870 case SEC_OID_ANSIX962_EC_C2PNB208W1: | |
871 return 193; | |
872 | |
873 case SEC_OID_SECG_EC_SECP224K1: | |
874 return 225; | |
875 case SEC_OID_SECG_EC_SECP224R1: | |
876 return 224; | |
877 | |
878 case SEC_OID_SECG_EC_SECT233K1: | |
879 return 232; | |
880 case SEC_OID_SECG_EC_SECT233R1: | |
881 return 233; | |
882 | |
883 case SEC_OID_SECG_EC_SECT239K1: | |
884 case SEC_OID_ANSIX962_EC_C2TNB239V1: | |
885 return 238; | |
886 case SEC_OID_ANSIX962_EC_C2TNB239V2: | |
887 return 237; | |
888 case SEC_OID_ANSIX962_EC_C2TNB239V3: | |
889 return 236; | |
890 case SEC_OID_ANSIX962_EC_C2ONB239V4: | |
891 return 238; | |
892 case SEC_OID_ANSIX962_EC_C2ONB239V5: | |
893 return 237; | |
894 case SEC_OID_ANSIX962_EC_PRIME239V1: | |
895 case SEC_OID_ANSIX962_EC_PRIME239V2: | |
896 case SEC_OID_ANSIX962_EC_PRIME239V3: | |
897 return 239; | |
898 | |
899 case SEC_OID_SECG_EC_SECP256K1: | |
900 case SEC_OID_ANSIX962_EC_PRIME256V1: | |
901 return 256; | |
902 | |
903 case SEC_OID_ANSIX962_EC_C2PNB272W1: | |
904 return 257; | |
905 | |
906 case SEC_OID_SECG_EC_SECT283K1: | |
907 return 281; | |
908 case SEC_OID_SECG_EC_SECT283R1: | |
909 return 282; | |
910 | |
911 case SEC_OID_ANSIX962_EC_C2PNB304W1: | |
912 return 289; | |
913 | |
914 case SEC_OID_ANSIX962_EC_C2TNB359V1: | |
915 return 353; | |
916 | |
917 case SEC_OID_ANSIX962_EC_C2PNB368W1: | |
918 return 353; | |
919 | |
920 case SEC_OID_SECG_EC_SECP384R1: | |
921 return 384; | |
922 | |
923 case SEC_OID_SECG_EC_SECT409K1: | |
924 return 407; | |
925 case SEC_OID_SECG_EC_SECT409R1: | |
926 return 409; | |
927 | |
928 case SEC_OID_ANSIX962_EC_C2TNB431R1: | |
929 return 418; | |
930 | |
931 case SEC_OID_SECG_EC_SECP521R1: | |
932 return 521; | |
933 | |
934 case SEC_OID_SECG_EC_SECT571K1: | |
935 case SEC_OID_SECG_EC_SECT571R1: | |
936 return 570; | |
937 | |
938 default: | |
939 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |
940 return 0; | |
941 } | |
942 } | |
943 | |
944 /* returns key strength in bytes (not bits) */ | |
945 unsigned | |
946 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk) | |
947 { | |
948 unsigned char b0; | |
949 unsigned size; | |
950 | |
951 /* interpret modulus length as key strength */ | |
952 if (!pubk) | |
953 goto loser; | |
954 switch (pubk->keyType) { | |
955 case rsaKey: | |
956 if (!pubk->u.rsa.modulus.data) break; | |
957 b0 = pubk->u.rsa.modulus.data[0]; | |
958 return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; | |
959 case dsaKey: | |
960 if (!pubk->u.dsa.publicValue.data) break; | |
961 b0 = pubk->u.dsa.publicValue.data[0]; | |
962 return b0 ? pubk->u.dsa.publicValue.len : | |
963 pubk->u.dsa.publicValue.len - 1; | |
964 case dhKey: | |
965 if (!pubk->u.dh.publicValue.data) break; | |
966 b0 = pubk->u.dh.publicValue.data[0]; | |
967 return b0 ? pubk->u.dh.publicValue.len : | |
968 pubk->u.dh.publicValue.len - 1; | |
969 case ecKey: | |
970 /* Get the key size in bits and adjust */ | |
971 size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); | |
972 return (size + 7)/8; | |
973 default: | |
974 break; | |
975 } | |
976 loser: | |
977 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
978 return 0; | |
979 } | |
980 | |
981 /* returns key strength in bits */ | |
982 unsigned | |
983 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk) | |
984 { | |
985 unsigned size; | |
986 switch (pubk->keyType) { | |
987 case rsaKey: | |
988 case dsaKey: | |
989 case dhKey: | |
990 return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */ | |
991 case ecKey: | |
992 size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); | |
993 return size; | |
994 default: | |
995 break; | |
996 } | |
997 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
998 return 0; | |
999 } | |
1000 | |
1001 /* returns signature length in bytes (not bits) */ | |
1002 unsigned | |
1003 SECKEY_SignatureLen(const SECKEYPublicKey *pubk) | |
1004 { | |
1005 unsigned char b0; | |
1006 unsigned size; | |
1007 | |
1008 switch (pubk->keyType) { | |
1009 case rsaKey: | |
1010 b0 = pubk->u.rsa.modulus.data[0]; | |
1011 return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; | |
1012 case dsaKey: | |
1013 return pubk->u.dsa.params.subPrime.len * 2; | |
1014 case ecKey: | |
1015 /* Get the base point order length in bits and adjust */ | |
1016 size = SECKEY_ECParamsToBasePointOrderLen( | |
1017 &pubk->u.ec.DEREncodedParams); | |
1018 return ((size + 7)/8) * 2; | |
1019 default: | |
1020 break; | |
1021 } | |
1022 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
1023 return 0; | |
1024 } | |
1025 | |
1026 SECKEYPrivateKey * | |
1027 SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk) | |
1028 { | |
1029 SECKEYPrivateKey *copyk; | |
1030 PLArenaPool *arena; | |
1031 | |
1032 if (!privk || !privk->pkcs11Slot) { | |
1033 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1034 return NULL; | |
1035 } | |
1036 | |
1037 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1038 if (arena == NULL) { | |
1039 return NULL; | |
1040 } | |
1041 | |
1042 copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey)); | |
1043 if (copyk) { | |
1044 copyk->arena = arena; | |
1045 copyk->keyType = privk->keyType; | |
1046 | |
1047 /* copy the PKCS #11 parameters */ | |
1048 copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot); | |
1049 /* if the key we're referencing was a temparary key we have just | |
1050 * created, that we want to go away when we're through, we need | |
1051 * to make a copy of it */ | |
1052 if (privk->pkcs11IsTemp) { | |
1053 copyk->pkcs11ID = | |
1054 PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID); | |
1055 if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; | |
1056 } else { | |
1057 copyk->pkcs11ID = privk->pkcs11ID; | |
1058 } | |
1059 copyk->pkcs11IsTemp = privk->pkcs11IsTemp; | |
1060 copyk->wincx = privk->wincx; | |
1061 copyk->staticflags = privk->staticflags; | |
1062 return copyk; | |
1063 } else { | |
1064 PORT_SetError (SEC_ERROR_NO_MEMORY); | |
1065 } | |
1066 | |
1067 fail: | |
1068 PORT_FreeArena (arena, PR_FALSE); | |
1069 return NULL; | |
1070 } | |
1071 | |
1072 SECKEYPublicKey * | |
1073 SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk) | |
1074 { | |
1075 SECKEYPublicKey *copyk; | |
1076 PLArenaPool *arena; | |
1077 SECStatus rv = SECSuccess; | |
1078 | |
1079 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1080 if (arena == NULL) { | |
1081 PORT_SetError (SEC_ERROR_NO_MEMORY); | |
1082 return NULL; | |
1083 } | |
1084 | |
1085 copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey)); | |
1086 if (!copyk) { | |
1087 PORT_FreeArena (arena, PR_FALSE); | |
1088 PORT_SetError (SEC_ERROR_NO_MEMORY); | |
1089 return NULL; | |
1090 } | |
1091 | |
1092 copyk->arena = arena; | |
1093 copyk->keyType = pubk->keyType; | |
1094 if (pubk->pkcs11Slot && | |
1095 PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { | |
1096 copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot); | |
1097 copyk->pkcs11ID = pubk->pkcs11ID; | |
1098 } else { | |
1099 copyk->pkcs11Slot = NULL; /* go get own reference */ | |
1100 copyk->pkcs11ID = CK_INVALID_HANDLE; | |
1101 } | |
1102 switch (pubk->keyType) { | |
1103 case rsaKey: | |
1104 rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, | |
1105 &pubk->u.rsa.modulus); | |
1106 if (rv == SECSuccess) { | |
1107 rv = SECITEM_CopyItem (arena, ©k->u.rsa.publicExponent, | |
1108 &pubk->u.rsa.publicExponent); | |
1109 if (rv == SECSuccess) | |
1110 return copyk; | |
1111 } | |
1112 break; | |
1113 case dsaKey: | |
1114 rv = SECITEM_CopyItem(arena, ©k->u.dsa.publicValue, | |
1115 &pubk->u.dsa.publicValue); | |
1116 if (rv != SECSuccess) break; | |
1117 rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.prime, | |
1118 &pubk->u.dsa.params.prime); | |
1119 if (rv != SECSuccess) break; | |
1120 rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.subPrime, | |
1121 &pubk->u.dsa.params.subPrime); | |
1122 if (rv != SECSuccess) break; | |
1123 rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.base, | |
1124 &pubk->u.dsa.params.base); | |
1125 break; | |
1126 case dhKey: | |
1127 rv = SECITEM_CopyItem(arena,©k->u.dh.prime,&pubk->u.dh.prime); | |
1128 if (rv != SECSuccess) break; | |
1129 rv = SECITEM_CopyItem(arena,©k->u.dh.base,&pubk->u.dh.base); | |
1130 if (rv != SECSuccess) break; | |
1131 rv = SECITEM_CopyItem(arena, ©k->u.dh.publicValue, | |
1132 &pubk->u.dh.publicValue); | |
1133 break; | |
1134 case ecKey: | |
1135 copyk->u.ec.size = pubk->u.ec.size; | |
1136 rv = SECITEM_CopyItem(arena,©k->u.ec.DEREncodedParams, | |
1137 &pubk->u.ec.DEREncodedParams); | |
1138 if (rv != SECSuccess) break; | |
1139 rv = SECITEM_CopyItem(arena,©k->u.ec.publicValue, | |
1140 &pubk->u.ec.publicValue); | |
1141 break; | |
1142 case nullKey: | |
1143 return copyk; | |
1144 default: | |
1145 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
1146 rv = SECFailure; | |
1147 break; | |
1148 } | |
1149 if (rv == SECSuccess) | |
1150 return copyk; | |
1151 | |
1152 SECKEY_DestroyPublicKey (copyk); | |
1153 return NULL; | |
1154 } | |
1155 | |
1156 | |
1157 SECKEYPublicKey * | |
1158 SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) | |
1159 { | |
1160 SECKEYPublicKey *pubk; | |
1161 PLArenaPool *arena; | |
1162 CERTCertificate *cert; | |
1163 SECStatus rv; | |
1164 | |
1165 /* | |
1166 * First try to look up the cert. | |
1167 */ | |
1168 cert = PK11_GetCertFromPrivateKey(privk); | |
1169 if (cert) { | |
1170 pubk = CERT_ExtractPublicKey(cert); | |
1171 CERT_DestroyCertificate(cert); | |
1172 return pubk; | |
1173 } | |
1174 | |
1175 /* couldn't find the cert, build pub key by hand */ | |
1176 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); | |
1177 if (arena == NULL) { | |
1178 PORT_SetError (SEC_ERROR_NO_MEMORY); | |
1179 return NULL; | |
1180 } | |
1181 pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, | |
1182 sizeof (SECKEYPublicKey)); | |
1183 if (pubk == NULL) { | |
1184 PORT_FreeArena(arena,PR_FALSE); | |
1185 return NULL; | |
1186 } | |
1187 pubk->keyType = privk->keyType; | |
1188 pubk->pkcs11Slot = NULL; | |
1189 pubk->pkcs11ID = CK_INVALID_HANDLE; | |
1190 pubk->arena = arena; | |
1191 | |
1192 switch(privk->keyType) { | |
1193 case nullKey: | |
1194 case dhKey: | |
1195 case dsaKey: | |
1196 /* Nothing to query, if the cert isn't there, we're done -- no way | |
1197 * to get the public key */ | |
1198 break; | |
1199 case rsaKey: | |
1200 rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, | |
1201 CKA_MODULUS,arena,&pubk->u.rsa.modulus); | |
1202 if (rv != SECSuccess) break; | |
1203 rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, | |
1204 CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent); | |
1205 if (rv != SECSuccess) break; | |
1206 return pubk; | |
1207 break; | |
1208 default: | |
1209 break; | |
1210 } | |
1211 | |
1212 PORT_FreeArena (arena, PR_FALSE); | |
1213 return NULL; | |
1214 } | |
1215 | |
1216 static CERTSubjectPublicKeyInfo * | |
1217 seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk) | |
1218 { | |
1219 CERTSubjectPublicKeyInfo *spki; | |
1220 PLArenaPool *arena; | |
1221 SECItem params = { siBuffer, NULL, 0 }; | |
1222 | |
1223 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1224 if (arena == NULL) { | |
1225 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
1226 return NULL; | |
1227 } | |
1228 | |
1229 spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki)); | |
1230 if (spki != NULL) { | |
1231 SECStatus rv; | |
1232 SECItem *rv_item; | |
1233 | |
1234 spki->arena = arena; | |
1235 switch(pubk->keyType) { | |
1236 case rsaKey: | |
1237 rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, | |
1238 SEC_OID_PKCS1_RSA_ENCRYPTION, 0); | |
1239 if (rv == SECSuccess) { | |
1240 /* | |
1241 * DER encode the public key into the subjectPublicKeyInfo. | |
1242 */ | |
1243 prepare_rsa_pub_key_for_asn1(pubk); | |
1244 rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, | |
1245 pubk, SECKEY_RSAPublicKeyTemplate); | |
1246 if (rv_item != NULL) { | |
1247 /* | |
1248 * The stored value is supposed to be a BIT_STRING, | |
1249 * so convert the length. | |
1250 */ | |
1251 spki->subjectPublicKey.len <<= 3; | |
1252 /* | |
1253 * We got a good one; return it. | |
1254 */ | |
1255 return spki; | |
1256 } | |
1257 } | |
1258 break; | |
1259 case dsaKey: | |
1260 /* DER encode the params. */ | |
1261 prepare_pqg_params_for_asn1(&pubk->u.dsa.params); | |
1262 rv_item = SEC_ASN1EncodeItem(arena, ¶ms, &pubk->u.dsa.params, | |
1263 SECKEY_PQGParamsTemplate); | |
1264 if (rv_item != NULL) { | |
1265 rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, | |
1266 SEC_OID_ANSIX9_DSA_SIGNATURE, | |
1267 ¶ms); | |
1268 if (rv == SECSuccess) { | |
1269 /* | |
1270 * DER encode the public key into the subjectPublicKeyInfo. | |
1271 */ | |
1272 prepare_dsa_pub_key_for_asn1(pubk); | |
1273 rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, | |
1274 pubk, | |
1275 SECKEY_DSAPublicKeyTemplate); | |
1276 if (rv_item != NULL) { | |
1277 /* | |
1278 * The stored value is supposed to be a BIT_STRING, | |
1279 * so convert the length. | |
1280 */ | |
1281 spki->subjectPublicKey.len <<= 3; | |
1282 /* | |
1283 * We got a good one; return it. | |
1284 */ | |
1285 return spki; | |
1286 } | |
1287 } | |
1288 } | |
1289 SECITEM_FreeItem(¶ms, PR_FALSE); | |
1290 break; | |
1291 case ecKey: | |
1292 rv = SECITEM_CopyItem(arena, ¶ms, | |
1293 &pubk->u.ec.DEREncodedParams); | |
1294 if (rv != SECSuccess) break; | |
1295 | |
1296 rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, | |
1297 SEC_OID_ANSIX962_EC_PUBLIC_KEY, | |
1298 ¶ms); | |
1299 if (rv != SECSuccess) break; | |
1300 | |
1301 rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, | |
1302 &pubk->u.ec.publicValue); | |
1303 | |
1304 if (rv == SECSuccess) { | |
1305 /* | |
1306 * The stored value is supposed to be a BIT_STRING, | |
1307 * so convert the length. | |
1308 */ | |
1309 spki->subjectPublicKey.len <<= 3; | |
1310 /* | |
1311 * We got a good one; return it. | |
1312 */ | |
1313 return spki; | |
1314 } | |
1315 break; | |
1316 case dhKey: /* later... */ | |
1317 | |
1318 break; | |
1319 default: | |
1320 break; | |
1321 } | |
1322 } else { | |
1323 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
1324 } | |
1325 | |
1326 PORT_FreeArena(arena, PR_FALSE); | |
1327 return NULL; | |
1328 } | |
1329 | |
1330 CERTSubjectPublicKeyInfo * | |
1331 SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk) | |
1332 { | |
1333 CERTSubjectPublicKeyInfo *spki; | |
1334 SECKEYPublicKey *tempKey; | |
1335 | |
1336 if (!pubk) { | |
1337 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1338 return NULL; | |
1339 } | |
1340 | |
1341 tempKey = SECKEY_CopyPublicKey(pubk); | |
1342 if (!tempKey) { | |
1343 return NULL; | |
1344 } | |
1345 spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey); | |
1346 SECKEY_DestroyPublicKey(tempKey); | |
1347 return spki; | |
1348 } | |
1349 | |
1350 void | |
1351 SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki) | |
1352 { | |
1353 if (spki && spki->arena) { | |
1354 PORT_FreeArena(spki->arena, PR_FALSE); | |
1355 } | |
1356 } | |
1357 | |
1358 SECItem * | |
1359 SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk) | |
1360 { | |
1361 CERTSubjectPublicKeyInfo *spki=NULL; | |
1362 SECItem *spkiDER=NULL; | |
1363 | |
1364 /* get the subjectpublickeyinfo */ | |
1365 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); | |
1366 if( spki == NULL ) { | |
1367 goto finish; | |
1368 } | |
1369 | |
1370 /* DER-encode the subjectpublickeyinfo */ | |
1371 spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki, | |
1372 CERT_SubjectPublicKeyInfoTemplate); | |
1373 | |
1374 SECKEY_DestroySubjectPublicKeyInfo(spki); | |
1375 | |
1376 finish: | |
1377 return spkiDER; | |
1378 } | |
1379 | |
1380 | |
1381 CERTSubjectPublicKeyInfo * | |
1382 SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider) | |
1383 { | |
1384 PLArenaPool *arena; | |
1385 CERTSubjectPublicKeyInfo *spki; | |
1386 SECStatus rv; | |
1387 SECItem newSpkider; | |
1388 | |
1389 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1390 if (arena == NULL) { | |
1391 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
1392 return NULL; | |
1393 } | |
1394 | |
1395 spki = (CERTSubjectPublicKeyInfo *) | |
1396 PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo)); | |
1397 if (spki != NULL) { | |
1398 spki->arena = arena; | |
1399 | |
1400 /* copy the DER into the arena, since Quick DER returns data that points | |
1401 into the DER input, which may get freed by the caller */ | |
1402 rv = SECITEM_CopyItem(arena, &newSpkider, spkider); | |
1403 if ( rv == SECSuccess ) { | |
1404 rv = SEC_QuickDERDecodeItem(arena,spki, | |
1405 CERT_SubjectPublicKeyInfoTemplate, &newSpkider); | |
1406 } | |
1407 if (rv == SECSuccess) | |
1408 return spki; | |
1409 } else { | |
1410 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
1411 } | |
1412 | |
1413 PORT_FreeArena(arena, PR_FALSE); | |
1414 return NULL; | |
1415 } | |
1416 | |
1417 /* | |
1418 * Decode a base64 ascii encoded DER encoded subject public key info. | |
1419 */ | |
1420 CERTSubjectPublicKeyInfo * | |
1421 SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr) | |
1422 { | |
1423 CERTSubjectPublicKeyInfo *spki; | |
1424 SECStatus rv; | |
1425 SECItem der; | |
1426 | |
1427 rv = ATOB_ConvertAsciiToItem(&der, spkistr); | |
1428 if (rv != SECSuccess) | |
1429 return NULL; | |
1430 | |
1431 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); | |
1432 | |
1433 PORT_Free(der.data); | |
1434 return spki; | |
1435 } | |
1436 | |
1437 /* | |
1438 * Decode a base64 ascii encoded DER encoded public key and challenge | |
1439 * Verify digital signature and make sure challenge matches | |
1440 */ | |
1441 CERTSubjectPublicKeyInfo * | |
1442 SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge, | |
1443 void *wincx) | |
1444 { | |
1445 CERTSubjectPublicKeyInfo *spki = NULL; | |
1446 CERTPublicKeyAndChallenge pkac; | |
1447 SECStatus rv; | |
1448 SECItem signedItem; | |
1449 PLArenaPool *arena = NULL; | |
1450 CERTSignedData sd; | |
1451 SECItem sig; | |
1452 SECKEYPublicKey *pubKey = NULL; | |
1453 unsigned int len; | |
1454 | |
1455 signedItem.data = NULL; | |
1456 | |
1457 /* convert the base64 encoded data to binary */ | |
1458 rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr); | |
1459 if (rv != SECSuccess) { | |
1460 goto loser; | |
1461 } | |
1462 | |
1463 /* create an arena */ | |
1464 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1465 if (arena == NULL) { | |
1466 goto loser; | |
1467 } | |
1468 | |
1469 /* decode the outer wrapping of signed data */ | |
1470 PORT_Memset(&sd, 0, sizeof(CERTSignedData)); | |
1471 rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem ); | |
1472 if ( rv ) { | |
1473 goto loser; | |
1474 } | |
1475 | |
1476 /* decode the public key and challenge wrapper */ | |
1477 PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge)); | |
1478 rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, | |
1479 &sd.data); | |
1480 if ( rv ) { | |
1481 goto loser; | |
1482 } | |
1483 | |
1484 /* decode the subject public key info */ | |
1485 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki); | |
1486 if ( spki == NULL ) { | |
1487 goto loser; | |
1488 } | |
1489 | |
1490 /* get the public key */ | |
1491 pubKey = seckey_ExtractPublicKey(spki); | |
1492 if ( pubKey == NULL ) { | |
1493 goto loser; | |
1494 } | |
1495 | |
1496 /* check the signature */ | |
1497 sig = sd.signature; | |
1498 DER_ConvertBitString(&sig); | |
1499 rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig, | |
1500 &(sd.signatureAlgorithm), NULL, wincx); | |
1501 if ( rv != SECSuccess ) { | |
1502 goto loser; | |
1503 } | |
1504 | |
1505 /* check the challenge */ | |
1506 if ( challenge ) { | |
1507 len = PORT_Strlen(challenge); | |
1508 /* length is right */ | |
1509 if ( len != pkac.challenge.len ) { | |
1510 goto loser; | |
1511 } | |
1512 /* actual data is right */ | |
1513 if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) { | |
1514 goto loser; | |
1515 } | |
1516 } | |
1517 goto done; | |
1518 | |
1519 loser: | |
1520 /* make sure that we return null if we got an error */ | |
1521 if ( spki ) { | |
1522 SECKEY_DestroySubjectPublicKeyInfo(spki); | |
1523 } | |
1524 spki = NULL; | |
1525 | |
1526 done: | |
1527 if ( signedItem.data ) { | |
1528 PORT_Free(signedItem.data); | |
1529 } | |
1530 if ( arena ) { | |
1531 PORT_FreeArena(arena, PR_FALSE); | |
1532 } | |
1533 if ( pubKey ) { | |
1534 SECKEY_DestroyPublicKey(pubKey); | |
1535 } | |
1536 | |
1537 return spki; | |
1538 } | |
1539 | |
1540 void | |
1541 SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk, | |
1542 PRBool freeit) | |
1543 { | |
1544 PLArenaPool *poolp; | |
1545 | |
1546 if(pvk != NULL) { | |
1547 if(pvk->arena) { | |
1548 poolp = pvk->arena; | |
1549 /* zero structure since PORT_FreeArena does not support | |
1550 * this yet. | |
1551 */ | |
1552 PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len); | |
1553 PORT_Memset((char *)pvk, 0, sizeof(*pvk)); | |
1554 if(freeit == PR_TRUE) { | |
1555 PORT_FreeArena(poolp, PR_TRUE); | |
1556 } else { | |
1557 pvk->arena = poolp; | |
1558 } | |
1559 } else { | |
1560 SECITEM_ZfreeItem(&pvk->version, PR_FALSE); | |
1561 SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE); | |
1562 SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE); | |
1563 PORT_Memset((char *)pvk, 0, sizeof(*pvk)); | |
1564 if(freeit == PR_TRUE) { | |
1565 PORT_Free(pvk); | |
1566 } | |
1567 } | |
1568 } | |
1569 } | |
1570 | |
1571 void | |
1572 SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki, | |
1573 PRBool freeit) | |
1574 { | |
1575 PLArenaPool *poolp; | |
1576 | |
1577 if(epki != NULL) { | |
1578 if(epki->arena) { | |
1579 poolp = epki->arena; | |
1580 /* zero structure since PORT_FreeArena does not support | |
1581 * this yet. | |
1582 */ | |
1583 PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len); | |
1584 PORT_Memset((char *)epki, 0, sizeof(*epki)); | |
1585 if(freeit == PR_TRUE) { | |
1586 PORT_FreeArena(poolp, PR_TRUE); | |
1587 } else { | |
1588 epki->arena = poolp; | |
1589 } | |
1590 } else { | |
1591 SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE); | |
1592 SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE); | |
1593 PORT_Memset((char *)epki, 0, sizeof(*epki)); | |
1594 if(freeit == PR_TRUE) { | |
1595 PORT_Free(epki); | |
1596 } | |
1597 } | |
1598 } | |
1599 } | |
1600 | |
1601 SECStatus | |
1602 SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp, | |
1603 SECKEYPrivateKeyInfo *to, | |
1604 const SECKEYPrivateKeyInfo *from) | |
1605 { | |
1606 SECStatus rv = SECFailure; | |
1607 | |
1608 if((to == NULL) || (from == NULL)) { | |
1609 return SECFailure; | |
1610 } | |
1611 | |
1612 rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); | |
1613 if(rv != SECSuccess) { | |
1614 return SECFailure; | |
1615 } | |
1616 rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey); | |
1617 if(rv != SECSuccess) { | |
1618 return SECFailure; | |
1619 } | |
1620 rv = SECITEM_CopyItem(poolp, &to->version, &from->version); | |
1621 | |
1622 return rv; | |
1623 } | |
1624 | |
1625 SECStatus | |
1626 SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp, | |
1627 SECKEYEncryptedPrivateKeyInfo *to, | |
1628 const SECKEYEncryptedPrivateKeyInfo *from) | |
1629 { | |
1630 SECStatus rv = SECFailure; | |
1631 | |
1632 if((to == NULL) || (from == NULL)) { | |
1633 return SECFailure; | |
1634 } | |
1635 | |
1636 rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); | |
1637 if(rv != SECSuccess) { | |
1638 return SECFailure; | |
1639 } | |
1640 rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData); | |
1641 | |
1642 return rv; | |
1643 } | |
1644 | |
1645 KeyType | |
1646 SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey) | |
1647 { | |
1648 return privKey->keyType; | |
1649 } | |
1650 | |
1651 KeyType | |
1652 SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey) | |
1653 { | |
1654 return pubKey->keyType; | |
1655 } | |
1656 | |
1657 SECKEYPublicKey* | |
1658 SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type) | |
1659 { | |
1660 SECKEYPublicKey *pubk = NULL; | |
1661 SECStatus rv = SECFailure; | |
1662 SECItem newDerKey; | |
1663 PLArenaPool *arena = NULL; | |
1664 | |
1665 if (!derKey) { | |
1666 return NULL; | |
1667 } | |
1668 | |
1669 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1670 if (arena == NULL) { | |
1671 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
1672 goto finish; | |
1673 } | |
1674 | |
1675 pubk = PORT_ArenaZNew(arena, SECKEYPublicKey); | |
1676 if (pubk == NULL) { | |
1677 goto finish; | |
1678 } | |
1679 pubk->arena = arena; | |
1680 | |
1681 rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey); | |
1682 if (SECSuccess != rv) { | |
1683 goto finish; | |
1684 } | |
1685 | |
1686 pubk->pkcs11Slot = NULL; | |
1687 pubk->pkcs11ID = CK_INVALID_HANDLE; | |
1688 | |
1689 switch( type ) { | |
1690 case CKK_RSA: | |
1691 prepare_rsa_pub_key_for_asn1(pubk); | |
1692 rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey); | |
1693 pubk->keyType = rsaKey; | |
1694 break; | |
1695 case CKK_DSA: | |
1696 prepare_dsa_pub_key_for_asn1(pubk); | |
1697 rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey); | |
1698 pubk->keyType = dsaKey; | |
1699 break; | |
1700 case CKK_DH: | |
1701 prepare_dh_pub_key_for_asn1(pubk); | |
1702 rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey); | |
1703 pubk->keyType = dhKey; | |
1704 break; | |
1705 default: | |
1706 rv = SECFailure; | |
1707 break; | |
1708 } | |
1709 | |
1710 finish: | |
1711 if (rv != SECSuccess) { | |
1712 if (arena != NULL) { | |
1713 PORT_FreeArena(arena, PR_FALSE); | |
1714 } | |
1715 pubk = NULL; | |
1716 } | |
1717 return pubk; | |
1718 } | |
1719 | |
1720 SECKEYPrivateKeyList* | |
1721 SECKEY_NewPrivateKeyList(void) | |
1722 { | |
1723 PLArenaPool *arena = NULL; | |
1724 SECKEYPrivateKeyList *ret = NULL; | |
1725 | |
1726 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1727 if ( arena == NULL ) { | |
1728 goto loser; | |
1729 } | |
1730 | |
1731 ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena, | |
1732 sizeof(SECKEYPrivateKeyList)); | |
1733 if ( ret == NULL ) { | |
1734 goto loser; | |
1735 } | |
1736 | |
1737 ret->arena = arena; | |
1738 | |
1739 PR_INIT_CLIST(&ret->list); | |
1740 | |
1741 return(ret); | |
1742 | |
1743 loser: | |
1744 if ( arena != NULL ) { | |
1745 PORT_FreeArena(arena, PR_FALSE); | |
1746 } | |
1747 | |
1748 return(NULL); | |
1749 } | |
1750 | |
1751 void | |
1752 SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys) | |
1753 { | |
1754 while( !PR_CLIST_IS_EMPTY(&keys->list) ) { | |
1755 SECKEY_RemovePrivateKeyListNode( | |
1756 (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); | |
1757 } | |
1758 | |
1759 PORT_FreeArena(keys->arena, PR_FALSE); | |
1760 | |
1761 return; | |
1762 } | |
1763 | |
1764 | |
1765 void | |
1766 SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node) | |
1767 { | |
1768 PR_ASSERT(node->key); | |
1769 SECKEY_DestroyPrivateKey(node->key); | |
1770 node->key = NULL; | |
1771 PR_REMOVE_LINK(&node->links); | |
1772 return; | |
1773 | |
1774 } | |
1775 | |
1776 SECStatus | |
1777 SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list, | |
1778 SECKEYPrivateKey *key) | |
1779 { | |
1780 SECKEYPrivateKeyListNode *node; | |
1781 | |
1782 node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena, | |
1783 sizeof(SECKEYPrivateKeyListNode)); | |
1784 if ( node == NULL ) { | |
1785 goto loser; | |
1786 } | |
1787 | |
1788 PR_INSERT_BEFORE(&node->links, &list->list); | |
1789 node->key = key; | |
1790 return(SECSuccess); | |
1791 | |
1792 loser: | |
1793 return(SECFailure); | |
1794 } | |
1795 | |
1796 | |
1797 SECKEYPublicKeyList* | |
1798 SECKEY_NewPublicKeyList(void) | |
1799 { | |
1800 PLArenaPool *arena = NULL; | |
1801 SECKEYPublicKeyList *ret = NULL; | |
1802 | |
1803 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1804 if ( arena == NULL ) { | |
1805 goto loser; | |
1806 } | |
1807 | |
1808 ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena, | |
1809 sizeof(SECKEYPublicKeyList)); | |
1810 if ( ret == NULL ) { | |
1811 goto loser; | |
1812 } | |
1813 | |
1814 ret->arena = arena; | |
1815 | |
1816 PR_INIT_CLIST(&ret->list); | |
1817 | |
1818 return(ret); | |
1819 | |
1820 loser: | |
1821 if ( arena != NULL ) { | |
1822 PORT_FreeArena(arena, PR_FALSE); | |
1823 } | |
1824 | |
1825 return(NULL); | |
1826 } | |
1827 | |
1828 void | |
1829 SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys) | |
1830 { | |
1831 while( !PR_CLIST_IS_EMPTY(&keys->list) ) { | |
1832 SECKEY_RemovePublicKeyListNode( | |
1833 (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); | |
1834 } | |
1835 | |
1836 PORT_FreeArena(keys->arena, PR_FALSE); | |
1837 | |
1838 return; | |
1839 } | |
1840 | |
1841 | |
1842 void | |
1843 SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node) | |
1844 { | |
1845 PR_ASSERT(node->key); | |
1846 SECKEY_DestroyPublicKey(node->key); | |
1847 node->key = NULL; | |
1848 PR_REMOVE_LINK(&node->links); | |
1849 return; | |
1850 | |
1851 } | |
1852 | |
1853 SECStatus | |
1854 SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list, | |
1855 SECKEYPublicKey *key) | |
1856 { | |
1857 SECKEYPublicKeyListNode *node; | |
1858 | |
1859 node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena, | |
1860 sizeof(SECKEYPublicKeyListNode)); | |
1861 if ( node == NULL ) { | |
1862 goto loser; | |
1863 } | |
1864 | |
1865 PR_INSERT_BEFORE(&node->links, &list->list); | |
1866 node->key = key; | |
1867 return(SECSuccess); | |
1868 | |
1869 loser: | |
1870 return(SECFailure); | |
1871 } | |
1872 | |
1873 #define SECKEY_CacheAttribute(key, attribute) \ | |
1874 if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \ | |
1875 key->staticflags |= SECKEY_##attribute; \ | |
1876 } else { \ | |
1877 key->staticflags &= (~SECKEY_##attribute); \ | |
1878 } | |
1879 | |
1880 SECStatus | |
1881 SECKEY_CacheStaticFlags(SECKEYPrivateKey* key) | |
1882 { | |
1883 SECStatus rv = SECFailure; | |
1884 if (key && key->pkcs11Slot && key->pkcs11ID) { | |
1885 key->staticflags |= SECKEY_Attributes_Cached; | |
1886 SECKEY_CacheAttribute(key, CKA_PRIVATE); | |
1887 SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE); | |
1888 rv = SECSuccess; | |
1889 } | |
1890 return rv; | |
1891 } |