/security/nss/lib/softoken/pkcs11.c
http://github.com/zpao/v8monkey · C · 4638 lines · 3412 code · 548 blank · 678 comment · 893 complexity · aeb4ec02f6831187d84fd2a682ca0239 MD5 · raw file
Large files are truncated click here to view the full file
- /* ***** 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 implements PKCS 11 on top of our existing security modules
- *
- * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
- * This implementation has two slots:
- * slot 1 is our generic crypto support. It does not require login.
- * It supports Public Key ops, and all they bulk ciphers and hashes.
- * It can also support Private Key ops for imported Private keys. It does
- * not have any token storage.
- * slot 2 is our private key support. It requires a login before use. It
- * can store Private Keys and Certs as token objects. Currently only private
- * keys and their associated Certificates are saved on the token.
- *
- * In this implementation, session objects are only visible to the session
- * that created or generated them.
- */
- #include "seccomon.h"
- #include "secitem.h"
- #include "pkcs11.h"
- #include "pkcs11i.h"
- #include "softoken.h"
- #include "lowkeyi.h"
- #include "blapi.h"
- #include "secder.h"
- #include "secport.h"
- #include "secrng.h"
- #include "prtypes.h"
- #include "nspr.h"
- #include "softkver.h"
- #include "secoid.h"
- #include "sftkdb.h"
- #include "sftkpars.h"
- #include "ec.h"
- #include "secasn1.h"
- PRBool parentForkedAfterC_Initialize;
- #ifndef NO_FORK_CHECK
- PRBool sftkForkCheckDisabled;
- #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED)
- PRBool forked = PR_FALSE;
- #endif
- #if defined(CHECK_FORK_GETPID) || defined(CHECK_FORK_MIXED)
- #include <unistd.h>
- pid_t myPid;
- #endif
- #ifdef CHECK_FORK_MIXED
- #include <sys/systeminfo.h>
- PRBool usePthread_atfork;
- #endif
- #endif
- /*
- * ******************** Static data *******************************
- */
- /* The next three strings must be exactly 32 characters long */
- static char *manufacturerID = "Mozilla Foundation ";
- static char manufacturerID_space[33];
- static char *libraryDescription = "NSS Internal Crypto Services ";
- static char libraryDescription_space[33];
- /*
- * In FIPS mode, we disallow login attempts for 1 second after a login
- * failure so that there are at most 60 login attempts per minute.
- */
- static PRIntervalTime loginWaitTime;
- static PRUint32 minSessionObjectHandle = 1U;
- #define __PASTE(x,y) x##y
- /*
- * we renamed all our internal functions, get the correct
- * definitions for them...
- */
- #undef CK_PKCS11_FUNCTION_INFO
- #undef CK_NEED_ARG_LIST
- #define CK_EXTERN extern
- #define CK_PKCS11_FUNCTION_INFO(func) \
- CK_RV __PASTE(NS,func)
- #define CK_NEED_ARG_LIST 1
-
- #include "pkcs11f.h"
-
-
-
- /* build the crypto module table */
- static const CK_FUNCTION_LIST sftk_funcList = {
- { 1, 10 },
-
- #undef CK_PKCS11_FUNCTION_INFO
- #undef CK_NEED_ARG_LIST
-
- #define CK_PKCS11_FUNCTION_INFO(func) \
- __PASTE(NS,func),
- #include "pkcs11f.h"
-
- };
-
- #undef CK_PKCS11_FUNCTION_INFO
- #undef CK_NEED_ARG_LIST
-
-
- #undef __PASTE
- /* List of DES Weak Keys */
- typedef unsigned char desKey[8];
- static const desKey sftk_desWeakTable[] = {
- #ifdef noParity
- /* weak */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e },
- { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 },
- { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
- /* semi-weak */
- { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe },
- { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe },
- { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 },
- { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },
- { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f },
- { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },
- { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
- { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },
- { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e },
- { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 },
- { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe },
- { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },
- #else
- /* weak */
- { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
- { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
- { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 },
- { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
- /* semi-weak */
- { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe },
- { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 },
- { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 },
- { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e },
- { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 },
- { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 },
- { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
- { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e },
- { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e },
- { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 },
- { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe },
- { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 }
- #endif
- };
-
- static const int sftk_desWeakTableSize = sizeof(sftk_desWeakTable)/
- sizeof(sftk_desWeakTable[0]);
- /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
- * that byte with the proper parity bit set */
- static const unsigned char parityTable[256] = {
- /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
- /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e,
- /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
- /* O */ 0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f,
- /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
- /* O */ 0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f,
- /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
- /* E */ 0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e,
- /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
- /* O */ 0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f,
- /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
- /* E */ 0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e,
- /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
- /* E */ 0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e,
- /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
- /* O */ 0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f,
- /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
- /* O */ 0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f,
- /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
- /* E */ 0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e,
- /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
- /* E */ 0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae,
- /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
- /* O */ 0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf,
- /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
- /* E */ 0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce,
- /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
- /* O */ 0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf,
- /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
- /* O */ 0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef,
- /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
- /* E */ 0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe,
- };
- /* Mechanisms */
- struct mechanismList {
- CK_MECHANISM_TYPE type;
- CK_MECHANISM_INFO info;
- PRBool privkey;
- };
- /*
- * the following table includes a complete list of mechanism defined by
- * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11
- * module are ifdef'ed out.
- */
- #define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT
- #define CKF_WR_UN CKF_WRAP | CKF_UNWRAP
- #define CKF_SN_VR CKF_SIGN | CKF_VERIFY
- #define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER
- #define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN
- #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE
- #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
- #define CKF_EC_PNU CKF_EC_FP | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS
- #define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU
- #define CK_MAX 0xffffffff
- static const struct mechanismList mechanisms[] = {
- /*
- * PKCS #11 Mechanism List.
- *
- * The first argument is the PKCS #11 Mechanism we support.
- * The second argument is Mechanism info structure. It includes:
- * The minimum key size,
- * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
- * in bytes for RC5, AES, Camellia, and CAST*
- * ignored for DES*, IDEA and FORTEZZA based
- * The maximum key size,
- * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
- * in bytes for RC5, AES, Camellia, and CAST*
- * ignored for DES*, IDEA and FORTEZZA based
- * Flags
- * What operations are supported by this mechanism.
- * The third argument is a bool which tells if this mechanism is
- * supported in the database token.
- *
- */
- /* ------------------------- RSA Operations ---------------------------*/
- {CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_GENERATE_KEY_PAIR},PR_TRUE},
- {CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_DUZ_IT_ALL}, PR_TRUE},
- {CKM_RSA_PKCS_PSS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- #ifdef SFTK_RSA9796_SUPPORTED
- {CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_DUZ_IT_ALL}, PR_TRUE},
- #endif
- {CKM_RSA_X_509, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_DUZ_IT_ALL}, PR_TRUE},
- /* -------------- RSA Multipart Signing Operations -------------------- */
- {CKM_MD2_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_MD5_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_SHA1_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_SHA224_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_SHA256_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_SHA384_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- {CKM_SHA512_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_SN_VR}, PR_TRUE},
- /* ------------------------- DSA Operations --------------------------- */
- {CKM_DSA_KEY_PAIR_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
- CKF_GENERATE_KEY_PAIR}, PR_TRUE},
- {CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
- CKF_SN_VR}, PR_TRUE},
- {CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
- CKF_SN_VR}, PR_TRUE},
- /* -------------------- Diffie Hellman Operations --------------------- */
- /* no diffie hellman yet */
- {CKM_DH_PKCS_KEY_PAIR_GEN, {DH_MIN_P_BITS, DH_MAX_P_BITS,
- CKF_GENERATE_KEY_PAIR}, PR_TRUE},
- {CKM_DH_PKCS_DERIVE, {DH_MIN_P_BITS, DH_MAX_P_BITS,
- CKF_DERIVE}, PR_TRUE},
- #ifdef NSS_ENABLE_ECC
- /* -------------------- Elliptic Curve Operations --------------------- */
- {CKM_EC_KEY_PAIR_GEN, {112, 571, CKF_GENERATE_KEY_PAIR|CKF_EC_BPNU}, PR_TRUE},
- {CKM_ECDH1_DERIVE, {112, 571, CKF_DERIVE|CKF_EC_BPNU}, PR_TRUE},
- {CKM_ECDSA, {112, 571, CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE},
- {CKM_ECDSA_SHA1, {112, 571, CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE},
- #endif /* NSS_ENABLE_ECC */
- /* ------------------------- RC2 Operations --------------------------- */
- {CKM_RC2_KEY_GEN, {1, 128, CKF_GENERATE}, PR_TRUE},
- {CKM_RC2_ECB, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_RC2_CBC, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_RC2_MAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_RC2_MAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_RC2_CBC_PAD, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* ------------------------- RC4 Operations --------------------------- */
- {CKM_RC4_KEY_GEN, {1, 256, CKF_GENERATE}, PR_FALSE},
- {CKM_RC4, {1, 256, CKF_EN_DE_WR_UN}, PR_FALSE},
- /* ------------------------- DES Operations --------------------------- */
- {CKM_DES_KEY_GEN, { 8, 8, CKF_GENERATE}, PR_TRUE},
- {CKM_DES_ECB, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_DES_CBC, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_DES_MAC, { 8, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_DES_MAC_GENERAL, { 8, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_DES_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_DES2_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE},
- {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE },
- {CKM_DES3_ECB, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
- {CKM_DES3_CBC, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
- {CKM_DES3_MAC, {24, 24, CKF_SN_VR}, PR_TRUE },
- {CKM_DES3_MAC_GENERAL, {24, 24, CKF_SN_VR}, PR_TRUE },
- {CKM_DES3_CBC_PAD, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
- /* ------------------------- CDMF Operations --------------------------- */
- {CKM_CDMF_KEY_GEN, {8, 8, CKF_GENERATE}, PR_TRUE},
- {CKM_CDMF_ECB, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CDMF_CBC, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CDMF_MAC, {8, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_CDMF_MAC_GENERAL, {8, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_CDMF_CBC_PAD, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* ------------------------- AES Operations --------------------------- */
- {CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE},
- {CKM_AES_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_AES_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_AES_MAC, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_AES_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_AES_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* ------------------------- Camellia Operations --------------------- */
- {CKM_CAMELLIA_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE},
- {CKM_CAMELLIA_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAMELLIA_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAMELLIA_MAC, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_CAMELLIA_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_CAMELLIA_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* ------------------------- SEED Operations --------------------------- */
- {CKM_SEED_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE},
- {CKM_SEED_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_SEED_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_SEED_MAC, {16, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_SEED_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_SEED_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* ------------------------- Hashing Operations ----------------------- */
- {CKM_MD2, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_MD2_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_MD2_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_MD5, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_MD5_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_MD5_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA_1, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_SHA_1_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA224, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_SHA224_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA224_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA256, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_SHA256_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA256_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA384, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_SHA384_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA384_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA512, {0, 0, CKF_DIGEST}, PR_FALSE},
- {CKM_SHA512_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_SHA512_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
- {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE},
- /* ------------------------- HKDF Operations -------------------------- */
- {CKM_NSS_HKDF_SHA1, {1, 128, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_HKDF_SHA256, {1, 128, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_HKDF_SHA384, {1, 128, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_HKDF_SHA512, {1, 128, CKF_DERIVE}, PR_TRUE},
- /* ------------------------- CAST Operations --------------------------- */
- #ifdef NSS_SOFTOKEN_DOES_CAST
- /* Cast operations are not supported ( yet? ) */
- {CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_TRUE},
- {CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST_CBC, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST_MAC, {1, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST_MAC_GENERAL, {1, 8, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST_CBC_PAD, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST3_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE},
- {CKM_CAST3_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST3_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST3_MAC, {1, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST3_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST3_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST5_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE},
- {CKM_CAST5_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST5_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_CAST5_MAC, {1, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST5_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_CAST5_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- #endif
- #if NSS_SOFTOKEN_DOES_RC5
- /* ------------------------- RC5 Operations --------------------------- */
- {CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE},
- {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_TRUE},
- {CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- #endif
- #ifdef NSS_SOFTOKEN_DOES_IDEA
- /* ------------------------- IDEA Operations -------------------------- */
- {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE},
- {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_IDEA_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_IDEA_MAC, {16, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_IDEA_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE},
- {CKM_IDEA_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE},
- #endif
- /* --------------------- Secret Key Operations ------------------------ */
- {CKM_GENERIC_SECRET_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE},
- {CKM_CONCATENATE_BASE_AND_KEY, {1, 32, CKF_GENERATE}, PR_FALSE},
- {CKM_CONCATENATE_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE},
- {CKM_CONCATENATE_DATA_AND_BASE, {1, 32, CKF_GENERATE}, PR_FALSE},
- {CKM_XOR_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE},
- {CKM_EXTRACT_KEY_FROM_KEY, {1, 32, CKF_DERIVE}, PR_FALSE},
- /* ---------------------- SSL Key Derivations ------------------------- */
- {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}, PR_FALSE},
- {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
- {CKM_SSL3_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE},
- {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
- {CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE}, PR_FALSE},
- {CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE}, PR_FALSE},
- {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE},
- {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE},
- {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE},
- {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
- {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE},
- {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE},
- /* ---------------------- PBE Key Derivations ------------------------ */
- {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE},
- {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE},
- /* ------------------ NETSCAPE PBE Key Derivations ------------------- */
- {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE},
- {CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE},
- {CKM_PBA_SHA1_WITH_SHA1_HMAC, {20,20, CKF_GENERATE}, PR_TRUE},
- {CKM_PKCS5_PBKD2, {1,256, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {20,20, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE},
- {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE},
- /* ------------------ AES Key Wrap (also encrypt) ------------------- */
- {CKM_NETSCAPE_AES_KEY_WRAP, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- {CKM_NETSCAPE_AES_KEY_WRAP_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
- /* --------------------------- J-PAKE -------------------------------- */
- {CKM_NSS_JPAKE_ROUND1_SHA1, {0, 0, CKF_GENERATE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND1_SHA256, {0, 0, CKF_GENERATE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND1_SHA384, {0, 0, CKF_GENERATE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND1_SHA512, {0, 0, CKF_GENERATE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND2_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND2_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND2_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_ROUND2_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_FINAL_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_FINAL_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_FINAL_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE},
- {CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}
- };
- static const CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
- /* sigh global so fipstokn can read it */
- PRBool nsc_init = PR_FALSE;
- #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED)
- #include <pthread.h>
- static void ForkedChild(void)
- {
- if (nsc_init || nsf_init) {
- forked = PR_TRUE;
- }
- }
- #endif
- static char *
- sftk_setStringName(const char *inString, char *buffer, int buffer_length, PRBool nullTerminate)
- {
- int full_length, string_length;
- full_length = nullTerminate ? buffer_length -1 : buffer_length;
- string_length = PORT_Strlen(inString);
- /*
- * shorten the string, respecting utf8 encoding
- * to do so, we work backward from the end
- * bytes looking from the end are either:
- * - ascii [0x00,0x7f]
- * - the [2-n]th byte of a multibyte sequence
- * [0x3F,0xBF], i.e, most significant 2 bits are '10'
- * - the first byte of a multibyte sequence [0xC0,0xFD],
- * i.e, most significant 2 bits are '11'
- *
- * When the string is too long, we lop off any trailing '10' bytes,
- * if any. When these are all eliminated we lop off
- * one additional byte. Thus if we lopped any '10'
- * we'll be lopping a '11' byte (the first byte of the multibyte sequence),
- * otherwise we're lopping off an ascii character.
- *
- * To test for '10' bytes, we first AND it with
- * 11000000 (0xc0) so that we get 10000000 (0x80) if and only if
- * the byte starts with 10. We test for equality.
- */
- while ( string_length > full_length ) {
- /* need to shorten */
- while ( string_length > 0 &&
- ((inString[string_length-1]&(char)0xc0) == (char)0x80)) {
- /* lop off '10' byte */
- string_length--;
- }
- /*
- * test string_length in case bad data is received
- * and string consisted of all '10' bytes,
- * avoiding any infinite loop
- */
- if ( string_length ) {
- /* remove either '11' byte or an asci byte */
- string_length--;
- }
- }
- PORT_Memset(buffer,' ',full_length);
- if (nullTerminate) {
- buffer[full_length] = 0;
- }
- PORT_Memcpy(buffer,inString,string_length);
- return buffer;
- }
- /*
- * Configuration utils
- */
- static CK_RV
- sftk_configure(const char *man, const char *libdes)
- {
- /* make sure the internationalization was done correctly... */
- if (man) {
- manufacturerID = sftk_setStringName(man,manufacturerID_space,
- sizeof(manufacturerID_space), PR_TRUE);
- }
- if (libdes) {
- libraryDescription = sftk_setStringName(libdes,
- libraryDescription_space, sizeof(libraryDescription_space),
- PR_TRUE);
- }
- return CKR_OK;
- }
- /*
- * ******************** Password Utilities *******************************
- */
- /*
- * see if the key DB password is enabled
- */
- static PRBool
- sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb)
- {
- PRBool pwenabled;
-
- pwenabled = PR_FALSE;
- if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
- PRBool tokenRemoved = PR_FALSE;
- SECStatus rv = sftkdb_CheckPassword(keydb, "", &tokenRemoved);
- if (tokenRemoved) {
- sftk_CloseAllSessions(slot, PR_FALSE);
- }
- return (rv == SECSuccess);
- }
- return pwenabled;
- }
- /*
- * ******************** Object Creation Utilities ***************************
- */
- /* Make sure a given attribute exists. If it doesn't, initialize it to
- * value and len
- */
- CK_RV
- sftk_defaultAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type,void *value,
- unsigned int len)
- {
- if ( !sftk_hasAttribute(object, type)) {
- return sftk_AddAttributeType(object,type,value,len);
- }
- return CKR_OK;
- }
- /*
- * check the consistancy and initialize a Data Object
- */
- static CK_RV
- sftk_handleDataObject(SFTKSession *session,SFTKObject *object)
- {
- CK_RV crv;
- /* first reject private and token data objects */
- if (sftk_isTrue(object,CKA_PRIVATE) || sftk_isTrue(object,CKA_TOKEN)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* now just verify the required date fields */
- crv = sftk_defaultAttribute(object,CKA_APPLICATION,NULL,0);
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_VALUE,NULL,0);
- if (crv != CKR_OK) return crv;
- return CKR_OK;
- }
- /*
- * check the consistancy and initialize a Certificate Object
- */
- static CK_RV
- sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
- {
- CK_CERTIFICATE_TYPE type;
- SFTKAttribute *attribute;
- CK_RV crv;
- /* certificates must have a type */
- if ( !sftk_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* we can't store any certs private */
- if (sftk_isTrue(object,CKA_PRIVATE)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- /* We only support X.509 Certs for now */
- attribute = sftk_FindAttribute(object,CKA_CERTIFICATE_TYPE);
- if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
- type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue;
- sftk_FreeAttribute(attribute);
- if (type != CKC_X_509) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* X.509 Certificate */
- /* make sure we have a cert */
- if ( !sftk_hasAttribute(object,CKA_VALUE) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* in PKCS #11, Subject is a required field */
- if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* in PKCS #11, Issuer is a required field */
- if ( !sftk_hasAttribute(object,CKA_ISSUER) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* in PKCS #11, Serial is a required field */
- if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* add it to the object */
- object->objectInfo = NULL;
- object->infoFree = (SFTKFree) NULL;
-
- /* now just verify the required date fields */
- crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0);
- if (crv != CKR_OK) { return crv; }
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(certHandle, object, &object->handle);
- sftk_freeDB(certHandle);
- return crv;
- }
- return CKR_OK;
- }
-
- /*
- * check the consistancy and initialize a Trust Object
- */
- static CK_RV
- sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
- {
- /* we can't store any certs private */
- if (sftk_isTrue(object,CKA_PRIVATE)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* certificates must have a type */
- if ( !sftk_hasAttribute(object,CKA_ISSUER) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object,CKA_CERT_SHA1_HASH) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object,CKA_CERT_MD5_HASH) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- CK_RV crv;
- if (certHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(certHandle, object, &object->handle);
- sftk_freeDB(certHandle);
- return crv;
- }
- return CKR_OK;
- }
- /*
- * check the consistancy and initialize a Trust Object
- */
- static CK_RV
- sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object)
- {
- /* we can't store any certs private */
- if (sftk_isTrue(object,CKA_PRIVATE)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* certificates must have a type */
- if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *certHandle;
- CK_RV crv;
- PORT_Assert(slot);
- if (slot == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
- }
- certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(certHandle, object, &object->handle);
- sftk_freeDB(certHandle);
- return crv;
- }
- return CKR_OK;
- }
- /*
- * check the consistancy and initialize a Trust Object
- */
- static CK_RV
- sftk_handleCrlObject(SFTKSession *session,SFTKObject *object)
- {
- /* we can't store any certs private */
- if (sftk_isTrue(object,CKA_PRIVATE)) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* certificates must have a type */
- if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object,CKA_VALUE) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- CK_RV crv;
- if (certHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(certHandle, object, &object->handle);
- sftk_freeDB(certHandle);
- return crv;
- }
- return CKR_OK;
- }
- /*
- * check the consistancy and initialize a Public Key Object
- */
- static CK_RV
- sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
- CK_KEY_TYPE key_type)
- {
- CK_BBOOL encrypt = CK_TRUE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL wrap = CK_TRUE;
- CK_BBOOL derive = CK_FALSE;
- CK_BBOOL verify = CK_TRUE;
- CK_RV crv;
- switch (key_type) {
- case CKK_RSA:
- crv = sftk_ConstrainAttribute(object, CKA_MODULUS,
- RSA_MIN_MODULUS_BITS, 0, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- break;
- case CKK_DSA:
- crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME,
- DSA_Q_BITS, DSA_Q_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_PRIME,
- DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DSA_MAX_P_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DSA_MAX_P_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- break;
- case CKK_DH:
- crv = sftk_ConstrainAttribute(object, CKA_PRIME,
- DH_MIN_P_BITS, DH_MAX_P_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DH_MAX_P_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DH_MAX_P_BITS, 0);
- if (crv != CKR_OK) {
- return crv;
- }
- verify = CK_FALSE;
- derive = CK_TRUE;
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- break;
- #ifdef NSS_ENABLE_ECC
- case CKK_EC:
- if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object, CKA_EC_POINT)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- derive = CK_TRUE; /* for ECDH */
- verify = CK_TRUE; /* for ECDSA */
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- break;
- #endif /* NSS_ENABLE_ECC */
- default:
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /* make sure the required fields exist */
- crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0);
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_VERIFY_RECOVER,
- &recover,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- object->objectInfo = sftk_GetPubKey(object,key_type, &crv);
- if (object->objectInfo == NULL) {
- return crv;
- }
- object->infoFree = (SFTKFree) nsslowkey_DestroyPublicKey;
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *certHandle = sftk_getCertDB(slot);
- if (certHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(certHandle, object, &object->handle);
- sftk_freeDB(certHandle);
- return crv;
- }
- return CKR_OK;
- }
- static NSSLOWKEYPrivateKey *
- sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp);
- static SECStatus
- sftk_fillRSAPrivateKey(SFTKObject *object);
- /*
- * check the consistancy and initialize a Private Key Object
- */
- static CK_RV
- sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE key_type)
- {
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL encrypt = CK_TRUE;
- CK_BBOOL sign = CK_FALSE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL wrap = CK_TRUE;
- CK_BBOOL derive = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- PRBool createObjectInfo = PR_TRUE;
- int missing_rsa_mod_component = 0;
- int missing_rsa_exp_component = 0;
- int missing_rsa_crt_component = 0;
-
- SECItem mod;
- CK_RV crv;
- switch (key_type) {
- case CKK_RSA:
- if ( !sftk_hasAttribute(object, CKA_MODULUS)) {
- missing_rsa_mod_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
- missing_rsa_exp_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) {
- missing_rsa_exp_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_PRIME_1)) {
- missing_rsa_mod_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_PRIME_2)) {
- missing_rsa_mod_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_EXPONENT_1)) {
- missing_rsa_crt_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_EXPONENT_2)) {
- missing_rsa_crt_component++;
- }
- if ( !sftk_hasAttribute(object, CKA_COEFFICIENT)) {
- missing_rsa_crt_component++;
- }
- if (missing_rsa_mod_component || missing_rsa_exp_component ||
- missing_rsa_crt_component) {
- /* we are missing a component, see if we have enough to rebuild
- * the rest */
- int have_exp = 2- missing_rsa_exp_component;
- int have_component = 5-
- (missing_rsa_exp_component+missing_rsa_mod_component);
- SECStatus rv;
- if ((have_exp == 0) || (have_component < 3)) {
- /* nope, not enough to reconstruct the private key */
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /*fill in the missing parameters */
- rv = sftk_fillRSAPrivateKey(object);
- if (rv != SECSuccess) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- }
-
- /* make sure Netscape DB attribute is set correctly */
- crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
- if (crv != CKR_OK) return crv;
- crv = sftk_forceAttribute(object, CKA_NETSCAPE_DB,
- sftk_item_expand(&mod));
- if (mod.data) PORT_Free(mod.data);
- if (crv != CKR_OK) return crv;
- sign = CK_TRUE;
- derive = CK_FALSE;
- break;
- case CKK_DSA:
- if ( !sftk_hasAttribute(object, CKA_SUBPRIME)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- sign = CK_TRUE;
- derive = CK_FALSE;
- /* fall through */
- case CKK_DH:
- if ( !sftk_hasAttribute(object, CKA_PRIME)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object, CKA_BASE)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object, CKA_VALUE)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- break;
- #ifdef NSS_ENABLE_ECC
- case CKK_EC:
- if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- if ( !sftk_hasAttribute(object, CKA_VALUE)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- encrypt = CK_FALSE;
- sign = CK_TRUE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- break;
- #endif /* NSS_ENABLE_ECC */
- case CKK_NSS_JPAKE_ROUND1:
- if (!sftk_hasAttribute(object, CKA_PRIME ||
- !sftk_hasAttribute(object, CKA_SUBPRIME) ||
- !sftk_hasAttribute(object, CKA_BASE))) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* fall through */
- case CKK_NSS_JPAKE_ROUND2:
- /* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in
- the J-PAKE code. */
- encrypt = sign = recover = wrap = CK_FALSE;
- derive = CK_TRUE;
- createObjectInfo = PR_FALSE;
- break;
- default:
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0);
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_DECRYPT,&encrypt,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_SIGN,&sign,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_SIGN_RECOVER,&recover,
- sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_UNWRAP,&wrap,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- /* the next two bits get modified only in the key gen and token cases */
- crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE,
- &ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE,
- &ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- /* should we check the non-token RSA private keys? */
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
- CK_RV crv;
- if (keyHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(keyHandle, object, &object->handle);
- sftk_freeDB(keyHandle);
- return crv;
- } else if (createObjectInfo) {
- object->objectInfo = sftk_mkPrivKey(object,key_type,&crv);
- if (object->objectInfo == NULL) return crv;
- object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey;
- }
- return CKR_OK;
- }
- /* forward declare the DES formating function for handleSecretKey */
- void sftk_FormatDESKey(unsigned char *key, int length);
- /* Validate secret key data, and set defaults */
- static CK_RV
- validateSecretKey(SFTKSession *session, SFTKObject *object,
- CK_KEY_TYPE key_type, PRBool isFIPS)
- {
- CK_RV crv;
- CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL ckfalse = CK_FALSE;
- SFTKAttribute *attribute = NULL;
- unsigned long requiredLen;
- crv = sftk_defaultAttribute(object,CKA_SENSITIVE,
- isFIPS?&cktrue:&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE,
- &cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_DECRYPT,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_SIGN,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_VERIFY,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_WRAP,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_UNWRAP,&cktrue,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- if ( !sftk_hasAttribute(object, CKA_VALUE)) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* the next two bits get modified only in the key gen and token cases */
- crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE,
- &ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE,
- &ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- /* some types of keys have a value length */
- crv = CKR_OK;
- switch (key_type) {
- /* force CKA_VALUE_LEN to be set */
- case CKK_GENERIC_SECRET:
- case CKK_RC2:
- case CKK_RC4:
- #if NSS_SOFTOKEN_DOES_RC5
- case CKK_RC5:
- #endif
- #ifdef NSS_SOFTOKEN_DOES_CAST
- case CKK_CAST:
- case CKK_CAST3:
- case CKK_CAST5:
- #endif
- #if NSS_SOFTOKEN_DOES_IDEA
- case CKK_IDEA:
- #endif
- attribute = sftk_FindAttribute(object,CKA_VALUE);
- /* shouldn't happen */
- if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
- crv = sftk_forceAttribute(object, CKA_VALUE_LEN,
- &attribute->attrib.ulValueLen, sizeof(CK_ULONG));
- sftk_FreeAttribute(attribute);
- break;
- /* force the value to have the correct parity */
- case CKK_DES:
- case CKK_DES2:
- case CKK_DES3:
- case CKK_CDMF:
- attribute = sftk_FindAttribute(object,CKA_VALUE);
- /* shouldn't happen */
- if (attribute == NULL)
- return CKR_TEMPLATE_INCOMPLETE;
- requiredLen = sftk_MapKeySize(key_type);
- if (attribute->attrib.ulValueLen != requiredLen) {
- sftk_FreeAttribute(attribute);
- return CKR_KEY_SIZE_RANGE;
- }
- sftk_FormatDESKey((unsigned char*)attribute->attrib.pValue,
- attribute->attrib.ulValueLen);
- sftk_FreeAttribute(attribute);
- break;
- case CKK_AES:
- attribute = sftk_FindAttribute(object,CKA_VALUE);
- /* shouldn't happen */
- if (attribute == NULL)
- return CKR_TEMPLATE_INCOMPLETE;
- if (attribute->attrib.ulValueLen != 16 &&
- attribute->attrib.ulValueLen != 24 &&
- attribute->attrib.ulValueLen != 32) {
- sftk_FreeAttribute(attribute);
- return CKR_KEY_SIZE_RANGE;
- }
- crv = sftk_forceAttribute(object, CKA_VALUE_LEN,
- &attribute->attrib.ulValueLen, sizeof(CK_ULONG));
- sftk_FreeAttribute(attribute);
- break;
- default:
- break;
- }
- return crv;
- }
- /*
- * check the consistancy and initialize a Secret Key Object
- */
- static CK_RV
- sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
- CK_KEY_TYPE key_type, PRBool isFIPS)
- {
- CK_RV crv;
- /* First validate and set defaults */
- crv = validateSecretKey(session, object, key_type, isFIPS);
- if (crv != CKR_OK) goto loser;
- /* If the object is a TOKEN object, store in the database */
- if (sftk_isTrue(object,CKA_TOKEN)) {
- SFTKSlot *slot = session->slot;
- SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
- CK_RV crv;
- if (keyHandle == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
- crv = sftkdb_write(keyHandle, object, &object->handle);
- sftk_freeDB(keyHandle);
- return crv;
- }
- loser:
- return crv;
- }
- /*
- * check the consistancy and initialize a Key Object
- */
- static CK_RV
- sftk_handleKeyObject(SFTKSession *session, SFTKObject *object)
- {
- SFTKAttribute *attribute;
- CK_KEY_TYPE key_type;
- CK_BBOOL ckfalse = CK_FALSE;
- CK_RV crv;
- /* verify the required fields */
- if ( !sftk_hasAttribute(object,CKA_KEY_TYPE) ) {
- return CKR_TEMPLATE_INCOMPLETE;
- }
- /* now verify the common fields */
- crv = sftk_defaultAttribute(object,CKA_ID,NULL,0);
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_START_DATE,NULL,0);
- if (crv != CKR_OK) return crv;
- crv = sftk_defaultAttribute(object,CKA_END_DATE,NULL,0);
- if (crv != CKR_OK) return crv;
- /* CKA_DERIVE is common to all keys, but it's default value is
- * key dependent */
- crv = sftk_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL));
- if (crv != CKR_OK) return crv;
- /* get the key type */
- attribute = sftk_FindAttribute(object,CKA_KEY_TYPE);
- if (!attribute) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
- sftk_FreeAttribute(attribute);
- switch (object->objclass) {
- case CKO_PUBLIC_KEY:
- return sftk_handlePublicKeyObject(session,object,key_type);
- case CKO_PRIVATE_KEY:
- return sftk_handlePrivateKeyObject(session,object,key_type);
- case CKO_SECRET_KEY:
- /* make sure the required fields exist */
- return sftk_handleSecretKeyObject(session,object,key_type,
- (PRBool)(session->slot->slotID == FIPS_SLOT_ID));
- default:
- break;
- }
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
- /*
- * check the consistancy and Verify a DSA Parameter Object
- */
- static CK_RV
- sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
- {
- SFTKAttribute *primeAttr = NULL;
- SFTKAttribute *subPrimeAttr = NULL;
- SFTKAttribute *baseAttr = NULL;
- SFTKAttribute *seedAttr = NULL;
- SFTKAttribute *hAttr = NULL;
- SFTKAttribute *attribute;
- CK_RV crv = CKR_TEMPLATE_INCOMPLETE;
- PQGParams params;
- PQGVerify vfy, *verify = NULL;
- SECStatus result,rv;
- primeAttr = sftk_FindAttribute(object,CKA_PRIME);
- if (primeAttr == NULL) goto loser;
- params.prime.data = primeAttr->attrib.pValue;
- params.prime.len = primeAttr->attrib.ulValueLen;
- subPrimeAttr = sftk_FindAttribute(object,CKA_SUBPRIME);
- if (subPrimeAttr == NULL) goto loser;
- params.subPrime.data = subPrimeAttr->attrib.pValue;
- params.subPrime.len = subPrimeAttr->attrib.ulValueLen;
- baseAttr = sftk_FindAttribute(object,CKA_BASE);
- if (baseAttr == NULL) goto loser;
- params.base.data = baseAttr->attrib.pValue;
- params.base.len = baseAttr->attrib.ulValueLen;
- attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER);
- if (attribute != NULL) {
- vfy.counter = *(CK_ULONG *) attribute->attrib.pValue;
- sftk_FreeAttribute(attribute);
- seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
- if (seedAttr == NULL) goto loser;
- vfy.seed.data = seedAttr->attrib.pValue;
- vfy.seed.len = seedAttr->attrib.ulValueLen;
- hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
- if (hAttr == NULL) goto loser;
- vfy.h.data = hAttr->attrib.pValue;
- vfy.h.len = hAttr->attrib.ulValueLen;
- verify = &vfy;
- }
- crv = CKR_FUNCTION_FAILED;
- rv = PQG_VerifyParams(¶ms,verify,&result);
- if (rv == SECSuccess) {
- crv = (result== SECSuccess) ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID;
- }
- loser:
- if (hAttr) sftk_FreeAttribute(hAttr);
- if (seedAttr) sftk_FreeAttribute(seedAttr);
- if (baseAttr) sftk_FreeAttribute(baseAttr);
- if (subPrimeAttr) sftk_FreeAttribute(subPrimeAttr);
- if (primeAttr) sftk_FreeAttribute(primeAttr);
- return crv;
- }
- /*
- * check the consistancy and initialize a Key Parameter Object
- */
- static CK_RV
- sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object)
- {
- SFTKAttribute *attribute;…