andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * This file maps various PKCS #11 Mechanisms to related mechanisms, key andre@0: * types, and ASN.1 encodings. andre@0: */ andre@0: #include "seccomon.h" andre@0: #include "secmod.h" andre@0: #include "secmodi.h" andre@0: #include "pkcs11t.h" andre@0: #include "pk11func.h" andre@0: #include "secitem.h" andre@0: #include "secder.h" andre@0: #include "secasn1.h" andre@0: #include "secoid.h" andre@0: #include "secerr.h" andre@0: andre@0: /************************************************************* andre@0: * local static and global data andre@0: *************************************************************/ andre@0: andre@0: /* andre@0: * Tables used for Extended mechanism mapping (currently not used) andre@0: */ andre@0: typedef struct { andre@0: CK_MECHANISM_TYPE keyGen; andre@0: CK_KEY_TYPE keyType; andre@0: CK_MECHANISM_TYPE type; andre@0: CK_MECHANISM_TYPE padType; andre@0: int blockSize; andre@0: int iv; andre@0: } pk11MechanismData; andre@0: andre@0: static pk11MechanismData pk11_default = andre@0: { CKM_GENERIC_SECRET_KEY_GEN, CKK_GENERIC_SECRET, andre@0: CKM_FAKE_RANDOM, CKM_FAKE_RANDOM, 8, 8 }; andre@0: static pk11MechanismData *pk11_MechanismTable = NULL; andre@0: static int pk11_MechTableSize = 0; andre@0: static int pk11_MechEntrySize = 0; andre@0: andre@0: /* andre@0: * list of mechanisms we're willing to wrap secret keys with. andre@0: * This list is ordered by preference. andre@0: */ andre@0: CK_MECHANISM_TYPE wrapMechanismList[] = { andre@0: CKM_DES3_ECB, andre@0: CKM_CAST5_ECB, andre@0: CKM_AES_ECB, andre@0: CKM_CAMELLIA_ECB, andre@0: CKM_SEED_ECB, andre@0: CKM_CAST5_ECB, andre@0: CKM_DES_ECB, andre@0: CKM_KEY_WRAP_LYNKS, andre@0: CKM_IDEA_ECB, andre@0: CKM_CAST3_ECB, andre@0: CKM_CAST_ECB, andre@0: CKM_RC5_ECB, andre@0: CKM_RC2_ECB, andre@0: CKM_CDMF_ECB, andre@0: CKM_SKIPJACK_WRAP, andre@0: }; andre@0: andre@0: int wrapMechanismCount = sizeof(wrapMechanismList)/sizeof(wrapMechanismList[0]); andre@0: andre@0: /********************************************************************* andre@0: * Mechanism Mapping functions andre@0: *********************************************************************/ andre@0: andre@0: /* andre@0: * lookup an entry in the mechanism table. If none found, return the andre@0: * default structure. andre@0: */ andre@0: static pk11MechanismData * andre@0: pk11_lookup(CK_MECHANISM_TYPE type) andre@0: { andre@0: int i; andre@0: for (i=0; i < pk11_MechEntrySize; i++) { andre@0: if (pk11_MechanismTable[i].type == type) { andre@0: return (&pk11_MechanismTable[i]); andre@0: } andre@0: } andre@0: return &pk11_default; andre@0: } andre@0: andre@0: /* andre@0: * find the best key wrap mechanism for this slot. andre@0: */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_GetBestWrapMechanism(PK11SlotInfo *slot) andre@0: { andre@0: int i; andre@0: for (i=0; i < wrapMechanismCount; i++) { andre@0: if (PK11_DoesMechanism(slot,wrapMechanismList[i])) { andre@0: return wrapMechanismList[i]; andre@0: } andre@0: } andre@0: return CKM_INVALID_MECHANISM; andre@0: } andre@0: andre@0: /* andre@0: * NOTE: This is not thread safe. Called at init time, and when loading andre@0: * a new Entry. It is reasonably safe as long as it is not re-entered andre@0: * (readers will always see a consistant table) andre@0: * andre@0: * This routine is called to add entries to the mechanism table, once there, andre@0: * they can not be removed. andre@0: */ andre@0: void andre@0: PK11_AddMechanismEntry(CK_MECHANISM_TYPE type, CK_KEY_TYPE key, andre@0: CK_MECHANISM_TYPE keyGen, andre@0: CK_MECHANISM_TYPE padType, andre@0: int ivLen, int blockSize) andre@0: { andre@0: int tableSize = pk11_MechTableSize; andre@0: int size = pk11_MechEntrySize; andre@0: int entry = size++; andre@0: pk11MechanismData *old = pk11_MechanismTable; andre@0: pk11MechanismData *newt = pk11_MechanismTable; andre@0: andre@0: andre@0: if (size > tableSize) { andre@0: int oldTableSize = tableSize; andre@0: tableSize += 10; andre@0: newt = PORT_NewArray(pk11MechanismData, tableSize); andre@0: if (newt == NULL) return; andre@0: andre@0: if (old) PORT_Memcpy(newt, old, oldTableSize*sizeof(*newt)); andre@0: } else old = NULL; andre@0: andre@0: newt[entry].type = type; andre@0: newt[entry].keyType = key; andre@0: newt[entry].keyGen = keyGen; andre@0: newt[entry].padType = padType; andre@0: newt[entry].iv = ivLen; andre@0: newt[entry].blockSize = blockSize; andre@0: andre@0: pk11_MechanismTable = newt; andre@0: pk11_MechTableSize = tableSize; andre@0: pk11_MechEntrySize = size; andre@0: if (old) PORT_Free(old); andre@0: } andre@0: andre@0: /* andre@0: * Get the mechanism needed for the given key type andre@0: */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_GetKeyMechanism(CK_KEY_TYPE type) andre@0: { andre@0: switch (type) { andre@0: case CKK_SEED: andre@0: return CKM_SEED_CBC; andre@0: case CKK_CAMELLIA: andre@0: return CKM_CAMELLIA_CBC; andre@0: case CKK_NSS_CHACHA20: andre@0: return CKM_NSS_CHACHA20_POLY1305; andre@0: case CKK_AES: andre@0: return CKM_AES_CBC; andre@0: case CKK_DES: andre@0: return CKM_DES_CBC; andre@0: case CKK_DES3: andre@0: return CKM_DES3_KEY_GEN; andre@0: case CKK_DES2: andre@0: return CKM_DES2_KEY_GEN; andre@0: case CKK_CDMF: andre@0: return CKM_CDMF_CBC; andre@0: case CKK_RC2: andre@0: return CKM_RC2_CBC; andre@0: case CKK_RC4: andre@0: return CKM_RC4; andre@0: case CKK_RC5: andre@0: return CKM_RC5_CBC; andre@0: case CKK_SKIPJACK: andre@0: return CKM_SKIPJACK_CBC64; andre@0: case CKK_BATON: andre@0: return CKM_BATON_CBC128; andre@0: case CKK_JUNIPER: andre@0: return CKM_JUNIPER_CBC128; andre@0: case CKK_IDEA: andre@0: return CKM_IDEA_CBC; andre@0: case CKK_CAST: andre@0: return CKM_CAST_CBC; andre@0: case CKK_CAST3: andre@0: return CKM_CAST3_CBC; andre@0: case CKK_CAST5: andre@0: return CKM_CAST5_CBC; andre@0: case CKK_RSA: andre@0: return CKM_RSA_PKCS; andre@0: case CKK_DSA: andre@0: return CKM_DSA; andre@0: case CKK_DH: andre@0: return CKM_DH_PKCS_DERIVE; andre@0: case CKK_KEA: andre@0: return CKM_KEA_KEY_DERIVE; andre@0: case CKK_EC: /* CKK_ECDSA is deprecated */ andre@0: return CKM_ECDSA; andre@0: case CKK_GENERIC_SECRET: andre@0: default: andre@0: return CKM_SHA_1_HMAC; andre@0: } andre@0: } andre@0: andre@0: /* andre@0: * Get the key type needed for the given mechanism andre@0: */ andre@0: CK_KEY_TYPE andre@0: PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) andre@0: { andre@0: switch (type) { andre@0: case CKM_SEED_ECB: andre@0: case CKM_SEED_CBC: andre@0: case CKM_SEED_MAC: andre@0: case CKM_SEED_MAC_GENERAL: andre@0: case CKM_SEED_CBC_PAD: andre@0: case CKM_SEED_KEY_GEN: andre@0: return CKK_SEED; andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_CAMELLIA_MAC: andre@0: case CKM_CAMELLIA_MAC_GENERAL: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_CAMELLIA_KEY_GEN: andre@0: return CKK_CAMELLIA; andre@0: case CKM_NSS_CHACHA20_POLY1305: andre@0: return CKK_NSS_CHACHA20; andre@0: case CKM_AES_ECB: andre@0: case CKM_AES_CBC: andre@0: case CKM_AES_CCM: andre@0: case CKM_AES_CTR: andre@0: case CKM_AES_CTS: andre@0: case CKM_AES_GCM: andre@0: case CKM_AES_MAC: andre@0: case CKM_AES_MAC_GENERAL: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_AES_KEY_GEN: andre@0: case CKM_NETSCAPE_AES_KEY_WRAP: andre@0: case CKM_NETSCAPE_AES_KEY_WRAP_PAD: andre@0: return CKK_AES; andre@0: case CKM_DES_ECB: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES_MAC: andre@0: case CKM_DES_MAC_GENERAL: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES_KEY_GEN: andre@0: case CKM_KEY_WRAP_LYNKS: andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: return CKK_DES; andre@0: case CKM_DES3_ECB: andre@0: case CKM_DES3_CBC: andre@0: case CKM_DES3_MAC: andre@0: case CKM_DES3_MAC_GENERAL: andre@0: case CKM_DES3_CBC_PAD: andre@0: return (len == 16) ? CKK_DES2 : CKK_DES3; andre@0: case CKM_DES2_KEY_GEN: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: return CKK_DES2; andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_DES3_KEY_GEN: andre@0: return CKK_DES3; andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CDMF_MAC: andre@0: case CKM_CDMF_MAC_GENERAL: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CDMF_KEY_GEN: andre@0: return CKK_CDMF; andre@0: case CKM_RC2_ECB: andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_MAC: andre@0: case CKM_RC2_MAC_GENERAL: andre@0: case CKM_RC2_CBC_PAD: andre@0: case CKM_RC2_KEY_GEN: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: return CKK_RC2; andre@0: case CKM_RC4: andre@0: case CKM_RC4_KEY_GEN: andre@0: return CKK_RC4; andre@0: case CKM_RC5_ECB: andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_MAC: andre@0: case CKM_RC5_MAC_GENERAL: andre@0: case CKM_RC5_CBC_PAD: andre@0: case CKM_RC5_KEY_GEN: andre@0: return CKK_RC5; andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_SKIPJACK_KEY_GEN: andre@0: case CKM_SKIPJACK_WRAP: andre@0: case CKM_SKIPJACK_PRIVATE_WRAP: andre@0: return CKK_SKIPJACK; andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_BATON_WRAP: andre@0: case CKM_BATON_KEY_GEN: andre@0: return CKK_BATON; andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: case CKM_JUNIPER_WRAP: andre@0: case CKM_JUNIPER_KEY_GEN: andre@0: return CKK_JUNIPER; andre@0: case CKM_IDEA_CBC: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_IDEA_MAC: andre@0: case CKM_IDEA_MAC_GENERAL: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_IDEA_KEY_GEN: andre@0: return CKK_IDEA; andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST_MAC: andre@0: case CKM_CAST_MAC_GENERAL: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST_KEY_GEN: andre@0: case CKM_PBE_MD5_CAST_CBC: andre@0: return CKK_CAST; andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST3_MAC: andre@0: case CKM_CAST3_MAC_GENERAL: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST3_KEY_GEN: andre@0: case CKM_PBE_MD5_CAST3_CBC: andre@0: return CKK_CAST3; andre@0: case CKM_CAST5_ECB: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_CAST5_MAC: andre@0: case CKM_CAST5_MAC_GENERAL: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_CAST5_KEY_GEN: andre@0: case CKM_PBE_MD5_CAST5_CBC: andre@0: return CKK_CAST5; andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_9796: andre@0: case CKM_RSA_X_509: andre@0: case CKM_MD2_RSA_PKCS: andre@0: case CKM_MD5_RSA_PKCS: andre@0: case CKM_SHA1_RSA_PKCS: andre@0: case CKM_SHA224_RSA_PKCS: andre@0: case CKM_SHA256_RSA_PKCS: andre@0: case CKM_SHA384_RSA_PKCS: andre@0: case CKM_SHA512_RSA_PKCS: andre@0: case CKM_KEY_WRAP_SET_OAEP: andre@0: case CKM_RSA_PKCS_KEY_PAIR_GEN: andre@0: case CKM_RSA_X9_31_KEY_PAIR_GEN: andre@0: return CKK_RSA; andre@0: case CKM_DSA: andre@0: case CKM_DSA_SHA1: andre@0: case CKM_DSA_KEY_PAIR_GEN: andre@0: return CKK_DSA; andre@0: case CKM_DH_PKCS_DERIVE: andre@0: case CKM_DH_PKCS_KEY_PAIR_GEN: andre@0: return CKK_DH; andre@0: case CKM_KEA_KEY_DERIVE: andre@0: case CKM_KEA_KEY_PAIR_GEN: andre@0: return CKK_KEA; andre@0: case CKM_ECDSA: andre@0: case CKM_ECDSA_SHA1: andre@0: case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */ andre@0: case CKM_ECDH1_DERIVE: andre@0: return CKK_EC; /* CKK_ECDSA is deprecated */ andre@0: case CKM_SSL3_PRE_MASTER_KEY_GEN: andre@0: case CKM_GENERIC_SECRET_KEY_GEN: andre@0: case CKM_SSL3_MASTER_KEY_DERIVE: andre@0: case CKM_SSL3_MASTER_KEY_DERIVE_DH: andre@0: case CKM_SSL3_KEY_AND_MAC_DERIVE: andre@0: case CKM_SSL3_SHA1_MAC: andre@0: case CKM_SSL3_MD5_MAC: andre@0: case CKM_TLS_MASTER_KEY_DERIVE: andre@0: case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: andre@0: case CKM_TLS_MASTER_KEY_DERIVE_DH: andre@0: case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: andre@0: case CKM_TLS_KEY_AND_MAC_DERIVE: andre@0: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: andre@0: case CKM_SHA_1_HMAC: andre@0: case CKM_SHA_1_HMAC_GENERAL: andre@0: case CKM_SHA224_HMAC: andre@0: case CKM_SHA224_HMAC_GENERAL: andre@0: case CKM_SHA256_HMAC: andre@0: case CKM_SHA256_HMAC_GENERAL: andre@0: case CKM_SHA384_HMAC: andre@0: case CKM_SHA384_HMAC_GENERAL: andre@0: case CKM_SHA512_HMAC: andre@0: case CKM_SHA512_HMAC_GENERAL: andre@0: case CKM_MD2_HMAC: andre@0: case CKM_MD2_HMAC_GENERAL: andre@0: case CKM_MD5_HMAC: andre@0: case CKM_MD5_HMAC_GENERAL: andre@0: case CKM_TLS_PRF_GENERAL: andre@0: case CKM_NSS_TLS_PRF_GENERAL_SHA256: andre@0: return CKK_GENERIC_SECRET; andre@0: default: andre@0: return pk11_lookup(type)->keyType; andre@0: } andre@0: } andre@0: andre@0: /* andre@0: * Get the Key Gen Mechanism needed for the given andre@0: * crypto mechanism andre@0: */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_GetKeyGen(CK_MECHANISM_TYPE type) andre@0: { andre@0: return PK11_GetKeyGenWithSize(type, 0); andre@0: } andre@0: andre@0: CK_MECHANISM_TYPE andre@0: PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) andre@0: { andre@0: switch (type) { andre@0: case CKM_SEED_ECB: andre@0: case CKM_SEED_CBC: andre@0: case CKM_SEED_MAC: andre@0: case CKM_SEED_MAC_GENERAL: andre@0: case CKM_SEED_CBC_PAD: andre@0: case CKM_SEED_KEY_GEN: andre@0: return CKM_SEED_KEY_GEN; andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_CAMELLIA_MAC: andre@0: case CKM_CAMELLIA_MAC_GENERAL: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_CAMELLIA_KEY_GEN: andre@0: return CKM_CAMELLIA_KEY_GEN; andre@0: case CKM_NSS_CHACHA20_POLY1305: andre@0: return CKM_NSS_CHACHA20_KEY_GEN; andre@0: case CKM_AES_ECB: andre@0: case CKM_AES_CBC: andre@0: case CKM_AES_CCM: andre@0: case CKM_AES_CTR: andre@0: case CKM_AES_CTS: andre@0: case CKM_AES_GCM: andre@0: case CKM_AES_MAC: andre@0: case CKM_AES_MAC_GENERAL: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_AES_KEY_GEN: andre@0: return CKM_AES_KEY_GEN; andre@0: case CKM_DES_ECB: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES_MAC: andre@0: case CKM_DES_MAC_GENERAL: andre@0: case CKM_KEY_WRAP_LYNKS: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES_KEY_GEN: andre@0: return CKM_DES_KEY_GEN; andre@0: case CKM_DES3_ECB: andre@0: case CKM_DES3_CBC: andre@0: case CKM_DES3_MAC: andre@0: case CKM_DES3_MAC_GENERAL: andre@0: case CKM_DES3_CBC_PAD: andre@0: return (size == 16) ? CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN; andre@0: case CKM_DES3_KEY_GEN: andre@0: return CKM_DES3_KEY_GEN; andre@0: case CKM_DES2_KEY_GEN: andre@0: return CKM_DES2_KEY_GEN; andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CDMF_MAC: andre@0: case CKM_CDMF_MAC_GENERAL: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CDMF_KEY_GEN: andre@0: return CKM_CDMF_KEY_GEN; andre@0: case CKM_RC2_ECB: andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_MAC: andre@0: case CKM_RC2_MAC_GENERAL: andre@0: case CKM_RC2_CBC_PAD: andre@0: case CKM_RC2_KEY_GEN: andre@0: return CKM_RC2_KEY_GEN; andre@0: case CKM_RC4: andre@0: case CKM_RC4_KEY_GEN: andre@0: return CKM_RC4_KEY_GEN; andre@0: case CKM_RC5_ECB: andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_MAC: andre@0: case CKM_RC5_MAC_GENERAL: andre@0: case CKM_RC5_CBC_PAD: andre@0: case CKM_RC5_KEY_GEN: andre@0: return CKM_RC5_KEY_GEN; andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_SKIPJACK_WRAP: andre@0: case CKM_SKIPJACK_KEY_GEN: andre@0: return CKM_SKIPJACK_KEY_GEN; andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_BATON_WRAP: andre@0: case CKM_BATON_KEY_GEN: andre@0: return CKM_BATON_KEY_GEN; andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: case CKM_JUNIPER_WRAP: andre@0: case CKM_JUNIPER_KEY_GEN: andre@0: return CKM_JUNIPER_KEY_GEN; andre@0: case CKM_IDEA_CBC: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_IDEA_MAC: andre@0: case CKM_IDEA_MAC_GENERAL: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_IDEA_KEY_GEN: andre@0: return CKM_IDEA_KEY_GEN; andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST_MAC: andre@0: case CKM_CAST_MAC_GENERAL: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST_KEY_GEN: andre@0: return CKM_CAST_KEY_GEN; andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST3_MAC: andre@0: case CKM_CAST3_MAC_GENERAL: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST3_KEY_GEN: andre@0: return CKM_CAST3_KEY_GEN; andre@0: case CKM_CAST5_ECB: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_CAST5_MAC: andre@0: case CKM_CAST5_MAC_GENERAL: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_CAST5_KEY_GEN: andre@0: return CKM_CAST5_KEY_GEN; andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_9796: andre@0: case CKM_RSA_X_509: andre@0: case CKM_MD2_RSA_PKCS: andre@0: case CKM_MD5_RSA_PKCS: andre@0: case CKM_SHA1_RSA_PKCS: andre@0: case CKM_SHA224_RSA_PKCS: andre@0: case CKM_SHA256_RSA_PKCS: andre@0: case CKM_SHA384_RSA_PKCS: andre@0: case CKM_SHA512_RSA_PKCS: andre@0: case CKM_KEY_WRAP_SET_OAEP: andre@0: case CKM_RSA_PKCS_KEY_PAIR_GEN: andre@0: return CKM_RSA_PKCS_KEY_PAIR_GEN; andre@0: case CKM_RSA_X9_31_KEY_PAIR_GEN: andre@0: return CKM_RSA_X9_31_KEY_PAIR_GEN; andre@0: case CKM_DSA: andre@0: case CKM_DSA_SHA1: andre@0: case CKM_DSA_KEY_PAIR_GEN: andre@0: return CKM_DSA_KEY_PAIR_GEN; andre@0: case CKM_DH_PKCS_DERIVE: andre@0: case CKM_DH_PKCS_KEY_PAIR_GEN: andre@0: return CKM_DH_PKCS_KEY_PAIR_GEN; andre@0: case CKM_KEA_KEY_DERIVE: andre@0: case CKM_KEA_KEY_PAIR_GEN: andre@0: return CKM_KEA_KEY_PAIR_GEN; andre@0: case CKM_ECDSA: andre@0: case CKM_ECDSA_SHA1: andre@0: case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */ andre@0: case CKM_ECDH1_DERIVE: andre@0: return CKM_EC_KEY_PAIR_GEN; andre@0: case CKM_SSL3_PRE_MASTER_KEY_GEN: andre@0: case CKM_SSL3_MASTER_KEY_DERIVE: andre@0: case CKM_SSL3_KEY_AND_MAC_DERIVE: andre@0: case CKM_SSL3_SHA1_MAC: andre@0: case CKM_SSL3_MD5_MAC: andre@0: case CKM_TLS_MASTER_KEY_DERIVE: andre@0: case CKM_TLS_KEY_AND_MAC_DERIVE: andre@0: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: andre@0: return CKM_SSL3_PRE_MASTER_KEY_GEN; andre@0: case CKM_SHA_1_HMAC: andre@0: case CKM_SHA_1_HMAC_GENERAL: andre@0: case CKM_SHA224_HMAC: andre@0: case CKM_SHA224_HMAC_GENERAL: andre@0: case CKM_SHA256_HMAC: andre@0: case CKM_SHA256_HMAC_GENERAL: andre@0: case CKM_SHA384_HMAC: andre@0: case CKM_SHA384_HMAC_GENERAL: andre@0: case CKM_SHA512_HMAC: andre@0: case CKM_SHA512_HMAC_GENERAL: andre@0: case CKM_MD2_HMAC: andre@0: case CKM_MD2_HMAC_GENERAL: andre@0: case CKM_MD5_HMAC: andre@0: case CKM_MD5_HMAC_GENERAL: andre@0: case CKM_TLS_PRF_GENERAL: andre@0: case CKM_NSS_TLS_PRF_GENERAL_SHA256: andre@0: case CKM_GENERIC_SECRET_KEY_GEN: andre@0: return CKM_GENERIC_SECRET_KEY_GEN; andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_PBA_SHA1_WITH_SHA1_HMAC: andre@0: case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: andre@0: case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: andre@0: case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: case CKM_PKCS5_PBKD2: andre@0: return type; andre@0: default: andre@0: return pk11_lookup(type)->keyGen; andre@0: } andre@0: } andre@0: andre@0: /* andre@0: * get the mechanism block size andre@0: */ andre@0: int andre@0: PK11_GetBlockSize(CK_MECHANISM_TYPE type,SECItem *params) andre@0: { andre@0: CK_RC5_PARAMS *rc5_params; andre@0: CK_RC5_CBC_PARAMS *rc5_cbc_params; andre@0: switch (type) { andre@0: case CKM_RC5_ECB: andre@0: if ((params) && (params->data)) { andre@0: rc5_params = (CK_RC5_PARAMS *) params->data; andre@0: return (rc5_params->ulWordsize)*2; andre@0: } andre@0: return 8; andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: if ((params) && (params->data)) { andre@0: rc5_cbc_params = (CK_RC5_CBC_PARAMS *) params->data; andre@0: return (rc5_cbc_params->ulWordsize)*2; andre@0: } andre@0: return 8; andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_RC2_ECB: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: case CKM_RC2_CBC: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_RC2_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: return 8; andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: return 4; andre@0: case CKM_SEED_ECB: andre@0: case CKM_SEED_CBC: andre@0: case CKM_SEED_CBC_PAD: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_AES_ECB: andre@0: case CKM_AES_CBC: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: return 16; andre@0: case CKM_BATON_ECB96: andre@0: return 12; andre@0: case CKM_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: return 0; andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_9796: andre@0: case CKM_RSA_X_509: andre@0: /*actually it's the modulus length of the key!*/ andre@0: return -1; /* failure */ andre@0: default: andre@0: return pk11_lookup(type)->blockSize; andre@0: } andre@0: } andre@0: andre@0: /* andre@0: * get the iv length andre@0: */ andre@0: int andre@0: PK11_GetIVLength(CK_MECHANISM_TYPE type) andre@0: { andre@0: switch (type) { andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_RC2_ECB: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_SKIPJACK_WRAP: andre@0: case CKM_BATON_WRAP: andre@0: case CKM_RC5_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: return 0; andre@0: case CKM_RC2_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: case CKM_RC5_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_RC5_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: return 8; andre@0: case CKM_SEED_CBC: andre@0: case CKM_SEED_CBC_PAD: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_AES_CBC: andre@0: case CKM_AES_CBC_PAD: andre@0: return 16; andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: return 24; andre@0: case CKM_RC4: andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_9796: andre@0: case CKM_RSA_X_509: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: return 0; andre@0: default: andre@0: return pk11_lookup(type)->iv; andre@0: } andre@0: } andre@0: andre@0: andre@0: /* These next two utilities are here to help facilitate future andre@0: * Dynamic Encrypt/Decrypt symetric key mechanisms, and to allow functions andre@0: * like SSL and S-MIME to automatically add them. andre@0: */ andre@0: SECItem * andre@0: pk11_ParamFromIVWithLen(CK_MECHANISM_TYPE type, SECItem *iv, int keyLen) andre@0: { andre@0: CK_RC2_CBC_PARAMS *rc2_params = NULL; andre@0: CK_RC2_PARAMS *rc2_ecb_params = NULL; andre@0: CK_RC5_PARAMS *rc5_params = NULL; andre@0: CK_RC5_CBC_PARAMS *rc5_cbc_params = NULL; andre@0: SECItem *param; andre@0: andre@0: param = (SECItem *)PORT_Alloc(sizeof(SECItem)); andre@0: if (param == NULL) return NULL; andre@0: param->data = NULL; andre@0: param->len = 0; andre@0: param->type = 0; andre@0: switch (type) { andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_X_509: andre@0: case CKM_RSA_9796: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: case CKM_RC4: andre@0: break; andre@0: case CKM_RC2_ECB: andre@0: rc2_ecb_params = (CK_RC2_PARAMS *)PORT_Alloc(sizeof(CK_RC2_PARAMS)); andre@0: if (rc2_ecb_params == NULL) break; andre@0: /* Maybe we should pass the key size in too to get this value? */ andre@0: *rc2_ecb_params = keyLen ? keyLen*8 : 128; andre@0: param->data = (unsigned char *) rc2_ecb_params; andre@0: param->len = sizeof(CK_RC2_PARAMS); andre@0: break; andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: rc2_params = (CK_RC2_CBC_PARAMS *)PORT_Alloc(sizeof(CK_RC2_CBC_PARAMS)); andre@0: if (rc2_params == NULL) break; andre@0: /* Maybe we should pass the key size in too to get this value? */ andre@0: rc2_params->ulEffectiveBits = keyLen ? keyLen*8 : 128; andre@0: if (iv && iv->data) andre@0: PORT_Memcpy(rc2_params->iv,iv->data,sizeof(rc2_params->iv)); andre@0: param->data = (unsigned char *) rc2_params; andre@0: param->len = sizeof(CK_RC2_CBC_PARAMS); andre@0: break; andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: rc5_cbc_params = (CK_RC5_CBC_PARAMS *) andre@0: PORT_Alloc(sizeof(CK_RC5_CBC_PARAMS) + ((iv) ? iv->len : 0)); andre@0: if (rc5_cbc_params == NULL) break; andre@0: if (iv && iv->data && iv->len) { andre@0: rc5_cbc_params->pIv = ((CK_BYTE_PTR) rc5_cbc_params) andre@0: + sizeof(CK_RC5_CBC_PARAMS); andre@0: PORT_Memcpy(rc5_cbc_params->pIv,iv->data,iv->len); andre@0: rc5_cbc_params->ulIvLen = iv->len; andre@0: rc5_cbc_params->ulWordsize = iv->len/2; andre@0: } else { andre@0: rc5_cbc_params->ulWordsize = 4; andre@0: rc5_cbc_params->pIv = NULL; andre@0: rc5_cbc_params->ulIvLen = 0; andre@0: } andre@0: rc5_cbc_params->ulRounds = 16; andre@0: param->data = (unsigned char *) rc5_cbc_params; andre@0: param->len = sizeof(CK_RC5_CBC_PARAMS); andre@0: break; andre@0: case CKM_RC5_ECB: andre@0: rc5_params = (CK_RC5_PARAMS *)PORT_Alloc(sizeof(CK_RC5_PARAMS)); andre@0: if (rc5_params == NULL) break; andre@0: if (iv && iv->data && iv->len) { andre@0: rc5_params->ulWordsize = iv->len/2; andre@0: } else { andre@0: rc5_params->ulWordsize = 4; andre@0: } andre@0: rc5_params->ulRounds = 16; andre@0: param->data = (unsigned char *) rc5_params; andre@0: param->len = sizeof(CK_RC5_PARAMS); andre@0: break; andre@0: andre@0: case CKM_SEED_CBC: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_AES_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: if ((iv == NULL) || (iv->data == NULL)) break; andre@0: param->data = (unsigned char*)PORT_Alloc(iv->len); andre@0: if (param->data != NULL) { andre@0: PORT_Memcpy(param->data,iv->data,iv->len); andre@0: param->len = iv->len; andre@0: } andre@0: break; andre@0: /* unknown mechanism, pass IV in if it's there */ andre@0: default: andre@0: if (pk11_lookup(type)->iv == 0) { andre@0: break; andre@0: } andre@0: if ((iv == NULL) || (iv->data == NULL)) { andre@0: break; andre@0: } andre@0: param->data = (unsigned char*)PORT_Alloc(iv->len); andre@0: if (param->data != NULL) { andre@0: PORT_Memcpy(param->data,iv->data,iv->len); andre@0: param->len = iv->len; andre@0: } andre@0: break; andre@0: } andre@0: return param; andre@0: } andre@0: andre@0: /* These next two utilities are here to help facilitate future andre@0: * Dynamic Encrypt/Decrypt symetric key mechanisms, and to allow functions andre@0: * like SSL and S-MIME to automatically add them. andre@0: */ andre@0: SECItem * andre@0: PK11_ParamFromIV(CK_MECHANISM_TYPE type,SECItem *iv) andre@0: { andre@0: return pk11_ParamFromIVWithLen(type, iv, 0); andre@0: } andre@0: andre@0: unsigned char * andre@0: PK11_IVFromParam(CK_MECHANISM_TYPE type,SECItem *param,int *len) andre@0: { andre@0: CK_RC2_CBC_PARAMS *rc2_params; andre@0: CK_RC5_CBC_PARAMS *rc5_cbc_params; andre@0: andre@0: *len = 0; andre@0: switch (type) { andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_RSA_PKCS: andre@0: case CKM_RSA_X_509: andre@0: case CKM_RSA_9796: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: case CKM_RC4: andre@0: return NULL; andre@0: case CKM_RC2_ECB: andre@0: return NULL; andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: rc2_params = (CK_RC2_CBC_PARAMS *)param->data; andre@0: *len = sizeof(rc2_params->iv); andre@0: return &rc2_params->iv[0]; andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: rc5_cbc_params = (CK_RC5_CBC_PARAMS *) param->data; andre@0: *len = rc5_cbc_params->ulIvLen; andre@0: return rc5_cbc_params->pIv; andre@0: case CKM_SEED_CBC: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_AES_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: break; andre@0: /* unknown mechanism, pass IV in if it's there */ andre@0: default: andre@0: break; andre@0: } andre@0: if (param->data) { andre@0: *len = param->len; andre@0: } andre@0: return param->data; andre@0: } andre@0: andre@0: typedef struct sec_rc5cbcParameterStr { andre@0: SECItem version; andre@0: SECItem rounds; andre@0: SECItem blockSizeInBits; andre@0: SECItem iv; andre@0: } sec_rc5cbcParameter; andre@0: andre@0: static const SEC_ASN1Template sec_rc5ecb_parameter_template[] = { andre@0: { SEC_ASN1_SEQUENCE, andre@0: 0, NULL, sizeof(sec_rc5cbcParameter) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,version) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,rounds) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,blockSizeInBits) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template sec_rc5cbc_parameter_template[] = { andre@0: { SEC_ASN1_SEQUENCE, andre@0: 0, NULL, sizeof(sec_rc5cbcParameter) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,version) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,rounds) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc5cbcParameter,blockSizeInBits) }, andre@0: { SEC_ASN1_OCTET_STRING, andre@0: offsetof(sec_rc5cbcParameter,iv) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: typedef struct sec_rc2cbcParameterStr { andre@0: SECItem rc2ParameterVersion; andre@0: SECItem iv; andre@0: } sec_rc2cbcParameter; andre@0: andre@0: static const SEC_ASN1Template sec_rc2cbc_parameter_template[] = { andre@0: { SEC_ASN1_SEQUENCE, andre@0: 0, NULL, sizeof(sec_rc2cbcParameter) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc2cbcParameter,rc2ParameterVersion) }, andre@0: { SEC_ASN1_OCTET_STRING, andre@0: offsetof(sec_rc2cbcParameter,iv) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template sec_rc2ecb_parameter_template[] = { andre@0: { SEC_ASN1_SEQUENCE, andre@0: 0, NULL, sizeof(sec_rc2cbcParameter) }, andre@0: { SEC_ASN1_INTEGER, andre@0: offsetof(sec_rc2cbcParameter,rc2ParameterVersion) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: /* S/MIME picked id values to represent differnt keysizes */ andre@0: /* I do have a formula, but it ain't pretty, and it only works because you andre@0: * can always match three points to a parabola:) */ andre@0: static unsigned char rc2_map(SECItem *version) andre@0: { andre@0: long x; andre@0: andre@0: x = DER_GetInteger(version); andre@0: andre@0: switch (x) { andre@0: case 58: return 128; andre@0: case 120: return 64; andre@0: case 160: return 40; andre@0: } andre@0: return 128; andre@0: } andre@0: andre@0: static unsigned long rc2_unmap(unsigned long x) andre@0: { andre@0: switch (x) { andre@0: case 128: return 58; andre@0: case 64: return 120; andre@0: case 40: return 160; andre@0: } andre@0: return 58; andre@0: } andre@0: andre@0: andre@0: andre@0: /* Generate a mechaism param from a type, and iv. */ andre@0: SECItem * andre@0: PK11_ParamFromAlgid(SECAlgorithmID *algid) andre@0: { andre@0: CK_RC2_CBC_PARAMS * rc2_cbc_params = NULL; andre@0: CK_RC2_PARAMS * rc2_ecb_params = NULL; andre@0: CK_RC5_CBC_PARAMS * rc5_cbc_params = NULL; andre@0: CK_RC5_PARAMS * rc5_ecb_params = NULL; andre@0: PLArenaPool * arena = NULL; andre@0: SECItem * mech = NULL; andre@0: SECOidTag algtag; andre@0: SECStatus rv; andre@0: CK_MECHANISM_TYPE type; andre@0: /* initialize these to prevent UMRs in the ASN1 decoder. */ andre@0: SECItem iv = {siBuffer, NULL, 0}; andre@0: sec_rc2cbcParameter rc2 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; andre@0: sec_rc5cbcParameter rc5 = { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}, andre@0: {siBuffer, NULL, 0}, {siBuffer, NULL, 0} }; andre@0: andre@0: algtag = SECOID_GetAlgorithmTag(algid); andre@0: type = PK11_AlgtagToMechanism(algtag); andre@0: andre@0: mech = PORT_New(SECItem); andre@0: if (mech == NULL) { andre@0: return NULL; andre@0: } andre@0: mech->type = siBuffer; andre@0: mech->data = NULL; andre@0: mech->len = 0; andre@0: andre@0: arena = PORT_NewArena(1024); andre@0: if (!arena) { andre@0: goto loser; andre@0: } andre@0: andre@0: /* handle the complicated cases */ andre@0: switch (type) { andre@0: case CKM_RC2_ECB: andre@0: rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2ecb_parameter_template, andre@0: &(algid->parameters)); andre@0: if (rv != SECSuccess) { andre@0: goto loser; andre@0: } andre@0: rc2_ecb_params = PORT_New(CK_RC2_PARAMS); andre@0: if (rc2_ecb_params == NULL) { andre@0: goto loser; andre@0: } andre@0: *rc2_ecb_params = rc2_map(&rc2.rc2ParameterVersion); andre@0: mech->data = (unsigned char *) rc2_ecb_params; andre@0: mech->len = sizeof *rc2_ecb_params; andre@0: break; andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: rv = SEC_ASN1DecodeItem(arena, &rc2 ,sec_rc2cbc_parameter_template, andre@0: &(algid->parameters)); andre@0: if (rv != SECSuccess) { andre@0: goto loser; andre@0: } andre@0: rc2_cbc_params = PORT_New(CK_RC2_CBC_PARAMS); andre@0: if (rc2_cbc_params == NULL) { andre@0: goto loser; andre@0: } andre@0: mech->data = (unsigned char *) rc2_cbc_params; andre@0: mech->len = sizeof *rc2_cbc_params; andre@0: rc2_cbc_params->ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); andre@0: if (rc2.iv.len != sizeof rc2_cbc_params->iv) { andre@0: PORT_SetError(SEC_ERROR_INPUT_LEN); andre@0: goto loser; andre@0: } andre@0: PORT_Memcpy(rc2_cbc_params->iv, rc2.iv.data, rc2.iv.len); andre@0: break; andre@0: case CKM_RC5_ECB: andre@0: rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5ecb_parameter_template, andre@0: &(algid->parameters)); andre@0: if (rv != SECSuccess) { andre@0: goto loser; andre@0: } andre@0: rc5_ecb_params = PORT_New(CK_RC5_PARAMS); andre@0: if (rc5_ecb_params == NULL) { andre@0: goto loser; andre@0: } andre@0: rc5_ecb_params->ulRounds = DER_GetInteger(&rc5.rounds); andre@0: rc5_ecb_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; andre@0: mech->data = (unsigned char *) rc5_ecb_params; andre@0: mech->len = sizeof *rc5_ecb_params; andre@0: break; andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: rv = SEC_ASN1DecodeItem(arena, &rc5 ,sec_rc5cbc_parameter_template, andre@0: &(algid->parameters)); andre@0: if (rv != SECSuccess) { andre@0: goto loser; andre@0: } andre@0: rc5_cbc_params = (CK_RC5_CBC_PARAMS *) andre@0: PORT_Alloc(sizeof(CK_RC5_CBC_PARAMS) + rc5.iv.len); andre@0: if (rc5_cbc_params == NULL) { andre@0: goto loser; andre@0: } andre@0: mech->data = (unsigned char *) rc5_cbc_params; andre@0: mech->len = sizeof *rc5_cbc_params; andre@0: rc5_cbc_params->ulRounds = DER_GetInteger(&rc5.rounds); andre@0: rc5_cbc_params->ulWordsize = DER_GetInteger(&rc5.blockSizeInBits)/8; andre@0: rc5_cbc_params->pIv = ((CK_BYTE_PTR)rc5_cbc_params) andre@0: + sizeof(CK_RC5_CBC_PARAMS); andre@0: rc5_cbc_params->ulIvLen = rc5.iv.len; andre@0: PORT_Memcpy(rc5_cbc_params->pIv, rc5.iv.data, rc5.iv.len); andre@0: break; andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: case CKM_PKCS5_PBKD2: andre@0: rv = pbe_PK11AlgidToParam(algid,mech); andre@0: if (rv != SECSuccess) { andre@0: goto loser; andre@0: } andre@0: break; andre@0: case CKM_RC4: andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: break; andre@0: andre@0: default: andre@0: if (pk11_lookup(type)->iv == 0) { andre@0: break; andre@0: } andre@0: /* FALL THROUGH */ andre@0: case CKM_SEED_CBC: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_AES_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_SEED_CBC_PAD: andre@0: case CKM_CAMELLIA_CBC_PAD: andre@0: case CKM_AES_CBC_PAD: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: /* simple cases are simply octet string encoded IVs */ andre@0: rv = SEC_ASN1DecodeItem(arena, &iv, andre@0: SEC_ASN1_GET(SEC_OctetStringTemplate), andre@0: &(algid->parameters)); andre@0: if (rv != SECSuccess || iv.data == NULL) { andre@0: goto loser; andre@0: } andre@0: /* XXX Should be some IV length sanity check here. */ andre@0: mech->data = (unsigned char*)PORT_Alloc(iv.len); andre@0: if (mech->data == NULL) { andre@0: goto loser; andre@0: } andre@0: PORT_Memcpy(mech->data, iv.data, iv.len); andre@0: mech->len = iv.len; andre@0: break; andre@0: } andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: return mech; andre@0: andre@0: loser: andre@0: if (arena) andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: SECITEM_FreeItem(mech,PR_TRUE); andre@0: return NULL; andre@0: } andre@0: andre@0: /* andre@0: * Generate an IV for the given mechanism andre@0: */ andre@0: static SECStatus andre@0: pk11_GenIV(CK_MECHANISM_TYPE type, SECItem *iv) { andre@0: int iv_size = PK11_GetIVLength(type); andre@0: SECStatus rv; andre@0: andre@0: iv->len = iv_size; andre@0: if (iv_size == 0) { andre@0: iv->data = NULL; andre@0: return SECSuccess; andre@0: } andre@0: andre@0: iv->data = (unsigned char *) PORT_Alloc(iv_size); andre@0: if (iv->data == NULL) { andre@0: iv->len = 0; andre@0: return SECFailure; andre@0: } andre@0: andre@0: rv = PK11_GenerateRandom(iv->data,iv->len); andre@0: if (rv != SECSuccess) { andre@0: PORT_Free(iv->data); andre@0: iv->data = NULL; iv->len = 0; andre@0: return SECFailure; andre@0: } andre@0: return SECSuccess; andre@0: } andre@0: andre@0: andre@0: /* andre@0: * create a new parameter block from the passed in MECHANISM and the andre@0: * key. Use Netscape's S/MIME Rules for the New param block. andre@0: */ andre@0: SECItem * andre@0: pk11_GenerateNewParamWithKeyLen(CK_MECHANISM_TYPE type, int keyLen) andre@0: { andre@0: CK_RC2_CBC_PARAMS *rc2_params; andre@0: CK_RC2_PARAMS *rc2_ecb_params; andre@0: SECItem *mech; andre@0: SECItem iv; andre@0: SECStatus rv; andre@0: andre@0: andre@0: mech = (SECItem *) PORT_Alloc(sizeof(SECItem)); andre@0: if (mech == NULL) return NULL; andre@0: andre@0: rv = SECSuccess; andre@0: mech->type = siBuffer; andre@0: switch (type) { andre@0: case CKM_RC4: andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: mech->data = NULL; andre@0: mech->len = 0; andre@0: break; andre@0: case CKM_RC2_ECB: andre@0: rc2_ecb_params = (CK_RC2_PARAMS *)PORT_Alloc(sizeof(CK_RC2_PARAMS)); andre@0: if (rc2_ecb_params == NULL) { andre@0: rv = SECFailure; andre@0: break; andre@0: } andre@0: /* NOTE PK11_GetKeyLength can return -1 if the key isn't and RC2, RC5, andre@0: * or RC4 key. Of course that wouldn't happen here doing RC2:).*/ andre@0: *rc2_ecb_params = keyLen ? keyLen*8 : 128; andre@0: mech->data = (unsigned char *) rc2_ecb_params; andre@0: mech->len = sizeof(CK_RC2_PARAMS); andre@0: break; andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: rv = pk11_GenIV(type,&iv); andre@0: if (rv != SECSuccess) { andre@0: break; andre@0: } andre@0: rc2_params = (CK_RC2_CBC_PARAMS *)PORT_Alloc(sizeof(CK_RC2_CBC_PARAMS)); andre@0: if (rc2_params == NULL) { andre@0: PORT_Free(iv.data); andre@0: rv = SECFailure; andre@0: break; andre@0: } andre@0: /* NOTE PK11_GetKeyLength can return -1 if the key isn't and RC2, RC5, andre@0: * or RC4 key. Of course that wouldn't happen here doing RC2:).*/ andre@0: rc2_params->ulEffectiveBits = keyLen ? keyLen*8 : 128; andre@0: if (iv.data) andre@0: PORT_Memcpy(rc2_params->iv,iv.data,sizeof(rc2_params->iv)); andre@0: mech->data = (unsigned char *) rc2_params; andre@0: mech->len = sizeof(CK_RC2_CBC_PARAMS); andre@0: PORT_Free(iv.data); andre@0: break; andre@0: case CKM_RC5_ECB: andre@0: PORT_Free(mech); andre@0: return PK11_ParamFromIV(type,NULL); andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: rv = pk11_GenIV(type,&iv); andre@0: if (rv != SECSuccess) { andre@0: break; andre@0: } andre@0: PORT_Free(mech); andre@0: return PK11_ParamFromIV(type,&iv); andre@0: default: andre@0: if (pk11_lookup(type)->iv == 0) { andre@0: mech->data = NULL; andre@0: mech->len = 0; andre@0: break; andre@0: } andre@0: case CKM_SEED_CBC: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_AES_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: rv = pk11_GenIV(type,&iv); andre@0: if (rv != SECSuccess) { andre@0: break; andre@0: } andre@0: mech->data = (unsigned char*)PORT_Alloc(iv.len); andre@0: if (mech->data == NULL) { andre@0: PORT_Free(iv.data); andre@0: rv = SECFailure; andre@0: break; andre@0: } andre@0: PORT_Memcpy(mech->data,iv.data,iv.len); andre@0: mech->len = iv.len; andre@0: PORT_Free(iv.data); andre@0: break; andre@0: } andre@0: if (rv != SECSuccess) { andre@0: SECITEM_FreeItem(mech,PR_TRUE); andre@0: return NULL; andre@0: } andre@0: return mech; andre@0: andre@0: } andre@0: andre@0: SECItem * andre@0: PK11_GenerateNewParam(CK_MECHANISM_TYPE type, PK11SymKey *key) andre@0: { andre@0: int keyLen = key ? PK11_GetKeyLength(key) : 0; andre@0: andre@0: return pk11_GenerateNewParamWithKeyLen(type, keyLen); andre@0: } andre@0: andre@0: #define RC5_V10 0x10 andre@0: andre@0: /* turn a PKCS #11 parameter into a DER Encoded Algorithm ID */ andre@0: SECStatus andre@0: PK11_ParamToAlgid(SECOidTag algTag, SECItem *param, andre@0: PLArenaPool *arena, SECAlgorithmID *algid) { andre@0: CK_RC2_CBC_PARAMS *rc2_params; andre@0: sec_rc2cbcParameter rc2; andre@0: CK_RC5_CBC_PARAMS *rc5_params; andre@0: sec_rc5cbcParameter rc5; andre@0: CK_MECHANISM_TYPE type = PK11_AlgtagToMechanism(algTag); andre@0: SECItem *newParams = NULL; andre@0: SECStatus rv = SECFailure; andre@0: unsigned long rc2version; andre@0: andre@0: switch (type) { andre@0: case CKM_RC4: andre@0: case CKM_SEED_ECB: andre@0: case CKM_CAMELLIA_ECB: andre@0: case CKM_AES_ECB: andre@0: case CKM_DES_ECB: andre@0: case CKM_DES3_ECB: andre@0: case CKM_IDEA_ECB: andre@0: case CKM_CDMF_ECB: andre@0: case CKM_CAST_ECB: andre@0: case CKM_CAST3_ECB: andre@0: case CKM_CAST5_ECB: andre@0: newParams = NULL; andre@0: rv = SECSuccess; andre@0: break; andre@0: case CKM_RC2_ECB: andre@0: break; andre@0: case CKM_RC2_CBC: andre@0: case CKM_RC2_CBC_PAD: andre@0: rc2_params = (CK_RC2_CBC_PARAMS *)param->data; andre@0: rc2version = rc2_unmap(rc2_params->ulEffectiveBits); andre@0: if (SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion), andre@0: rc2version) == NULL) andre@0: break; andre@0: rc2.iv.data = rc2_params->iv; andre@0: rc2.iv.len = sizeof(rc2_params->iv); andre@0: newParams = SEC_ASN1EncodeItem (NULL, NULL, &rc2, andre@0: sec_rc2cbc_parameter_template); andre@0: PORT_Free(rc2.rc2ParameterVersion.data); andre@0: if (newParams == NULL) andre@0: break; andre@0: rv = SECSuccess; andre@0: break; andre@0: andre@0: case CKM_RC5_ECB: /* well not really... */ andre@0: break; andre@0: case CKM_RC5_CBC: andre@0: case CKM_RC5_CBC_PAD: andre@0: rc5_params = (CK_RC5_CBC_PARAMS *)param->data; andre@0: if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.version, RC5_V10) == NULL) andre@0: break; andre@0: if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.blockSizeInBits, andre@0: rc5_params->ulWordsize*8) == NULL) { andre@0: PORT_Free(rc5.version.data); andre@0: break; andre@0: } andre@0: if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.rounds, andre@0: rc5_params->ulWordsize*8) == NULL) { andre@0: PORT_Free(rc5.blockSizeInBits.data); andre@0: PORT_Free(rc5.version.data); andre@0: break; andre@0: } andre@0: rc5.iv.data = rc5_params->pIv; andre@0: rc5.iv.len = rc5_params->ulIvLen; andre@0: newParams = SEC_ASN1EncodeItem (NULL, NULL, &rc5, andre@0: sec_rc5cbc_parameter_template); andre@0: PORT_Free(rc5.version.data); andre@0: PORT_Free(rc5.blockSizeInBits.data); andre@0: PORT_Free(rc5.rounds.data); andre@0: if (newParams == NULL) andre@0: break; andre@0: rv = SECSuccess; andre@0: break; andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: case CKM_PBE_SHA1_RC2_128_CBC: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: return PBE_PK11ParamToAlgid(algTag, param, arena, algid); andre@0: default: andre@0: if (pk11_lookup(type)->iv == 0) { andre@0: rv = SECSuccess; andre@0: newParams = NULL; andre@0: break; andre@0: } andre@0: case CKM_SEED_CBC: andre@0: case CKM_CAMELLIA_CBC: andre@0: case CKM_AES_CBC: andre@0: case CKM_DES_CBC: andre@0: case CKM_DES3_CBC: andre@0: case CKM_IDEA_CBC: andre@0: case CKM_CDMF_CBC: andre@0: case CKM_CAST_CBC: andre@0: case CKM_CAST3_CBC: andre@0: case CKM_CAST5_CBC: andre@0: case CKM_DES_CBC_PAD: andre@0: case CKM_DES3_CBC_PAD: andre@0: case CKM_IDEA_CBC_PAD: andre@0: case CKM_CDMF_CBC_PAD: andre@0: case CKM_CAST_CBC_PAD: andre@0: case CKM_CAST3_CBC_PAD: andre@0: case CKM_CAST5_CBC_PAD: andre@0: case CKM_SKIPJACK_CBC64: andre@0: case CKM_SKIPJACK_ECB64: andre@0: case CKM_SKIPJACK_OFB64: andre@0: case CKM_SKIPJACK_CFB64: andre@0: case CKM_SKIPJACK_CFB32: andre@0: case CKM_SKIPJACK_CFB16: andre@0: case CKM_SKIPJACK_CFB8: andre@0: case CKM_BATON_ECB128: andre@0: case CKM_BATON_ECB96: andre@0: case CKM_BATON_CBC128: andre@0: case CKM_BATON_COUNTER: andre@0: case CKM_BATON_SHUFFLE: andre@0: case CKM_JUNIPER_ECB128: andre@0: case CKM_JUNIPER_CBC128: andre@0: case CKM_JUNIPER_COUNTER: andre@0: case CKM_JUNIPER_SHUFFLE: andre@0: newParams = SEC_ASN1EncodeItem(NULL,NULL,param, andre@0: SEC_ASN1_GET(SEC_OctetStringTemplate) ); andre@0: if (newParams == NULL) andre@0: break; andre@0: rv = SECSuccess; andre@0: break; andre@0: } andre@0: andre@0: if (rv != SECSuccess) { andre@0: if (newParams) SECITEM_FreeItem(newParams,PR_TRUE); andre@0: return rv; andre@0: } andre@0: andre@0: rv = SECOID_SetAlgorithmID(arena, algid, algTag, newParams); andre@0: SECITEM_FreeItem(newParams,PR_TRUE); andre@0: return rv; andre@0: } andre@0: andre@0: /* turn an OID algorithm tag into a PKCS #11 mechanism. This allows us to andre@0: * map OID's directly into the PKCS #11 mechanism we want to call. We find andre@0: * this mapping in our standard OID table */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_AlgtagToMechanism(SECOidTag algTag) { andre@0: SECOidData *oid = SECOID_FindOIDByTag(algTag); andre@0: andre@0: if (oid) return (CK_MECHANISM_TYPE) oid->mechanism; andre@0: return CKM_INVALID_MECHANISM; andre@0: } andre@0: andre@0: /* turn a mechanism into an oid. */ andre@0: SECOidTag andre@0: PK11_MechanismToAlgtag(CK_MECHANISM_TYPE type) { andre@0: SECOidData *oid = SECOID_FindOIDByMechanism((unsigned long)type); andre@0: andre@0: if (oid) return oid->offset; andre@0: return SEC_OID_UNKNOWN; andre@0: } andre@0: andre@0: /* Determine appropriate blocking mechanism, used when wrapping private keys andre@0: * which require PKCS padding. If the mechanism does not map to a padding andre@0: * mechanism, we simply return the mechanism. andre@0: */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_GetPadMechanism(CK_MECHANISM_TYPE type) { andre@0: switch(type) { andre@0: case CKM_SEED_CBC: andre@0: return CKM_SEED_CBC_PAD; andre@0: case CKM_CAMELLIA_CBC: andre@0: return CKM_CAMELLIA_CBC_PAD; andre@0: case CKM_AES_CBC: andre@0: return CKM_AES_CBC_PAD; andre@0: case CKM_DES_CBC: andre@0: return CKM_DES_CBC_PAD; andre@0: case CKM_DES3_CBC: andre@0: return CKM_DES3_CBC_PAD; andre@0: case CKM_RC2_CBC: andre@0: return CKM_RC2_CBC_PAD; andre@0: case CKM_CDMF_CBC: andre@0: return CKM_CDMF_CBC_PAD; andre@0: case CKM_CAST_CBC: andre@0: return CKM_CAST_CBC_PAD; andre@0: case CKM_CAST3_CBC: andre@0: return CKM_CAST3_CBC_PAD; andre@0: case CKM_CAST5_CBC: andre@0: return CKM_CAST5_CBC_PAD; andre@0: case CKM_RC5_CBC: andre@0: return CKM_RC5_CBC_PAD; andre@0: case CKM_IDEA_CBC: andre@0: return CKM_IDEA_CBC_PAD; andre@0: default: andre@0: break; andre@0: } andre@0: andre@0: return type; andre@0: } andre@0: andre@0: static PRBool andre@0: pk11_isAllZero(unsigned char *data,int len) { andre@0: while (len--) { andre@0: if (*data++) { andre@0: return PR_FALSE; andre@0: } andre@0: } andre@0: return PR_TRUE; andre@0: } andre@0: andre@0: CK_RV andre@0: PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, andre@0: CK_MECHANISM_PTR pCryptoMechanism, andre@0: SECItem *pbe_pwd, PRBool faulty3DES) andre@0: { andre@0: int iv_len = 0; andre@0: CK_PBE_PARAMS_PTR pPBEparams; andre@0: CK_RC2_CBC_PARAMS_PTR rc2_params; andre@0: CK_ULONG rc2_key_len; andre@0: andre@0: if((pPBEMechanism == CK_NULL_PTR) || (pCryptoMechanism == CK_NULL_PTR)) { andre@0: return CKR_HOST_MEMORY; andre@0: } andre@0: andre@0: /* pkcs5 v2 cannot be supported by this interface. andre@0: * use PK11_GetPBECryptoMechanism instead. andre@0: */ andre@0: if ((pPBEMechanism->mechanism == CKM_INVALID_MECHANISM) || andre@0: (pPBEMechanism->mechanism == CKM_PKCS5_PBKD2)) { andre@0: return CKR_MECHANISM_INVALID; andre@0: } andre@0: andre@0: pPBEparams = (CK_PBE_PARAMS_PTR)pPBEMechanism->pParameter; andre@0: iv_len = PK11_GetIVLength(pPBEMechanism->mechanism); andre@0: andre@0: if (iv_len) { andre@0: if (pk11_isAllZero(pPBEparams->pInitVector,iv_len)) { andre@0: SECItem param; andre@0: PK11SymKey *symKey; andre@0: PK11SlotInfo *intSlot = PK11_GetInternalSlot(); andre@0: andre@0: if (intSlot == NULL) { andre@0: return CKR_DEVICE_ERROR; andre@0: } andre@0: andre@0: param.data = pPBEMechanism->pParameter; andre@0: param.len = pPBEMechanism->ulParameterLen; andre@0: andre@0: symKey = PK11_RawPBEKeyGen(intSlot, andre@0: pPBEMechanism->mechanism, ¶m, pbe_pwd, faulty3DES, NULL); andre@0: PK11_FreeSlot(intSlot); andre@0: if (symKey== NULL) { andre@0: return CKR_DEVICE_ERROR; /* sigh */ andre@0: } andre@0: PK11_FreeSymKey(symKey); andre@0: } andre@0: } andre@0: andre@0: switch(pPBEMechanism->mechanism) { andre@0: case CKM_PBE_MD2_DES_CBC: andre@0: case CKM_PBE_MD5_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: andre@0: pCryptoMechanism->mechanism = CKM_DES_CBC; andre@0: goto have_crypto_mechanism; andre@0: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: andre@0: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: andre@0: case CKM_PBE_SHA1_DES3_EDE_CBC: andre@0: case CKM_PBE_SHA1_DES2_EDE_CBC: andre@0: pCryptoMechanism->mechanism = CKM_DES3_CBC; andre@0: have_crypto_mechanism: andre@0: pCryptoMechanism->pParameter = PORT_Alloc(iv_len); andre@0: pCryptoMechanism->ulParameterLen = (CK_ULONG)iv_len; andre@0: if(pCryptoMechanism->pParameter == NULL) { andre@0: return CKR_HOST_MEMORY; andre@0: } andre@0: PORT_Memcpy((unsigned char *)(pCryptoMechanism->pParameter), andre@0: (unsigned char *)(pPBEparams->pInitVector), andre@0: iv_len); andre@0: break; andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: andre@0: case CKM_PBE_SHA1_RC4_40: andre@0: case CKM_PBE_SHA1_RC4_128: andre@0: pCryptoMechanism->mechanism = CKM_RC4; andre@0: pCryptoMechanism->ulParameterLen = 0; andre@0: pCryptoMechanism->pParameter = CK_NULL_PTR; andre@0: break; andre@0: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: andre@0: case CKM_PBE_SHA1_RC2_40_CBC: andre@0: rc2_key_len = 40; andre@0: goto have_key_len; andre@0: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: andre@0: rc2_key_len = 128; andre@0: have_key_len: andre@0: pCryptoMechanism->mechanism = CKM_RC2_CBC; andre@0: pCryptoMechanism->ulParameterLen = (CK_ULONG) andre@0: sizeof(CK_RC2_CBC_PARAMS); andre@0: pCryptoMechanism->pParameter = (CK_RC2_CBC_PARAMS_PTR) andre@0: PORT_ZAlloc(sizeof(CK_RC2_CBC_PARAMS)); andre@0: if(pCryptoMechanism->pParameter == NULL) { andre@0: return CKR_HOST_MEMORY; andre@0: } andre@0: rc2_params = (CK_RC2_CBC_PARAMS_PTR)pCryptoMechanism->pParameter; andre@0: PORT_Memcpy((unsigned char *)rc2_params->iv, andre@0: (unsigned char *)pPBEparams->pInitVector, andre@0: iv_len); andre@0: rc2_params->ulEffectiveBits = rc2_key_len; andre@0: break; andre@0: default: andre@0: return CKR_MECHANISM_INVALID; andre@0: } andre@0: andre@0: return CKR_OK; andre@0: } andre@0: andre@0: /* Make a Key type to an appropriate signing/verification mechanism */ andre@0: CK_MECHANISM_TYPE andre@0: PK11_MapSignKeyType(KeyType keyType) andre@0: { andre@0: switch (keyType) { andre@0: case rsaKey: andre@0: return CKM_RSA_PKCS; andre@0: case fortezzaKey: andre@0: case dsaKey: andre@0: return CKM_DSA; andre@0: case ecKey: andre@0: return CKM_ECDSA; andre@0: case dhKey: andre@0: default: andre@0: break; andre@0: } andre@0: return CKM_INVALID_MECHANISM; andre@0: } andre@0: andre@0: CK_MECHANISM_TYPE andre@0: pk11_mapWrapKeyType(KeyType keyType) andre@0: { andre@0: switch (keyType) { andre@0: case rsaKey: andre@0: return CKM_RSA_PKCS; andre@0: /* Add fortezza?? */ andre@0: default: andre@0: break; andre@0: } andre@0: return CKM_INVALID_MECHANISM; andre@0: } andre@0: andre@0: SECOidTag andre@0: PK11_FortezzaMapSig(SECOidTag algTag) andre@0: { andre@0: switch (algTag) { andre@0: case SEC_OID_MISSI_KEA_DSS: andre@0: case SEC_OID_MISSI_DSS: andre@0: case SEC_OID_MISSI_DSS_OLD: andre@0: case SEC_OID_MISSI_KEA_DSS_OLD: andre@0: case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: andre@0: return SEC_OID_ANSIX9_DSA_SIGNATURE; andre@0: default: andre@0: break; andre@0: } andre@0: return algTag; andre@0: }