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,&param,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, &copyk->u.rsa.modulus,
1105 &pubk->u.rsa.modulus);
1106 if (rv == SECSuccess) {
1107 rv = SECITEM_CopyItem (arena, &copyk->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, &copyk->u.dsa.publicValue,
1115 &pubk->u.dsa.publicValue);
1116 if (rv != SECSuccess) break;
1117 rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
1118 &pubk->u.dsa.params.prime);
1119 if (rv != SECSuccess) break;
1120 rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
1121 &pubk->u.dsa.params.subPrime);
1122 if (rv != SECSuccess) break;
1123 rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
1124 &pubk->u.dsa.params.base);
1125 break;
1126 case dhKey:
1127 rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
1128 if (rv != SECSuccess) break;
1129 rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
1130 if (rv != SECSuccess) break;
1131 rv = SECITEM_CopyItem(arena, &copyk->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,&copyk->u.ec.DEREncodedParams,
1137 &pubk->u.ec.DEREncodedParams);
1138 if (rv != SECSuccess) break;
1139 rv = SECITEM_CopyItem(arena,&copyk->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, &params, &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 &params);
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(&params, PR_FALSE);
1290 break;
1291 case ecKey:
1292 rv = SECITEM_CopyItem(arena, &params,
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 &params);
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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)