comparison nss/lib/softoken/legacydb/lgcreate.c @ 3:150b72113545

Add DBM and legacydb support
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 05 Aug 2014 18:32:02 +0200
parents
children
comparison
equal deleted inserted replaced
2:a945361df361 3:150b72113545
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 "secitem.h"
5 #include "pkcs11.h"
6 #include "lgdb.h"
7 #include "pcert.h"
8 #include "lowkeyi.h"
9 #include "blapi.h"
10 #include "secder.h"
11 #include "secasn1.h"
12
13 #include "keydbi.h"
14
15 /*
16 * ******************** Object Creation Utilities ***************************
17 */
18
19 /*
20 * check the consistancy and initialize a Certificate Object
21 */
22 static CK_RV
23 lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
24 const CK_ATTRIBUTE *templ, CK_ULONG count)
25 {
26 SECItem derCert;
27 NSSLOWCERTCertificate *cert;
28 NSSLOWCERTCertTrust *trust = NULL;
29 NSSLOWCERTCertTrust userTrust =
30 { CERTDB_USER, CERTDB_USER, CERTDB_USER };
31 NSSLOWCERTCertTrust defTrust =
32 { CERTDB_TRUSTED_UNKNOWN,
33 CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
34 char *label = NULL;
35 char *email = NULL;
36 SECStatus rv;
37 CK_RV crv;
38 PRBool inDB = PR_TRUE;
39 NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
40 NSSLOWKEYDBHandle *keyHandle = NULL;
41 CK_CERTIFICATE_TYPE type;
42 const CK_ATTRIBUTE *attribute;
43
44 /* we can't store any certs private */
45 if (lg_isTrue(CKA_PRIVATE, templ, count)) {
46 return CKR_ATTRIBUTE_VALUE_INVALID;
47 }
48
49 /* We only support X.509 Certs for now */
50 crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE, templ, count, &type);
51 if (crv != CKR_OK) {
52 return crv;
53 }
54
55 if (type != CKC_X_509) {
56 return CKR_ATTRIBUTE_VALUE_INVALID;
57 }
58
59 /* X.509 Certificate */
60
61
62 if (certHandle == NULL) {
63 return CKR_TOKEN_WRITE_PROTECTED;
64 }
65
66 /* get the der cert */
67 attribute = lg_FindAttribute(CKA_VALUE, templ, count);
68 if (!attribute) {
69 return CKR_ATTRIBUTE_VALUE_INVALID;
70 }
71
72 derCert.type = 0;
73 derCert.data = (unsigned char *)attribute->pValue;
74 derCert.len = attribute->ulValueLen ;
75
76 label = lg_getString(CKA_LABEL, templ, count);
77
78 cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
79 if (cert == NULL) {
80 cert = nsslowcert_DecodeDERCertificate(&derCert, label);
81 inDB = PR_FALSE;
82 }
83 if (cert == NULL) {
84 if (label) PORT_Free(label);
85 return CKR_ATTRIBUTE_VALUE_INVALID;
86 }
87
88 keyHandle = lg_getKeyDB(sdb);
89 if (keyHandle) {
90 if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
91 trust = &userTrust;
92 }
93 }
94
95 if (!inDB) {
96 if (!trust) trust = &defTrust;
97 rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
98 } else {
99 rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
100 SECSuccess;
101 }
102
103 if (label) PORT_Free(label);
104
105 if (rv != SECSuccess) {
106 nsslowcert_DestroyCertificate(cert);
107 return CKR_DEVICE_ERROR;
108 }
109
110 /*
111 * Add a NULL S/MIME profile if necessary.
112 */
113 email = lg_getString(CKA_NSS_EMAIL, templ, count);
114 if (email) {
115 certDBEntrySMime *entry;
116
117 entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
118 if (!entry) {
119 nsslowcert_SaveSMimeProfile(certHandle, email,
120 &cert->derSubject, NULL, NULL);
121 } else {
122 nsslowcert_DestroyDBEntry((certDBEntry *)entry);
123 }
124 PORT_Free(email);
125 }
126 *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
127 nsslowcert_DestroyCertificate(cert);
128
129 return CKR_OK;
130 }
131
132 unsigned int
133 lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
134 {
135 unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
136 CERTDB_TRUSTED_CA;
137 switch (trust) {
138 case CKT_NSS_TRUSTED:
139 return CERTDB_TERMINAL_RECORD|CERTDB_TRUSTED;
140 case CKT_NSS_TRUSTED_DELEGATOR:
141 return CERTDB_VALID_CA|trustCA;
142 case CKT_NSS_MUST_VERIFY_TRUST:
143 return CERTDB_MUST_VERIFY;
144 case CKT_NSS_NOT_TRUSTED:
145 return CERTDB_TERMINAL_RECORD;
146 case CKT_NSS_VALID_DELEGATOR: /* implies must verify */
147 return CERTDB_VALID_CA;
148 default:
149 break;
150 }
151 return CERTDB_TRUSTED_UNKNOWN;
152 }
153
154
155 /*
156 * check the consistancy and initialize a Trust Object
157 */
158 static CK_RV
159 lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
160 const CK_ATTRIBUTE *templ, CK_ULONG count)
161 {
162 const CK_ATTRIBUTE *issuer = NULL;
163 const CK_ATTRIBUTE *serial = NULL;
164 NSSLOWCERTCertificate *cert = NULL;
165 const CK_ATTRIBUTE *trust;
166 CK_TRUST sslTrust = CKT_NSS_TRUST_UNKNOWN;
167 CK_TRUST clientTrust = CKT_NSS_TRUST_UNKNOWN;
168 CK_TRUST emailTrust = CKT_NSS_TRUST_UNKNOWN;
169 CK_TRUST signTrust = CKT_NSS_TRUST_UNKNOWN;
170 CK_BBOOL stepUp;
171 NSSLOWCERTCertTrust dbTrust = { 0 };
172 SECStatus rv;
173 NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
174 NSSLOWCERTIssuerAndSN issuerSN;
175
176 /* we can't store any certs private */
177 if (lg_isTrue(CKA_PRIVATE, templ, count)) {
178 return CKR_ATTRIBUTE_VALUE_INVALID;
179 }
180
181 if (certHandle == NULL) {
182 return CKR_TOKEN_WRITE_PROTECTED;
183 }
184
185 issuer = lg_FindAttribute(CKA_ISSUER, templ, count);
186 serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count);
187
188 if (issuer && serial) {
189 issuerSN.derIssuer.data = (unsigned char *)issuer->pValue;
190 issuerSN.derIssuer.len = issuer->ulValueLen ;
191
192 issuerSN.serialNumber.data = (unsigned char *)serial->pValue;
193 issuerSN.serialNumber.len = serial->ulValueLen ;
194
195 cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
196 }
197
198 if (cert == NULL) {
199 return CKR_ATTRIBUTE_VALUE_INVALID;
200 }
201
202 lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust);
203 lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust);
204 lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust);
205 lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust);
206 stepUp = CK_FALSE;
207 trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
208 if (trust) {
209 if (trust->ulValueLen == sizeof(CK_BBOOL)) {
210 stepUp = *(CK_BBOOL*)trust->pValue;
211 }
212 }
213
214 /* preserve certain old fields */
215 if (cert->trust) {
216 dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
217 dbTrust.emailFlags=
218 cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
219 dbTrust.objectSigningFlags =
220 cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
221 }
222
223 dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE);
224 dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE);
225 dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE);
226 dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE);
227 if (stepUp) {
228 dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
229 }
230
231 rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
232 *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST);
233 nsslowcert_DestroyCertificate(cert);
234 if (rv != SECSuccess) {
235 return CKR_DEVICE_ERROR;
236 }
237
238 return CKR_OK;
239 }
240
241 /*
242 * check the consistancy and initialize a Trust Object
243 */
244 static CK_RV
245 lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
246 const CK_ATTRIBUTE *templ, CK_ULONG count)
247 {
248 SECItem derSubj,rawProfile,rawTime,emailKey;
249 SECItem *pRawProfile = NULL;
250 SECItem *pRawTime = NULL;
251 char *email = NULL;
252 const CK_ATTRIBUTE *subject = NULL,
253 *profile = NULL,
254 *time = NULL;
255 SECStatus rv;
256 NSSLOWCERTCertDBHandle *certHandle;
257 CK_RV ck_rv = CKR_OK;
258
259 /* we can't store any certs private */
260 if (lg_isTrue(CKA_PRIVATE,templ,count)) {
261 return CKR_ATTRIBUTE_VALUE_INVALID;
262 }
263
264 certHandle = lg_getCertDB(sdb);
265 if (certHandle == NULL) {
266 return CKR_TOKEN_WRITE_PROTECTED;
267 }
268
269 /* lookup SUBJECT */
270 subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
271 PORT_Assert(subject);
272 if (!subject) {
273 ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
274 goto loser;
275 }
276
277 derSubj.data = (unsigned char *)subject->pValue;
278 derSubj.len = subject->ulValueLen ;
279 derSubj.type = 0;
280
281 /* lookup VALUE */
282 profile = lg_FindAttribute(CKA_VALUE,templ,count);
283 if (profile) {
284 rawProfile.data = (unsigned char *)profile->pValue;
285 rawProfile.len = profile->ulValueLen ;
286 rawProfile.type = siBuffer;
287 pRawProfile = &rawProfile;
288 }
289
290 /* lookup Time */
291 time = lg_FindAttribute(CKA_NSS_SMIME_TIMESTAMP,templ,count);
292 if (time) {
293 rawTime.data = (unsigned char *)time->pValue;
294 rawTime.len = time->ulValueLen ;
295 rawTime.type = siBuffer;
296 pRawTime = &rawTime;
297 }
298
299
300 email = lg_getString(CKA_NSS_EMAIL,templ,count);
301 if (!email) {
302 ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
303 goto loser;
304 }
305
306 /* Store S/MIME Profile by SUBJECT */
307 rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
308 pRawProfile,pRawTime);
309 if (rv != SECSuccess) {
310 ck_rv = CKR_DEVICE_ERROR;
311 goto loser;
312 }
313 emailKey.data = (unsigned char *)email;
314 emailKey.len = PORT_Strlen(email)+1;
315
316 *handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
317
318 loser:
319 if (email) PORT_Free(email);
320
321 return ck_rv;
322 }
323
324 /*
325 * check the consistancy and initialize a Trust Object
326 */
327 static CK_RV
328 lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
329 const CK_ATTRIBUTE *templ, CK_ULONG count)
330 {
331 PRBool isKRL = PR_FALSE;
332 SECItem derSubj,derCrl;
333 char *url = NULL;
334 const CK_ATTRIBUTE *subject,*crl;
335 SECStatus rv;
336 NSSLOWCERTCertDBHandle *certHandle;
337
338 certHandle = lg_getCertDB(sdb);
339
340 /* we can't store any private crls */
341 if (lg_isTrue(CKA_PRIVATE,templ,count)) {
342 return CKR_ATTRIBUTE_VALUE_INVALID;
343 }
344
345 if (certHandle == NULL) {
346 return CKR_TOKEN_WRITE_PROTECTED;
347 }
348
349 /* lookup SUBJECT */
350 subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
351 if (!subject) {
352 return CKR_ATTRIBUTE_VALUE_INVALID;
353 }
354
355 derSubj.data = (unsigned char *)subject->pValue;
356 derSubj.len = subject->ulValueLen ;
357
358 /* lookup VALUE */
359 crl = lg_FindAttribute(CKA_VALUE,templ,count);
360 PORT_Assert(crl);
361 if (!crl) {
362 return CKR_ATTRIBUTE_VALUE_INVALID;
363 }
364 derCrl.data = (unsigned char *)crl->pValue;
365 derCrl.len = crl->ulValueLen ;
366
367 url = lg_getString(CKA_NSS_URL,templ,count);
368 isKRL = lg_isTrue(CKA_NSS_KRL,templ,count);
369
370 /* Store CRL by SUBJECT */
371 rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
372
373 if (url) {
374 PORT_Free(url);
375 }
376 if (rv != SECSuccess) {
377 return CKR_DEVICE_ERROR;
378 }
379
380 /* if we overwrote the existing CRL, poison the handle entry so we get
381 * a new object handle */
382 (void) lg_poisonHandle(sdb, &derSubj,
383 isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
384 *handle = lg_mkHandle(sdb, &derSubj,
385 isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
386
387 return CKR_OK;
388 }
389
390 /*
391 * check the consistancy and initialize a Public Key Object
392 */
393 static CK_RV
394 lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
395 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
396 {
397 CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
398 CK_RV crv = CKR_OK;
399 NSSLOWKEYPrivateKey *priv;
400 SECItem pubKeySpace = {siBuffer, NULL, 0};
401 SECItem *pubKey;
402 #ifndef NSS_DISABLE_ECC
403 SECItem pubKey2Space = {siBuffer, NULL, 0};
404 PLArenaPool *arena = NULL;
405 #endif /* NSS_DISABLE_ECC */
406 NSSLOWKEYDBHandle *keyHandle = NULL;
407
408
409 switch (key_type) {
410 case CKK_RSA:
411 pubKeyAttr = CKA_MODULUS;
412 break;
413 #ifndef NSS_DISABLE_ECC
414 case CKK_EC:
415 pubKeyAttr = CKA_EC_POINT;
416 break;
417 #endif /* NSS_DISABLE_ECC */
418 case CKK_DSA:
419 case CKK_DH:
420 break;
421 default:
422 return CKR_ATTRIBUTE_VALUE_INVALID;
423 }
424
425
426 pubKey = &pubKeySpace;
427 crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,pubKey);
428 if (crv != CKR_OK) return crv;
429
430 #ifndef NSS_DISABLE_ECC
431 if (key_type == CKK_EC) {
432 SECStatus rv;
433 /*
434 * for ECC, use the decoded key first.
435 */
436 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
437 if (arena == NULL) {
438 crv = CKR_HOST_MEMORY;
439 goto done;
440 }
441 rv= SEC_QuickDERDecodeItem(arena, &pubKey2Space,
442 SEC_ASN1_GET(SEC_OctetStringTemplate),
443 pubKey);
444 if (rv != SECSuccess) {
445 /* decode didn't work, just try the pubKey */
446 PORT_FreeArena(arena, PR_FALSE);
447 arena = NULL;
448 } else {
449 /* try the decoded pub key first */
450 pubKey = &pubKey2Space;
451 }
452 }
453 #endif /* NSS_DISABLE_ECC */
454
455 PORT_Assert(pubKey->data);
456 if (pubKey->data == NULL) {
457 crv = CKR_ATTRIBUTE_VALUE_INVALID;
458 goto done;
459 }
460 keyHandle = lg_getKeyDB(sdb);
461 if (keyHandle == NULL) {
462 crv = CKR_TOKEN_WRITE_PROTECTED;
463 goto done;
464 }
465 if (keyHandle->version != 3) {
466 unsigned char buf[SHA1_LENGTH];
467 SHA1_HashBuf(buf,pubKey->data,pubKey->len);
468 PORT_Memcpy(pubKey->data,buf,sizeof(buf));
469 pubKey->len = sizeof(buf);
470 }
471 /* make sure the associated private key already exists */
472 /* only works if we are logged in */
473 priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/);
474 #ifndef NSS_DISABLE_ECC
475 if (priv == NULL && pubKey == &pubKey2Space) {
476 /* no match on the decoded key, match the original pubkey */
477 pubKey = &pubKeySpace;
478 priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey,
479 sdb /*password*/);
480 }
481 #endif
482 if (priv == NULL) {
483 /* the legacy database can only 'store' public keys which already
484 * have their corresponding private keys in the database */
485 crv = CKR_ATTRIBUTE_VALUE_INVALID;
486 goto done;
487 }
488 lg_nsslowkey_DestroyPrivateKey(priv);
489 crv = CKR_OK;
490
491 *handle = lg_mkHandle(sdb, pubKey, LG_TOKEN_TYPE_PUB);
492
493 done:
494 PORT_Free(pubKeySpace.data);
495 #ifndef NSS_DISABLE_ECC
496 if (arena)
497 PORT_FreeArena(arena, PR_FALSE);
498 #endif
499
500 return crv;
501 }
502
503 /* make a private key from a verified object */
504 static NSSLOWKEYPrivateKey *
505 lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
506 CK_KEY_TYPE key_type, CK_RV *crvp)
507 {
508 NSSLOWKEYPrivateKey *privKey;
509 PLArenaPool *arena;
510 CK_RV crv = CKR_OK;
511 SECStatus rv;
512
513 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
514 if (arena == NULL) {
515 *crvp = CKR_HOST_MEMORY;
516 return NULL;
517 }
518
519 privKey = (NSSLOWKEYPrivateKey *)
520 PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
521 if (privKey == NULL) {
522 PORT_FreeArena(arena,PR_FALSE);
523 *crvp = CKR_HOST_MEMORY;
524 return NULL;
525 }
526
527 /* in future this would be a switch on key_type */
528 privKey->arena = arena;
529 switch (key_type) {
530 case CKK_RSA:
531 privKey->keyType = NSSLOWKEYRSAKey;
532 crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count,
533 &privKey->u.rsa.modulus);
534 if (crv != CKR_OK) break;
535 crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count,
536 &privKey->u.rsa.publicExponent);
537 if (crv != CKR_OK) break;
538 crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count,
539 &privKey->u.rsa.privateExponent, sdb);
540 if (crv != CKR_OK) break;
541 crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count,
542 &privKey->u.rsa.prime1, sdb);
543 if (crv != CKR_OK) break;
544 crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count,
545 &privKey->u.rsa.prime2, sdb);
546 if (crv != CKR_OK) break;
547 crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count,
548 &privKey->u.rsa.exponent1, sdb);
549 if (crv != CKR_OK) break;
550 crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count,
551 &privKey->u.rsa.exponent2, sdb);
552 if (crv != CKR_OK) break;
553 crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count,
554 &privKey->u.rsa.coefficient, sdb);
555 if (crv != CKR_OK) break;
556 rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
557 NSSLOWKEY_VERSION);
558 if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
559 break;
560
561 case CKK_DSA:
562 privKey->keyType = NSSLOWKEYDSAKey;
563 crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
564 &privKey->u.dsa.params.prime);
565 if (crv != CKR_OK) break;
566 crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count,
567 &privKey->u.dsa.params.subPrime);
568 if (crv != CKR_OK) break;
569 crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
570 &privKey->u.dsa.params.base);
571 if (crv != CKR_OK) break;
572 crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
573 &privKey->u.dsa.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.dsa.publicValue);
578 /* privKey was zero'd so public value is already set to NULL, 0
579 * if we don't set it explicitly */
580 }
581 break;
582
583 case CKK_DH:
584 privKey->keyType = NSSLOWKEYDHKey;
585 crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
586 &privKey->u.dh.prime);
587 if (crv != CKR_OK) break;
588 crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
589 &privKey->u.dh.base);
590 if (crv != CKR_OK) break;
591 crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
592 &privKey->u.dh.privateValue, sdb);
593 if (crv != CKR_OK) break;
594 if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
595 crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
596 &privKey->u.dh.publicValue);
597 /* privKey was zero'd so public value is already set to NULL, 0
598 * if we don't set it explicitly */
599 }
600 break;
601
602 #ifndef NSS_DISABLE_ECC
603 case CKK_EC:
604 privKey->keyType = NSSLOWKEYECKey;
605 crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count,
606 &privKey->u.ec.ecParams.DEREncoding);
607 if (crv != CKR_OK) break;
608
609 /* Fill out the rest of the ecParams structure
610 * based on the encoded params
611 */
612 if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
613 &privKey->u.ec.ecParams) != SECSuccess) {
614 crv = CKR_DOMAIN_PARAMS_INVALID;
615 break;
616 }
617 crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
618 &privKey->u.ec.privateValue, sdb);
619 if (crv != CKR_OK) break;
620 if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) {
621 crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
622 &privKey->u.ec.publicValue);
623 if (crv != CKR_OK) break;
624 /* privKey was zero'd so public value is already set to NULL, 0
625 * if we don't set it explicitly */
626 }
627 rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
628 NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
629 if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
630 break;
631 #endif /* NSS_DISABLE_ECC */
632
633 default:
634 crv = CKR_KEY_TYPE_INCONSISTENT;
635 break;
636 }
637 *crvp = crv;
638 if (crv != CKR_OK) {
639 PORT_FreeArena(arena,PR_FALSE);
640 return NULL;
641 }
642 return privKey;
643 }
644
645 /*
646 * check the consistancy and initialize a Private Key Object
647 */
648 static CK_RV
649 lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
650 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
651 {
652 NSSLOWKEYPrivateKey *privKey;
653 char *label;
654 SECStatus rv = SECSuccess;
655 CK_RV crv = CKR_DEVICE_ERROR;
656 SECItem pubKey;
657 NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb);
658
659 if (keyHandle == NULL) {
660 return CKR_TOKEN_WRITE_PROTECTED;
661 }
662
663 privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv);
664 if (privKey == NULL) return crv;
665 label = lg_getString(CKA_LABEL,templ,count);
666
667 crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey);
668 if (crv != CKR_OK) {
669 crv = CKR_TEMPLATE_INCOMPLETE;
670 rv = SECFailure;
671 goto fail;
672 }
673 #ifdef notdef
674 if (keyHandle->version != 3) {
675 unsigned char buf[SHA1_LENGTH];
676 SHA1_HashBuf(buf,pubKey.data,pubKey.len);
677 PORT_Memcpy(pubKey.data,buf,sizeof(buf));
678 pubKey.len = sizeof(buf);
679 }
680 #endif
681 /* get the key type */
682 if (key_type == CKK_RSA) {
683 rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
684 if (rv == SECFailure) {
685 goto fail;
686 }
687 }
688 rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
689 label, sdb /*->password*/);
690
691 fail:
692 if (label) PORT_Free(label);
693 *handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV);
694 if (pubKey.data) PORT_Free(pubKey.data);
695 lg_nsslowkey_DestroyPrivateKey(privKey);
696 if (rv != SECSuccess) return crv;
697
698 return CKR_OK;
699 }
700
701
702 #define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
703 #define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
704 /*
705 * Secret keys must have a CKA_ID value to be stored in the database. This code
706 * will generate one if there wasn't one already.
707 */
708 static CK_RV
709 lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
710 {
711 unsigned int retries;
712 SECStatus rv = SECSuccess;
713 CK_RV crv = CKR_OK;
714
715 id->data = NULL;
716 if (label) {
717 id->data = (unsigned char *)PORT_Strdup(label);
718 if (id->data == NULL) {
719 return CKR_HOST_MEMORY;
720 }
721 id->len = PORT_Strlen(label)+1;
722 if (!nsslowkey_KeyForIDExists(handle,id)) {
723 return CKR_OK;
724 }
725 PORT_Free(id->data);
726 id->data = NULL;
727 id->len = 0;
728 }
729 id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE);
730 if (id->data == NULL) {
731 return CKR_HOST_MEMORY;
732 }
733 id->len = LG_KEY_ID_SIZE;
734
735 retries = 0;
736 do {
737 rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
738 } while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
739 (++retries <= LG_KEY_MAX_RETRIES));
740
741 if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) {
742 crv = CKR_DEVICE_ERROR; /* random number generator is bad */
743 PORT_Free(id->data);
744 id->data = NULL;
745 id->len = 0;
746 }
747 return crv;
748 }
749
750
751 static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ,
752 CK_ULONG count, CK_KEY_TYPE key_type,
753 SECItem *pubkey, SDB *sdbpw)
754 {
755 NSSLOWKEYPrivateKey *privKey = 0;
756 PLArenaPool *arena = 0;
757 CK_KEY_TYPE keyType;
758 PRUint32 keyTypeStorage;
759 SECItem keyTypeItem;
760 CK_RV crv;
761 SECStatus rv;
762 static unsigned char derZero[1] = { 0 };
763
764 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
765 if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
766
767 privKey = (NSSLOWKEYPrivateKey *)
768 PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
769 if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
770
771 privKey->arena = arena;
772
773 /* Secret keys are represented in the database as "fake" RSA keys.
774 * The RSA key is marked as a secret key representation by setting the
775 * public exponent field to 0, which is an invalid RSA exponent.
776 * The other fields are set as follows:
777 * modulus - CKA_ID value for the secret key
778 * private exponent - CKA_VALUE (the key itself)
779 * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
780 * is used for the key.
781 * all others - set to integer 0
782 */
783 privKey->keyType = NSSLOWKEYRSAKey;
784
785 /* The modulus is set to the key id of the symmetric key */
786 privKey->u.rsa.modulus.data =
787 (unsigned char *) PORT_ArenaAlloc(arena, pubkey->len);
788 if (privKey->u.rsa.modulus.data == NULL) {
789 crv = CKR_HOST_MEMORY;
790 goto loser;
791 }
792 privKey->u.rsa.modulus.len = pubkey->len;
793 PORT_Memcpy(privKey->u.rsa.modulus.data, pubkey->data, pubkey->len);
794
795 /* The public exponent is set to 0 to indicate a special key */
796 privKey->u.rsa.publicExponent.len = sizeof derZero;
797 privKey->u.rsa.publicExponent.data = derZero;
798
799 /* The private exponent is the actual key value */
800 crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count,
801 &privKey->u.rsa.privateExponent, sdbpw);
802 if (crv != CKR_OK) goto loser;
803
804 /* All other fields empty - needs testing */
805 privKey->u.rsa.prime1.len = sizeof derZero;
806 privKey->u.rsa.prime1.data = derZero;
807
808 privKey->u.rsa.prime2.len = sizeof derZero;
809 privKey->u.rsa.prime2.data = derZero;
810
811 privKey->u.rsa.exponent1.len = sizeof derZero;
812 privKey->u.rsa.exponent1.data = derZero;
813
814 privKey->u.rsa.exponent2.len = sizeof derZero;
815 privKey->u.rsa.exponent2.data = derZero;
816
817 /* Coeficient set to KEY_TYPE */
818 crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType);
819 if (crv != CKR_OK) goto loser;
820 /* on 64 bit platforms, we still want to store 32 bits of keyType (This is
821 * safe since the PKCS #11 defines for all types are 32 bits or less). */
822 keyTypeStorage = (PRUint32) keyType;
823 keyTypeStorage = PR_htonl(keyTypeStorage);
824 keyTypeItem.data = (unsigned char *)&keyTypeStorage;
825 keyTypeItem.len = sizeof (keyTypeStorage);
826 rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
827 if (rv != SECSuccess) {
828 crv = CKR_HOST_MEMORY;
829 goto loser;
830 }
831
832 /* Private key version field set normally for compatibility */
833 rv = DER_SetUInteger(privKey->arena,
834 &privKey->u.rsa.version, NSSLOWKEY_VERSION);
835 if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
836
837 loser:
838 if (crv != CKR_OK) {
839 PORT_FreeArena(arena,PR_FALSE);
840 privKey = 0;
841 }
842
843 return privKey;
844 }
845
846 /*
847 * check the consistancy and initialize a Secret Key Object
848 */
849 static CK_RV
850 lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
851 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
852 {
853 CK_RV crv;
854 NSSLOWKEYPrivateKey *privKey = NULL;
855 NSSLOWKEYDBHandle *keyHandle = NULL;
856 SECItem pubKey;
857 char *label = NULL;
858 SECStatus rv = SECSuccess;
859
860 pubKey.data = 0;
861
862 /* If the object is a TOKEN object, store in the database */
863 keyHandle = lg_getKeyDB(sdb);
864
865 if (keyHandle == NULL) {
866 return CKR_TOKEN_WRITE_PROTECTED;
867 }
868
869 label = lg_getString(CKA_LABEL,templ,count);
870
871 crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey);
872 /* Should this be ID? */
873 if (crv != CKR_OK) goto loser;
874
875 /* if we don't have an ID, generate one */
876 if (pubKey.len == 0) {
877 if (pubKey.data) {
878 PORT_Free(pubKey.data);
879 pubKey.data = NULL;
880 }
881 crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
882 if (crv != CKR_OK) goto loser;
883 }
884
885 privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb);
886 if (privKey == NULL) {
887 crv = CKR_HOST_MEMORY;
888 goto loser;
889 }
890
891 rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
892 privKey, &pubKey, label, sdb /*->password*/);
893 if (rv != SECSuccess) {
894 crv = CKR_DEVICE_ERROR;
895 goto loser;
896 }
897
898 *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
899
900 loser:
901 if (label) PORT_Free(label);
902 if (privKey) lg_nsslowkey_DestroyPrivateKey(privKey);
903 if (pubKey.data) PORT_Free(pubKey.data);
904
905 return crv;
906 }
907
908 /*
909 * check the consistancy and initialize a Key Object
910 */
911 static CK_RV
912 lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
913 CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
914 {
915 CK_RV crv;
916 CK_KEY_TYPE key_type;
917
918 /* get the key type */
919 crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
920 if (crv != CKR_OK) {
921 return crv;
922 }
923
924 switch (objclass) {
925 case CKO_PUBLIC_KEY:
926 return lg_createPublicKeyObject(sdb,key_type,handle,templ,count);
927 case CKO_PRIVATE_KEY:
928 return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count);
929 case CKO_SECRET_KEY:
930 return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
931 default:
932 break;
933 }
934 return CKR_ATTRIBUTE_VALUE_INVALID;
935 }
936
937 /*
938 * Parse the template and create an object stored in the DB that reflects.
939 * the object specified in the database.
940 */
941 CK_RV
942 lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
943 const CK_ATTRIBUTE *templ, CK_ULONG count)
944 {
945 CK_RV crv;
946 CK_OBJECT_CLASS objclass;
947
948 /* get the object class */
949 crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
950 if (crv != CKR_OK) {
951 return crv;
952 }
953
954 /* Now handle the specific object class.
955 */
956 switch (objclass) {
957 case CKO_CERTIFICATE:
958 crv = lg_createCertObject(sdb,handle,templ,count);
959 break;
960 case CKO_NSS_TRUST:
961 crv = lg_createTrustObject(sdb,handle,templ,count);
962 break;
963 case CKO_NSS_CRL:
964 crv = lg_createCrlObject(sdb,handle,templ,count);
965 break;
966 case CKO_NSS_SMIME:
967 crv = lg_createSMimeObject(sdb,handle,templ,count);
968 break;
969 case CKO_PRIVATE_KEY:
970 case CKO_PUBLIC_KEY:
971 case CKO_SECRET_KEY:
972 crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
973 break;
974 default:
975 crv = CKR_ATTRIBUTE_VALUE_INVALID;
976 break;
977 }
978
979 return crv;
980 }
981
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)