mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 16:46:26 +00:00
1864 lines
50 KiB
C
1864 lines
50 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Dr Stephen Henson <stephen.henson@gemplus.com>
|
|
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
/*
|
|
* 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_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 key type needed for the given mechanism
|
|
*/
|
|
CK_MECHANISM_TYPE
|
|
PK11_GetKeyMechanism(CK_KEY_TYPE type)
|
|
{
|
|
switch (type) {
|
|
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_MECHANISM_TYPE
|
|
PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len)
|
|
{
|
|
switch (type) {
|
|
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_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_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_TLS_MASTER_KEY_DERIVE_DH:
|
|
case CKM_TLS_KEY_AND_MAC_DERIVE:
|
|
case CKM_SHA_1_HMAC:
|
|
case CKM_SHA_1_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:
|
|
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_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_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_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:
|
|
return CKM_SSL3_PRE_MASTER_KEY_GEN;
|
|
case CKM_SHA_1_HMAC:
|
|
case CKM_SHA_1_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_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_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_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_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_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_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_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_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;
|
|
PRArenaPool * 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_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_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:
|
|
/* 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 paramter 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_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_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,
|
|
PRArenaPool *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_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_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_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;
|
|
}
|