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