security/nss/lib/softoken/legacydb/lgcreate.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial