pkcs11c.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:155k
- context->multi = PR_TRUE;
- switch(pMechanism->mechanism) {
- case CKM_RSA_PKCS:
- case CKM_RSA_X_509:
- if (key_type != CKK_RSA) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- context->multi = PR_FALSE;
- pubKey = pk11_GetPubKey(key,CKK_RSA);
- if (pubKey == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- context->cipherInfo = pubKey;
- context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
- ? RSA_CheckSignRecoverRaw : RSA_CheckSignRecover);
- context->destroy = pk11_Null;
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- break;
- }
- pk11_FreeObject(key);
- if (crv != CKR_OK) {
- PORT_Free(context);
- pk11_FreeSession(session);
- return crv;
- }
- pk11_SetContextByType(session, PK11_VERIFY_RECOVER, context);
- pk11_FreeSession(session);
- return CKR_OK;
- }
- /* NSC_VerifyRecover verifies a signature in a single-part operation,
- * where the data is recovered from the signature.
- * E.g. Decryption with the user's public key */
- CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,
- CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
- {
- PK11Session *session;
- PK11SessionContext *context;
- unsigned int outlen;
- unsigned int maxoutlen = *pulDataLen;
- CK_RV crv;
- SECStatus rv;
- /* make sure we're legal */
- crv = pk11_GetContext(hSession,&context,PK11_VERIFY_RECOVER,
- PR_FALSE,&session);
- if (crv != CKR_OK) return crv;
- rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
- pSignature, ulSignatureLen);
- *pulDataLen = (CK_ULONG) outlen;
- pk11_FreeContext(context);
- pk11_SetContextByType(session, PK11_VERIFY_RECOVER, NULL);
- pk11_FreeSession(session);
- return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
- }
- /*
- **************************** Random Functions: ************************
- */
- /* NSC_SeedRandom mixes additional seed material into the token's random number
- * generator. */
- CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
- CK_ULONG ulSeedLen)
- {
- SECStatus rv;
- rv = RNG_RandomUpdate(pSeed, ulSeedLen);
- return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
- }
- /* NSC_GenerateRandom generates random data. */
- CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
- {
- SECStatus rv;
- rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
- return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
- }
- /*
- **************************** Key Functions: ************************
- */
- /*
- * generate a password based encryption key. This code uses
- * PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is
- * a utility function in secpkcs5.c. This function is used in here
- * and in PK11_ParamToAlgid.
- */
- CK_RV
- pk11_pbe_key_gen(SECOidTag algtag,CK_MECHANISM_PTR pMechanism,
- char *buf,int *key_length, PRBool faulty3DES)
- {
- SECAlgorithmID algid;
- SECItem *pbe_key = NULL, mech;
- CK_PBE_PARAMS *pbe_params = NULL;
- SECStatus pbe_rv;
- *key_length = 0;
- mech.data = (unsigned char *)pMechanism->pParameter;
- mech.len = (unsigned int)pMechanism->ulParameterLen;
- /* A common routine to map from Params to AlgIDs for PBE
- * algorithms was created in secpkcs5.c. This function is
- * called both by PK11_ParamToAlgid and this function.
- */
- pbe_rv = PBE_PK11ParamToAlgid(algtag, &mech, NULL, &algid);
- if (pbe_rv != SECSuccess) {
- return CKR_DATA_INVALID;
- }
- pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
- mech.data = (unsigned char *)pbe_params->pPassword;
- mech.len = (unsigned int)pbe_params->ulPasswordLen;
- pbe_key = SEC_PKCS5GetKey(&algid, &mech, faulty3DES);
- if (pbe_key == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- return CKR_HOST_MEMORY;
- }
- PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
- *key_length = pbe_key->len;
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- pbe_key = NULL;
- if (pbe_params->pInitVector == NULL) {
- pbe_key = SEC_PKCS5GetIV(&algid, &mech, faulty3DES);
- if (pbe_key == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- return CKR_HOST_MEMORY;
- }
- pbe_params->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(pbe_key->len);
- if (pbe_params->pInitVector == NULL) {
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- return CKR_HOST_MEMORY;
- }
- PORT_Memcpy(pbe_params->pInitVector, pbe_key->data, pbe_key->len);
- }
- SECITEM_ZfreeItem(pbe_key, PR_TRUE);
- SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
- return CKR_OK;
- }
- /* NSC_GenerateKey generates a secret key, creating a new key object. */
- CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
- CK_OBJECT_HANDLE_PTR phKey)
- {
- PK11Object *key;
- PK11Session *session;
- PRBool checkWeak = PR_FALSE;
- int key_length = 0;
- CK_KEY_TYPE key_type;
- CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
- CK_RV crv = CKR_OK;
- CK_BBOOL cktrue = CK_TRUE;
- int i;
- PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
- char buf[MAX_KEY_LEN];
- enum {pk11_pbe, pk11_ssl, pk11_bulk} key_gen_type;
- SECOidTag algtag = SEC_OID_UNKNOWN;
- SSL3RSAPreMasterSecret *rsa_pms;
- CK_VERSION *version;
- /* in very old versions of NSS, there were implementation errors with key
- * generation methods. We want to beable to read these, but not
- * produce them any more. The affected algorithm was 3DES.
- */
- PRBool faultyPBE3DES = PR_FALSE;
- /*
- * now lets create an object to hang the attributes off of
- */
- key = pk11_NewObject(slot); /* fill in the handle later */
- if (key == NULL) {
- return CKR_HOST_MEMORY;
- }
- /*
- * load the template values into the object
- */
- for (i=0; i < (int) ulCount; i++) {
- if (pTemplate[i].type == CKA_VALUE_LEN) {
- key_length = *(CK_ULONG *)pTemplate[i].pValue;
- continue;
- }
- crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
- if (crv != CKR_OK) break;
- }
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
- /* make sure we don't have any class, key_type, or value fields */
- pk11_DeleteAttributeType(key,CKA_CLASS);
- pk11_DeleteAttributeType(key,CKA_KEY_TYPE);
- pk11_DeleteAttributeType(key,CKA_VALUE);
- /* Now Set up the parameters to generate the key (based on mechanism) */
- key_gen_type = pk11_bulk; /* bulk key by default */
- switch (pMechanism->mechanism) {
- case CKM_RC2_KEY_GEN:
- key_type = CKK_RC2;
- if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- #if NSS_SOFTOKEN_DOES_RC5
- case CKM_RC5_KEY_GEN:
- key_type = CKK_RC5;
- if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- #endif
- case CKM_RC4_KEY_GEN:
- key_type = CKK_RC4;
- if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- case CKM_GENERIC_SECRET_KEY_GEN:
- key_type = CKK_GENERIC_SECRET;
- if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- case CKM_CDMF_KEY_GEN:
- key_type = CKK_CDMF;
- key_length = 8;
- checkWeak = PR_TRUE;
- break;
- case CKM_DES_KEY_GEN:
- key_type = CKK_DES;
- key_length = 8;
- checkWeak = PR_TRUE;
- break;
- case CKM_DES2_KEY_GEN:
- key_type = CKK_DES2;
- key_length = 16;
- checkWeak = PR_TRUE;
- break;
- case CKM_DES3_KEY_GEN:
- key_type = CKK_DES3;
- key_length = 24;
- checkWeak = PR_TRUE;
- break;
- case CKM_SSL3_PRE_MASTER_KEY_GEN:
- key_type = CKK_GENERIC_SECRET;
- key_length = 48;
- key_gen_type = pk11_ssl;
- break;
- case CKM_PBE_MD2_DES_CBC:
- algtag = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
- key_type = CKK_DES;
- goto have_key_type;
- case CKM_PBE_MD5_DES_CBC:
- algtag = SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC;
- key_type = CKK_DES;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
- algtag = SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
- key_type = CKK_DES;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
- faultyPBE3DES = PR_TRUE;
- case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
- algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
- key_type = CKK_DES3;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
- algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
- key_type = CKK_RC2;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
- algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
- key_type = CKK_RC2;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
- algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4;
- key_type = CKK_RC4;
- goto have_key_type;
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
- algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4;
- key_type = CKK_RC4;
- goto have_key_type;
- case CKM_PBE_SHA1_RC4_40:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
- key_length = 5;
- key_type = CKK_RC4;
- goto have_key_type;
- case CKM_PBE_SHA1_RC4_128:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
- key_length = 16;
- key_type = CKK_RC4;
- goto have_key_type;
- case CKM_PBE_SHA1_RC2_40_CBC:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
- key_length = 5;
- key_type = CKK_RC2;
- goto have_key_type;
- case CKM_PBE_SHA1_RC2_128_CBC:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
- key_length = 16;
- key_type = CKK_RC2;
- goto have_key_type;
- case CKM_PBE_SHA1_DES3_EDE_CBC:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
- key_length = 24;
- key_type = CKK_DES3;
- goto have_key_type;
- case CKM_PBE_SHA1_DES2_EDE_CBC:
- algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
- key_length = 16;
- key_type = CKK_DES2;
- checkWeak = PR_FALSE;
- have_key_type:
- key_gen_type = pk11_pbe;
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- }
- /* make sure we aren't going to overflow the buffer */
- if (sizeof(buf) < key_length) {
- /* someone is getting pretty optimistic about how big their key can
- * be... */
- crv = CKR_TEMPLATE_INCONSISTENT;
- }
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- /*
- * now to the actual key gen.
- */
- switch (key_gen_type) {
- case pk11_pbe:
- crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length,
- faultyPBE3DES);
- break;
- case pk11_ssl:
- rsa_pms = (SSL3RSAPreMasterSecret *)buf;
- version = (CK_VERSION *)pMechanism->pParameter;
- rsa_pms->client_version[0] = version->major;
- rsa_pms->client_version[1] = version->minor;
- crv =
- NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
- break;
- case pk11_bulk:
- /* get the key, check for weak keys and repeat if found */
- do {
- crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length);
- } while (crv == CKR_OK && checkWeak &&
- pk11_IsWeakKey((unsigned char *)buf,key_type));
- break;
- }
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- /* Add the class, key_type, and value */
- crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- crv = pk11_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- crv = pk11_AddAttributeType(key,CKA_VALUE,buf,key_length);
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- /* get the session */
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- pk11_FreeObject(key);
- return CKR_SESSION_HANDLE_INVALID;
- }
- /*
- * handle the base object stuff
- */
- crv = pk11_handleObject(key,session);
- pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
- if (pk11_isTrue(key,CKA_SENSITIVE)) {
- pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
- }
- if (!pk11_isTrue(key,CKA_EXTRACTABLE)) {
- pk11_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
- }
- *phKey = key->handle;
- return CKR_OK;
- }
- /* NSC_GenerateKeyPair generates a public-key/private-key pair,
- * creating new key objects. */
- CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
- CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
- CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPrivateKey,
- CK_OBJECT_HANDLE_PTR phPublicKey)
- {
- PK11Object * publicKey,*privateKey;
- PK11Session * session;
- CK_KEY_TYPE key_type;
- CK_RV crv = CKR_OK;
- CK_BBOOL cktrue = CK_TRUE;
- SECStatus rv;
- CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
- CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
- int i;
- PK11Slot * slot = pk11_SlotFromSessionHandle(hSession);
- /* RSA */
- int public_modulus_bits = 0;
- SECItem pubExp;
- RSAPrivateKey * rsaPriv;
- /* DSA */
- PQGParams pqgParam;
- DHParams dhParam;
- DSAPrivateKey * dsaPriv;
- /* Diffie Hellman */
- int private_value_bits = 0;
- DHPrivateKey * dhPriv;
- /*
- * now lets create an object to hang the attributes off of
- */
- publicKey = pk11_NewObject(slot); /* fill in the handle later */
- if (publicKey == NULL) {
- return CKR_HOST_MEMORY;
- }
- /*
- * load the template values into the publicKey
- */
- for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {
- if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
- public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
- continue;
- }
- crv = pk11_AddAttributeType(publicKey,
- pk11_attr_expand(&pPublicKeyTemplate[i]));
- if (crv != CKR_OK) break;
- }
- if (crv != CKR_OK) {
- pk11_FreeObject(publicKey);
- return CKR_HOST_MEMORY;
- }
- privateKey = pk11_NewObject(slot); /* fill in the handle later */
- if (privateKey == NULL) {
- pk11_FreeObject(publicKey);
- return CKR_HOST_MEMORY;
- }
- /*
- * now load the private key template
- */
- for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {
- if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
- private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;
- continue;
- }
- crv = pk11_AddAttributeType(privateKey,
- pk11_attr_expand(&pPrivateKeyTemplate[i]));
- if (crv != CKR_OK) break;
- }
- if (crv != CKR_OK) {
- pk11_FreeObject(publicKey);
- pk11_FreeObject(privateKey);
- return CKR_HOST_MEMORY;
- }
- pk11_DeleteAttributeType(privateKey,CKA_CLASS);
- pk11_DeleteAttributeType(privateKey,CKA_KEY_TYPE);
- pk11_DeleteAttributeType(privateKey,CKA_VALUE);
- pk11_DeleteAttributeType(publicKey,CKA_CLASS);
- pk11_DeleteAttributeType(publicKey,CKA_KEY_TYPE);
- pk11_DeleteAttributeType(publicKey,CKA_VALUE);
- /* Now Set up the parameters to generate the key (based on mechanism) */
- switch (pMechanism->mechanism) {
- case CKM_RSA_PKCS_KEY_PAIR_GEN:
- /* format the keys */
- pk11_DeleteAttributeType(publicKey,CKA_MODULUS);
- pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
- pk11_DeleteAttributeType(privateKey,CKA_MODULUS);
- pk11_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);
- pk11_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);
- pk11_DeleteAttributeType(privateKey,CKA_PRIME_1);
- pk11_DeleteAttributeType(privateKey,CKA_PRIME_2);
- pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_1);
- pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_2);
- pk11_DeleteAttributeType(privateKey,CKA_COEFFICIENT);
- key_type = CKK_RSA;
- if (public_modulus_bits == 0) {
- crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- }
- /* extract the exponent */
- crv=pk11_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
- pk11_item_expand(&pubExp));
- if (crv != CKR_OK) {
- PORT_Free(pubExp.data);
- break;
- }
- rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
- PORT_Free(pubExp.data);
- if (rsaPriv == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- /* now fill in the RSA dependent paramenters in the public key */
- crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
- pk11_item_expand(&rsaPriv->modulus));
- if (crv != CKR_OK) goto kpg_done;
- /* now fill in the RSA dependent paramenters in the private key */
- crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
- pk11_item_expand(&rsaPriv->modulus));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_MODULUS,
- pk11_item_expand(&rsaPriv->modulus));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,
- pk11_item_expand(&rsaPriv->privateExponent));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,
- pk11_item_expand(&rsaPriv->prime1));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,
- pk11_item_expand(&rsaPriv->prime2));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,
- pk11_item_expand(&rsaPriv->exponent1));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,
- pk11_item_expand(&rsaPriv->exponent2));
- if (crv != CKR_OK) goto kpg_done;
- crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,
- pk11_item_expand(&rsaPriv->coefficient));
- kpg_done:
- /* Should zeroize the contents first, since this func doesn't. */
- PORT_FreeArena(rsaPriv->arena, PR_TRUE);
- break;
- case CKM_DSA_KEY_PAIR_GEN:
- pk11_DeleteAttributeType(publicKey,CKA_VALUE);
- pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
- pk11_DeleteAttributeType(privateKey,CKA_PRIME);
- pk11_DeleteAttributeType(privateKey,CKA_SUBPRIME);
- pk11_DeleteAttributeType(privateKey,CKA_BASE);
- key_type = CKK_DSA;
- /* extract the necessary paramters and copy them to the private key */
- crv=pk11_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);
- if (crv != CKR_OK) break;
- crv=pk11_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,
- CKA_SUBPRIME);
- if (crv != CKR_OK) {
- PORT_Free(pqgParam.prime.data);
- break;
- }
- crv=pk11_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);
- if (crv != CKR_OK) {
- PORT_Free(pqgParam.prime.data);
- PORT_Free(pqgParam.subPrime.data);
- break;
- }
- crv = pk11_AddAttributeType(privateKey,CKA_PRIME,
- pk11_item_expand(&pqgParam.prime));
- if (crv != CKR_OK) {
- PORT_Free(pqgParam.prime.data);
- PORT_Free(pqgParam.subPrime.data);
- PORT_Free(pqgParam.base.data);
- break;
- }
- crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME,
- pk11_item_expand(&pqgParam.subPrime));
- if (crv != CKR_OK) {
- PORT_Free(pqgParam.prime.data);
- PORT_Free(pqgParam.subPrime.data);
- PORT_Free(pqgParam.base.data);
- break;
- }
- crv = pk11_AddAttributeType(privateKey,CKA_BASE,
- pk11_item_expand(&pqgParam.base));
- if (crv != CKR_OK) {
- PORT_Free(pqgParam.prime.data);
- PORT_Free(pqgParam.subPrime.data);
- PORT_Free(pqgParam.base.data);
- break;
- }
- /* Generate the key */
- rv = DSA_NewKey(&pqgParam, &dsaPriv);
- PORT_Free(pqgParam.prime.data);
- PORT_Free(pqgParam.subPrime.data);
- PORT_Free(pqgParam.base.data);
- if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; break; }
- /* store the generated key into the attributes */
- crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
- pk11_item_expand(&dsaPriv->publicValue));
- if (crv != CKR_OK) goto dsagn_done;
- /* now fill in the RSA dependent paramenters in the private key */
- crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
- pk11_item_expand(&dsaPriv->publicValue));
- if (crv != CKR_OK) goto dsagn_done;
- crv = pk11_AddAttributeType(privateKey,CKA_VALUE,
- pk11_item_expand(&dsaPriv->privateValue));
- dsagn_done:
- /* should zeroize, since this function doesn't. */
- PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
- break;
- case CKM_DH_PKCS_KEY_PAIR_GEN:
- pk11_DeleteAttributeType(privateKey,CKA_PRIME);
- pk11_DeleteAttributeType(privateKey,CKA_BASE);
- pk11_DeleteAttributeType(privateKey,CKA_VALUE);
- key_type = CKK_DH;
- /* extract the necessary parameters and copy them to private keys */
- crv = pk11_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
- CKA_PRIME);
- if (crv != CKR_OK) break;
- crv = pk11_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
- if (crv != CKR_OK) {
- PORT_Free(dhParam.prime.data);
- break;
- }
- crv = pk11_AddAttributeType(privateKey, CKA_PRIME,
- pk11_item_expand(&dhParam.prime));
- if (crv != CKR_OK) {
- PORT_Free(dhParam.prime.data);
- PORT_Free(dhParam.base.data);
- break;
- }
- crv = pk11_AddAttributeType(privateKey, CKA_BASE,
- pk11_item_expand(&dhParam.base));
- if (crv != CKR_OK) goto dhgn_done;
- rv = DH_NewKey(&dhParam, &dhPriv);
- PORT_Free(dhParam.prime.data);
- PORT_Free(dhParam.base.data);
- if (rv != SECSuccess) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- crv=pk11_AddAttributeType(publicKey, CKA_VALUE,
- pk11_item_expand(&dhPriv->publicValue));
- if (crv != CKR_OK) goto dhgn_done;
- crv=pk11_AddAttributeType(privateKey, CKA_VALUE,
- pk11_item_expand(&dhPriv->privateValue));
- dhgn_done:
- /* should zeroize, since this function doesn't. */
- PORT_FreeArena(dhPriv->arena, PR_TRUE);
- break;
- default:
- crv = CKR_MECHANISM_INVALID;
- }
- if (crv != CKR_OK) {
- pk11_FreeObject(privateKey);
- pk11_FreeObject(publicKey);
- return crv;
- }
- /* Add the class, key_type The loop lets us check errors blow out
- * on errors and clean up at the bottom */
- session = NULL; /* make pedtantic happy... session cannot leave the*/
- /* loop below NULL unless an error is set... */
- do {
- crv = pk11_AddAttributeType(privateKey,CKA_CLASS,&privClass,
- sizeof(CK_OBJECT_CLASS));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
- sizeof(CK_OBJECT_CLASS));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
- sizeof(CK_KEY_TYPE));
- if (crv != CKR_OK) break;
- crv = pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
- sizeof(CK_KEY_TYPE));
- if (crv != CKR_OK) break;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;
- } while (0);
- if (crv != CKR_OK) {
- pk11_FreeObject(privateKey);
- pk11_FreeObject(publicKey);
- return crv;
- }
- /*
- * handle the base object cleanup for the public Key
- */
- crv = pk11_handleObject(publicKey,session);
- if (crv != CKR_OK) {
- pk11_FreeSession(session);
- pk11_FreeObject(privateKey);
- pk11_FreeObject(publicKey);
- return crv;
- }
- /*
- * handle the base object cleanup for the private Key
- * If we have any problems, we destroy the public Key we've
- * created and linked.
- */
- crv = pk11_handleObject(privateKey,session);
- pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(privateKey);
- NSC_DestroyObject(hSession,publicKey->handle);
- return crv;
- }
- if (pk11_isTrue(privateKey,CKA_SENSITIVE)) {
- pk11_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,
- &cktrue,sizeof(CK_BBOOL));
- }
- if (pk11_isTrue(publicKey,CKA_SENSITIVE)) {
- pk11_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,
- &cktrue,sizeof(CK_BBOOL));
- }
- if (!pk11_isTrue(privateKey,CKA_EXTRACTABLE)) {
- pk11_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,
- &cktrue,sizeof(CK_BBOOL));
- }
- if (!pk11_isTrue(publicKey,CKA_EXTRACTABLE)) {
- pk11_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,
- &cktrue,sizeof(CK_BBOOL));
- }
- *phPrivateKey = privateKey->handle;
- *phPublicKey = publicKey->handle;
- return CKR_OK;
- }
- static SECItem *pk11_PackagePrivateKey(PK11Object *key)
- {
- SECKEYLowPrivateKey *lk = NULL;
- SECKEYPrivateKeyInfo *pki = NULL;
- PK11Attribute *attribute = NULL;
- PLArenaPool *arena = NULL;
- SECOidTag algorithm = SEC_OID_UNKNOWN;
- void *dummy, *param = NULL;
- SECStatus rv = SECSuccess;
- SECItem *encodedKey = NULL;
- if(!key) {
- return NULL;
- }
- attribute = pk11_FindAttribute(key, CKA_KEY_TYPE);
- if(!attribute) {
- return NULL;
- }
- lk = pk11_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue);
- pk11_FreeAttribute(attribute);
- if(!lk) {
- return NULL;
- }
- arena = PORT_NewArena(2048); /* XXX different size? */
- if(!arena) {
- rv = SECFailure;
- goto loser;
- }
- pki = (SECKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYPrivateKeyInfo));
- if(!pki) {
- rv = SECFailure;
- goto loser;
- }
- pki->arena = arena;
- param = NULL;
- switch(lk->keyType) {
- case rsaKey:
- dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
- SECKEY_RSAPrivateKeyTemplate);
- algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
- break;
- case dsaKey:
- dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
- SECKEY_DSAPrivateKeyExportTemplate);
- param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
- SECKEY_PQGParamsTemplate);
- algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
- break;
- case fortezzaKey:
- case dhKey:
- default:
- dummy = NULL;
- break;
- }
-
- if(!dummy || ((lk->keyType == dsaKey) && !param)) {
- goto loser;
- }
- rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
- (SECItem*)param);
- if(rv != SECSuccess) {
- rv = SECFailure;
- goto loser;
- }
- dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
- SEC_PRIVATE_KEY_INFO_VERSION);
- if(!dummy) {
- rv = SECFailure;
- goto loser;
- }
- encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
- SECKEY_PrivateKeyInfoTemplate);
- loser:
- if(arena) {
- PORT_FreeArena(arena, PR_TRUE);
- }
- if(lk && (lk != key->objectInfo)) {
- SECKEY_LowDestroyPrivateKey(lk);
- }
-
- if(param) {
- SECITEM_ZfreeItem((SECItem*)param, PR_TRUE);
- }
- if(rv != SECSuccess) {
- return NULL;
- }
- return encodedKey;
- }
-
- /* it doesn't matter yet, since we colapse error conditions in the
- * level above, but we really should map those few key error differences */
- CK_RV pk11_mapWrap(CK_RV crv) { return crv; }
- /* NSC_WrapKey wraps (i.e., encrypts) a key. */
- CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
- CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
- CK_ULONG_PTR pulWrappedKeyLen)
- {
- PK11Session *session;
- PK11Attribute *attribute;
- PK11Object *key;
- CK_RV crv;
- PRBool isLynks = PR_FALSE;
- CK_ULONG len = 0;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
- }
- key = pk11_ObjectFromHandle(hKey,session);
- pk11_FreeSession(session);
- if (key == NULL) {
- return CKR_KEY_HANDLE_INVALID;
- }
- switch(key->objclass) {
- case CKO_SECRET_KEY:
- attribute = pk11_FindAttribute(key,CKA_VALUE);
- if (attribute == NULL) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- if (pMechanism->mechanism == CKM_KEY_WRAP_LYNKS) {
- isLynks = PR_TRUE;
- pMechanism->mechanism = CKM_DES_ECB;
- len = *pulWrappedKeyLen;
- }
-
- crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey,
- CKA_WRAP, PK11_ENCRYPT);
- if (crv != CKR_OK) {
- pk11_FreeAttribute(attribute);
- break;
- }
- crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)attribute->attrib.pValue,
- attribute->attrib.ulValueLen,pWrappedKey,pulWrappedKeyLen);
- if (isLynks && (crv == CKR_OK)) {
- unsigned char buf[2];
- crv = pk11_calcLynxChecksum(hSession,hWrappingKey,buf,
- (unsigned char*)attribute->attrib.pValue,
- attribute->attrib.ulValueLen);
- if (len >= 10) {
- pWrappedKey[8] = buf[0];
- pWrappedKey[9] = buf[1];
- *pulWrappedKeyLen = 10;
- }
- }
- pk11_FreeAttribute(attribute);
- break;
- case CKO_PRIVATE_KEY:
- {
- SECItem *bpki = pk11_PackagePrivateKey(key);
- if(!bpki) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey,
- CKA_WRAP, PK11_ENCRYPT);
- if(crv != CKR_OK) {
- SECITEM_ZfreeItem(bpki, PR_TRUE);
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
- pWrappedKey, pulWrappedKeyLen);
- SECITEM_ZfreeItem(bpki, PR_TRUE);
- break;
- }
- default:
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- pk11_FreeObject(key);
- return pk11_mapWrap(crv);
- }
- /*
- * import a pprivate key info into the desired slot
- */
- static SECStatus
- pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
- {
- CK_BBOOL cktrue = CK_TRUE;
- CK_KEY_TYPE keyType = CKK_RSA;
- SECStatus rv = SECFailure;
- const SEC_ASN1Template *keyTemplate, *paramTemplate;
- void *paramDest = NULL;
- PLArenaPool *arena;
- SECKEYLowPrivateKey *lpk = NULL;
- SECKEYPrivateKeyInfo *pki = NULL;
- SECItem *ck_id = NULL;
- CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
- arena = PORT_NewArena(2048);
- if(!arena) {
- return SECFailure;
- }
- pki = (SECKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYPrivateKeyInfo));
- if(!pki) {
- PORT_FreeArena(arena, PR_TRUE);
- return SECFailure;
- }
- if(SEC_ASN1DecodeItem(arena, pki, SECKEY_PrivateKeyInfoTemplate, bpki)
- != SECSuccess) {
- PORT_FreeArena(arena, PR_FALSE);
- return SECFailure;
- }
- lpk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(arena,
- sizeof(SECKEYLowPrivateKey));
- if(lpk == NULL) {
- goto loser;
- }
- lpk->arena = arena;
- switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
- case SEC_OID_PKCS1_RSA_ENCRYPTION:
- keyTemplate = SECKEY_RSAPrivateKeyTemplate;
- paramTemplate = NULL;
- paramDest = NULL;
- lpk->keyType = rsaKey;
- break;
- case SEC_OID_ANSIX9_DSA_SIGNATURE:
- keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
- paramTemplate = SECKEY_PQGParamsTemplate;
- paramDest = &(lpk->u.dsa.params);
- lpk->keyType = dsaKey;
- break;
- /* case dhKey: */
- /* case fortezzaKey: */
- default:
- keyTemplate = NULL;
- paramTemplate = NULL;
- paramDest = NULL;
- break;
- }
- if(!keyTemplate) {
- goto loser;
- }
- /* decode the private key and any algorithm parameters */
- rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
- if(rv != SECSuccess) {
- goto loser;
- }
- if(paramDest && paramTemplate) {
- rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
- &(pki->algorithm.parameters));
- if(rv != SECSuccess) {
- goto loser;
- }
- }
- rv = SECFailure;
- switch (lpk->keyType) {
- case rsaKey:
- keyType = CKK_RSA;
- if(pk11_hasAttribute(key, CKA_NETSCAPE_DB)) {
- pk11_DeleteAttributeType(key, CKA_NETSCAPE_DB);
- }
- crv = pk11_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
- sizeof(keyType));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_UNWRAP, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_DECRYPT, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_SIGN, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_MODULUS,
- pk11_item_expand(&lpk->u.rsa.modulus));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
- pk11_item_expand(&lpk->u.rsa.publicExponent));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
- pk11_item_expand(&lpk->u.rsa.privateExponent));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_PRIME_1,
- pk11_item_expand(&lpk->u.rsa.prime1));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_PRIME_2,
- pk11_item_expand(&lpk->u.rsa.prime2));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_EXPONENT_1,
- pk11_item_expand(&lpk->u.rsa.exponent1));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_EXPONENT_2,
- pk11_item_expand(&lpk->u.rsa.exponent2));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_COEFFICIENT,
- pk11_item_expand(&lpk->u.rsa.coefficient));
- break;
- case dsaKey:
- keyType = CKK_DSA;
- crv = (pk11_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
- CKR_KEY_TYPE_INCONSISTENT;
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
- sizeof(keyType));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_SIGN, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
- sizeof(CK_BBOOL));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_PRIME,
- pk11_item_expand(&lpk->u.dsa.params.prime));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_SUBPRIME,
- pk11_item_expand(&lpk->u.dsa.params.subPrime));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_BASE,
- pk11_item_expand(&lpk->u.dsa.params.base));
- if(crv != CKR_OK) break;
- crv = pk11_AddAttributeType(key, CKA_VALUE,
- pk11_item_expand(&lpk->u.dsa.privateValue));
- if(crv != CKR_OK) break;
- break;
- #ifdef notdef
- case dhKey:
- template = dhTemplate;
- templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
- keyType = CKK_DH;
- break;
- #endif
- /* what about fortezza??? */
- default:
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- loser:
- if(ck_id) {
- SECITEM_ZfreeItem(ck_id, PR_TRUE);
- }
- if(lpk) {
- SECKEY_LowDestroyPrivateKey(lpk);
- }
- if(crv != CKR_OK) {
- return SECFailure;
- }
- return SECSuccess;
- }
- /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
- CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
- CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
- CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
- CK_OBJECT_HANDLE_PTR phKey)
- {
- PK11Object *key = NULL;
- PK11Session *session;
- int key_length = 0;
- unsigned char * buf = NULL;
- CK_RV crv = CKR_OK;
- int i;
- CK_ULONG bsize = ulWrappedKeyLen;
- PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
- PK11Attribute *attr = NULL;
- SECItem bpki;
- CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
- PRBool isLynks = PR_FALSE;
- /*
- * now lets create an object to hang the attributes off of
- */
- key = pk11_NewObject(slot); /* fill in the handle later */
- if (key == NULL) {
- return CKR_HOST_MEMORY;
- }
- /*
- * load the template values into the object
- */
- for (i=0; i < (int) ulAttributeCount; i++) {
- if (pTemplate[i].type == CKA_VALUE_LEN) {
- key_length = *(CK_ULONG *)pTemplate[i].pValue;
- continue;
- }
- if (pTemplate[i].type == CKA_CLASS) {
- target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
- }
- crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
- if (crv != CKR_OK) break;
- }
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
- /* LYNKS is a special key wrapping mechanism */
- if (pMechanism->mechanism == CKM_KEY_WRAP_LYNKS) {
- isLynks = PR_TRUE;
- pMechanism->mechanism = CKM_DES_ECB;
- ulWrappedKeyLen -= 2; /* don't decrypt the checksum */
- }
- crv = pk11_DecryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
- PK11_DECRYPT);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return pk11_mapWrap(crv);
- }
- /* allocate the buffer to decrypt into
- * this assumes the unwrapped key is never larger than the
- * wrapped key. For all the mechanisms we support this is true */
- buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen);
- bsize = ulWrappedKeyLen;
- crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- PORT_Free(buf);
- return pk11_mapWrap(crv);
- }
- switch(target_type) {
- case CKO_SECRET_KEY:
- if (!pk11_hasAttribute(key,CKA_KEY_TYPE)) {
- crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- }
- /* verify the Lynx checksum */
- if (isLynks) {
- unsigned char checkSum[2];
- crv = pk11_calcLynxChecksum(hSession,hUnwrappingKey,checkSum,
- buf,bsize);
- if (crv != CKR_OK) break;
- if ((ulWrappedKeyLen != 8) || (pWrappedKey[8] != checkSum[0])
- || (pWrappedKey[9] != checkSum[1])) {
- crv = CKR_WRAPPED_KEY_INVALID;
- break;
- }
- }
- if(key_length == 0) {
- key_length = bsize;
- }
- if (key_length > MAX_KEY_LEN) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
-
- /* add the value */
- crv = pk11_AddAttributeType(key,CKA_VALUE,buf,key_length);
- break;
- case CKO_PRIVATE_KEY:
- bpki.data = (unsigned char *)buf;
- bpki.len = bsize;
- crv = CKR_OK;
- if(pk11_unwrapPrivateKey(key, &bpki) != SECSuccess) {
- crv = CKR_TEMPLATE_INCOMPLETE;
- }
- break;
- default:
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- PORT_ZFree(buf, bsize);
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- /* get the session */
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- pk11_FreeObject(key);
- return CKR_SESSION_HANDLE_INVALID;
- }
- /*
- * handle the base object stuff
- */
- crv = pk11_handleObject(key,session);
- pk11_FreeSession(session);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
- *phKey = key->handle;
- return CKR_OK;
- }
- /*
- * The SSL key gen mechanism create's lots of keys. This function handles the
- * details of each of these key creation.
- */
- static CK_RV
- pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey,
- PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
- CK_OBJECT_HANDLE *keyHandle)
- {
- PK11Object *key;
- PK11Session *session;
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_RV crv = CKR_HOST_MEMORY;
- /*
- * now lets create an object to hang the attributes off of
- */
- *keyHandle = CK_INVALID_KEY;
- key = pk11_NewObject(baseKey->slot);
- if (key == NULL) return CKR_HOST_MEMORY;
- key->wasDerived = PR_TRUE;
- crv = pk11_CopyObject(key,baseKey);
- if (crv != CKR_OK) goto loser;
- if (isMacKey) {
- crv = pk11_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- crv = pk11_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) goto loser;
- }
- crv = pk11_forceAttribute(key,CKA_VALUE,keyBlock,keySize);
- if (crv != CKR_OK) goto loser;
- /* get the session */
- crv = CKR_HOST_MEMORY;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) { goto loser; }
- crv = pk11_handleObject(key,session);
- pk11_FreeSession(session);
- if (crv == CKR_OK) {
- *keyHandle = key->handle;
- return crv;
- }
- loser:
- if (key) pk11_FreeObject(key);
- return crv;
- }
- /*
- * if there is an error, we need to free the keys we already created in SSL
- * This is the routine that will do it..
- */
- static void
- pk11_freeSSLKeys(CK_SESSION_HANDLE session,
- CK_SSL3_KEY_MAT_OUT *returnedMaterial ) {
- if (returnedMaterial->hClientMacSecret != CK_INVALID_KEY) {
- NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
- }
- if (returnedMaterial->hServerMacSecret != CK_INVALID_KEY) {
- NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
- }
- if (returnedMaterial->hClientKey != CK_INVALID_KEY) {
- NSC_DestroyObject(session, returnedMaterial->hClientKey);
- }
- if (returnedMaterial->hServerKey != CK_INVALID_KEY) {
- NSC_DestroyObject(session, returnedMaterial->hServerKey);
- }
- }
- /*
- * when deriving from sensitive and extractable keys, we need to preserve some
- * of the semantics in the derived key. This helper routine maintains these
- * semantics.
- */
- static CK_RV
- pk11_DeriveSensitiveCheck(PK11Object *baseKey,PK11Object *destKey) {
- PRBool hasSensitive;
- PRBool sensitive;
- PRBool hasExtractable;
- PRBool extractable;
- CK_RV crv = PR_TRUE;
- PK11Attribute *att;
- hasSensitive = PR_FALSE;
- att = pk11_FindAttribute(destKey,CKA_SENSITIVE);
- if (att) {
- hasSensitive = PR_FALSE;
- sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
- pk11_FreeAttribute(att);
- }
- hasExtractable = PR_FALSE;
- att = pk11_FindAttribute(destKey,CKA_EXTRACTABLE);
- if (att) {
- hasExtractable = PR_FALSE;
- extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
- pk11_FreeAttribute(att);
- }
- /* don't make a key more accessible */
- if (pk11_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive &&
- (sensitive == PR_FALSE)) {
- return CKR_KEY_FUNCTION_NOT_PERMITTED;
- }
- if (!pk11_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable &&
- (extractable == PR_TRUE)) {
- return CKR_KEY_FUNCTION_NOT_PERMITTED;
- }
- /* inherit parent's sensitivity */
- if (!hasSensitive) {
- att = pk11_FindAttribute(baseKey,CKA_SENSITIVE);
- if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
- crv = pk11_defaultAttribute(destKey,pk11_attr_expand(&att->attrib));
- pk11_FreeAttribute(att);
- if (crv != CKR_OK) return crv;
- }
- if (!hasExtractable) {
- att = pk11_FindAttribute(baseKey,CKA_EXTRACTABLE);
- if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
- crv = pk11_defaultAttribute(destKey,pk11_attr_expand(&att->attrib));
- pk11_FreeAttribute(att);
- if (crv != CKR_OK) return crv;
- }
- /* we should inherit the parent's always extractable/ never sensitive info,
- * but handleObject always forces this attributes, so we would need to do
- * something special. */
- return CKR_OK;
- }
- /*
- * make known fixed PKCS #11 key types to their sizes in bytes
- */
- static unsigned long
- pk11_MapKeySize(CK_KEY_TYPE keyType) {
- switch (keyType) {
- case CKK_CDMF:
- return 8;
- case CKK_DES:
- return 8;
- case CKK_DES2:
- return 16;
- case CKK_DES3:
- return 24;
- /* IDEA and CAST need to be added */
- default:
- break;
- }
- return 0;
- }
- #define PHASH_STATE_MAX_LEN 20
- /* TLS P_hash function */
- static SECStatus
- pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label,
- SECItem *seed, SECItem *result)
- {
- unsigned char state[PHASH_STATE_MAX_LEN];
- unsigned char outbuf[PHASH_STATE_MAX_LEN];
- unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size;
- unsigned int remaining;
- unsigned char *res;
- SECStatus status;
- HMACContext *cx;
- SECStatus rv = SECFailure;
- PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
- PORT_Assert((seed != NULL) && (seed->data != NULL));
- PORT_Assert((result != NULL) && (result->data != NULL));
- remaining = result->len;
- res = result->data;
- if (label != NULL)
- label_len = PORT_Strlen(label);
- cx = HMAC_Create(alg, secret->data, secret->len);
- if (cx == NULL)
- goto loser;
- /* initialize the state = A(1) = HMAC_hash(secret, seed) */
- HMAC_Begin(cx);
- HMAC_Update(cx, (unsigned char *)label, label_len);
- HMAC_Update(cx, seed->data, seed->len);
- status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
- if (status != SECSuccess)
- goto loser;
- /* generate a block at a time until we're done */
- while (remaining > 0) {
- HMAC_Begin(cx);
- HMAC_Update(cx, state, state_len);
- if (label_len)
- HMAC_Update(cx, (unsigned char *)label, label_len);
- HMAC_Update(cx, seed->data, seed->len);
- status = HMAC_Finish(cx, outbuf, &outbuf_len, PHASH_STATE_MAX_LEN);
- if (status != SECSuccess)
- goto loser;
- /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */
- HMAC_Begin(cx);
- HMAC_Update(cx, state, state_len);
- status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
- if (status != SECSuccess)
- goto loser;
- chunk_size = PR_MIN(outbuf_len, remaining);
- PORT_Memcpy(res, &outbuf, chunk_size);
- res += chunk_size;
- remaining -= chunk_size;
- }
- rv = SECSuccess;
- loser:
- /* if (cx) HMAC_Destroy(cx); */
- /* clear out state so it's not left on the stack */
- if (cx) HMAC_Destroy(cx);
- PORT_Memset(state, 0, sizeof(state));
- PORT_Memset(outbuf, 0, sizeof(outbuf));
- return rv;
- }
- static SECStatus
- pk11_PRF(const SECItem *secret, const char *label, SECItem *seed,
- SECItem *result)
- {
- SECStatus rv = SECFailure, status;
- unsigned int i;
- SECItem tmp = { siBuffer, NULL, 0};
- SECItem S1;
- SECItem S2;
- PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
- PORT_Assert((seed != NULL) && (seed->data != NULL));
- PORT_Assert((result != NULL) && (result->data != NULL));
- S1.type = siBuffer;
- S1.len = (secret->len / 2) + (secret->len & 1);
- S1.data = secret->data;
- S2.type = siBuffer;
- S2.len = S1.len;
- S2.data = secret->data + (secret->len - S2.len);
- tmp.data = (unsigned char*)PORT_Alloc(result->len);
- if (tmp.data == NULL)
- goto loser;
- tmp.len = result->len;
- status = pk11_P_hash(SEC_OID_MD5, &S1, label, seed, result);
- if (status != SECSuccess)
- goto loser;
- status = pk11_P_hash(SEC_OID_SHA1, &S2, label, seed, &tmp);
- if (status != SECSuccess)
- goto loser;
- for (i = 0; i < result->len; i++)
- result->data[i] ^= tmp.data[i];
- rv = SECSuccess;
- loser:
- if (tmp.data != NULL)
- PORT_ZFree(tmp.data, tmp.len);
- return rv;
- }
- /*
- * SSL Key generation given pre master secret
- */
- static char *mixers[] = { "A", "BB", "CCC", "DDDD", "EEEEE", "FFFFFF", "GGGGGGG"};
- #define NUM_MIXERS 7
- #define SSL3_PMS_LENGTH 48
- #define SSL3_MASTER_SECRET_LENGTH 48
- /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
- CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
- CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
- CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
- CK_OBJECT_HANDLE_PTR phKey)
- {
- PK11Session * session;
- PK11Slot * slot = pk11_SlotFromSessionHandle(hSession);
- PK11Object * key;
- PK11Object * sourceKey;
- PK11Attribute * att;
- PK11Attribute * att2;
- unsigned char * buf;
- SHA1Context * sha;
- MD5Context * md5;
- MD2Context * md2;
- CK_ULONG macSize;
- CK_ULONG tmpKeySize;
- CK_ULONG IVSize;
- CK_ULONG keySize = 0;
- CK_RV crv = CKR_OK;
- CK_BBOOL cktrue = CK_TRUE;
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
- CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
- CK_KEY_DERIVATION_STRING_DATA *stringPtr;
- PRBool isTLS = PR_FALSE;
- SECStatus rv;
- int i;
- unsigned int outLen;
- unsigned char sha_out[SHA1_LENGTH];
- unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
- unsigned char key_block2[MD5_LENGTH];
- /*
- * now lets create an object to hang the attributes off of
- */
- if (phKey) *phKey = CK_INVALID_KEY;
- key = pk11_NewObject(slot); /* fill in the handle later */
- if (key == NULL) {
- return CKR_HOST_MEMORY;
- }
- /*
- * load the template values into the object
- */
- for (i=0; i < (int) ulAttributeCount; i++) {
- crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
- if (crv != CKR_OK) break;
- if (pTemplate[i].type == CKA_KEY_TYPE) {
- keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
- }
- if (pTemplate[i].type == CKA_VALUE_LEN) {
- keySize = *(CK_ULONG *)pTemplate[i].pValue;
- }
- }
- if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
- if (keySize == 0) {
- keySize = pk11_MapKeySize(keyType);
- }
- /* Derive can only create SECRET KEY's currently... */
- classType = CKO_SECRET_KEY;
- crv = pk11_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- return crv;
- }
- /* look up the base key we're deriving with */
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- pk11_FreeObject(key);
- return CKR_SESSION_HANDLE_INVALID;
- }
- sourceKey = pk11_ObjectFromHandle(hBaseKey,session);
- pk11_FreeSession(session);
- if (sourceKey == NULL) {
- pk11_FreeObject(key);
- return CKR_KEY_HANDLE_INVALID;
- }
- /* don't use key derive to expose sensitive keys */
- crv = pk11_DeriveSensitiveCheck(sourceKey,key);
- if (crv != CKR_OK) {
- pk11_FreeObject(key);
- pk11_FreeObject(sourceKey);
- return crv;
- }
- /* get the value of the base key */
- att = pk11_FindAttribute(sourceKey,CKA_VALUE);
- if (att == NULL) {
- pk11_FreeObject(key);
- pk11_FreeObject(sourceKey);
- return CKR_KEY_HANDLE_INVALID;
- }
- switch (pMechanism->mechanism) {
- /*
- * generate the master secret
- */
- case CKM_TLS_MASTER_KEY_DERIVE:
- isTLS = PR_TRUE;
- /* fall thru */
- case CKM_SSL3_MASTER_KEY_DERIVE:
- {
- CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
- SSL3RSAPreMasterSecret *rsa_pms;
- /* first do the consistancy checkes */
- if (att->attrib.ulValueLen != SSL3_PMS_LENGTH) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);
- if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
- CKK_GENERIC_SECRET)) {
- if (att2) pk11_FreeAttribute(att2);
- crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
- break;
- }
- pk11_FreeAttribute(att2);
- if (keyType != CKK_GENERIC_SECRET) {
- crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
- break;
- }
- if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
- crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
- break;
- }
- /* finally do the key gen */
- ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
- pMechanism->pParameter;
- if (ssl3_master->pVersion) {
- rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
- /* don't leak more key material then necessary for SSL to work */
- if (key->wasDerived) {
- ssl3_master->pVersion->major = 0xff;
- ssl3_master->pVersion->minor = 0xff;
- } else {
- ssl3_master->pVersion->major = rsa_pms->client_version[0];
- ssl3_master->pVersion->minor = rsa_pms->client_version[1];
- }
- }
- if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
- crv = CKR_MECHANISM_PARAM_INVALID;
- break;
- }
- if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
- crv = CKR_MECHANISM_PARAM_INVALID;
- break;
- }
- if (isTLS) {
- unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
- SECItem crsr = { siBuffer, NULL, 0 };
- SECItem master = { siBuffer, NULL, 0 };
- SECItem pms = { siBuffer, NULL, 0 };
- SECStatus status;
- pms.data = (unsigned char*)att->attrib.pValue;
- pms.len = att->attrib.ulValueLen;
- master.data = key_block;
- master.len = SSL3_MASTER_SECRET_LENGTH;
- crsr.data = crsrdata;
- crsr.len = sizeof(crsrdata);
- PORT_Memcpy(crsrdata, ssl3_master->RandomInfo.pClientRandom,
- SSL3_RANDOM_LENGTH);
- PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
- ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
- status = pk11_PRF(&pms, "master secret", &crsr, &master);
- if (status != SECSuccess) {
- crv = CKR_FUNCTION_FAILED;
- break;
- }
- } else {
- /* now allocate the hash contexts */
- md5 = MD5_NewContext();
- if (md5 == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- sha = SHA1_NewContext();
- if (sha == NULL) {
- PORT_Free(md5);
- crv = CKR_HOST_MEMORY;
- break;
- }
- for (i = 0; i < 3; i++) {
- SHA1_Begin(sha);
- SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
- SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- SHA1_Update(sha, ssl3_master->RandomInfo.pClientRandom,
- ssl3_master->RandomInfo.ulClientRandomLen);
- SHA1_Update(sha, ssl3_master->RandomInfo.pServerRandom,
- ssl3_master->RandomInfo.ulServerRandomLen);
- SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
- PORT_Assert(outLen == SHA1_LENGTH);
- MD5_Begin(md5);
- MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- MD5_Update(md5, sha_out, outLen);
- MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
- PORT_Assert(outLen == MD5_LENGTH);
- }
- PORT_Free(md5);
- PORT_Free(sha);
- }
- /* store the results */
- crv = pk11_forceAttribute
- (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);
- if (crv != CKR_OK) break;
- keyType = CKK_GENERIC_SECRET;
- crv = pk11_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
- if (isTLS) {
- /* TLS's master secret is used to "sign" finished msgs with PRF. */
- /* XXX This seems like a hack. But PK11_Derive only accepts
- * one "operation" argument. */
- crv = pk11_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) break;
- crv = pk11_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) break;
- /* While we're here, we might as well force this, too. */
- crv = pk11_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) break;
- }
- break;
- }
- case CKM_TLS_KEY_AND_MAC_DERIVE:
- isTLS = PR_TRUE;
- /* fall thru */
- case CKM_SSL3_KEY_AND_MAC_DERIVE:
- {
- CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
- CK_SSL3_KEY_MAT_OUT * ssl3_keys_out;
- CK_ULONG effKeySize;
- crv = pk11_DeriveSensitiveCheck(sourceKey,key);
- if (crv != CKR_OK) break;
- if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
- crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
- break;
- }
- att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);
- if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
- CKK_GENERIC_SECRET)) {
- if (att2) pk11_FreeAttribute(att2);
- crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
- break;
- }
- pk11_FreeAttribute(att2);
- md5 = MD5_NewContext();
- if (md5 == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- sha = SHA1_NewContext();
- if (sha == NULL) {
- PORT_Free(md5);
- crv = CKR_HOST_MEMORY;
- break;
- }
- ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
- /*
- * clear out our returned keys so we can recover on failure
- */
- ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
- ssl3_keys_out->hClientMacSecret = CK_INVALID_KEY;
- ssl3_keys_out->hServerMacSecret = CK_INVALID_KEY;
- ssl3_keys_out->hClientKey = CK_INVALID_KEY;
- ssl3_keys_out->hServerKey = CK_INVALID_KEY;
- /*
- * generate the key material: This looks amazingly similar to the
- * PMS code, and is clearly crying out for a function to provide it.
- */
- if (isTLS) {
- SECStatus status;
- SECItem master = { siBuffer, NULL, 0 };
- SECItem srcr = { siBuffer, NULL, 0 };
- SECItem keyblk = { siBuffer, NULL, 0 };
- unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
- master.data = (unsigned char*)att->attrib.pValue;
- master.len = att->attrib.ulValueLen;
- srcr.data = srcrdata;
- srcr.len = sizeof srcrdata;
- keyblk.data = key_block;
- keyblk.len = sizeof key_block;
- PORT_Memcpy(srcrdata,
- ssl3_keys->RandomInfo.pServerRandom,
- SSL3_RANDOM_LENGTH);
- PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
- ssl3_keys->RandomInfo.pClientRandom,
- SSL3_RANDOM_LENGTH);
- status = pk11_PRF(&master, "key expansion", &srcr, &keyblk);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- } else {
- /* key_block =
- * MD5(master_secret + SHA('A' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * MD5(master_secret + SHA('BB' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * MD5(master_secret + SHA('CCC' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * [...];
- */
- for (i = 0; i < NUM_MIXERS; i++) {
- SHA1_Begin(sha);
- SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
- SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- SHA1_Update(sha, ssl3_keys->RandomInfo.pServerRandom,
- ssl3_keys->RandomInfo.ulServerRandomLen);
- SHA1_Update(sha, ssl3_keys->RandomInfo.pClientRandom,
- ssl3_keys->RandomInfo.ulClientRandomLen);
- SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
- PORT_Assert(outLen == SHA1_LENGTH);
- MD5_Begin(md5);
- MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- MD5_Update(md5, sha_out, outLen);
- MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
- PORT_Assert(outLen == MD5_LENGTH);
- }
- }
- /*
- * Put the key material where it goes.
- */
- i = 0; /* now shows how much consumed */
- macSize = ssl3_keys->ulMacSizeInBits/8;
- effKeySize = ssl3_keys->ulKeySizeInBits/8;
- IVSize = ssl3_keys->ulIVSizeInBits/8;
- if (keySize == 0) {
- effKeySize = keySize;
- }
- /*
- * The key_block is partitioned as follows:
- * client_write_MAC_secret[CipherSpec.hash_size]
- */
- crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
- &ssl3_keys_out->hClientMacSecret);
- if (crv != CKR_OK)
- goto key_and_mac_derive_fail;
- i += macSize;
- /*
- * server_write_MAC_secret[CipherSpec.hash_size]
- */
- crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
- &ssl3_keys_out->hServerMacSecret);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- i += macSize;
- if (keySize) {
- if (!ssl3_keys->bIsExport) {
- /*
- ** Generate Domestic write keys and IVs.
- ** client_write_key[CipherSpec.key_material]
- */
- crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
- keySize, &ssl3_keys_out->hClientKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- i += keySize;
- /*
- ** server_write_key[CipherSpec.key_material]
- */
- crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
- keySize, &ssl3_keys_out->hServerKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- i += keySize;
- /*
- ** client_write_IV[CipherSpec.IV_size]
- */
- PORT_Memcpy(ssl3_keys_out->pIVClient, &key_block[i], IVSize);
- i += IVSize;
- /*
- ** server_write_IV[CipherSpec.IV_size]
- */
- PORT_Memcpy(ssl3_keys_out->pIVServer, &key_block[i], IVSize);
- i += IVSize;
- } else if (!isTLS) {
- /*
- ** Generate SSL3 Export write keys and IVs.
- ** client_write_key[CipherSpec.key_material]
- ** final_client_write_key = MD5(client_write_key +
- ** ClientHello.random + ServerHello.random);
- */
- MD5_Begin(md5);
- MD5_Update(md5, &key_block[i], effKeySize);
- MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
- ssl3_keys->RandomInfo.ulClientRandomLen);
- MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom,
- ssl3_keys->RandomInfo.ulServerRandomLen);
- MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
- i += effKeySize;
- crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,
- keySize,&ssl3_keys_out->hClientKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- /*
- ** server_write_key[CipherSpec.key_material]
- ** final_server_write_key = MD5(server_write_key +
- ** ServerHello.random + ClientHello.random);
- */
- MD5_Begin(md5);
- MD5_Update(md5, &key_block[i], effKeySize);
- MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom,
- ssl3_keys->RandomInfo.ulServerRandomLen);
- MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
- ssl3_keys->RandomInfo.ulClientRandomLen);
- MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
- i += effKeySize;
- crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,
- keySize,&ssl3_keys_out->hServerKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- /*
- ** client_write_IV =
- ** MD5(ClientHello.random + ServerHello.random);
- */
- MD5_Begin(md5);
- MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
- ssl3_keys->RandomInfo.ulClientRandomLen);
- MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom,
- ssl3_keys->RandomInfo.ulServerRandomLen);
- MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
- PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
- /*
- ** server_write_IV =
- ** MD5(ServerHello.random + ClientHello.random);
- */
- MD5_Begin(md5);
- MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom,
- ssl3_keys->RandomInfo.ulServerRandomLen);
- MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
- ssl3_keys->RandomInfo.ulClientRandomLen);
- MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
- PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
- } else {
- /*
- ** Generate TLS Export write keys and IVs.
- */
- SECStatus status;
- SECItem secret = { siBuffer, NULL, 0 };
- SECItem crsr = { siBuffer, NULL, 0 };
- SECItem keyblk = { siBuffer, NULL, 0 };
- unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
- crsr.data = crsrdata;
- crsr.len = sizeof crsrdata;
- PORT_Memcpy(crsrdata,
- ssl3_keys->RandomInfo.pClientRandom,
- SSL3_RANDOM_LENGTH);
- PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
- ssl3_keys->RandomInfo.pServerRandom,
- SSL3_RANDOM_LENGTH);
- /*
- ** client_write_key[CipherSpec.key_material]
- ** final_client_write_key = PRF(client_write_key,
- ** "client write key",
- ** client_random + server_random);
- */
- secret.data = &key_block[i];
- secret.len = effKeySize;
- i += effKeySize;
- keyblk.data = key_block2;
- keyblk.len = sizeof key_block2;
- status = pk11_PRF(&secret, "client write key", &crsr, &keyblk);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2,
- keySize, &ssl3_keys_out->hClientKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- /*
- ** server_write_key[CipherSpec.key_material]
- ** final_server_write_key = PRF(server_write_key,
- ** "server write key",
- ** client_random + server_random);
- */
- secret.data = &key_block[i];
- secret.len = effKeySize;
- i += effKeySize;
- keyblk.data = key_block2;
- keyblk.len = sizeof key_block2;
- status = pk11_PRF(&secret, "server write key", &crsr, &keyblk);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2,
- keySize, &ssl3_keys_out->hServerKey);
- if (crv != CKR_OK) {
- goto key_and_mac_derive_fail;
- }
- /*
- ** iv_block = PRF("", "IV block",
- ** client_random + server_random);
- ** client_write_IV[SecurityParameters.IV_size]
- ** server_write_IV[SecurityParameters.IV_size]
- */
- if (IVSize) {
- secret.data = NULL;
- secret.len = 0;
- keyblk.data = &key_block[i];
- keyblk.len = 2 * IVSize;
- status = pk11_PRF(&secret, "IV block", &crsr, &keyblk);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
- PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
- IVSize);
- }
- }
- }
- crv = CKR_OK;
- if (0) {
- key_and_mac_derive_fail:
- if (crv == CKR_OK)
- crv = CKR_FUNCTION_FAILED;
- pk11_freeSSLKeys(hSession, ssl3_keys_out);
- }
- MD5_DestroyContext(md5, PR_TRUE);
- SHA1_DestroyContext(sha, PR_TRUE);
- pk11_FreeObject(key);
- key = NULL;
- break;
- }
- case CKM_CONCATENATE_BASE_AND_KEY:
- {
- PK11Object *newKey;
- crv = pk11_DeriveSensitiveCheck(sourceKey,key);
- if (crv != CKR_OK) break;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- crv = CKR_SESSION_HANDLE_INVALID;
- break;
- }
- newKey = pk11_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
- pMechanism->pParameter,session);
- pk11_FreeSession(session);
- if ( newKey == NULL) {
- crv = CKR_KEY_HANDLE_INVALID;
- break;
- }
- if (pk11_isTrue(newKey,CKA_SENSITIVE)) {
- crv = pk11_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,
- sizeof(CK_BBOOL));
- if (crv != CKR_OK) {
- pk11_FreeObject(newKey);
- break;
- }
- }
- att2 = pk11_FindAttribute(newKey,CKA_VALUE);
- if (att2 == NULL) {
- pk11_FreeObject(newKey);
- crv = CKR_KEY_HANDLE_INVALID;
- break;
- }
- tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;
- if (keySize == 0) keySize = tmpKeySize;
- if (keySize > tmpKeySize) {
- pk11_FreeObject(newKey);
- pk11_FreeAttribute(att2);
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- buf = (unsigned char*)PORT_Alloc(tmpKeySize);
- if (buf == NULL) {
- pk11_FreeAttribute(att2);
- pk11_FreeObject(newKey);
- crv = CKR_HOST_MEMORY;
- break;
- }
- PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
- PORT_Memcpy(buf+att->attrib.ulValueLen,
- att2->attrib.pValue,att2->attrib.ulValueLen);
- crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
- PORT_ZFree(buf,tmpKeySize);
- pk11_FreeAttribute(att2);
- pk11_FreeObject(newKey);
- break;
- }
- case CKM_CONCATENATE_BASE_AND_DATA:
- stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
- tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
- if (keySize == 0) keySize = tmpKeySize;
- if (keySize > tmpKeySize) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- buf = (unsigned char*)PORT_Alloc(tmpKeySize);
- if (buf == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
- PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,
- stringPtr->ulLen);
- crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
- PORT_ZFree(buf,tmpKeySize);
- break;
- case CKM_CONCATENATE_DATA_AND_BASE:
- stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
- tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
- if (keySize == 0) keySize = tmpKeySize;
- if (keySize > tmpKeySize) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- buf = (unsigned char*)PORT_Alloc(tmpKeySize);
- if (buf == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);
- PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,
- att->attrib.ulValueLen);
- crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
- PORT_ZFree(buf,tmpKeySize);
- break;
- case CKM_XOR_BASE_AND_DATA:
- stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
- tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);
- if (keySize == 0) keySize = tmpKeySize;
- if (keySize > tmpKeySize) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- buf = (unsigned char*)PORT_Alloc(keySize);
- if (buf == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
-
- PORT_Memcpy(buf,att->attrib.pValue,keySize);
- for (i=0; i < (int)keySize; i++) {
- buf[i] ^= stringPtr->pData[i];
- }
- crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
- PORT_ZFree(buf,keySize);
- break;
- case CKM_EXTRACT_KEY_FROM_KEY:
- {
- /* the following assumes 8 bits per byte */
- CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
- CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
- CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
- if (keySize == 0) {
- crv = CKR_TEMPLATE_INCOMPLETE;
- break;
- }
- /* make sure we have enough bits in the original key */
- if (att->attrib.ulValueLen <
- (offset + keySize + ((shift != 0)? 1 :0)) ) {
- crv = CKR_MECHANISM_PARAM_INVALID;
- break;
- }
- buf = (unsigned char*)PORT_Alloc(keySize);
- if (buf == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- /* copy the bits we need into the new key */
- for (i=0; i < (int)keySize; i++) {
- unsigned char *value =
- ((unsigned char *)att->attrib.pValue)+offset+i;
- if (shift) {
- buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
- } else {
- buf[i] = value[0];
- }
- }
- crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
- PORT_ZFree(buf,keySize);
- break;
- }
- case CKM_MD2_KEY_DERIVATION:
- if (keySize == 0) keySize = MD2_LENGTH;
- if (keySize > MD2_LENGTH) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- /* now allocate the hash contexts */
- md2 = MD2_NewContext();
- if (md2 == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- MD2_Begin(md2);
- MD2_Update(md2,(const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- MD2_End(md2,key_block,&outLen,MD2_LENGTH);
- MD2_DestroyContext(md2, PR_TRUE);
- crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);
- break;
- case CKM_MD5_KEY_DERIVATION:
- if (keySize == 0) keySize = MD5_LENGTH;
- if (keySize > MD5_LENGTH) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- /* now allocate the hash contexts */
- md5 = MD5_NewContext();
- if (md5 == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- MD5_Begin(md5);
- MD5_Update(md5,(const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- MD5_End(md5,key_block,&outLen,MD5_LENGTH);
- MD5_DestroyContext(md5, PR_TRUE);
- crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);
- break;
- case CKM_SHA1_KEY_DERIVATION:
- if (keySize == 0) keySize = SHA1_LENGTH;
- if (keySize > SHA1_LENGTH) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- /* now allocate the hash contexts */
- sha = SHA1_NewContext();
- if (sha == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- SHA1_Begin(sha);
- SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,
- att->attrib.ulValueLen);
- SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);
- SHA1_DestroyContext(sha, PR_TRUE);
- crv = pk11_forceAttribute(key,CKA_VALUE,key_block,keySize);
- break;
- case CKM_DH_PKCS_DERIVE:
- {
- SECItem derived, dhPublic;
- SECItem dhPrime, dhValue;
- /* sourceKey - values for the local existing low key */
- /* get prime and value attributes */
- crv = pk11_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
- if (crv != SECSuccess) break;
- crv = pk11_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
- if (crv != SECSuccess) {
- PORT_Free(dhPrime.data);
- break;
- }
- dhPublic.data = pMechanism->pParameter;
- dhPublic.len = pMechanism->ulParameterLen;
- /* calculate private value - oct */
- rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
- PORT_Free(dhPrime.data);
- PORT_Free(dhValue.data);
-
- if (rv == SECSuccess) {
- pk11_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
- PORT_ZFree(derived.data, derived.len);
- } else
- crv = CKR_HOST_MEMORY;
-
- break;
- }
- default:
- crv = CKR_MECHANISM_INVALID;
- }
- pk11_FreeAttribute(att);
- pk11_FreeObject(sourceKey);
- if (crv != CKR_OK) {
- if (key) pk11_FreeObject(key);
- return crv;
- }
- /* link the key object into the list */
- if (key) {
- /* get the session */
- key->wasDerived = PR_TRUE;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) {
- pk11_FreeObject(key);
- return CKR_HOST_MEMORY;
- }
- crv = pk11_handleObject(key,session);
- pk11_FreeSession(session);
- if (crv == CKR_OK) {
- *phKey = key->handle;
- return crv;
- }
- pk11_FreeObject(key);
- }
- return crv;
- }
- /* NSC_GetFunctionStatus obtains an updated status of a function running
- * in parallel with an application. */
- CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
- {
- return CKR_FUNCTION_NOT_PARALLEL;
- }
- /* NSC_CancelFunction cancels a function running in parallel */
- CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession)
- {
- return CKR_FUNCTION_NOT_PARALLEL;
- }
- /* NSC_GetOperationState saves the state of the cryptographic
- *operation in a session.
- * NOTE: This code only works for digest functions for now. eventually need
- * to add full flatten/resurect to our state stuff so that all types of state
- * can be saved */
- CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
- {
- PK11SessionContext *context;
- PK11Session *session;
- CK_RV crv;
- /* make sure we're legal */
- crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, &session);
- if (crv != CKR_OK) return crv;
- *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE)
- + sizeof(PK11ContextType);
- if (pOperationState == NULL) {
- pk11_FreeSession(session);
- return CKR_OK;
- }
- PORT_Memcpy(pOperationState,&context->type,sizeof(PK11ContextType));
- pOperationState += sizeof(PK11ContextType);
- PORT_Memcpy(pOperationState,&context->currentMech,
- sizeof(CK_MECHANISM_TYPE));
- pOperationState += sizeof(CK_MECHANISM_TYPE);
- PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen);
- pk11_FreeSession(session);
- return CKR_OK;
- }
- #define pk11_Decrement(stateSize,len)
- stateSize = ((stateSize) > (CK_ULONG)(len)) ?
- ((stateSize) - (CK_ULONG)(len)) : 0;
- /* NSC_SetOperationState restores the state of the cryptographic
- * operation in a session. This is coded like it can restore lots of
- * states, but it only works for truly flat cipher structures. */
- CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
- CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
- {
- PK11SessionContext *context;
- PK11Session *session;
- PK11ContextType type;
- CK_MECHANISM mech;
- CK_RV crv = CKR_OK;
- while (ulOperationStateLen != 0) {
- /* get what type of state we're dealing with... */
- PORT_Memcpy(&type,pOperationState, sizeof(PK11ContextType));
- /* fix up session contexts based on type */
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
- context = pk11_ReturnContextByType(session, type);
- pk11_SetContextByType(session, type, NULL);
- if (context) {
- pk11_FreeContext(context);
- }
- pOperationState += sizeof(PK11ContextType);
- pk11_Decrement(ulOperationStateLen,sizeof(PK11ContextType));
- /* get the mechanism structure */
- PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE));
- pOperationState += sizeof(CK_MECHANISM_TYPE);
- pk11_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
- /* should be filled in... but not necessary for hash */
- mech.pParameter = NULL;
- mech.ulParameterLen = 0;
- switch (type) {
- case PK11_HASH:
- crv = NSC_DigestInit(hSession,&mech);
- if (crv != CKR_OK) break;
- crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE,
- NULL);
- if (crv != CKR_OK) break;
- PORT_Memcpy(context->cipherInfo,pOperationState,
- context->cipherInfoLen);
- pOperationState += context->cipherInfoLen;
- pk11_Decrement(ulOperationStateLen,context->cipherInfoLen);
- break;
- default:
- /* do sign/encrypt/decrypt later */
- crv = CKR_SAVED_STATE_INVALID;
- }
- pk11_FreeSession(session);
- if (crv != CKR_OK) break;
- }
- return crv;
- }
- /* Dual-function cryptographic operations */
- /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
- * operation. */
- CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
- CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
- CK_ULONG_PTR pulEncryptedPartLen)
- {
- CK_RV crv;
- crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
- pulEncryptedPartLen);
- if (crv != CKR_OK) return crv;
- crv = NSC_DigestUpdate(hSession,pPart,ulPartLen);
- return crv;
- }
- /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
- * digesting operation. */
- CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
- CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
- {
- CK_RV crv;
- crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen,
- pPart, pulPartLen);
- if (crv != CKR_OK) return crv;
- crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen);
- return crv;
- }
- /* NSC_SignEncryptUpdate continues a multiple-part signing and
- * encryption operation. */
- CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
- CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
- CK_ULONG_PTR pulEncryptedPartLen)
- {
- CK_RV crv;
- crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
- pulEncryptedPartLen);
- if (crv != CKR_OK) return crv;
- crv = NSC_SignUpdate(hSession,pPart,ulPartLen);
- return crv;
- }
- /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
- * and verify operation. */
- CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
- CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
- CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
- {
- CK_RV crv;
- crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen,
- pData, pulDataLen);
- if (crv != CKR_OK) return crv;
- crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
- return crv;
- }
- /* NSC_DigestKey continues a multi-part message-digesting operation,
- * by digesting the value of a secret key as part of the data already digested.
- */
- CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
- {
- PK11Session *session = NULL;
- PK11Object *key = NULL;
- PK11Attribute *att;
- CK_RV crv;
- session = pk11_SessionFromHandle(hSession);
- if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
- key = pk11_ObjectFromHandle(hKey,session);
- pk11_FreeSession(session);
- if (key == NULL) return CKR_KEY_HANDLE_INVALID;
- /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
- /* make sure it's a valid key for this operation */
- if (key->objclass != CKO_SECRET_KEY) {
- pk11_FreeObject(key);
- return CKR_KEY_TYPE_INCONSISTENT;
- }
- /* get the key value */
- att = pk11_FindAttribute(key,CKA_VALUE);
- pk11_FreeObject(key);
- crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue,
- att->attrib.ulValueLen);
- pk11_FreeAttribute(att);
- return crv;
- }