summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtchang%redhat.com <devnull@localhost>2005-09-09 00:03:10 +0000
committerwtchang%redhat.com <devnull@localhost>2005-09-09 00:03:10 +0000
commit0f8d84f0e231ca0258db620ab4c696b35cfad597 (patch)
tree27c9abf3a9575451b15d2e5cff6eebfcfe63769f
parentf16e7cfdaacb42476a299d24d0b111e8e0ab168c (diff)
downloadnss-hg-0f8d84f0e231ca0258db620ab4c696b35cfad597.tar.gz
Bugzilla Bug 299197: ported the fix back to the NSS_3_10_BRANCH. Added
the PK11AttrFlags type and the PK11_ATTR_XXX bitflags. Added PK11_GenerateKeyPairWithFlags and changed PK11_TokenKeyGenWithFlags to use PK11AttrFlags. Modified Files: Tag: NSS_3_10_BRANCH nss/nss.def pk11wrap/pk11akey.c pk11wrap/pk11obj.c pk11wrap/pk11pub.h pk11wrap/pk11skey.c pk11wrap/secmodi.h pk11wrap/secmodt.h
-rw-r--r--security/nss/lib/nss/nss.def1
-rw-r--r--security/nss/lib/pk11wrap/pk11akey.c566
-rw-r--r--security/nss/lib/pk11wrap/pk11obj.c48
-rw-r--r--security/nss/lib/pk11wrap/pk11pub.h13
-rw-r--r--security/nss/lib/pk11wrap/pk11skey.c38
-rw-r--r--security/nss/lib/pk11wrap/secmodi.h8
-rw-r--r--security/nss/lib/pk11wrap/secmodt.h135
7 files changed, 786 insertions, 23 deletions
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index 9418d9293..208638a77 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -853,6 +853,7 @@ NSS_Get_CERT_SignedCrlTemplate;
;+NSS_3.10.2 { # NSS 3.10.2 release
;+ global:
PK11_TokenKeyGenWithFlags;
+PK11_GenerateKeyPairWithFlags;
;+ local:
;+ *;
;+};
diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c
index 4e1745adc..55db33995 100644
--- a/security/nss/lib/pk11wrap/pk11akey.c
+++ b/security/nss/lib/pk11wrap/pk11akey.c
@@ -767,6 +767,148 @@ failure:
* This is used to do a key gen using one pkcs11 module and storing the
* result into another.
*/
+static SECKEYPrivateKey *
+pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags)
+{
+ CK_ATTRIBUTE privTemplate[] = {
+ /* class must be first */
+ { CKA_CLASS, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+#ifdef notdef
+ { CKA_LABEL, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+#endif
+ /* RSA */
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 },
+ { CKA_PRIME_1, NULL, 0 },
+ { CKA_PRIME_2, NULL, 0 },
+ { CKA_EXPONENT_1, NULL, 0 },
+ { CKA_EXPONENT_2, NULL, 0 },
+ { CKA_COEFFICIENT, NULL, 0 },
+ /* reserve space for the attributes that may be
+ * specified in attrFlags */
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_SENSITIVE, NULL, 0 },
+ { CKA_EXTRACTABLE, NULL, 0 },
+#define NUM_RESERVED_ATTRS 5 /* number of reserved attributes above */
+ };
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_BBOOL ckfalse = CK_FALSE;
+ CK_ATTRIBUTE *attrs = NULL, *ap;
+ const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]);
+ PRArenaPool *arena;
+ CK_OBJECT_HANDLE objectID;
+ int i, count = 0;
+ int extra_count = 0;
+ CK_RV crv;
+ SECStatus rv;
+ PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
+
+ if (pk11_BadAttrFlags(attrFlags)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ for (i=0; i < templateSize; i++) {
+ if (privTemplate[i].type == CKA_MODULUS) {
+ attrs= &privTemplate[i];
+ count = i;
+ break;
+ }
+ }
+ PORT_Assert(attrs != NULL);
+ if (attrs == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+
+ ap = attrs;
+
+ switch (privKey->keyType) {
+ case rsaKey:
+ count = templateSize - NUM_RESERVED_ATTRS;
+ extra_count = count - (attrs - privTemplate);
+ break;
+ case dsaKey:
+ ap->type = CKA_PRIME; ap++; count++; extra_count++;
+ ap->type = CKA_SUBPRIME; ap++; count++; extra_count++;
+ ap->type = CKA_BASE; ap++; count++; extra_count++;
+ ap->type = CKA_VALUE; ap++; count++; extra_count++;
+ break;
+ case dhKey:
+ ap->type = CKA_PRIME; ap++; count++; extra_count++;
+ ap->type = CKA_BASE; ap++; count++; extra_count++;
+ ap->type = CKA_VALUE; ap++; count++; extra_count++;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case ecKey:
+ ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
+ ap->type = CKA_VALUE; ap++; count++; extra_count++;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ default:
+ count = 0;
+ extra_count = 0;
+ break;
+ }
+
+ if (count == 0) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+
+ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) return NULL;
+ /*
+ * read out the old attributes.
+ */
+ crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
+ privTemplate,count);
+ if (crv != CKR_OK) {
+ PORT_SetError( PK11_MapError(crv) );
+ PORT_FreeArena(arena, PR_TRUE);
+ return NULL;
+ }
+
+ /* Set token, private, modifiable, sensitive, and extractable */
+ count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
+ &cktrue, &ckfalse);
+
+ /* Not everyone can handle zero padded key values, give
+ * them the raw data as unsigned */
+ for (ap=attrs; extra_count; ap++, extra_count--) {
+ pk11_SignedToUnsigned(ap);
+ }
+
+ /* now Store the puppies */
+ rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate,
+ count, token, &objectID);
+ PORT_FreeArena(arena, PR_TRUE);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+
+ /* try loading the public key */
+ if (pubKey) {
+ PK11_ImportPublicKey(slot, pubKey, token);
+ if (pubKey->pkcs11Slot) {
+ PK11_FreeSlot(pubKey->pkcs11Slot);
+ pubKey->pkcs11Slot = NULL;
+ pubKey->pkcs11ID = CK_INVALID_HANDLE;
+ }
+ }
+
+ /* build new key structure */
+ return PK11_MakePrivKey(slot, privKey->keyType, !token,
+ objectID, privKey->wincx);
+}
+
SECKEYPrivateKey *
pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive)
@@ -910,9 +1052,427 @@ PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
/*
- * Use the token to Generate a key. keySize must be 'zero' for fixed key
- * length algorithms. NOTE: this means we can never generate a DES2 key
- * from this interface!
+ * Use the token to generate a key pair.
+ */
+SECKEYPrivateKey *
+PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
+ void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
+{
+ /* we have to use these native types because when we call PKCS 11 modules
+ * we have to make sure that we are using the correct sizes for all the
+ * parameters. */
+ CK_BBOOL ckfalse = CK_FALSE;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_ULONG modulusBits;
+ CK_BYTE publicExponent[4];
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_SENSITIVE, NULL, 0},
+ { CKA_TOKEN, NULL, 0},
+ { CKA_PRIVATE, NULL, 0},
+ { CKA_DERIVE, NULL, 0},
+ { CKA_UNWRAP, NULL, 0},
+ { CKA_SIGN, NULL, 0},
+ { CKA_DECRYPT, NULL, 0},
+ { CKA_EXTRACTABLE, NULL, 0},
+ { CKA_MODIFIABLE, NULL, 0},
+ };
+ CK_ATTRIBUTE rsaPubTemplate[] = {
+ { CKA_MODULUS_BITS, NULL, 0},
+ { CKA_PUBLIC_EXPONENT, NULL, 0},
+ { CKA_TOKEN, NULL, 0},
+ { CKA_DERIVE, NULL, 0},
+ { CKA_WRAP, NULL, 0},
+ { CKA_VERIFY, NULL, 0},
+ { CKA_VERIFY_RECOVER, NULL, 0},
+ { CKA_ENCRYPT, NULL, 0},
+ { CKA_MODIFIABLE, NULL, 0},
+ };
+ CK_ATTRIBUTE dsaPubTemplate[] = {
+ { CKA_PRIME, NULL, 0 },
+ { CKA_SUBPRIME, NULL, 0 },
+ { CKA_BASE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0},
+ { CKA_DERIVE, NULL, 0},
+ { CKA_WRAP, NULL, 0},
+ { CKA_VERIFY, NULL, 0},
+ { CKA_VERIFY_RECOVER, NULL, 0},
+ { CKA_ENCRYPT, NULL, 0},
+ { CKA_MODIFIABLE, NULL, 0},
+ };
+ CK_ATTRIBUTE dhPubTemplate[] = {
+ { CKA_PRIME, NULL, 0 },
+ { CKA_BASE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0},
+ { CKA_DERIVE, NULL, 0},
+ { CKA_WRAP, NULL, 0},
+ { CKA_VERIFY, NULL, 0},
+ { CKA_VERIFY_RECOVER, NULL, 0},
+ { CKA_ENCRYPT, NULL, 0},
+ { CKA_MODIFIABLE, NULL, 0},
+ };
+#ifdef NSS_ENABLE_ECC
+ CK_ATTRIBUTE ecPubTemplate[] = {
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_TOKEN, NULL, 0},
+ { CKA_DERIVE, NULL, 0},
+ { CKA_WRAP, NULL, 0},
+ { CKA_VERIFY, NULL, 0},
+ { CKA_VERIFY_RECOVER, NULL, 0},
+ { CKA_ENCRYPT, NULL, 0},
+ { CKA_MODIFIABLE, NULL, 0},
+ };
+ SECKEYECParams * ecParams;
+#endif /* NSS_ENABLE_ECC */
+
+ /*CK_ULONG key_size = 0;*/
+ CK_ATTRIBUTE *pubTemplate;
+ int privCount = 0;
+ int pubCount = 0;
+ PK11RSAGenParams *rsaParams;
+ SECKEYPQGParams *dsaParams;
+ SECKEYDHParams * dhParams;
+ CK_MECHANISM mechanism;
+ CK_MECHANISM test_mech;
+ CK_SESSION_HANDLE session_handle;
+ CK_RV crv;
+ CK_OBJECT_HANDLE privID,pubID;
+ SECKEYPrivateKey *privKey;
+ KeyType keyType;
+ PRBool restore;
+ int peCount,i;
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *privattrs;
+ SECItem *pubKeyIndex;
+ CK_ATTRIBUTE setTemplate;
+ SECStatus rv;
+ CK_MECHANISM_INFO mechanism_info;
+ CK_OBJECT_CLASS keyClass;
+ SECItem *cka_id;
+ PRBool haslock = PR_FALSE;
+ PRBool pubIsToken = PR_FALSE;
+ PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
+ /* subset of attrFlags applicable to the public key */
+ PK11AttrFlags pubKeyAttrFlags = attrFlags &
+ (PK11_ATTR_TOKEN | PK11_ATTR_SESSION
+ | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
+
+ if (pk11_BadAttrFlags(attrFlags)) {
+ PORT_SetError( SEC_ERROR_INVALID_ARGS );
+ return NULL;
+ }
+
+ PORT_Assert(slot != NULL);
+ if (slot == NULL) {
+ PORT_SetError( SEC_ERROR_NO_MODULE);
+ return NULL;
+ }
+
+ /* if our slot really doesn't do this mechanism, Generate the key
+ * in our internal token and write it out */
+ if (!PK11_DoesMechanism(slot,type)) {
+ PK11SlotInfo *int_slot = PK11_GetInternalSlot();
+
+ /* don't loop forever looking for a slot */
+ if (slot == int_slot) {
+ PK11_FreeSlot(int_slot);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+
+ /* if there isn't a suitable slot, then we can't do the keygen */
+ if (int_slot == NULL) {
+ PORT_SetError( SEC_ERROR_NO_MODULE );
+ return NULL;
+ }
+
+ /* generate the temporary key to load */
+ privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE,
+ PR_FALSE, wincx);
+ PK11_FreeSlot(int_slot);
+
+ /* if successful, load the temp key into the new token */
+ if (privKey != NULL) {
+ SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
+ privKey,*pubKey,attrFlags);
+ SECKEY_DestroyPrivateKey(privKey);
+ if (newPrivKey == NULL) {
+ SECKEY_DestroyPublicKey(*pubKey);
+ *pubKey = NULL;
+ }
+ return newPrivKey;
+ }
+ return NULL;
+ }
+
+
+ mechanism.mechanism = type;
+ mechanism.pParameter = NULL;
+ mechanism.ulParameterLen = 0;
+ test_mech.pParameter = NULL;
+ test_mech.ulParameterLen = 0;
+
+ /* set up the private key template */
+ privattrs = privTemplate;
+ privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
+ &cktrue, &ckfalse);
+
+ /* set up the mechanism specific info */
+ switch (type) {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ rsaParams = (PK11RSAGenParams *)param;
+ modulusBits = rsaParams->keySizeInBits;
+ peCount = 0;
+
+ /* convert pe to a PKCS #11 string */
+ for (i=0; i < 4; i++) {
+ if (peCount || (rsaParams->pe &
+ ((unsigned long)0xff000000L >> (i*8)))) {
+ publicExponent[peCount] =
+ (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
+ peCount++;
+ }
+ }
+ PORT_Assert(peCount != 0);
+ attrs = rsaPubTemplate;
+ PK11_SETATTRS(attrs, CKA_MODULUS_BITS,
+ &modulusBits, sizeof(modulusBits)); attrs++;
+ PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
+ publicExponent, peCount);attrs++;
+ pubTemplate = rsaPubTemplate;
+ keyType = rsaKey;
+ test_mech.mechanism = CKM_RSA_PKCS;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ dsaParams = (SECKEYPQGParams *)param;
+ attrs = dsaPubTemplate;
+ PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
+ dsaParams->prime.len); attrs++;
+ PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
+ dsaParams->subPrime.len); attrs++;
+ PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
+ dsaParams->base.len); attrs++;
+ pubTemplate = dsaPubTemplate;
+ keyType = dsaKey;
+ test_mech.mechanism = CKM_DSA;
+ break;
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ dhParams = (SECKEYDHParams *)param;
+ attrs = dhPubTemplate;
+ PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
+ dhParams->prime.len); attrs++;
+ PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
+ dhParams->base.len); attrs++;
+ pubTemplate = dhPubTemplate;
+ keyType = dhKey;
+ test_mech.mechanism = CKM_DH_PKCS_DERIVE;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case CKM_EC_KEY_PAIR_GEN:
+ ecParams = (SECKEYECParams *)param;
+ attrs = ecPubTemplate;
+ PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
+ ecParams->len); attrs++;
+ pubTemplate = ecPubTemplate;
+ keyType = ecKey;
+ /* XXX An EC key can be used for other mechanisms too such
+ * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect
+ * that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY
+ * attributes are set correctly?
+ */
+ test_mech.mechanism = CKM_ECDH1_DERIVE;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ default:
+ PORT_SetError( SEC_ERROR_BAD_KEY );
+ return NULL;
+ }
+
+ /* now query the slot to find out how "good" a key we can generate */
+ if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
+ crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
+ test_mech.mechanism,&mechanism_info);
+ if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
+ if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
+ /* must be old module... guess what it should be... */
+ switch (test_mech.mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT |
+ CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);;
+ break;
+ case CKM_DSA:
+ mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_DH_PKCS_DERIVE:
+ mechanism_info.flags = CKF_DERIVE;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case CKM_ECDH1_DERIVE:
+ mechanism_info.flags = CKF_DERIVE;
+ break;
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA1:
+ mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ default:
+ break;
+ }
+ }
+ /* set the public key attributes */
+ attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
+ &cktrue, &ckfalse);
+ PK11_SETATTRS(attrs, CKA_DERIVE,
+ mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); attrs++;
+ PK11_SETATTRS(attrs, CKA_WRAP,
+ mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); attrs++;
+ PK11_SETATTRS(attrs, CKA_VERIFY,
+ mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); attrs++;
+ PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER,
+ mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); attrs++;
+ PK11_SETATTRS(attrs, CKA_ENCRYPT,
+ mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); attrs++;
+ /* set the private key attributes */
+ PK11_SETATTRS(privattrs, CKA_DERIVE,
+ mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); privattrs++;
+ PK11_SETATTRS(privattrs, CKA_UNWRAP,
+ mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); privattrs++;
+ PK11_SETATTRS(privattrs, CKA_SIGN,
+ mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); privattrs++;
+ PK11_SETATTRS(privattrs, CKA_DECRYPT,
+ mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
+ sizeof(CK_BBOOL)); privattrs++;
+
+ if (token) {
+ session_handle = PK11_GetRWSession(slot);
+ haslock = PK11_RWSessionHasLock(slot,session_handle);
+ restore = PR_TRUE;
+ } else {
+ PK11_EnterSlotMonitor(slot); /* gross!! */
+ session_handle = slot->session;
+ restore = PR_FALSE;
+ haslock = PR_TRUE;
+ }
+
+ privCount = privattrs - privTemplate;
+ pubCount = attrs - pubTemplate;
+ crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
+ pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
+
+ if (crv != CKR_OK) {
+ if (restore) {
+ PK11_RestoreROSession(slot,session_handle);
+ } else PK11_ExitSlotMonitor(slot);
+ PORT_SetError( PK11_MapError(crv) );
+ return NULL;
+ }
+ /* This locking code is dangerous and needs to be more thought
+ * out... the real problem is that we're holding the mutex open this long
+ */
+ if (haslock) { PK11_ExitSlotMonitor(slot); }
+
+ /* swap around the ID's for older PKCS #11 modules */
+ keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
+ if (keyClass != CKO_PUBLIC_KEY) {
+ CK_OBJECT_HANDLE tmp = pubID;
+ pubID = privID;
+ privID = tmp;
+ }
+
+ *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
+ if (*pubKey == NULL) {
+ if (restore) {
+ /* we may have to restore the mutex so it get's exited properly
+ * in RestoreROSession */
+ if (haslock) PK11_EnterSlotMonitor(slot);
+ PK11_RestoreROSession(slot,session_handle);
+ }
+ PK11_DestroyObject(slot,pubID);
+ PK11_DestroyObject(slot,privID);
+ return NULL;
+ }
+
+ /* set the ID to the public key so we can find it again */
+ pubKeyIndex = NULL;
+ switch (type) {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ pubKeyIndex = &(*pubKey)->u.rsa.modulus;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ pubKeyIndex = &(*pubKey)->u.dsa.publicValue;
+ break;
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ pubKeyIndex = &(*pubKey)->u.dh.publicValue;
+ break;
+#ifdef NSS_ENABLE_ECC
+ case CKM_EC_KEY_PAIR_GEN:
+ pubKeyIndex = &(*pubKey)->u.ec.publicValue;
+ break;
+#endif /* NSS_ENABLE_ECC */
+ }
+ PORT_Assert(pubKeyIndex != NULL);
+
+ cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);
+ pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
+
+ PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
+
+ if (haslock) { PK11_EnterSlotMonitor(slot); }
+ crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
+ &setTemplate, 1);
+
+ if (crv == CKR_OK && pubIsToken) {
+ crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
+ &setTemplate, 1);
+ }
+
+
+ if (restore) {
+ PK11_RestoreROSession(slot,session_handle);
+ } else {
+ PK11_ExitSlotMonitor(slot);
+ }
+ SECITEM_FreeItem(cka_id,PR_TRUE);
+
+
+ if (crv != CKR_OK) {
+ PK11_DestroyObject(slot,pubID);
+ PK11_DestroyObject(slot,privID);
+ PORT_SetError( PK11_MapError(crv) );
+ *pubKey = NULL;
+ return NULL;
+ }
+
+ privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
+ if (privKey == NULL) {
+ SECKEY_DestroyPublicKey(*pubKey);
+ PK11_DestroyObject(slot,privID);
+ *pubKey = NULL;
+ return NULL;
+ }
+
+ /* Perform PKCS #11 pairwise consistency check. */
+ rv = pk11_PairwiseConsistencyCheck( *pubKey, privKey, &test_mech, wincx );
+ if( rv != SECSuccess ) {
+ SECKEY_DestroyPublicKey( *pubKey );
+ SECKEY_DestroyPrivateKey( privKey );
+ *pubKey = NULL;
+ privKey = NULL;
+ return NULL; /* due to pairwise consistency check */
+ }
+
+ return privKey;
+}
+
+/*
+ * Use the token to generate a key pair.
*/
SECKEYPrivateKey *
PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c
index 8d065f928..0af025539 100644
--- a/security/nss/lib/pk11wrap/pk11obj.c
+++ b/security/nss/lib/pk11wrap/pk11obj.c
@@ -408,7 +408,7 @@ PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
unsigned int
-pk11_FlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
+pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
{
const static CK_ATTRIBUTE_TYPE attrTypes[12] = {
@@ -436,6 +436,52 @@ pk11_FlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
}
/*
+ * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE
+ * and PK11_ATTR_PUBLIC are set.
+ */
+PRBool
+pk11_BadAttrFlags(PK11AttrFlags attrFlags)
+{
+ PK11AttrFlags trueFlags = attrFlags & 0x55555555;
+ PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555;
+ return ((trueFlags & falseFlags) != 0);
+}
+
+/*
+ * This function may add a maximum of 5 attributes.
+ * The caller must make sure the attribute flags don't have conflicts.
+ */
+unsigned int
+pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs,
+ CK_BBOOL *ckTrue, CK_BBOOL *ckFalse)
+{
+ const static CK_ATTRIBUTE_TYPE attrTypes[5] = {
+ CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_SENSITIVE,
+ CKA_EXTRACTABLE
+ };
+
+ const CK_ATTRIBUTE_TYPE *pType = attrTypes;
+ CK_ATTRIBUTE *attr = attrs;
+ PK11AttrFlags test = PK11_ATTR_TOKEN;
+
+ PR_ASSERT(!pk11_BadAttrFlags(attrFlags));
+
+ /* we test two related bitflags in each iteration */
+ for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE; test <<= 2, ++pType) {
+ if (test & attrFlags) {
+ attrFlags ^= test;
+ PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue);
+ ++attr;
+ } else if ((test << 1) & attrFlags) {
+ attrFlags ^= (test << 1);
+ PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse);
+ ++attr;
+ }
+ }
+ return (attr - attrs);
+}
+
+/*
* Some non-compliant PKCS #11 vendors do not give us the modulus, so actually
* set up a signature to get the signaure length.
*/
diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h
index 462f5573b..51cce7c62 100644
--- a/security/nss/lib/pk11wrap/pk11pub.h
+++ b/security/nss/lib/pk11wrap/pk11pub.h
@@ -238,8 +238,8 @@ PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
PRBool isToken, void *wincx);
PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, SECItem *param,
- int keySize, SECItem *keyid, CK_FLAGS flags,
- PRBool isToken, void *wincx);
+ int keySize, SECItem *keyid, CK_FLAGS opFlags,
+ PK11AttrFlags attrFlags, void *wincx);
PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname,
void *wincx);
PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey);
@@ -349,6 +349,15 @@ SECStatus PK11_ExtractKeyValue(PK11SymKey *symKey);
SECItem * PK11_GetKeyData(PK11SymKey *symKey);
PK11SlotInfo * PK11_GetSlotFromKey(PK11SymKey *symKey);
void *PK11_GetWindow(PK11SymKey *symKey);
+/*
+ * The attrFlags is the logical OR of the PK11_ATTR_XXX bitflags.
+ * These flags apply to the private key. The PK11_ATTR_TOKEN,
+ * PK11_ATTR_SESSION, PK11_ATTR_MODIFIABLE, and PK11_ATTR_UNMODIFIABLE
+ * flags also apply to the public key.
+ */
+SECKEYPrivateKey *PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,
+ CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk,
+ PK11AttrFlags attrFlags, void *wincx);
SECKEYPrivateKey *PK11_GenerateKeyPair(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk,
PRBool isPerm, PRBool isSensitive, void *wincx);
diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c
index 7fa1285c1..299702a48 100644
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/lib/pk11wrap/pk11skey.c
@@ -409,7 +409,7 @@ PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
* default for secret keys */
PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++;
}
- attrs += pk11_FlagsToAttributes(flags, attrs, &cktrue);
+ attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
if ((operation != CKA_FLAGS_ONLY) &&
!pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) {
PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); attrs++;
@@ -773,11 +773,14 @@ PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
* NOTE: this means to generate a DES2 key from this interface you must
* specify CKM_DES2_KEY_GEN as the mechanism directly; specifying
* CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work.
+ *
+ * CK_FLAGS flags: key operation flags
+ * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
*/
PK11SymKey *
PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
- SECItem *param, int keySize, SECItem *keyid, CK_FLAGS flags,
- PRBool isToken, void *wincx)
+ SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags,
+ PK11AttrFlags attrFlags, void *wincx)
{
PK11SymKey *symKey;
CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS];
@@ -787,7 +790,14 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_MECHANISM mechanism;
CK_RV crv;
CK_BBOOL cktrue = CK_TRUE;
+ CK_BBOOL ckfalse = CK_FALSE;
CK_ULONG ck_key_size; /* only used for variable-length keys */
+ PRBool isToken = ((attrFlags & PK11_ATTR_TOKEN) != 0);
+
+ if (pk11_BadAttrFlags(attrFlags)) {
+ PORT_SetError( SEC_ERROR_INVALID_ARGS );
+ return NULL;
+ }
if (keySize != 0) {
ck_key_size = keySize; /* Convert to PK11 type */
@@ -801,12 +811,8 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++;
}
- if (isToken) {
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
- PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue)); attrs++;
- }
-
- attrs += pk11_FlagsToAttributes(flags, attrs, &cktrue);
+ attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
+ attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
count = attrs - genTemplate;
PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE));
@@ -937,7 +943,7 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) {
PK11SlotInfo *bestSlot;
- bestSlot = PK11_GetBestSlot(type,wincx); /* TNH: references the slot? */
+ bestSlot = PK11_GetBestSlot(type,wincx);
if (bestSlot == NULL) {
PORT_SetError( SEC_ERROR_NO_MODULE );
return NULL;
@@ -1280,7 +1286,7 @@ PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
unsigned int templateCount;
- templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue);
+ templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation,
keySize, keyTemplate, templateCount, PR_FALSE);
}
@@ -1300,7 +1306,7 @@ PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++;
}
templateCount = attrs - keyTemplate;
- templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue);
+ templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation,
keySize, keyTemplate, templateCount, isPerm);
}
@@ -1963,7 +1969,7 @@ PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
unsigned int templateCount;
- templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue);
+ templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
wrapType, param, wrappedKey, target, operation, keySize,
wrappingKey->cx, keyTemplate, templateCount, PR_FALSE);
@@ -1986,7 +1992,7 @@ PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey,
PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++;
}
templateCount = attrs-keyTemplate;
- templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue);
+ templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
wrapType, param, wrappedKey, target, operation, keySize,
@@ -2023,7 +2029,7 @@ PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey,
unsigned int templateCount;
PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
- templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue);
+ templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) {
PK11_HandlePasswordCheck(slot,wrappingKey->wincx);
@@ -2053,7 +2059,7 @@ PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey,
}
templateCount = attrs-keyTemplate;
- templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue);
+ templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) {
PK11_HandlePasswordCheck(slot,wrappingKey->wincx);
diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h
index d8c4b1d3a..4514cdaf5 100644
--- a/security/nss/lib/pk11wrap/secmodi.h
+++ b/security/nss/lib/pk11wrap/secmodi.h
@@ -124,8 +124,14 @@ CK_SESSION_HANDLE pk11_GetNewSession(PK11SlotInfo *slot, PRBool *owner);
void pk11_CloseSession(PK11SlotInfo *slot, CK_SESSION_HANDLE sess, PRBool own);
PK11SymKey *pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation);
-unsigned int pk11_FlagsToAttributes(CK_FLAGS flags,
+/* Convert key operation flags to PKCS #11 attributes. */
+unsigned int pk11_OpFlagsToAttributes(CK_FLAGS flags,
CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue);
+/* Check for bad (conflicting) attribute flags */
+PRBool pk11_BadAttrFlags(PK11AttrFlags attrFlags);
+/* Convert key attribute flags to PKCS #11 attributes. */
+unsigned int pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags,
+ CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue, CK_BBOOL *ckFalse);
PRBool pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
CK_ATTRIBUTE_TYPE target);
diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h
index 7a07f5302..73d14f726 100644
--- a/security/nss/lib/pk11wrap/secmodt.h
+++ b/security/nss/lib/pk11wrap/secmodt.h
@@ -194,6 +194,141 @@ struct PK11DefaultArrayEntryStr {
#define CKA_DIGEST 0x81000000L
#define CKA_FLAGS_ONLY 0 /* CKA_CLASS */
+/*
+ * PK11AttrFlags
+ *
+ * A 32-bit bitmask of PK11_ATTR_XXX flags
+ */
+typedef PRUint32 PK11AttrFlags;
+
+/*
+ * PK11_ATTR_XXX
+ *
+ * The following PK11_ATTR_XXX bitflags are used to specify
+ * PKCS #11 object attributes that have Boolean values. Some NSS
+ * functions have a "PK11AttrFlags attrFlags" parameter whose value
+ * is the logical OR of these bitflags. NSS use these bitflags on
+ * private keys or secret keys. Some of these bitflags also apply
+ * to the public keys associated with the private keys.
+ *
+ * For each PKCS #11 object attribute, we need two bitflags to
+ * specify not only "true" and "false" but also "default". For
+ * example, PK11_ATTR_PRIVATE and PK11_ATTR_PUBLIC control the
+ * CKA_PRIVATE attribute. If PK11_ATTR_PRIVATE is set, we add
+ * { CKA_PRIVATE, &cktrue, sizeof(CK_BBOOL) }
+ * to the template. If PK11_ATTR_PUBLIC is set, we add
+ * { CKA_PRIVATE, &ckfalse, sizeof(CK_BBOOL) }
+ * to the template. If neither flag is set, we don't add any
+ * CKA_PRIVATE entry to the template.
+ */
+
+/*
+ * Attributes for PKCS #11 storage objects, which include not only
+ * keys but also certificates and domain parameters.
+ */
+
+/*
+ * PK11_ATTR_TOKEN
+ * PK11_ATTR_SESSION
+ *
+ * These two flags determine whether the object is a token or
+ * session object.
+ *
+ * These two flags are related and cannot both be set.
+ * If the PK11_ATTR_TOKEN flag is set, the object is a token
+ * object. If the PK11_ATTR_SESSION flag is set, the object is
+ * a session object. If neither flag is set, the object is *by
+ * default* a session object.
+ *
+ * These two flags specify the value of the PKCS #11 CKA_TOKEN
+ * attribute.
+ */
+#define PK11_ATTR_TOKEN 0x00000001L
+#define PK11_ATTR_SESSION 0x00000002L
+
+/*
+ * PK11_ATTR_PRIVATE
+ * PK11_ATTR_PUBLIC
+ *
+ * These two flags determine whether the object is a private or
+ * public object. A user may not access a private object until the
+ * user has authenticated to the token.
+ *
+ * These two flags are related and cannot both be set.
+ * If the PK11_ATTR_PRIVATE flag is set, the object is a private
+ * object. If the PK11_ATTR_PUBLIC flag is set, the object is a
+ * public object. If neither flag is set, it is token-specific
+ * whether the object is private or public.
+ *
+ * These two flags specify the value of the PKCS #11 CKA_PRIVATE
+ * attribute. NSS only uses this attribute on private and secret
+ * keys, so public keys created by NSS get the token-specific
+ * default value of the CKA_PRIVATE attribute.
+ */
+#define PK11_ATTR_PRIVATE 0x00000004L
+#define PK11_ATTR_PUBLIC 0x00000008L
+
+/*
+ * PK11_ATTR_MODIFIABLE
+ * PK11_ATTR_UNMODIFIABLE
+ *
+ * These two flags determine whether the object is modifiable or
+ * read-only.
+ *
+ * These two flags are related and cannot both be set.
+ * If the PK11_ATTR_MODIFIABLE flag is set, the object can be
+ * modified. If the PK11_ATTR_UNMODIFIABLE flag is set, the object
+ * is read-only. If neither flag is set, the object is *by default*
+ * modifiable.
+ *
+ * These two flags specify the value of the PKCS #11 CKA_MODIFIABLE
+ * attribute.
+ */
+#define PK11_ATTR_MODIFIABLE 0x00000010L
+#define PK11_ATTR_UNMODIFIABLE 0x00000020L
+
+/* Attributes for PKCS #11 key objects. */
+
+/*
+ * PK11_ATTR_SENSITIVE
+ * PK11_ATTR_INSENSITIVE
+ *
+ * These two flags are related and cannot both be set.
+ * If the PK11_ATTR_SENSITIVE flag is set, the key is sensitive.
+ * If the PK11_ATTR_INSENSITIVE flag is set, the key is not
+ * sensitive. If neither flag is set, it is token-specific whether
+ * the key is sensitive or not.
+ *
+ * If a key is sensitive, certain attributes of the key cannot be
+ * revealed in plaintext outside the token.
+ *
+ * This flag specifies the value of the PKCS #11 CKA_SENSITIVE
+ * attribute. Although the default value of the CKA_SENSITIVE
+ * attribute for secret keys is CK_FALSE per PKCS #11, some FIPS
+ * tokens set the default value to CK_TRUE because only CK_TRUE
+ * is allowed. So in practice the default value of this attribute
+ * is token-specific, hence the need for two bitflags.
+ */
+#define PK11_ATTR_SENSITIVE 0x00000040L
+#define PK11_ATTR_INSENSITIVE 0x00000080L
+
+/*
+ * PK11_ATTR_EXTRACTABLE
+ * PK11_ATTR_UNEXTRACTABLE
+ *
+ * These two flags are related and cannot both be set.
+ * If the PK11_ATTR_EXTRACTABLE flag is set, the key is extractable
+ * and can be wrapped. If the PK11_ATTR_UNEXTRACTABLE flag is set,
+ * the key is not extractable, and certain attributes of the key
+ * cannot be revealed in plaintext outside the token (just like a
+ * sensitive key). If neither flag is set, it is token-specific
+ * whether the key is extractable or not.
+ *
+ * These two flags specify the value of the PKCS #11 CKA_EXTRACTABLE
+ * attribute.
+ */
+#define PK11_ATTR_EXTRACTABLE 0x00000100L
+#define PK11_ATTR_UNEXTRACTABLE 0x00000200L
/* Cryptographic module types */
#define SECMOD_EXTERNAL 0 /* external module */