diff nss/lib/pk11wrap/pk11mech.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/pk11wrap/pk11mech.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,1892 @@
+/* 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_NSS_CHACHA20:
+	return CKM_NSS_CHACHA20_POLY1305;
+    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_NSS_CHACHA20_POLY1305:
+	return CKK_NSS_CHACHA20;
+    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_NSS_CHACHA20_POLY1305:
+	return CKM_NSS_CHACHA20_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;
+    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:
+	mech->data = NULL;
+	mech->len = 0;
+	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) {
+	    mech->data = NULL;
+	    mech->len = 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, &param, 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;
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)