Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  pkcs11.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * This file 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 "utilpars.h"
#include "ec.h"
#include "secasn1.h"
#include "secerr.h"
#include "lgglue.h"
#include "kem.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

#ifdef XP_UNIX
#define LIB_PARAM_DEFAULT_FILE_LOCATION "/etc/nss/params.config"
#endif

#define LIB_PARAM_DEFAULT " configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB,noModDB "
/*
 * ******************** 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;

#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_PKCS11_3_0 1
#define CK_EXTERN extern
#define CK_PKCS11_FUNCTION_INFO(func) \
    CK_RV __PASTE(NS, func)
#define CK_NEED_ARG_LIST 1

#include "pkcs11f.h"

#ifndef NSS_FIPS_DISABLE
/* ------------- forward declare all the FIPS functions ------------- */
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO

#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(F, name)
#define CK_NEED_ARG_LIST 1

#include "pkcs11f.h"
#endif

/* build the crypto module table */
static CK_FUNCTION_LIST_3_0 sftk_funcList = {
    { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },

#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST

#define CK_PKCS11_FUNCTION_INFO(func) \
    __PASTE(NS, func)                 \
    ,
#include "pkcs11f.h"

};

/* need a special version of get info for version 2 which returns the version
 * 2.4 version number */

CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
                             CK_MECHANISM_INFO_PTR pInfo);

/* build the crypto module table */
static CK_FUNCTION_LIST sftk_funcList_v2 = {
    { 2, 40 },

#undef CK_PKCS11_3_0
#define CK_PKCS_11_2_0_ONLY 1
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST
#define C_GetInfo C_GetInfoV2
#define C_GetMechanismInfo C_GetMechanismInfoV2

#define CK_PKCS11_FUNCTION_INFO(func) \
    __PASTE(NS, func)                 \
    ,
#include "pkcs11f.h"

};

#undef C_GetInfo
#undef C_GetMechanismInfo
#undef CK_PKCS_11_2_0_ONLY
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST

#undef __PASTE

CK_NSS_MODULE_FUNCTIONS sftk_module_funcList = {
    { 1, 0 },
    NSC_ModuleDBFunc
};

static CK_RV
nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession,
                     CK_OBJECT_HANDLE hObject,
                     CK_ULONG ulOperationType,
                     CK_ULONG *pulFIPSStatus);
CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList = {
    { 1, 0 },
    nsc_NSSGetFIPSStatus
};

CK_NSS_KEM_FUNCTIONS sftk_kem_funcList = {
    { 1, 0 },
    NSC_Encapsulate,
    NSC_Decapsulate
};

/*
 * Array is orderd by default first
 */

static CK_INTERFACE nss_interfaces[] = {
    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList, NSS_INTERFACE_FLAGS },
    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v2, NSS_INTERFACE_FLAGS },
    { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS },
    { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS },
    { (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface", &sftk_kem_funcList, NSS_INTERFACE_FLAGS }
};
/* must match the count of interfaces in nss_interfaces above */
#define NSS_INTERFACE_COUNT 5

/* 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_MSG CKF_ENCRYPT | CKF_DECRYPT | CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT

#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_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS

#define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU
#define CKF_EC_POC CKF_EC_F_P | CKF_EC_OID | CKF_EC_COMPRESS

#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 },
    { CKM_RSA_PKCS_OAEP, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_EN_DE_WR_UN }, 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 },
    { CKM_SHA1_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA224_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA256_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA384_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA512_RSA_PKCS_PSS, { 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_PARAMETER_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE }, PR_TRUE },
    { CKM_DSA_SHA1, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
    { CKM_DSA_SHA224, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
    { CKM_DSA_SHA256, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
    { CKM_DSA_SHA384, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
    { CKM_DSA_SHA512, { 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 },
    /* -------------------- Elliptic Curve Operations --------------------- */
    { CKM_EC_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDH1_DERIVE, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_DERIVE | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA_SHA1, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA_SHA224, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA_SHA256, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA_SHA384, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_ECDSA_SHA512, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
    { CKM_EC_EDWARDS_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
    { CKM_EC_MONTGOMERY_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
    { CKM_EDDSA, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_POC }, PR_TRUE },
    /* ------------------------- 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_CMAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
    { CKM_AES_CMAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
    { CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
    { CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
    { CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
    { CKM_AES_GCM, { 16, 32, CKF_EN_DE_MSG }, PR_TRUE },
    { CKM_AES_XCBC_MAC_96, { 12, 12, CKF_SN_VR }, PR_TRUE },
    { CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, 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 --------------------------- */
#ifndef NSS_DISABLE_DEPRECATED_SEED
    { 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 },
#endif
/* ------------------------- ChaCha20 Operations ---------------------- */
#ifndef NSS_DISABLE_CHACHAPOLY
    { CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
    { CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
    { CKM_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
    { CKM_CHACHA20, { 32, 32, CKF_EN_DE }, PR_TRUE },
    { CKM_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE_MSG }, PR_TRUE },
#endif /* NSS_DISABLE_CHACHAPOLY */
    /* ------------------------- 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_SHA3_224, { 0, 0, CKF_DIGEST }, PR_FALSE },
    { CKM_SHA3_224_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_224_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_256, { 0, 0, CKF_DIGEST }, PR_FALSE },
    { CKM_SHA3_256_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_256_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_384, { 0, 0, CKF_DIGEST }, PR_FALSE },
    { CKM_SHA3_384_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_384_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_512, { 0, 0, CKF_DIGEST }, PR_FALSE },
    { CKM_SHA3_512_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_SHA3_512_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
    { CKM_TLS_PRF_GENERAL, { 0, 512, CKF_SN_VR }, PR_FALSE },
    { CKM_TLS_MAC, { 0, 512, CKF_SN_VR }, PR_FALSE },
    { CKM_NSS_TLS_PRF_GENERAL_SHA256,
      { 0, 512, CKF_SN_VR },
      PR_FALSE },
    /* ------------------------- HKDF Operations -------------------------- */
    { CKM_HKDF_DERIVE, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
    { CKM_HKDF_DATA, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
    { CKM_HKDF_KEY_GEN, { 20, 64, CKF_GENERATE }, PR_TRUE },
    { 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_DERIVE }, PR_FALSE },
    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
#ifndef NSS_DISABLE_DEPRECATED_SEED
    { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
#endif
    /* ---------------------- 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_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE }, PR_FALSE },
    { CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE }, PR_FALSE },
    { CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE }, PR_FALSE },
    { CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE }, PR_FALSE },
    { CKM_TLS_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
    { CKM_TLS12_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
    { CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256,
      { 48, 48, CKF_DERIVE },
      PR_FALSE },
    { CKM_TLS_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
    { CKM_TLS12_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
    { CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256,
      { 8, 128, CKF_DERIVE },
      PR_FALSE },
    { CKM_TLS_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
    { CKM_TLS12_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
    { CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256,
      { 48, 48, CKF_DERIVE },
      PR_FALSE },
    { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE,
      { 48, 128, CKF_DERIVE },
      PR_FALSE },
    { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH,
      { 48, 128, 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 },
    /* ------------------ NSS PBE Key Derivations  ------------------- */
    { CKM_NSS_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_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_NSS_PBE_SHA1_HMAC_KEY_GEN, { 20, 20, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PBE_MD5_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PBE_MD2_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 28, 28, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_TRUE },
    { CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 64, 64, CKF_GENERATE }, PR_TRUE },
    /* ------------------ NIST 800-108 Key Derivations  ------------------- */
    { CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    { CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
    /* ------------------ AES Key Wrap (also encrypt)  ------------------- */
    { CKM_NSS_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
    { CKM_NSS_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
    { CKM_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
    { CKM_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
    { CKM_AES_KEY_WRAP_KWP, { 1, 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 },
    /* -------------------- Constant Time TLS MACs ----------------------- */
    { CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
    { CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
    /* -------------------- IPSEC ----------------------- */
    { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
    { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
    /* -------------------- Kyber Operations ----------------------- */
    { CKM_NSS_KYBER_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
    { CKM_NSS_KYBER, { 0, 0, 0 }, PR_TRUE },
    { CKM_NSS_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
    { CKM_NSS_ML_KEM, { 0, 0, 0 }, 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

#define SFTKFreeWrap(ctxtype, mmm) \
    void SFTKFree_##mmm(void *vp)  \
    {                              \
        ctxtype *p = vp;           \
        mmm(p);                    \
    }

SFTKFreeWrap(NSSLOWKEYPublicKey, nsslowkey_DestroyPublicKey);
SFTKFreeWrap(NSSLOWKEYPrivateKey, nsslowkey_DestroyPrivateKey);

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_CheckPasswordNull(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,
                      const 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_NSS_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_MIN_Q_BITS, DSA_MAX_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, 2, DSA_MAX_P_BITS, 0);
            if (crv != CKR_OK) {
                return crv;
            }
            crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, 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, 2, DH_MAX_P_BITS, 0);
            if (crv != CKR_OK) {
                return crv;
            }
            crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, 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;
        case CKK_EC_MONTGOMERY:
        case CKK_EC_EDWARDS:
        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;
            }
            /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
            derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE;    /* CK_TRUE for ECDH */
            verify = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
            encrypt = CK_FALSE;
            recover = CK_FALSE;
            wrap = CK_FALSE;
            break;
        case CKK_NSS_KYBER:
        case CKK_NSS_ML_KEM:
            if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) {
                return CKR_TEMPLATE_INCOMPLETE;
            }
            derive = CK_FALSE;
            verify = CK_FALSE;
            encrypt = CK_FALSE;
            recover = CK_FALSE;
            wrap = CK_FALSE;
            break;
        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;

    /* Check that an imported EC key is valid */
    if (key_type == CKK_EC || key_type == CKK_EC_EDWARDS || key_type == CKK_EC_MONTGOMERY) {
        NSSLOWKEYPublicKey *pubKey = (NSSLOWKEYPublicKey *)object->objectInfo;
        SECStatus rv = EC_ValidatePublicKey(&pubKey->u.ec.ecParams,
                                            &pubKey->u.ec.publicValue);

        if (rv != SECSuccess) {
            return CKR_TEMPLATE_INCONSISTENT;
        }
    }

    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_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded);

/*
 * 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;
    PRBool fillPrivateKey = PR_FALSE;
    int missing_rsa_mod_component = 0;
    int missing_rsa_exp_component = 0;
    int missing_rsa_crt_component = 0;

    SECItem mod;
    CK_RV crv;
    SECStatus rv;

    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);

                if ((have_exp == 0) || (have_component < 3)) {
                    /* nope, not enough to reconstruct the private key */
                    return CKR_TEMPLATE_INCOMPLETE;
                }
                fillPrivateKey = PR_TRUE;
            }
            /*verify the parameters for consistency*/
            rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey);
            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_NSS_DB,
                                      sftk_item_expand(&mod));
            if (mod.data)
                SECITEM_ZfreeItem(&mod, PR_FALSE);
            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;
            }
            /* allow subprime to be set after the fact */
            crv = sftk_defaultAttribute(object, CKA_SUBPRIME, NULL, 0);
            if (crv != CKR_OK) {
                return crv;
            }
            encrypt = CK_FALSE;
            recover = CK_FALSE;
            wrap = CK_FALSE;
            break;
        case CKK_EC:
        case CKK_EC_EDWARDS:
        case CKK_EC_MONTGOMERY:
            if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) {
                return CKR_TEMPLATE_INCOMPLETE;
            }
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
                return CKR_TEMPLATE_INCOMPLETE;
            }
            /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
            derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE;  /* CK_TRUE for ECDH */
            sign = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
            encrypt = CK_FALSE;
            recover = CK_FALSE;
            wrap = CK_FALSE;
            break;
        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;
        case CKK_NSS_KYBER:
        case CKK_NSS_ML_KEM:
            if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
                return CKR_TEMPLATE_INCOMPLETE;
            }
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
                return CKR_TEMPLATE_INCOMPLETE;
            }
            encrypt = sign = recover = wrap = CK_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);

        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);

        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)(sftk_isFIPS(session->slot->slotID)));
        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;
    /* This bool keeps track of whether or not we need verify parameters.
     * If a P, Q and G or supplied, we dont' need verify parameters, as we
     * have PQ and G.
     *   - If G is not supplied, the presumption is that we want to
     * verify P and Q only.
     *   - If counter is supplied, it is presumed we want to verify PQ because
     * the counter is only used in verification.
     *   - If H is supplied, is is presumed we want to verify G because H is
     * only used to verify G.
     *   - Any verification step must have the SEED (counter or H could be
     * missing depending on exactly what we want to verify). If SEED is supplied,
     * the code just goes ahead and runs verify (other errors are parameter
     * errors are detected by the PQG_VerifyParams function). If SEED is not
     * supplied, but we determined that we are trying to verify (because needVfy
     * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE.
     */

    PRBool needVfy = PR_FALSE;

    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) {
        params.base.data = baseAttr->attrib.pValue;
        params.base.len = baseAttr->attrib.ulValueLen;
    } else {
        params.base.data = NULL;
        params.base.len = 0;
        needVfy = PR_TRUE; /* presumably only including PQ so we can verify
                            * them. */

    }

    attribute = sftk_FindAttribute(object, CKA_NSS_PQG_COUNTER);
    if (attribute != NULL) {
        vfy.counter = *(CK_ULONG *)attribute->attrib.pValue;
        sftk_FreeAttribute(attribute);
        needVfy = PR_TRUE; /* included a count so we can verify PQ */
    } else {
        vfy.counter = -1;
    }

    hAttr = sftk_FindAttribute(object, CKA_NSS_PQG_H);
    if (hAttr != NULL) {
        vfy.h.data = hAttr->attrib.pValue;
        vfy.h.len = hAttr->attrib.ulValueLen;
        needVfy = PR_TRUE; /* included H so we can verify G */
    } else {
        vfy.h.data = NULL;
        vfy.h.len = 0;
    }
    seedAttr = sftk_FindAttribute(object, CKA_NSS_PQG_SEED);
    if (seedAttr != NULL) {
        vfy.seed.data = seedAttr->attrib.pValue;
        vfy.seed.len = seedAttr->attrib.ulValueLen;

        verify = &vfy;
    } else if (needVfy) {
        goto loser; /* Verify always needs seed, if we need verify and not seed
                     * then fail */

    }

    crv = CKR_FUNCTION_FAILED;
    rv = PQG_VerifyParams(¶ms, verify, &result);
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=91 H=98 G=94

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge