1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/legacydb/lgcreate.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,981 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "secitem.h" 1.8 +#include "pkcs11.h" 1.9 +#include "lgdb.h" 1.10 +#include "pcert.h" 1.11 +#include "lowkeyi.h" 1.12 +#include "blapi.h" 1.13 +#include "secder.h" 1.14 +#include "secasn1.h" 1.15 + 1.16 +#include "keydbi.h" 1.17 + 1.18 +/* 1.19 + * ******************** Object Creation Utilities *************************** 1.20 + */ 1.21 + 1.22 +/* 1.23 + * check the consistancy and initialize a Certificate Object 1.24 + */ 1.25 +static CK_RV 1.26 +lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle, 1.27 + const CK_ATTRIBUTE *templ, CK_ULONG count) 1.28 +{ 1.29 + SECItem derCert; 1.30 + NSSLOWCERTCertificate *cert; 1.31 + NSSLOWCERTCertTrust *trust = NULL; 1.32 + NSSLOWCERTCertTrust userTrust = 1.33 + { CERTDB_USER, CERTDB_USER, CERTDB_USER }; 1.34 + NSSLOWCERTCertTrust defTrust = 1.35 + { CERTDB_TRUSTED_UNKNOWN, 1.36 + CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN }; 1.37 + char *label = NULL; 1.38 + char *email = NULL; 1.39 + SECStatus rv; 1.40 + CK_RV crv; 1.41 + PRBool inDB = PR_TRUE; 1.42 + NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb); 1.43 + NSSLOWKEYDBHandle *keyHandle = NULL; 1.44 + CK_CERTIFICATE_TYPE type; 1.45 + const CK_ATTRIBUTE *attribute; 1.46 + 1.47 + /* we can't store any certs private */ 1.48 + if (lg_isTrue(CKA_PRIVATE, templ, count)) { 1.49 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.50 + } 1.51 + 1.52 + /* We only support X.509 Certs for now */ 1.53 + crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE, templ, count, &type); 1.54 + if (crv != CKR_OK) { 1.55 + return crv; 1.56 + } 1.57 + 1.58 + if (type != CKC_X_509) { 1.59 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.60 + } 1.61 + 1.62 + /* X.509 Certificate */ 1.63 + 1.64 + 1.65 + if (certHandle == NULL) { 1.66 + return CKR_TOKEN_WRITE_PROTECTED; 1.67 + } 1.68 + 1.69 + /* get the der cert */ 1.70 + attribute = lg_FindAttribute(CKA_VALUE, templ, count); 1.71 + if (!attribute) { 1.72 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.73 + } 1.74 + 1.75 + derCert.type = 0; 1.76 + derCert.data = (unsigned char *)attribute->pValue; 1.77 + derCert.len = attribute->ulValueLen ; 1.78 + 1.79 + label = lg_getString(CKA_LABEL, templ, count); 1.80 + 1.81 + cert = nsslowcert_FindCertByDERCert(certHandle, &derCert); 1.82 + if (cert == NULL) { 1.83 + cert = nsslowcert_DecodeDERCertificate(&derCert, label); 1.84 + inDB = PR_FALSE; 1.85 + } 1.86 + if (cert == NULL) { 1.87 + if (label) PORT_Free(label); 1.88 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.89 + } 1.90 + 1.91 + keyHandle = lg_getKeyDB(sdb); 1.92 + if (keyHandle) { 1.93 + if (nsslowkey_KeyForCertExists(keyHandle,cert)) { 1.94 + trust = &userTrust; 1.95 + } 1.96 + } 1.97 + 1.98 + if (!inDB) { 1.99 + if (!trust) trust = &defTrust; 1.100 + rv = nsslowcert_AddPermCert(certHandle, cert, label, trust); 1.101 + } else { 1.102 + rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) : 1.103 + SECSuccess; 1.104 + } 1.105 + 1.106 + if (label) PORT_Free(label); 1.107 + 1.108 + if (rv != SECSuccess) { 1.109 + nsslowcert_DestroyCertificate(cert); 1.110 + return CKR_DEVICE_ERROR; 1.111 + } 1.112 + 1.113 + /* 1.114 + * Add a NULL S/MIME profile if necessary. 1.115 + */ 1.116 + email = lg_getString(CKA_NSS_EMAIL, templ, count); 1.117 + if (email) { 1.118 + certDBEntrySMime *entry; 1.119 + 1.120 + entry = nsslowcert_ReadDBSMimeEntry(certHandle,email); 1.121 + if (!entry) { 1.122 + nsslowcert_SaveSMimeProfile(certHandle, email, 1.123 + &cert->derSubject, NULL, NULL); 1.124 + } else { 1.125 + nsslowcert_DestroyDBEntry((certDBEntry *)entry); 1.126 + } 1.127 + PORT_Free(email); 1.128 + } 1.129 + *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT); 1.130 + nsslowcert_DestroyCertificate(cert); 1.131 + 1.132 + return CKR_OK; 1.133 +} 1.134 + 1.135 +unsigned int 1.136 +lg_MapTrust(CK_TRUST trust, PRBool clientAuth) 1.137 +{ 1.138 + unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA : 1.139 + CERTDB_TRUSTED_CA; 1.140 + switch (trust) { 1.141 + case CKT_NSS_TRUSTED: 1.142 + return CERTDB_TERMINAL_RECORD|CERTDB_TRUSTED; 1.143 + case CKT_NSS_TRUSTED_DELEGATOR: 1.144 + return CERTDB_VALID_CA|trustCA; 1.145 + case CKT_NSS_MUST_VERIFY_TRUST: 1.146 + return CERTDB_MUST_VERIFY; 1.147 + case CKT_NSS_NOT_TRUSTED: 1.148 + return CERTDB_TERMINAL_RECORD; 1.149 + case CKT_NSS_VALID_DELEGATOR: /* implies must verify */ 1.150 + return CERTDB_VALID_CA; 1.151 + default: 1.152 + break; 1.153 + } 1.154 + return CERTDB_TRUSTED_UNKNOWN; 1.155 +} 1.156 + 1.157 + 1.158 +/* 1.159 + * check the consistancy and initialize a Trust Object 1.160 + */ 1.161 +static CK_RV 1.162 +lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle, 1.163 + const CK_ATTRIBUTE *templ, CK_ULONG count) 1.164 +{ 1.165 + const CK_ATTRIBUTE *issuer = NULL; 1.166 + const CK_ATTRIBUTE *serial = NULL; 1.167 + NSSLOWCERTCertificate *cert = NULL; 1.168 + const CK_ATTRIBUTE *trust; 1.169 + CK_TRUST sslTrust = CKT_NSS_TRUST_UNKNOWN; 1.170 + CK_TRUST clientTrust = CKT_NSS_TRUST_UNKNOWN; 1.171 + CK_TRUST emailTrust = CKT_NSS_TRUST_UNKNOWN; 1.172 + CK_TRUST signTrust = CKT_NSS_TRUST_UNKNOWN; 1.173 + CK_BBOOL stepUp; 1.174 + NSSLOWCERTCertTrust dbTrust = { 0 }; 1.175 + SECStatus rv; 1.176 + NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb); 1.177 + NSSLOWCERTIssuerAndSN issuerSN; 1.178 + 1.179 + /* we can't store any certs private */ 1.180 + if (lg_isTrue(CKA_PRIVATE, templ, count)) { 1.181 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.182 + } 1.183 + 1.184 + if (certHandle == NULL) { 1.185 + return CKR_TOKEN_WRITE_PROTECTED; 1.186 + } 1.187 + 1.188 + issuer = lg_FindAttribute(CKA_ISSUER, templ, count); 1.189 + serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count); 1.190 + 1.191 + if (issuer && serial) { 1.192 + issuerSN.derIssuer.data = (unsigned char *)issuer->pValue; 1.193 + issuerSN.derIssuer.len = issuer->ulValueLen ; 1.194 + 1.195 + issuerSN.serialNumber.data = (unsigned char *)serial->pValue; 1.196 + issuerSN.serialNumber.len = serial->ulValueLen ; 1.197 + 1.198 + cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN); 1.199 + } 1.200 + 1.201 + if (cert == NULL) { 1.202 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.203 + } 1.204 + 1.205 + lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust); 1.206 + lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust); 1.207 + lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust); 1.208 + lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust); 1.209 + stepUp = CK_FALSE; 1.210 + trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count); 1.211 + if (trust) { 1.212 + if (trust->ulValueLen == sizeof(CK_BBOOL)) { 1.213 + stepUp = *(CK_BBOOL*)trust->pValue; 1.214 + } 1.215 + } 1.216 + 1.217 + /* preserve certain old fields */ 1.218 + if (cert->trust) { 1.219 + dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS; 1.220 + dbTrust.emailFlags= 1.221 + cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS; 1.222 + dbTrust.objectSigningFlags = 1.223 + cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS; 1.224 + } 1.225 + 1.226 + dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE); 1.227 + dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE); 1.228 + dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE); 1.229 + dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE); 1.230 + if (stepUp) { 1.231 + dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA; 1.232 + } 1.233 + 1.234 + rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust); 1.235 + *handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST); 1.236 + nsslowcert_DestroyCertificate(cert); 1.237 + if (rv != SECSuccess) { 1.238 + return CKR_DEVICE_ERROR; 1.239 + } 1.240 + 1.241 + return CKR_OK; 1.242 +} 1.243 + 1.244 +/* 1.245 + * check the consistancy and initialize a Trust Object 1.246 + */ 1.247 +static CK_RV 1.248 +lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle, 1.249 + const CK_ATTRIBUTE *templ, CK_ULONG count) 1.250 +{ 1.251 + SECItem derSubj,rawProfile,rawTime,emailKey; 1.252 + SECItem *pRawProfile = NULL; 1.253 + SECItem *pRawTime = NULL; 1.254 + char *email = NULL; 1.255 + const CK_ATTRIBUTE *subject = NULL, 1.256 + *profile = NULL, 1.257 + *time = NULL; 1.258 + SECStatus rv; 1.259 + NSSLOWCERTCertDBHandle *certHandle; 1.260 + CK_RV ck_rv = CKR_OK; 1.261 + 1.262 + /* we can't store any certs private */ 1.263 + if (lg_isTrue(CKA_PRIVATE,templ,count)) { 1.264 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.265 + } 1.266 + 1.267 + certHandle = lg_getCertDB(sdb); 1.268 + if (certHandle == NULL) { 1.269 + return CKR_TOKEN_WRITE_PROTECTED; 1.270 + } 1.271 + 1.272 + /* lookup SUBJECT */ 1.273 + subject = lg_FindAttribute(CKA_SUBJECT,templ,count); 1.274 + PORT_Assert(subject); 1.275 + if (!subject) { 1.276 + ck_rv = CKR_ATTRIBUTE_VALUE_INVALID; 1.277 + goto loser; 1.278 + } 1.279 + 1.280 + derSubj.data = (unsigned char *)subject->pValue; 1.281 + derSubj.len = subject->ulValueLen ; 1.282 + derSubj.type = 0; 1.283 + 1.284 + /* lookup VALUE */ 1.285 + profile = lg_FindAttribute(CKA_VALUE,templ,count); 1.286 + if (profile) { 1.287 + rawProfile.data = (unsigned char *)profile->pValue; 1.288 + rawProfile.len = profile->ulValueLen ; 1.289 + rawProfile.type = siBuffer; 1.290 + pRawProfile = &rawProfile; 1.291 + } 1.292 + 1.293 + /* lookup Time */ 1.294 + time = lg_FindAttribute(CKA_NSS_SMIME_TIMESTAMP,templ,count); 1.295 + if (time) { 1.296 + rawTime.data = (unsigned char *)time->pValue; 1.297 + rawTime.len = time->ulValueLen ; 1.298 + rawTime.type = siBuffer; 1.299 + pRawTime = &rawTime; 1.300 + } 1.301 + 1.302 + 1.303 + email = lg_getString(CKA_NSS_EMAIL,templ,count); 1.304 + if (!email) { 1.305 + ck_rv = CKR_ATTRIBUTE_VALUE_INVALID; 1.306 + goto loser; 1.307 + } 1.308 + 1.309 + /* Store S/MIME Profile by SUBJECT */ 1.310 + rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj, 1.311 + pRawProfile,pRawTime); 1.312 + if (rv != SECSuccess) { 1.313 + ck_rv = CKR_DEVICE_ERROR; 1.314 + goto loser; 1.315 + } 1.316 + emailKey.data = (unsigned char *)email; 1.317 + emailKey.len = PORT_Strlen(email)+1; 1.318 + 1.319 + *handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME); 1.320 + 1.321 +loser: 1.322 + if (email) PORT_Free(email); 1.323 + 1.324 + return ck_rv; 1.325 +} 1.326 + 1.327 +/* 1.328 + * check the consistancy and initialize a Trust Object 1.329 + */ 1.330 +static CK_RV 1.331 +lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle, 1.332 + const CK_ATTRIBUTE *templ, CK_ULONG count) 1.333 +{ 1.334 + PRBool isKRL = PR_FALSE; 1.335 + SECItem derSubj,derCrl; 1.336 + char *url = NULL; 1.337 + const CK_ATTRIBUTE *subject,*crl; 1.338 + SECStatus rv; 1.339 + NSSLOWCERTCertDBHandle *certHandle; 1.340 + 1.341 + certHandle = lg_getCertDB(sdb); 1.342 + 1.343 + /* we can't store any private crls */ 1.344 + if (lg_isTrue(CKA_PRIVATE,templ,count)) { 1.345 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.346 + } 1.347 + 1.348 + if (certHandle == NULL) { 1.349 + return CKR_TOKEN_WRITE_PROTECTED; 1.350 + } 1.351 + 1.352 + /* lookup SUBJECT */ 1.353 + subject = lg_FindAttribute(CKA_SUBJECT,templ,count); 1.354 + if (!subject) { 1.355 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.356 + } 1.357 + 1.358 + derSubj.data = (unsigned char *)subject->pValue; 1.359 + derSubj.len = subject->ulValueLen ; 1.360 + 1.361 + /* lookup VALUE */ 1.362 + crl = lg_FindAttribute(CKA_VALUE,templ,count); 1.363 + PORT_Assert(crl); 1.364 + if (!crl) { 1.365 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.366 + } 1.367 + derCrl.data = (unsigned char *)crl->pValue; 1.368 + derCrl.len = crl->ulValueLen ; 1.369 + 1.370 + url = lg_getString(CKA_NSS_URL,templ,count); 1.371 + isKRL = lg_isTrue(CKA_NSS_KRL,templ,count); 1.372 + 1.373 + /* Store CRL by SUBJECT */ 1.374 + rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL); 1.375 + 1.376 + if (url) { 1.377 + PORT_Free(url); 1.378 + } 1.379 + if (rv != SECSuccess) { 1.380 + return CKR_DEVICE_ERROR; 1.381 + } 1.382 + 1.383 + /* if we overwrote the existing CRL, poison the handle entry so we get 1.384 + * a new object handle */ 1.385 + (void) lg_poisonHandle(sdb, &derSubj, 1.386 + isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL); 1.387 + *handle = lg_mkHandle(sdb, &derSubj, 1.388 + isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL); 1.389 + 1.390 + return CKR_OK; 1.391 +} 1.392 + 1.393 +/* 1.394 + * check the consistancy and initialize a Public Key Object 1.395 + */ 1.396 +static CK_RV 1.397 +lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type, 1.398 + CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) 1.399 +{ 1.400 + CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE; 1.401 + CK_RV crv = CKR_OK; 1.402 + NSSLOWKEYPrivateKey *priv; 1.403 + SECItem pubKeySpace = {siBuffer, NULL, 0}; 1.404 + SECItem *pubKey; 1.405 +#ifndef NSS_DISABLE_ECC 1.406 + SECItem pubKey2Space = {siBuffer, NULL, 0}; 1.407 + PLArenaPool *arena = NULL; 1.408 +#endif /* NSS_DISABLE_ECC */ 1.409 + NSSLOWKEYDBHandle *keyHandle = NULL; 1.410 + 1.411 + 1.412 + switch (key_type) { 1.413 + case CKK_RSA: 1.414 + pubKeyAttr = CKA_MODULUS; 1.415 + break; 1.416 +#ifndef NSS_DISABLE_ECC 1.417 + case CKK_EC: 1.418 + pubKeyAttr = CKA_EC_POINT; 1.419 + break; 1.420 +#endif /* NSS_DISABLE_ECC */ 1.421 + case CKK_DSA: 1.422 + case CKK_DH: 1.423 + break; 1.424 + default: 1.425 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.426 + } 1.427 + 1.428 + 1.429 + pubKey = &pubKeySpace; 1.430 + crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,pubKey); 1.431 + if (crv != CKR_OK) return crv; 1.432 + 1.433 +#ifndef NSS_DISABLE_ECC 1.434 + if (key_type == CKK_EC) { 1.435 + SECStatus rv; 1.436 + /* 1.437 + * for ECC, use the decoded key first. 1.438 + */ 1.439 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.440 + if (arena == NULL) { 1.441 + crv = CKR_HOST_MEMORY; 1.442 + goto done; 1.443 + } 1.444 + rv= SEC_QuickDERDecodeItem(arena, &pubKey2Space, 1.445 + SEC_ASN1_GET(SEC_OctetStringTemplate), 1.446 + pubKey); 1.447 + if (rv != SECSuccess) { 1.448 + /* decode didn't work, just try the pubKey */ 1.449 + PORT_FreeArena(arena, PR_FALSE); 1.450 + arena = NULL; 1.451 + } else { 1.452 + /* try the decoded pub key first */ 1.453 + pubKey = &pubKey2Space; 1.454 + } 1.455 + } 1.456 +#endif /* NSS_DISABLE_ECC */ 1.457 + 1.458 + PORT_Assert(pubKey->data); 1.459 + if (pubKey->data == NULL) { 1.460 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.461 + goto done; 1.462 + } 1.463 + keyHandle = lg_getKeyDB(sdb); 1.464 + if (keyHandle == NULL) { 1.465 + crv = CKR_TOKEN_WRITE_PROTECTED; 1.466 + goto done; 1.467 + } 1.468 + if (keyHandle->version != 3) { 1.469 + unsigned char buf[SHA1_LENGTH]; 1.470 + SHA1_HashBuf(buf,pubKey->data,pubKey->len); 1.471 + PORT_Memcpy(pubKey->data,buf,sizeof(buf)); 1.472 + pubKey->len = sizeof(buf); 1.473 + } 1.474 + /* make sure the associated private key already exists */ 1.475 + /* only works if we are logged in */ 1.476 + priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/); 1.477 +#ifndef NSS_DISABLE_ECC 1.478 + if (priv == NULL && pubKey == &pubKey2Space) { 1.479 + /* no match on the decoded key, match the original pubkey */ 1.480 + pubKey = &pubKeySpace; 1.481 + priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, 1.482 + sdb /*password*/); 1.483 + } 1.484 +#endif 1.485 + if (priv == NULL) { 1.486 + /* the legacy database can only 'store' public keys which already 1.487 + * have their corresponding private keys in the database */ 1.488 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.489 + goto done; 1.490 + } 1.491 + lg_nsslowkey_DestroyPrivateKey(priv); 1.492 + crv = CKR_OK; 1.493 + 1.494 + *handle = lg_mkHandle(sdb, pubKey, LG_TOKEN_TYPE_PUB); 1.495 + 1.496 +done: 1.497 + PORT_Free(pubKeySpace.data); 1.498 +#ifndef NSS_DISABLE_ECC 1.499 + if (arena) 1.500 + PORT_FreeArena(arena, PR_FALSE); 1.501 +#endif 1.502 + 1.503 + return crv; 1.504 +} 1.505 + 1.506 +/* make a private key from a verified object */ 1.507 +static NSSLOWKEYPrivateKey * 1.508 +lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count, 1.509 + CK_KEY_TYPE key_type, CK_RV *crvp) 1.510 +{ 1.511 + NSSLOWKEYPrivateKey *privKey; 1.512 + PLArenaPool *arena; 1.513 + CK_RV crv = CKR_OK; 1.514 + SECStatus rv; 1.515 + 1.516 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.517 + if (arena == NULL) { 1.518 + *crvp = CKR_HOST_MEMORY; 1.519 + return NULL; 1.520 + } 1.521 + 1.522 + privKey = (NSSLOWKEYPrivateKey *) 1.523 + PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); 1.524 + if (privKey == NULL) { 1.525 + PORT_FreeArena(arena,PR_FALSE); 1.526 + *crvp = CKR_HOST_MEMORY; 1.527 + return NULL; 1.528 + } 1.529 + 1.530 + /* in future this would be a switch on key_type */ 1.531 + privKey->arena = arena; 1.532 + switch (key_type) { 1.533 + case CKK_RSA: 1.534 + privKey->keyType = NSSLOWKEYRSAKey; 1.535 + crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count, 1.536 + &privKey->u.rsa.modulus); 1.537 + if (crv != CKR_OK) break; 1.538 + crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count, 1.539 + &privKey->u.rsa.publicExponent); 1.540 + if (crv != CKR_OK) break; 1.541 + crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count, 1.542 + &privKey->u.rsa.privateExponent, sdb); 1.543 + if (crv != CKR_OK) break; 1.544 + crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count, 1.545 + &privKey->u.rsa.prime1, sdb); 1.546 + if (crv != CKR_OK) break; 1.547 + crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count, 1.548 + &privKey->u.rsa.prime2, sdb); 1.549 + if (crv != CKR_OK) break; 1.550 + crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count, 1.551 + &privKey->u.rsa.exponent1, sdb); 1.552 + if (crv != CKR_OK) break; 1.553 + crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count, 1.554 + &privKey->u.rsa.exponent2, sdb); 1.555 + if (crv != CKR_OK) break; 1.556 + crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count, 1.557 + &privKey->u.rsa.coefficient, sdb); 1.558 + if (crv != CKR_OK) break; 1.559 + rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, 1.560 + NSSLOWKEY_VERSION); 1.561 + if (rv != SECSuccess) crv = CKR_HOST_MEMORY; 1.562 + break; 1.563 + 1.564 + case CKK_DSA: 1.565 + privKey->keyType = NSSLOWKEYDSAKey; 1.566 + crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count, 1.567 + &privKey->u.dsa.params.prime); 1.568 + if (crv != CKR_OK) break; 1.569 + crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count, 1.570 + &privKey->u.dsa.params.subPrime); 1.571 + if (crv != CKR_OK) break; 1.572 + crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count, 1.573 + &privKey->u.dsa.params.base); 1.574 + if (crv != CKR_OK) break; 1.575 + crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count, 1.576 + &privKey->u.dsa.privateValue, sdb); 1.577 + if (crv != CKR_OK) break; 1.578 + if (lg_hasAttribute(CKA_NETSCAPE_DB, templ,count)) { 1.579 + crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count, 1.580 + &privKey->u.dsa.publicValue); 1.581 + /* privKey was zero'd so public value is already set to NULL, 0 1.582 + * if we don't set it explicitly */ 1.583 + } 1.584 + break; 1.585 + 1.586 + case CKK_DH: 1.587 + privKey->keyType = NSSLOWKEYDHKey; 1.588 + crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count, 1.589 + &privKey->u.dh.prime); 1.590 + if (crv != CKR_OK) break; 1.591 + crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count, 1.592 + &privKey->u.dh.base); 1.593 + if (crv != CKR_OK) break; 1.594 + crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count, 1.595 + &privKey->u.dh.privateValue, sdb); 1.596 + if (crv != CKR_OK) break; 1.597 + if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) { 1.598 + crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count, 1.599 + &privKey->u.dh.publicValue); 1.600 + /* privKey was zero'd so public value is already set to NULL, 0 1.601 + * if we don't set it explicitly */ 1.602 + } 1.603 + break; 1.604 + 1.605 +#ifndef NSS_DISABLE_ECC 1.606 + case CKK_EC: 1.607 + privKey->keyType = NSSLOWKEYECKey; 1.608 + crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count, 1.609 + &privKey->u.ec.ecParams.DEREncoding); 1.610 + if (crv != CKR_OK) break; 1.611 + 1.612 + /* Fill out the rest of the ecParams structure 1.613 + * based on the encoded params 1.614 + */ 1.615 + if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding, 1.616 + &privKey->u.ec.ecParams) != SECSuccess) { 1.617 + crv = CKR_DOMAIN_PARAMS_INVALID; 1.618 + break; 1.619 + } 1.620 + crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count, 1.621 + &privKey->u.ec.privateValue, sdb); 1.622 + if (crv != CKR_OK) break; 1.623 + if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) { 1.624 + crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count, 1.625 + &privKey->u.ec.publicValue); 1.626 + if (crv != CKR_OK) break; 1.627 + /* privKey was zero'd so public value is already set to NULL, 0 1.628 + * if we don't set it explicitly */ 1.629 + } 1.630 + rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, 1.631 + NSSLOWKEY_EC_PRIVATE_KEY_VERSION); 1.632 + if (rv != SECSuccess) crv = CKR_HOST_MEMORY; 1.633 + break; 1.634 +#endif /* NSS_DISABLE_ECC */ 1.635 + 1.636 + default: 1.637 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.638 + break; 1.639 + } 1.640 + *crvp = crv; 1.641 + if (crv != CKR_OK) { 1.642 + PORT_FreeArena(arena,PR_FALSE); 1.643 + return NULL; 1.644 + } 1.645 + return privKey; 1.646 +} 1.647 + 1.648 +/* 1.649 + * check the consistancy and initialize a Private Key Object 1.650 + */ 1.651 +static CK_RV 1.652 +lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type, 1.653 + CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) 1.654 +{ 1.655 + NSSLOWKEYPrivateKey *privKey; 1.656 + char *label; 1.657 + SECStatus rv = SECSuccess; 1.658 + CK_RV crv = CKR_DEVICE_ERROR; 1.659 + SECItem pubKey; 1.660 + NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb); 1.661 + 1.662 + if (keyHandle == NULL) { 1.663 + return CKR_TOKEN_WRITE_PROTECTED; 1.664 + } 1.665 + 1.666 + privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv); 1.667 + if (privKey == NULL) return crv; 1.668 + label = lg_getString(CKA_LABEL,templ,count); 1.669 + 1.670 + crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey); 1.671 + if (crv != CKR_OK) { 1.672 + crv = CKR_TEMPLATE_INCOMPLETE; 1.673 + rv = SECFailure; 1.674 + goto fail; 1.675 + } 1.676 +#ifdef notdef 1.677 + if (keyHandle->version != 3) { 1.678 + unsigned char buf[SHA1_LENGTH]; 1.679 + SHA1_HashBuf(buf,pubKey.data,pubKey.len); 1.680 + PORT_Memcpy(pubKey.data,buf,sizeof(buf)); 1.681 + pubKey.len = sizeof(buf); 1.682 + } 1.683 +#endif 1.684 + /* get the key type */ 1.685 + if (key_type == CKK_RSA) { 1.686 + rv = RSA_PrivateKeyCheck(&privKey->u.rsa); 1.687 + if (rv == SECFailure) { 1.688 + goto fail; 1.689 + } 1.690 + } 1.691 + rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey, 1.692 + label, sdb /*->password*/); 1.693 + 1.694 +fail: 1.695 + if (label) PORT_Free(label); 1.696 + *handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV); 1.697 + if (pubKey.data) PORT_Free(pubKey.data); 1.698 + lg_nsslowkey_DestroyPrivateKey(privKey); 1.699 + if (rv != SECSuccess) return crv; 1.700 + 1.701 + return CKR_OK; 1.702 +} 1.703 + 1.704 + 1.705 +#define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */ 1.706 +#define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */ 1.707 +/* 1.708 + * Secret keys must have a CKA_ID value to be stored in the database. This code 1.709 + * will generate one if there wasn't one already. 1.710 + */ 1.711 +static CK_RV 1.712 +lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label) 1.713 +{ 1.714 + unsigned int retries; 1.715 + SECStatus rv = SECSuccess; 1.716 + CK_RV crv = CKR_OK; 1.717 + 1.718 + id->data = NULL; 1.719 + if (label) { 1.720 + id->data = (unsigned char *)PORT_Strdup(label); 1.721 + if (id->data == NULL) { 1.722 + return CKR_HOST_MEMORY; 1.723 + } 1.724 + id->len = PORT_Strlen(label)+1; 1.725 + if (!nsslowkey_KeyForIDExists(handle,id)) { 1.726 + return CKR_OK; 1.727 + } 1.728 + PORT_Free(id->data); 1.729 + id->data = NULL; 1.730 + id->len = 0; 1.731 + } 1.732 + id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE); 1.733 + if (id->data == NULL) { 1.734 + return CKR_HOST_MEMORY; 1.735 + } 1.736 + id->len = LG_KEY_ID_SIZE; 1.737 + 1.738 + retries = 0; 1.739 + do { 1.740 + rv = RNG_GenerateGlobalRandomBytes(id->data,id->len); 1.741 + } while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) && 1.742 + (++retries <= LG_KEY_MAX_RETRIES)); 1.743 + 1.744 + if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) { 1.745 + crv = CKR_DEVICE_ERROR; /* random number generator is bad */ 1.746 + PORT_Free(id->data); 1.747 + id->data = NULL; 1.748 + id->len = 0; 1.749 + } 1.750 + return crv; 1.751 +} 1.752 + 1.753 + 1.754 +static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ, 1.755 + CK_ULONG count, CK_KEY_TYPE key_type, 1.756 + SECItem *pubkey, SDB *sdbpw) 1.757 +{ 1.758 + NSSLOWKEYPrivateKey *privKey = 0; 1.759 + PLArenaPool *arena = 0; 1.760 + CK_KEY_TYPE keyType; 1.761 + PRUint32 keyTypeStorage; 1.762 + SECItem keyTypeItem; 1.763 + CK_RV crv; 1.764 + SECStatus rv; 1.765 + static unsigned char derZero[1] = { 0 }; 1.766 + 1.767 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.768 + if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; } 1.769 + 1.770 + privKey = (NSSLOWKEYPrivateKey *) 1.771 + PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); 1.772 + if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } 1.773 + 1.774 + privKey->arena = arena; 1.775 + 1.776 + /* Secret keys are represented in the database as "fake" RSA keys. 1.777 + * The RSA key is marked as a secret key representation by setting the 1.778 + * public exponent field to 0, which is an invalid RSA exponent. 1.779 + * The other fields are set as follows: 1.780 + * modulus - CKA_ID value for the secret key 1.781 + * private exponent - CKA_VALUE (the key itself) 1.782 + * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm 1.783 + * is used for the key. 1.784 + * all others - set to integer 0 1.785 + */ 1.786 + privKey->keyType = NSSLOWKEYRSAKey; 1.787 + 1.788 + /* The modulus is set to the key id of the symmetric key */ 1.789 + privKey->u.rsa.modulus.data = 1.790 + (unsigned char *) PORT_ArenaAlloc(arena, pubkey->len); 1.791 + if (privKey->u.rsa.modulus.data == NULL) { 1.792 + crv = CKR_HOST_MEMORY; 1.793 + goto loser; 1.794 + } 1.795 + privKey->u.rsa.modulus.len = pubkey->len; 1.796 + PORT_Memcpy(privKey->u.rsa.modulus.data, pubkey->data, pubkey->len); 1.797 + 1.798 + /* The public exponent is set to 0 to indicate a special key */ 1.799 + privKey->u.rsa.publicExponent.len = sizeof derZero; 1.800 + privKey->u.rsa.publicExponent.data = derZero; 1.801 + 1.802 + /* The private exponent is the actual key value */ 1.803 + crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count, 1.804 + &privKey->u.rsa.privateExponent, sdbpw); 1.805 + if (crv != CKR_OK) goto loser; 1.806 + 1.807 + /* All other fields empty - needs testing */ 1.808 + privKey->u.rsa.prime1.len = sizeof derZero; 1.809 + privKey->u.rsa.prime1.data = derZero; 1.810 + 1.811 + privKey->u.rsa.prime2.len = sizeof derZero; 1.812 + privKey->u.rsa.prime2.data = derZero; 1.813 + 1.814 + privKey->u.rsa.exponent1.len = sizeof derZero; 1.815 + privKey->u.rsa.exponent1.data = derZero; 1.816 + 1.817 + privKey->u.rsa.exponent2.len = sizeof derZero; 1.818 + privKey->u.rsa.exponent2.data = derZero; 1.819 + 1.820 + /* Coeficient set to KEY_TYPE */ 1.821 + crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType); 1.822 + if (crv != CKR_OK) goto loser; 1.823 + /* on 64 bit platforms, we still want to store 32 bits of keyType (This is 1.824 + * safe since the PKCS #11 defines for all types are 32 bits or less). */ 1.825 + keyTypeStorage = (PRUint32) keyType; 1.826 + keyTypeStorage = PR_htonl(keyTypeStorage); 1.827 + keyTypeItem.data = (unsigned char *)&keyTypeStorage; 1.828 + keyTypeItem.len = sizeof (keyTypeStorage); 1.829 + rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem); 1.830 + if (rv != SECSuccess) { 1.831 + crv = CKR_HOST_MEMORY; 1.832 + goto loser; 1.833 + } 1.834 + 1.835 + /* Private key version field set normally for compatibility */ 1.836 + rv = DER_SetUInteger(privKey->arena, 1.837 + &privKey->u.rsa.version, NSSLOWKEY_VERSION); 1.838 + if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; } 1.839 + 1.840 +loser: 1.841 + if (crv != CKR_OK) { 1.842 + PORT_FreeArena(arena,PR_FALSE); 1.843 + privKey = 0; 1.844 + } 1.845 + 1.846 + return privKey; 1.847 +} 1.848 + 1.849 +/* 1.850 + * check the consistancy and initialize a Secret Key Object 1.851 + */ 1.852 +static CK_RV 1.853 +lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type, 1.854 + CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) 1.855 +{ 1.856 + CK_RV crv; 1.857 + NSSLOWKEYPrivateKey *privKey = NULL; 1.858 + NSSLOWKEYDBHandle *keyHandle = NULL; 1.859 + SECItem pubKey; 1.860 + char *label = NULL; 1.861 + SECStatus rv = SECSuccess; 1.862 + 1.863 + pubKey.data = 0; 1.864 + 1.865 + /* If the object is a TOKEN object, store in the database */ 1.866 + keyHandle = lg_getKeyDB(sdb); 1.867 + 1.868 + if (keyHandle == NULL) { 1.869 + return CKR_TOKEN_WRITE_PROTECTED; 1.870 + } 1.871 + 1.872 + label = lg_getString(CKA_LABEL,templ,count); 1.873 + 1.874 + crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey); 1.875 + /* Should this be ID? */ 1.876 + if (crv != CKR_OK) goto loser; 1.877 + 1.878 + /* if we don't have an ID, generate one */ 1.879 + if (pubKey.len == 0) { 1.880 + if (pubKey.data) { 1.881 + PORT_Free(pubKey.data); 1.882 + pubKey.data = NULL; 1.883 + } 1.884 + crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label); 1.885 + if (crv != CKR_OK) goto loser; 1.886 + } 1.887 + 1.888 + privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb); 1.889 + if (privKey == NULL) { 1.890 + crv = CKR_HOST_MEMORY; 1.891 + goto loser; 1.892 + } 1.893 + 1.894 + rv = nsslowkey_StoreKeyByPublicKey(keyHandle, 1.895 + privKey, &pubKey, label, sdb /*->password*/); 1.896 + if (rv != SECSuccess) { 1.897 + crv = CKR_DEVICE_ERROR; 1.898 + goto loser; 1.899 + } 1.900 + 1.901 + *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY); 1.902 + 1.903 +loser: 1.904 + if (label) PORT_Free(label); 1.905 + if (privKey) lg_nsslowkey_DestroyPrivateKey(privKey); 1.906 + if (pubKey.data) PORT_Free(pubKey.data); 1.907 + 1.908 + return crv; 1.909 +} 1.910 + 1.911 +/* 1.912 + * check the consistancy and initialize a Key Object 1.913 + */ 1.914 +static CK_RV 1.915 +lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass, 1.916 + CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) 1.917 +{ 1.918 + CK_RV crv; 1.919 + CK_KEY_TYPE key_type; 1.920 + 1.921 + /* get the key type */ 1.922 + crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type); 1.923 + if (crv != CKR_OK) { 1.924 + return crv; 1.925 + } 1.926 + 1.927 + switch (objclass) { 1.928 + case CKO_PUBLIC_KEY: 1.929 + return lg_createPublicKeyObject(sdb,key_type,handle,templ,count); 1.930 + case CKO_PRIVATE_KEY: 1.931 + return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count); 1.932 + case CKO_SECRET_KEY: 1.933 + return lg_createSecretKeyObject(sdb,key_type,handle,templ,count); 1.934 + default: 1.935 + break; 1.936 + } 1.937 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.938 +} 1.939 + 1.940 +/* 1.941 + * Parse the template and create an object stored in the DB that reflects. 1.942 + * the object specified in the database. 1.943 + */ 1.944 +CK_RV 1.945 +lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle, 1.946 + const CK_ATTRIBUTE *templ, CK_ULONG count) 1.947 +{ 1.948 + CK_RV crv; 1.949 + CK_OBJECT_CLASS objclass; 1.950 + 1.951 + /* get the object class */ 1.952 + crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass); 1.953 + if (crv != CKR_OK) { 1.954 + return crv; 1.955 + } 1.956 + 1.957 + /* Now handle the specific object class. 1.958 + */ 1.959 + switch (objclass) { 1.960 + case CKO_CERTIFICATE: 1.961 + crv = lg_createCertObject(sdb,handle,templ,count); 1.962 + break; 1.963 + case CKO_NSS_TRUST: 1.964 + crv = lg_createTrustObject(sdb,handle,templ,count); 1.965 + break; 1.966 + case CKO_NSS_CRL: 1.967 + crv = lg_createCrlObject(sdb,handle,templ,count); 1.968 + break; 1.969 + case CKO_NSS_SMIME: 1.970 + crv = lg_createSMimeObject(sdb,handle,templ,count); 1.971 + break; 1.972 + case CKO_PRIVATE_KEY: 1.973 + case CKO_PUBLIC_KEY: 1.974 + case CKO_SECRET_KEY: 1.975 + crv = lg_createKeyObject(sdb,objclass,handle,templ,count); 1.976 + break; 1.977 + default: 1.978 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.979 + break; 1.980 + } 1.981 + 1.982 + return crv; 1.983 +} 1.984 +