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

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

mercurial