Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / softoken / legacydb / lgcreate.c
blob1dd1b2709f3c87194062eb951d736b006bdfc0b9
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
12 * License.
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.
21 * Contributor(s):
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 ***** */
37 #include "secitem.h"
38 #include "pkcs11.h"
39 #include "lgdb.h"
40 #include "pcert.h"
41 #include "lowkeyi.h"
42 #include "blapi.h"
43 #include "secder.h"
45 #include "keydbi.h"
48 * ******************** Object Creation Utilities ***************************
52 * check the consistancy and initialize a Certificate Object
54 static CK_RV
55 lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
56 const CK_ATTRIBUTE *templ, CK_ULONG count)
58 SECItem derCert;
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 };
66 char *label = NULL;
67 char *email = NULL;
68 SECStatus rv;
69 CK_RV crv;
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);
83 if (crv != CKR_OK) {
84 return crv;
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);
100 if (!attribute) {
101 return CKR_ATTRIBUTE_VALUE_INVALID;
104 derCert.type = 0;
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);
111 if (cert == NULL) {
112 cert = nsslowcert_DecodeDERCertificate(&derCert, label);
113 inDB = PR_FALSE;
115 if (cert == NULL) {
116 if (label) PORT_Free(label);
117 return CKR_ATTRIBUTE_VALUE_INVALID;
120 keyHandle = lg_getKeyDB(sdb);
121 if (keyHandle) {
122 if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
123 trust = &userTrust;
127 if (!inDB) {
128 if (!trust) trust = &defTrust;
129 rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
130 } else {
131 rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
132 SECSuccess;
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);
146 if (email) {
147 certDBEntrySMime *entry;
149 entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
150 if (!entry) {
151 nsslowcert_SaveSMimeProfile(certHandle, email,
152 &cert->derSubject, NULL, NULL);
153 } else {
154 nsslowcert_DestroyDBEntry((certDBEntry *)entry);
156 PORT_Free(email);
158 *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
159 nsslowcert_DestroyCertificate(cert);
161 return CKR_OK;
164 unsigned int
165 lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
167 unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
168 CERTDB_TRUSTED_CA;
169 switch (trust) {
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:
177 return 0;
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;
182 default:
183 break;
185 return CERTDB_TRUSTED_UNKNOWN;
190 * check the consistancy and initialize a Trust Object
192 static CK_RV
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;
204 CK_BBOOL stepUp;
205 NSSLOWCERTCertTrust dbTrust = { 0 };
206 SECStatus rv;
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);
232 if (cert == NULL) {
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);
240 stepUp = CK_FALSE;
241 trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
242 if (trust) {
243 if (trust->ulValueLen == sizeof(CK_BBOOL)) {
244 stepUp = *(CK_BBOOL*)trust->pValue;
248 /* preserve certain old fields */
249 if (cert->trust) {
250 dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
251 dbTrust.emailFlags=
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);
261 if (stepUp) {
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;
272 return CKR_OK;
276 * check the consistancy and initialize a Trust Object
278 static CK_RV
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;
285 char *email = NULL;
286 const CK_ATTRIBUTE *subject = NULL,
287 *profile = NULL,
288 *time = NULL;
289 SECStatus rv;
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;
303 /* lookup SUBJECT */
304 subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
305 PORT_Assert(subject);
306 if (!subject) {
307 ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
308 goto loser;
311 derSubj.data = (unsigned char *)subject->pValue;
312 derSubj.len = subject->ulValueLen ;
313 derSubj.type = 0;
315 /* lookup VALUE */
316 profile = lg_FindAttribute(CKA_VALUE,templ,count);
317 if (profile) {
318 rawProfile.data = (unsigned char *)profile->pValue;
319 rawProfile.len = profile->ulValueLen ;
320 rawProfile.type = siBuffer;
321 pRawProfile = &rawProfile;
324 /* lookup Time */
325 time = lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP,templ,count);
326 if (time) {
327 rawTime.data = (unsigned char *)time->pValue;
328 rawTime.len = time->ulValueLen ;
329 rawTime.type = siBuffer;
330 pRawTime = &rawTime;
334 email = lg_getString(CKA_NETSCAPE_EMAIL,templ,count);
335 if (!email) {
336 ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
337 goto loser;
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;
345 goto loser;
347 emailKey.data = (unsigned char *)email;
348 emailKey.len = PORT_Strlen(email)+1;
350 *handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
352 loser:
353 if (email) PORT_Free(email);
355 return ck_rv;
359 * check the consistancy and initialize a Trust Object
361 static CK_RV
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;
367 char *url = NULL;
368 const CK_ATTRIBUTE *subject,*crl;
369 SECStatus rv;
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;
383 /* lookup SUBJECT */
384 subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
385 if (!subject) {
386 return CKR_ATTRIBUTE_VALUE_INVALID;
389 derSubj.data = (unsigned char *)subject->pValue;
390 derSubj.len = subject->ulValueLen ;
392 /* lookup VALUE */
393 crl = lg_FindAttribute(CKA_VALUE,templ,count);
394 PORT_Assert(crl);
395 if (!crl) {
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);
407 if (url) {
408 PORT_Free(url);
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);
421 return CKR_OK;
425 * check the consistancy and initialize a Public Key Object
427 static CK_RV
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;
432 CK_RV crv;
433 NSSLOWKEYPrivateKey *priv;
434 SECItem pubKey;
435 NSSLOWKEYDBHandle *keyHandle = NULL;
437 switch (key_type) {
438 case CKK_RSA:
439 pubKeyAttr = CKA_MODULUS;
440 break;
441 #ifdef NSS_ENABLE_ECC
442 case CKK_EC:
443 pubKeyAttr = CKA_EC_POINT;
444 break;
445 #endif /* NSS_ENABLE_ECC */
446 case CKK_DSA:
447 case CKK_DH:
448 break;
449 default:
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*/);
472 if (priv == NULL) {
473 PORT_Free(pubKey.data);
474 return crv;
476 nsslowkey_DestroyPrivateKey(priv);
478 *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PUB);
479 PORT_Free(pubKey.data);
481 return CKR_OK;
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;
490 PLArenaPool *arena;
491 CK_RV crv = CKR_OK;
492 SECStatus rv;
494 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
495 if (arena == NULL) {
496 *crvp = CKR_HOST_MEMORY;
497 return NULL;
500 privKey = (NSSLOWKEYPrivateKey *)
501 PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
502 if (privKey == NULL) {
503 PORT_FreeArena(arena,PR_FALSE);
504 *crvp = CKR_HOST_MEMORY;
505 return NULL;
508 /* in future this would be a switch on key_type */
509 privKey->arena = arena;
510 switch (key_type) {
511 case CKK_RSA:
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,
538 NSSLOWKEY_VERSION);
539 if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
540 break;
542 case CKK_DSA:
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 */
562 break;
564 case CKK_DH:
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 */
581 break;
583 #ifdef NSS_ENABLE_ECC
584 case CKK_EC:
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;
596 break;
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;
611 break;
612 #endif /* NSS_ENABLE_ECC */
614 default:
615 crv = CKR_KEY_TYPE_INCONSISTENT;
616 break;
618 *crvp = crv;
619 if (crv != CKR_OK) {
620 PORT_FreeArena(arena,PR_FALSE);
621 return NULL;
623 return privKey;
627 * check the consistancy and initialize a Private Key Object
629 static CK_RV
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;
634 char *label;
635 SECStatus rv = SECSuccess;
636 CK_RV crv = CKR_DEVICE_ERROR;
637 SECItem pubKey;
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);
649 if (crv != CKR_OK) {
650 crv = CKR_TEMPLATE_INCOMPLETE;
651 rv = SECFailure;
652 goto fail;
654 #ifdef notdef
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);
661 #endif
662 /* get the key type */
663 if (key_type == CKK_RSA) {
664 rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
665 if (rv == SECFailure) {
666 goto fail;
669 rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
670 label, sdb /*->password*/);
672 fail:
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;
679 return CKR_OK;
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.
689 static CK_RV
690 lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
692 unsigned int retries;
693 SECStatus rv = SECSuccess;
694 CK_RV crv = CKR_OK;
696 id->data = NULL;
697 if (label) {
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)) {
704 return CKR_OK;
706 PORT_Free(id->data);
707 id->data = NULL;
708 id->len = 0;
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;
716 retries = 0;
717 do {
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 */
724 PORT_Free(id->data);
725 id->data = NULL;
726 id->len = 0;
728 return crv;
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;
738 CK_KEY_TYPE keyType;
739 PRUint32 keyTypeStorage;
740 SECItem keyTypeItem;
741 CK_RV crv;
742 SECStatus rv;
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;
805 goto loser;
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; }
813 loser:
814 if (crv != CKR_OK) {
815 PORT_FreeArena(arena,PR_FALSE);
816 privKey = 0;
819 return privKey;
823 * check the consistancy and initialize a Secret Key Object
825 static CK_RV
826 lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
827 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
829 CK_RV crv;
830 NSSLOWKEYPrivateKey *privKey = NULL;
831 NSSLOWKEYDBHandle *keyHandle = NULL;
832 SECItem pubKey;
833 char *label = NULL;
834 SECStatus rv = SECSuccess;
836 pubKey.data = 0;
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) {
853 if (pubKey.data) {
854 PORT_Free(pubKey.data);
855 pubKey.data = NULL;
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;
864 goto loser;
867 rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
868 privKey, &pubKey, label, sdb /*->password*/);
869 if (rv != SECSuccess) {
870 crv = CKR_DEVICE_ERROR;
871 goto loser;
874 *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
876 loser:
877 if (label) PORT_Free(label);
878 if (privKey) nsslowkey_DestroyPrivateKey(privKey);
879 if (pubKey.data) PORT_Free(pubKey.data);
881 return crv;
885 * check the consistancy and initialize a Key Object
887 static CK_RV
888 lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
889 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
891 CK_RV crv;
892 CK_KEY_TYPE key_type;
894 /* get the key type */
895 crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
896 if (crv != CKR_OK) {
897 return crv;
900 switch (objclass) {
901 case CKO_PUBLIC_KEY:
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);
905 case CKO_SECRET_KEY:
906 return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
907 default:
908 break;
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.
917 CK_RV
918 lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
919 const CK_ATTRIBUTE *templ, CK_ULONG count)
921 CK_RV crv;
922 CK_OBJECT_CLASS objclass;
924 /* get the object class */
925 crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
926 if (crv != CKR_OK) {
927 return crv;
930 /* Now handle the specific object class.
932 switch (objclass) {
933 case CKO_CERTIFICATE:
934 crv = lg_createCertObject(sdb,handle,templ,count);
935 break;
936 case CKO_NETSCAPE_TRUST:
937 crv = lg_createTrustObject(sdb,handle,templ,count);
938 break;
939 case CKO_NETSCAPE_CRL:
940 crv = lg_createCrlObject(sdb,handle,templ,count);
941 break;
942 case CKO_NETSCAPE_SMIME:
943 crv = lg_createSMimeObject(sdb,handle,templ,count);
944 break;
945 case CKO_PRIVATE_KEY:
946 case CKO_PUBLIC_KEY:
947 case CKO_SECRET_KEY:
948 crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
949 break;
950 default:
951 crv = CKR_ATTRIBUTE_VALUE_INVALID;
952 break;
955 return crv;