1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
48 * ******************** Object Creation Utilities ***************************
52 * check the consistancy and initialize a Certificate Object
55 lg_createCertObject(SDB
*sdb
, CK_OBJECT_HANDLE
*handle
,
56 const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
59 NSSLOWCERTCertificate
*cert
;
60 NSSLOWCERTCertTrust
*trust
= NULL
;
61 NSSLOWCERTCertTrust userTrust
=
62 { CERTDB_USER
, CERTDB_USER
, CERTDB_USER
};
63 NSSLOWCERTCertTrust defTrust
=
64 { CERTDB_TRUSTED_UNKNOWN
,
65 CERTDB_TRUSTED_UNKNOWN
, CERTDB_TRUSTED_UNKNOWN
};
70 PRBool inDB
= PR_TRUE
;
71 NSSLOWCERTCertDBHandle
*certHandle
= lg_getCertDB(sdb
);
72 NSSLOWKEYDBHandle
*keyHandle
= NULL
;
73 CK_CERTIFICATE_TYPE type
;
74 const CK_ATTRIBUTE
*attribute
;
76 /* we can't store any certs private */
77 if (lg_isTrue(CKA_PRIVATE
, templ
, count
)) {
78 return CKR_ATTRIBUTE_VALUE_INVALID
;
81 /* We only support X.509 Certs for now */
82 crv
= lg_GetULongAttribute(CKA_CERTIFICATE_TYPE
, templ
, count
, &type
);
87 if (type
!= CKC_X_509
) {
88 return CKR_ATTRIBUTE_VALUE_INVALID
;
91 /* X.509 Certificate */
94 if (certHandle
== NULL
) {
95 return CKR_TOKEN_WRITE_PROTECTED
;
98 /* get the der cert */
99 attribute
= lg_FindAttribute(CKA_VALUE
, templ
, count
);
101 return CKR_ATTRIBUTE_VALUE_INVALID
;
105 derCert
.data
= (unsigned char *)attribute
->pValue
;
106 derCert
.len
= attribute
->ulValueLen
;
108 label
= lg_getString(CKA_LABEL
, templ
, count
);
110 cert
= nsslowcert_FindCertByDERCert(certHandle
, &derCert
);
112 cert
= nsslowcert_DecodeDERCertificate(&derCert
, label
);
116 if (label
) PORT_Free(label
);
117 return CKR_ATTRIBUTE_VALUE_INVALID
;
120 keyHandle
= lg_getKeyDB(sdb
);
122 if (nsslowkey_KeyForCertExists(keyHandle
,cert
)) {
128 if (!trust
) trust
= &defTrust
;
129 rv
= nsslowcert_AddPermCert(certHandle
, cert
, label
, trust
);
131 rv
= trust
? nsslowcert_ChangeCertTrust(certHandle
,cert
,trust
) :
135 if (label
) PORT_Free(label
);
137 if (rv
!= SECSuccess
) {
138 nsslowcert_DestroyCertificate(cert
);
139 return CKR_DEVICE_ERROR
;
143 * Add a NULL S/MIME profile if necessary.
145 email
= lg_getString(CKA_NETSCAPE_EMAIL
, templ
, count
);
147 certDBEntrySMime
*entry
;
149 entry
= nsslowcert_ReadDBSMimeEntry(certHandle
,email
);
151 nsslowcert_SaveSMimeProfile(certHandle
, email
,
152 &cert
->derSubject
, NULL
, NULL
);
154 nsslowcert_DestroyDBEntry((certDBEntry
*)entry
);
158 *handle
=lg_mkHandle(sdb
,&cert
->certKey
,LG_TOKEN_TYPE_CERT
);
159 nsslowcert_DestroyCertificate(cert
);
165 lg_MapTrust(CK_TRUST trust
, PRBool clientAuth
)
167 unsigned int trustCA
= clientAuth
? CERTDB_TRUSTED_CLIENT_CA
:
170 case CKT_NETSCAPE_TRUSTED
:
171 return CERTDB_VALID_PEER
|CERTDB_TRUSTED
;
172 case CKT_NETSCAPE_TRUSTED_DELEGATOR
:
173 return CERTDB_VALID_CA
|trustCA
;
174 case CKT_NETSCAPE_UNTRUSTED
:
175 return CERTDB_NOT_TRUSTED
;
176 case CKT_NETSCAPE_MUST_VERIFY
:
178 case CKT_NETSCAPE_VALID
: /* implies must verify */
179 return CERTDB_VALID_PEER
;
180 case CKT_NETSCAPE_VALID_DELEGATOR
: /* implies must verify */
181 return CERTDB_VALID_CA
;
185 return CERTDB_TRUSTED_UNKNOWN
;
190 * check the consistancy and initialize a Trust Object
193 lg_createTrustObject(SDB
*sdb
, CK_OBJECT_HANDLE
*handle
,
194 const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
196 const CK_ATTRIBUTE
*issuer
= NULL
;
197 const CK_ATTRIBUTE
*serial
= NULL
;
198 NSSLOWCERTCertificate
*cert
= NULL
;
199 const CK_ATTRIBUTE
*trust
;
200 CK_TRUST sslTrust
= CKT_NETSCAPE_TRUST_UNKNOWN
;
201 CK_TRUST clientTrust
= CKT_NETSCAPE_TRUST_UNKNOWN
;
202 CK_TRUST emailTrust
= CKT_NETSCAPE_TRUST_UNKNOWN
;
203 CK_TRUST signTrust
= CKT_NETSCAPE_TRUST_UNKNOWN
;
205 NSSLOWCERTCertTrust dbTrust
= { 0 };
207 NSSLOWCERTCertDBHandle
*certHandle
= lg_getCertDB(sdb
);
208 NSSLOWCERTIssuerAndSN issuerSN
;
210 /* we can't store any certs private */
211 if (lg_isTrue(CKA_PRIVATE
, templ
, count
)) {
212 return CKR_ATTRIBUTE_VALUE_INVALID
;
215 if (certHandle
== NULL
) {
216 return CKR_TOKEN_WRITE_PROTECTED
;
219 issuer
= lg_FindAttribute(CKA_ISSUER
, templ
, count
);
220 serial
= lg_FindAttribute(CKA_SERIAL_NUMBER
, templ
, count
);
222 if (issuer
&& serial
) {
223 issuerSN
.derIssuer
.data
= (unsigned char *)issuer
->pValue
;
224 issuerSN
.derIssuer
.len
= issuer
->ulValueLen
;
226 issuerSN
.serialNumber
.data
= (unsigned char *)serial
->pValue
;
227 issuerSN
.serialNumber
.len
= serial
->ulValueLen
;
229 cert
= nsslowcert_FindCertByIssuerAndSN(certHandle
,&issuerSN
);
233 return CKR_ATTRIBUTE_VALUE_INVALID
;
236 lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH
, templ
, count
, &sslTrust
);
237 lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH
, templ
, count
, &clientTrust
);
238 lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION
, templ
, count
, &emailTrust
);
239 lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING
, templ
, count
, &signTrust
);
241 trust
= lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED
, templ
, count
);
243 if (trust
->ulValueLen
== sizeof(CK_BBOOL
)) {
244 stepUp
= *(CK_BBOOL
*)trust
->pValue
;
248 /* preserve certain old fields */
250 dbTrust
.sslFlags
= cert
->trust
->sslFlags
& CERTDB_PRESERVE_TRUST_BITS
;
252 cert
->trust
->emailFlags
& CERTDB_PRESERVE_TRUST_BITS
;
253 dbTrust
.objectSigningFlags
=
254 cert
->trust
->objectSigningFlags
& CERTDB_PRESERVE_TRUST_BITS
;
257 dbTrust
.sslFlags
|= lg_MapTrust(sslTrust
,PR_FALSE
);
258 dbTrust
.sslFlags
|= lg_MapTrust(clientTrust
,PR_TRUE
);
259 dbTrust
.emailFlags
|= lg_MapTrust(emailTrust
,PR_FALSE
);
260 dbTrust
.objectSigningFlags
|= lg_MapTrust(signTrust
,PR_FALSE
);
262 dbTrust
.sslFlags
|= CERTDB_GOVT_APPROVED_CA
;
265 rv
= nsslowcert_ChangeCertTrust(certHandle
,cert
,&dbTrust
);
266 *handle
=lg_mkHandle(sdb
,&cert
->certKey
,LG_TOKEN_TYPE_TRUST
);
267 nsslowcert_DestroyCertificate(cert
);
268 if (rv
!= SECSuccess
) {
269 return CKR_DEVICE_ERROR
;
276 * check the consistancy and initialize a Trust Object
279 lg_createSMimeObject(SDB
*sdb
, CK_OBJECT_HANDLE
*handle
,
280 const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
282 SECItem derSubj
,rawProfile
,rawTime
,emailKey
;
283 SECItem
*pRawProfile
= NULL
;
284 SECItem
*pRawTime
= NULL
;
286 const CK_ATTRIBUTE
*subject
= NULL
,
290 NSSLOWCERTCertDBHandle
*certHandle
;
291 CK_RV ck_rv
= CKR_OK
;
293 /* we can't store any certs private */
294 if (lg_isTrue(CKA_PRIVATE
,templ
,count
)) {
295 return CKR_ATTRIBUTE_VALUE_INVALID
;
298 certHandle
= lg_getCertDB(sdb
);
299 if (certHandle
== NULL
) {
300 return CKR_TOKEN_WRITE_PROTECTED
;
304 subject
= lg_FindAttribute(CKA_SUBJECT
,templ
,count
);
305 PORT_Assert(subject
);
307 ck_rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
311 derSubj
.data
= (unsigned char *)subject
->pValue
;
312 derSubj
.len
= subject
->ulValueLen
;
316 profile
= lg_FindAttribute(CKA_VALUE
,templ
,count
);
318 rawProfile
.data
= (unsigned char *)profile
->pValue
;
319 rawProfile
.len
= profile
->ulValueLen
;
320 rawProfile
.type
= siBuffer
;
321 pRawProfile
= &rawProfile
;
325 time
= lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP
,templ
,count
);
327 rawTime
.data
= (unsigned char *)time
->pValue
;
328 rawTime
.len
= time
->ulValueLen
;
329 rawTime
.type
= siBuffer
;
334 email
= lg_getString(CKA_NETSCAPE_EMAIL
,templ
,count
);
336 ck_rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
340 /* Store S/MIME Profile by SUBJECT */
341 rv
= nsslowcert_SaveSMimeProfile(certHandle
, email
, &derSubj
,
342 pRawProfile
,pRawTime
);
343 if (rv
!= SECSuccess
) {
344 ck_rv
= CKR_DEVICE_ERROR
;
347 emailKey
.data
= (unsigned char *)email
;
348 emailKey
.len
= PORT_Strlen(email
)+1;
350 *handle
= lg_mkHandle(sdb
, &emailKey
, LG_TOKEN_TYPE_SMIME
);
353 if (email
) PORT_Free(email
);
359 * check the consistancy and initialize a Trust Object
362 lg_createCrlObject(SDB
*sdb
, CK_OBJECT_HANDLE
*handle
,
363 const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
365 PRBool isKRL
= PR_FALSE
;
366 SECItem derSubj
,derCrl
;
368 const CK_ATTRIBUTE
*subject
,*crl
;
370 NSSLOWCERTCertDBHandle
*certHandle
;
372 certHandle
= lg_getCertDB(sdb
);
374 /* we can't store any private crls */
375 if (lg_isTrue(CKA_PRIVATE
,templ
,count
)) {
376 return CKR_ATTRIBUTE_VALUE_INVALID
;
379 if (certHandle
== NULL
) {
380 return CKR_TOKEN_WRITE_PROTECTED
;
384 subject
= lg_FindAttribute(CKA_SUBJECT
,templ
,count
);
386 return CKR_ATTRIBUTE_VALUE_INVALID
;
389 derSubj
.data
= (unsigned char *)subject
->pValue
;
390 derSubj
.len
= subject
->ulValueLen
;
393 crl
= lg_FindAttribute(CKA_VALUE
,templ
,count
);
396 return CKR_ATTRIBUTE_VALUE_INVALID
;
398 derCrl
.data
= (unsigned char *)crl
->pValue
;
399 derCrl
.len
= crl
->ulValueLen
;
401 url
= lg_getString(CKA_NETSCAPE_URL
,templ
,count
);
402 isKRL
= lg_isTrue(CKA_NETSCAPE_KRL
,templ
,count
);
404 /* Store CRL by SUBJECT */
405 rv
= nsslowcert_AddCrl(certHandle
, &derCrl
, &derSubj
, url
, isKRL
);
410 if (rv
!= SECSuccess
) {
411 return CKR_DEVICE_ERROR
;
414 /* if we overwrote the existing CRL, poison the handle entry so we get
415 * a new object handle */
416 (void) lg_poisonHandle(sdb
, &derSubj
,
417 isKRL
? LG_TOKEN_KRL_HANDLE
: LG_TOKEN_TYPE_CRL
);
418 *handle
= lg_mkHandle(sdb
, &derSubj
,
419 isKRL
? LG_TOKEN_KRL_HANDLE
: LG_TOKEN_TYPE_CRL
);
425 * check the consistancy and initialize a Public Key Object
428 lg_createPublicKeyObject(SDB
*sdb
, CK_KEY_TYPE key_type
,
429 CK_OBJECT_HANDLE
*handle
, const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
431 CK_ATTRIBUTE_TYPE pubKeyAttr
= CKA_VALUE
;
433 NSSLOWKEYPrivateKey
*priv
;
435 NSSLOWKEYDBHandle
*keyHandle
= NULL
;
439 pubKeyAttr
= CKA_MODULUS
;
441 #ifdef NSS_ENABLE_ECC
443 pubKeyAttr
= CKA_EC_POINT
;
445 #endif /* NSS_ENABLE_ECC */
450 return CKR_ATTRIBUTE_VALUE_INVALID
;
454 crv
= lg_Attribute2SSecItem(NULL
,pubKeyAttr
,templ
,count
,&pubKey
);
455 if (crv
!= CKR_OK
) return crv
;
457 PORT_Assert(pubKey
.data
);
458 keyHandle
= lg_getKeyDB(sdb
);
459 if (keyHandle
== NULL
) {
460 PORT_Free(pubKey
.data
);
461 return CKR_TOKEN_WRITE_PROTECTED
;
463 if (keyHandle
->version
!= 3) {
464 unsigned char buf
[SHA1_LENGTH
];
465 SHA1_HashBuf(buf
,pubKey
.data
,pubKey
.len
);
466 PORT_Memcpy(pubKey
.data
,buf
,sizeof(buf
));
467 pubKey
.len
= sizeof(buf
);
469 /* make sure the associated private key already exists */
470 /* only works if we are logged in */
471 priv
= nsslowkey_FindKeyByPublicKey(keyHandle
, &pubKey
, sdb
/*password*/);
473 PORT_Free(pubKey
.data
);
476 nsslowkey_DestroyPrivateKey(priv
);
478 *handle
= lg_mkHandle(sdb
, &pubKey
, LG_TOKEN_TYPE_PUB
);
479 PORT_Free(pubKey
.data
);
484 /* make a private key from a verified object */
485 static NSSLOWKEYPrivateKey
*
486 lg_mkPrivKey(SDB
*sdb
, const CK_ATTRIBUTE
*templ
, CK_ULONG count
,
487 CK_KEY_TYPE key_type
, CK_RV
*crvp
)
489 NSSLOWKEYPrivateKey
*privKey
;
494 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
496 *crvp
= CKR_HOST_MEMORY
;
500 privKey
= (NSSLOWKEYPrivateKey
*)
501 PORT_ArenaZAlloc(arena
,sizeof(NSSLOWKEYPrivateKey
));
502 if (privKey
== NULL
) {
503 PORT_FreeArena(arena
,PR_FALSE
);
504 *crvp
= CKR_HOST_MEMORY
;
508 /* in future this would be a switch on key_type */
509 privKey
->arena
= arena
;
512 privKey
->keyType
= NSSLOWKEYRSAKey
;
513 crv
=lg_Attribute2SSecItem(arena
,CKA_MODULUS
,templ
,count
,
514 &privKey
->u
.rsa
.modulus
);
515 if (crv
!= CKR_OK
) break;
516 crv
=lg_Attribute2SSecItem(arena
,CKA_PUBLIC_EXPONENT
,templ
,count
,
517 &privKey
->u
.rsa
.publicExponent
);
518 if (crv
!= CKR_OK
) break;
519 crv
=lg_PrivAttr2SSecItem(arena
,CKA_PRIVATE_EXPONENT
,templ
,count
,
520 &privKey
->u
.rsa
.privateExponent
, sdb
);
521 if (crv
!= CKR_OK
) break;
522 crv
=lg_PrivAttr2SSecItem(arena
,CKA_PRIME_1
,templ
,count
,
523 &privKey
->u
.rsa
.prime1
, sdb
);
524 if (crv
!= CKR_OK
) break;
525 crv
=lg_PrivAttr2SSecItem(arena
,CKA_PRIME_2
,templ
,count
,
526 &privKey
->u
.rsa
.prime2
, sdb
);
527 if (crv
!= CKR_OK
) break;
528 crv
=lg_PrivAttr2SSecItem(arena
,CKA_EXPONENT_1
,templ
,count
,
529 &privKey
->u
.rsa
.exponent1
, sdb
);
530 if (crv
!= CKR_OK
) break;
531 crv
=lg_PrivAttr2SSecItem(arena
,CKA_EXPONENT_2
,templ
,count
,
532 &privKey
->u
.rsa
.exponent2
, sdb
);
533 if (crv
!= CKR_OK
) break;
534 crv
=lg_PrivAttr2SSecItem(arena
,CKA_COEFFICIENT
,templ
,count
,
535 &privKey
->u
.rsa
.coefficient
, sdb
);
536 if (crv
!= CKR_OK
) break;
537 rv
= DER_SetUInteger(privKey
->arena
, &privKey
->u
.rsa
.version
,
539 if (rv
!= SECSuccess
) crv
= CKR_HOST_MEMORY
;
543 privKey
->keyType
= NSSLOWKEYDSAKey
;
544 crv
= lg_Attribute2SSecItem(arena
,CKA_PRIME
,templ
,count
,
545 &privKey
->u
.dsa
.params
.prime
);
546 if (crv
!= CKR_OK
) break;
547 crv
= lg_Attribute2SSecItem(arena
,CKA_SUBPRIME
,templ
,count
,
548 &privKey
->u
.dsa
.params
.subPrime
);
549 if (crv
!= CKR_OK
) break;
550 crv
= lg_Attribute2SSecItem(arena
,CKA_BASE
,templ
,count
,
551 &privKey
->u
.dsa
.params
.base
);
552 if (crv
!= CKR_OK
) break;
553 crv
= lg_PrivAttr2SSecItem(arena
,CKA_VALUE
,templ
,count
,
554 &privKey
->u
.dsa
.privateValue
, sdb
);
555 if (crv
!= CKR_OK
) break;
556 if (lg_hasAttribute(CKA_NETSCAPE_DB
, templ
,count
)) {
557 crv
= lg_Attribute2SSecItem(arena
, CKA_NETSCAPE_DB
,templ
,count
,
558 &privKey
->u
.dsa
.publicValue
);
559 /* privKey was zero'd so public value is already set to NULL, 0
560 * if we don't set it explicitly */
565 privKey
->keyType
= NSSLOWKEYDHKey
;
566 crv
= lg_Attribute2SSecItem(arena
,CKA_PRIME
,templ
,count
,
567 &privKey
->u
.dh
.prime
);
568 if (crv
!= CKR_OK
) break;
569 crv
= lg_Attribute2SSecItem(arena
,CKA_BASE
,templ
,count
,
570 &privKey
->u
.dh
.base
);
571 if (crv
!= CKR_OK
) break;
572 crv
= lg_PrivAttr2SSecItem(arena
,CKA_VALUE
,templ
,count
,
573 &privKey
->u
.dh
.privateValue
, sdb
);
574 if (crv
!= CKR_OK
) break;
575 if (lg_hasAttribute(CKA_NETSCAPE_DB
, templ
, count
)) {
576 crv
= lg_Attribute2SSecItem(arena
, CKA_NETSCAPE_DB
,templ
,count
,
577 &privKey
->u
.dh
.publicValue
);
578 /* privKey was zero'd so public value is already set to NULL, 0
579 * if we don't set it explicitly */
583 #ifdef NSS_ENABLE_ECC
585 privKey
->keyType
= NSSLOWKEYECKey
;
586 crv
= lg_Attribute2SSecItem(arena
, CKA_EC_PARAMS
,templ
,count
,
587 &privKey
->u
.ec
.ecParams
.DEREncoding
);
588 if (crv
!= CKR_OK
) break;
590 /* Fill out the rest of the ecParams structure
591 * based on the encoded params
593 if (LGEC_FillParams(arena
, &privKey
->u
.ec
.ecParams
.DEREncoding
,
594 &privKey
->u
.ec
.ecParams
) != SECSuccess
) {
595 crv
= CKR_DOMAIN_PARAMS_INVALID
;
598 crv
= lg_PrivAttr2SSecItem(arena
,CKA_VALUE
,templ
,count
,
599 &privKey
->u
.ec
.privateValue
, sdb
);
600 if (crv
!= CKR_OK
) break;
601 if (lg_hasAttribute(CKA_NETSCAPE_DB
,templ
,count
)) {
602 crv
= lg_Attribute2SSecItem(arena
, CKA_NETSCAPE_DB
,templ
,count
,
603 &privKey
->u
.ec
.publicValue
);
604 if (crv
!= CKR_OK
) break;
605 /* privKey was zero'd so public value is already set to NULL, 0
606 * if we don't set it explicitly */
608 rv
= DER_SetUInteger(privKey
->arena
, &privKey
->u
.ec
.version
,
609 NSSLOWKEY_EC_PRIVATE_KEY_VERSION
);
610 if (rv
!= SECSuccess
) crv
= CKR_HOST_MEMORY
;
612 #endif /* NSS_ENABLE_ECC */
615 crv
= CKR_KEY_TYPE_INCONSISTENT
;
620 PORT_FreeArena(arena
,PR_FALSE
);
627 * check the consistancy and initialize a Private Key Object
630 lg_createPrivateKeyObject(SDB
*sdb
, CK_KEY_TYPE key_type
,
631 CK_OBJECT_HANDLE
*handle
, const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
633 NSSLOWKEYPrivateKey
*privKey
;
635 SECStatus rv
= SECSuccess
;
636 CK_RV crv
= CKR_DEVICE_ERROR
;
638 NSSLOWKEYDBHandle
*keyHandle
= lg_getKeyDB(sdb
);
640 if (keyHandle
== NULL
) {
641 return CKR_TOKEN_WRITE_PROTECTED
;
644 privKey
=lg_mkPrivKey(sdb
, templ
,count
,key_type
,&crv
);
645 if (privKey
== NULL
) return crv
;
646 label
= lg_getString(CKA_LABEL
,templ
,count
);
648 crv
= lg_Attribute2SSecItem(NULL
,CKA_NETSCAPE_DB
,templ
,count
,&pubKey
);
650 crv
= CKR_TEMPLATE_INCOMPLETE
;
655 if (keyHandle
->version
!= 3) {
656 unsigned char buf
[SHA1_LENGTH
];
657 SHA1_HashBuf(buf
,pubKey
.data
,pubKey
.len
);
658 PORT_Memcpy(pubKey
.data
,buf
,sizeof(buf
));
659 pubKey
.len
= sizeof(buf
);
662 /* get the key type */
663 if (key_type
== CKK_RSA
) {
664 rv
= RSA_PrivateKeyCheck(&privKey
->u
.rsa
);
665 if (rv
== SECFailure
) {
669 rv
= nsslowkey_StoreKeyByPublicKey(keyHandle
, privKey
, &pubKey
,
670 label
, sdb
/*->password*/);
673 if (label
) PORT_Free(label
);
674 *handle
= lg_mkHandle(sdb
,&pubKey
,LG_TOKEN_TYPE_PRIV
);
675 if (pubKey
.data
) PORT_Free(pubKey
.data
);
676 nsslowkey_DestroyPrivateKey(privKey
);
677 if (rv
!= SECSuccess
) return crv
;
683 #define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
684 #define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
686 * Secret keys must have a CKA_ID value to be stored in the database. This code
687 * will generate one if there wasn't one already.
690 lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle
*handle
, SECItem
*id
, char *label
)
692 unsigned int retries
;
693 SECStatus rv
= SECSuccess
;
698 id
->data
= (unsigned char *)PORT_Strdup(label
);
699 if (id
->data
== NULL
) {
700 return CKR_HOST_MEMORY
;
702 id
->len
= PORT_Strlen(label
)+1;
703 if (!nsslowkey_KeyForIDExists(handle
,id
)) {
710 id
->data
= (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE
);
711 if (id
->data
== NULL
) {
712 return CKR_HOST_MEMORY
;
714 id
->len
= LG_KEY_ID_SIZE
;
718 rv
= RNG_GenerateGlobalRandomBytes(id
->data
,id
->len
);
719 } while (rv
== SECSuccess
&& nsslowkey_KeyForIDExists(handle
,id
) &&
720 (++retries
<= LG_KEY_MAX_RETRIES
));
722 if ((rv
!= SECSuccess
) || (retries
> LG_KEY_MAX_RETRIES
)) {
723 crv
= CKR_DEVICE_ERROR
; /* random number generator is bad */
732 static NSSLOWKEYPrivateKey
*lg_mkSecretKeyRep(const CK_ATTRIBUTE
*templ
,
733 CK_ULONG count
, CK_KEY_TYPE key_type
,
734 SECItem
*pubkey
, SDB
*sdbpw
)
736 NSSLOWKEYPrivateKey
*privKey
= 0;
737 PLArenaPool
*arena
= 0;
739 PRUint32 keyTypeStorage
;
743 static unsigned char derZero
[1] = { 0 };
745 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
746 if (arena
== NULL
) { crv
= CKR_HOST_MEMORY
; goto loser
; }
748 privKey
= (NSSLOWKEYPrivateKey
*)
749 PORT_ArenaZAlloc(arena
,sizeof(NSSLOWKEYPrivateKey
));
750 if (privKey
== NULL
) { crv
= CKR_HOST_MEMORY
; goto loser
; }
752 privKey
->arena
= arena
;
754 /* Secret keys are represented in the database as "fake" RSA keys.
755 * The RSA key is marked as a secret key representation by setting the
756 * public exponent field to 0, which is an invalid RSA exponent.
757 * The other fields are set as follows:
758 * modulus - CKA_ID value for the secret key
759 * private exponent - CKA_VALUE (the key itself)
760 * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
761 * is used for the key.
762 * all others - set to integer 0
764 privKey
->keyType
= NSSLOWKEYRSAKey
;
766 /* The modulus is set to the key id of the symmetric key */
767 crv
= lg_Attribute2SecItem(arena
, CKA_ID
, templ
, count
,
768 &privKey
->u
.rsa
.modulus
);
769 if (crv
!= CKR_OK
) goto loser
;
771 /* The public exponent is set to 0 length to indicate a special key */
772 privKey
->u
.rsa
.publicExponent
.len
= sizeof derZero
;
773 privKey
->u
.rsa
.publicExponent
.data
= derZero
;
775 /* The private exponent is the actual key value */
776 crv
= lg_PrivAttr2SecItem(arena
, CKA_VALUE
, templ
, count
,
777 &privKey
->u
.rsa
.privateExponent
, sdbpw
);
778 if (crv
!= CKR_OK
) goto loser
;
780 /* All other fields empty - needs testing */
781 privKey
->u
.rsa
.prime1
.len
= sizeof derZero
;
782 privKey
->u
.rsa
.prime1
.data
= derZero
;
784 privKey
->u
.rsa
.prime2
.len
= sizeof derZero
;
785 privKey
->u
.rsa
.prime2
.data
= derZero
;
787 privKey
->u
.rsa
.exponent1
.len
= sizeof derZero
;
788 privKey
->u
.rsa
.exponent1
.data
= derZero
;
790 privKey
->u
.rsa
.exponent2
.len
= sizeof derZero
;
791 privKey
->u
.rsa
.exponent2
.data
= derZero
;
793 /* Coeficient set to KEY_TYPE */
794 crv
= lg_GetULongAttribute(CKA_KEY_TYPE
, templ
, count
, &keyType
);
795 if (crv
!= CKR_OK
) goto loser
;
796 /* on 64 bit platforms, we still want to store 32 bits of keyType (This is
797 * safe since the PKCS #11 defines for all types are 32 bits or less). */
798 keyTypeStorage
= (PRUint32
) keyType
;
799 keyTypeStorage
= PR_htonl(keyTypeStorage
);
800 keyTypeItem
.data
= (unsigned char *)&keyTypeStorage
;
801 keyTypeItem
.len
= sizeof (keyTypeStorage
);
802 rv
= SECITEM_CopyItem(arena
, &privKey
->u
.rsa
.coefficient
, &keyTypeItem
);
803 if (rv
!= SECSuccess
) {
804 crv
= CKR_HOST_MEMORY
;
808 /* Private key version field set normally for compatibility */
809 rv
= DER_SetUInteger(privKey
->arena
,
810 &privKey
->u
.rsa
.version
, NSSLOWKEY_VERSION
);
811 if (rv
!= SECSuccess
) { crv
= CKR_HOST_MEMORY
; goto loser
; }
815 PORT_FreeArena(arena
,PR_FALSE
);
823 * check the consistancy and initialize a Secret Key Object
826 lg_createSecretKeyObject(SDB
*sdb
, CK_KEY_TYPE key_type
,
827 CK_OBJECT_HANDLE
*handle
, const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
830 NSSLOWKEYPrivateKey
*privKey
= NULL
;
831 NSSLOWKEYDBHandle
*keyHandle
= NULL
;
834 SECStatus rv
= SECSuccess
;
838 /* If the object is a TOKEN object, store in the database */
839 keyHandle
= lg_getKeyDB(sdb
);
841 if (keyHandle
== NULL
) {
842 return CKR_TOKEN_WRITE_PROTECTED
;
845 label
= lg_getString(CKA_LABEL
,templ
,count
);
847 crv
= lg_Attribute2SecItem(NULL
,CKA_ID
,templ
,count
,&pubKey
);
848 /* Should this be ID? */
849 if (crv
!= CKR_OK
) goto loser
;
851 /* if we don't have an ID, generate one */
852 if (pubKey
.len
== 0) {
854 PORT_Free(pubKey
.data
);
857 crv
= lg_GenerateSecretCKA_ID(keyHandle
, &pubKey
, label
);
858 if (crv
!= CKR_OK
) goto loser
;
861 privKey
= lg_mkSecretKeyRep(templ
, count
, key_type
, &pubKey
, sdb
);
862 if (privKey
== NULL
) {
863 crv
= CKR_HOST_MEMORY
;
867 rv
= nsslowkey_StoreKeyByPublicKey(keyHandle
,
868 privKey
, &pubKey
, label
, sdb
/*->password*/);
869 if (rv
!= SECSuccess
) {
870 crv
= CKR_DEVICE_ERROR
;
874 *handle
= lg_mkHandle(sdb
, &pubKey
, LG_TOKEN_TYPE_KEY
);
877 if (label
) PORT_Free(label
);
878 if (privKey
) nsslowkey_DestroyPrivateKey(privKey
);
879 if (pubKey
.data
) PORT_Free(pubKey
.data
);
885 * check the consistancy and initialize a Key Object
888 lg_createKeyObject(SDB
*sdb
, CK_OBJECT_CLASS objclass
,
889 CK_OBJECT_HANDLE
*handle
, const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
892 CK_KEY_TYPE key_type
;
894 /* get the key type */
895 crv
= lg_GetULongAttribute(CKA_KEY_TYPE
, templ
, count
, &key_type
);
902 return lg_createPublicKeyObject(sdb
,key_type
,handle
,templ
,count
);
903 case CKO_PRIVATE_KEY
:
904 return lg_createPrivateKeyObject(sdb
,key_type
,handle
,templ
,count
);
906 return lg_createSecretKeyObject(sdb
,key_type
,handle
,templ
,count
);
910 return CKR_ATTRIBUTE_VALUE_INVALID
;
914 * Parse the template and create an object stored in the DB that reflects.
915 * the object specified in the database.
918 lg_CreateObject(SDB
*sdb
, CK_OBJECT_HANDLE
*handle
,
919 const CK_ATTRIBUTE
*templ
, CK_ULONG count
)
922 CK_OBJECT_CLASS objclass
;
924 /* get the object class */
925 crv
= lg_GetULongAttribute(CKA_CLASS
, templ
, count
, &objclass
);
930 /* Now handle the specific object class.
933 case CKO_CERTIFICATE
:
934 crv
= lg_createCertObject(sdb
,handle
,templ
,count
);
936 case CKO_NETSCAPE_TRUST
:
937 crv
= lg_createTrustObject(sdb
,handle
,templ
,count
);
939 case CKO_NETSCAPE_CRL
:
940 crv
= lg_createCrlObject(sdb
,handle
,templ
,count
);
942 case CKO_NETSCAPE_SMIME
:
943 crv
= lg_createSMimeObject(sdb
,handle
,templ
,count
);
945 case CKO_PRIVATE_KEY
:
948 crv
= lg_createKeyObject(sdb
,objclass
,handle
,templ
,count
);
951 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;