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