summaryrefslogtreecommitdiff
path: root/security/nss/lib
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib')
-rw-r--r--security/nss/lib/certhigh/certvfy.c12
-rw-r--r--security/nss/lib/cryptohi/secsign.c2
-rw-r--r--security/nss/lib/cryptohi/secvfy.c11
-rw-r--r--security/nss/lib/dev/devslot.c7
-rw-r--r--security/nss/lib/freebl/dsa.c4
-rw-r--r--security/nss/lib/freebl/loader.c26
-rw-r--r--security/nss/lib/freebl/rsa.c11
-rw-r--r--security/nss/lib/freebl/unix_rand.c2
-rw-r--r--security/nss/lib/nss/nss.def7
-rw-r--r--security/nss/lib/nss/nss.h6
-rw-r--r--security/nss/lib/pk11wrap/pk11akey.c566
-rw-r--r--security/nss/lib/pk11wrap/pk11auth.c63
-rw-r--r--security/nss/lib/pk11wrap/pk11load.c2
-rw-r--r--security/nss/lib/pk11wrap/pk11nobj.c3
-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.c144
-rw-r--r--security/nss/lib/pk11wrap/pk11util.c7
-rw-r--r--security/nss/lib/pk11wrap/secmodi.h8
-rw-r--r--security/nss/lib/pk11wrap/secmodt.h154
-rw-r--r--security/nss/lib/pki/pkistore.c6
-rw-r--r--security/nss/lib/pki/tdcache.c8
-rw-r--r--security/nss/lib/smime/cmslocal.h7
-rw-r--r--security/nss/lib/smime/cmssigdata.c31
-rw-r--r--security/nss/lib/smime/cmst.h3
-rw-r--r--security/nss/lib/softoken/pkcs11.c9
-rw-r--r--security/nss/lib/util/secasn1e.c210
-rw-r--r--security/nss/lib/util/secport.h10
28 files changed, 1233 insertions, 147 deletions
diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
index 580e3063b..25d0eaf42 100644
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -1139,14 +1139,14 @@ done:
return rv;
}
-#define NEXT_ITERATION() { \
+#define NEXT_USAGE() { \
i*=2; \
certUsage++; \
continue; \
}
#define VALID_USAGE() { \
- NEXT_ITERATION(); \
+ NEXT_USAGE(); \
}
#define INVALID_USAGE() { \
@@ -1156,7 +1156,7 @@ done:
if (PR_TRUE == requiredUsage) { \
valid = SECFailure; \
} \
- NEXT_ITERATION(); \
+ NEXT_USAGE(); \
}
/*
@@ -1233,7 +1233,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
for (i=1;i<=certificateUsageHighest && !(SECFailure == valid && !returnedUsages) ;) {
PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
- NEXT_ITERATION();
+ NEXT_USAGE();
}
if (returnedUsages) {
*returnedUsages |= i; /* start off assuming this usage is valid */
@@ -1264,7 +1264,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
case certUsageUserCertImport:
case certUsageVerifyCA:
/* these usages cannot be verified */
- NEXT_ITERATION();
+ NEXT_USAGE();
default:
PORT_Assert(0);
@@ -1408,7 +1408,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
}
}
- NEXT_ITERATION();
+ NEXT_USAGE();
}
return(valid);
diff --git a/security/nss/lib/cryptohi/secsign.c b/security/nss/lib/cryptohi/secsign.c
index 13b75abcc..68447be26 100644
--- a/security/nss/lib/cryptohi/secsign.c
+++ b/security/nss/lib/cryptohi/secsign.c
@@ -201,7 +201,7 @@ SGN_Update(SGNContext *cx, unsigned char *input, unsigned inputLen)
SECStatus
SGN_End(SGNContext *cx, SECItem *result)
{
- unsigned char digest[32];
+ unsigned char digest[HASH_LENGTH_MAX];
unsigned part1, signatureLen;
SECStatus rv;
SECItem digder, sigitem;
diff --git a/security/nss/lib/cryptohi/secvfy.c b/security/nss/lib/cryptohi/secvfy.c
index a9e3970da..4a5de4e0f 100644
--- a/security/nss/lib/cryptohi/secvfy.c
+++ b/security/nss/lib/cryptohi/secvfy.c
@@ -83,7 +83,7 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, SECKEYPublicKey *key,
*/
tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
/* XXX Check that tag is an appropriate algorithm? */
- if (di->digest.len > 32) {
+ if (di->digest.len > HASH_LENGTH_MAX) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
goto loser;
}
@@ -110,8 +110,11 @@ struct VFYContextStr {
SECOidTag alg;
VerifyType type;
SECKEYPublicKey *key;
- /* digest holds the full dsa signature... 40 bytes */
- unsigned char digest[DSA_SIGNATURE_LEN];
+ /*
+ * digest holds either the hash (<= HASH_LENGTH_MAX=64 bytes)
+ * in the RSA signature, or the full DSA signature (40 bytes).
+ */
+ unsigned char digest[HASH_LENGTH_MAX];
void * wincx;
void *hashcx;
const SECHashObject *hashobj;
@@ -350,7 +353,7 @@ VFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen)
SECStatus
VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
{
- unsigned char final[32];
+ unsigned char final[HASH_LENGTH_MAX];
unsigned part;
SECItem hash,dsasig; /* dsasig is also used for ECDSA */
SECStatus rv;
diff --git a/security/nss/lib/dev/devslot.c b/security/nss/lib/dev/devslot.c
index 9f51c6a35..586531f9c 100644
--- a/security/nss/lib/dev/devslot.c
+++ b/security/nss/lib/dev/devslot.c
@@ -356,8 +356,10 @@ nssSlot_IsTokenPresent (
if (session->handle != CK_INVALID_SESSION) {
return PR_TRUE;
} else {
- /* the token has been removed, and reinserted, invalidate all the old
- * information we had on this token */
+ /* the token has been removed, and reinserted, or the slot contains
+ * a token it doesn't recognize. invalidate all the old
+ * information we had on this token, if we can't refresh, clear
+ * the present flag */
#ifdef NSS_3_4_CODE
nssToken_NotifyCertsNotVisible(slot->token);
#endif /* NSS_3_4_CODE */
@@ -366,6 +368,7 @@ nssSlot_IsTokenPresent (
nssrv = nssSlot_Refresh(slot);
if (nssrv != PR_SUCCESS) {
slot->token->base.name[0] = 0; /* XXX */
+ slot->ckFlags &= ~CKF_TOKEN_PRESENT;
return PR_FALSE;
}
return PR_TRUE;
diff --git a/security/nss/lib/freebl/dsa.c b/security/nss/lib/freebl/dsa.c
index fe710cb64..85ceb2e51 100644
--- a/security/nss/lib/freebl/dsa.c
+++ b/security/nss/lib/freebl/dsa.c
@@ -188,11 +188,12 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
/* FIPS-compliance dictates that digest is a SHA1 hash. */
/* Check args. */
if (!key || !signature || !digest ||
- (signature->len != DSA_SIGNATURE_LEN) ||
+ (signature->len < DSA_SIGNATURE_LEN) ||
(digest->len != SHA1_LENGTH)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+
/* Initialize MPI integers. */
MP_DIGITS(&p) = 0;
MP_DIGITS(&q) = 0;
@@ -253,6 +254,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
DSA_SUBPRIME_LEN);
if (err < 0) goto cleanup;
err = MP_OKAY;
+ signature->len = DSA_SIGNATURE_LEN;
cleanup:
mp_clear(&p);
mp_clear(&q);
diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c
index 37bdaf839..3b3c4a68a 100644
--- a/security/nss/lib/freebl/loader.c
+++ b/security/nss/lib/freebl/loader.c
@@ -123,12 +123,38 @@ bl_LoadLibrary(const char *name)
{
BLLibrary *lib;
const char *error;
+ Dl_info dli;
lib = PR_NEWZAP(BLLibrary);
if (NULL == lib) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return NULL;
}
+
+ /*
+ * In setuid applications, Solaris is unwilling to load freebl unless
+ * we specify an absolute path. We construct one from the path of the
+ * library that contains this function.
+ */
+ if (dladdr((void *)bl_LoadLibrary, &dli) != 0) {
+ const char *slash = strrchr(dli.dli_fname, '/');
+ if (slash) {
+ size_t dirsize = slash - dli.dli_fname + 1;
+ char *pathname = PR_Malloc(dirsize + strlen(name) + 1);
+ if (NULL == pathname) {
+ PR_Free(lib);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ memcpy(pathname, dli.dli_fname, dirsize);
+ strcpy(pathname + dirsize, name);
+ lib->dlh = dlopen(pathname, RTLD_NOW | RTLD_LOCAL);
+ PR_Free(pathname);
+ if (NULL != lib->dlh)
+ return lib;
+ }
+ }
+
lib->dlh = dlopen(name, RTLD_NOW | RTLD_LOCAL);
if (NULL == lib->dlh) {
PR_SetError(PR_LOAD_LIBRARY_ERROR, 0);
diff --git a/security/nss/lib/freebl/rsa.c b/security/nss/lib/freebl/rsa.c
index d1ec6cfc5..33d41f1fc 100644
--- a/security/nss/lib/freebl/rsa.c
+++ b/security/nss/lib/freebl/rsa.c
@@ -66,6 +66,11 @@
#define MAX_RSA_MODULUS 1024 /* bytes, 8k bits */
#define MAX_RSA_EXPONENT 8 /* bytes, 64 bits */
+/* exponent should not be greater than modulus */
+#define BAD_RSA_KEY_SIZE(modLen, expLen) \
+ ((expLen) > (modLen) || (modLen) > MAX_RSA_MODULUS || \
+ (expLen) > MAX_RSA_EXPONENT)
+
/*
** RSABlindingParamsStr
**
@@ -231,7 +236,8 @@ RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
RSAPrivateKey *key = NULL;
PRArenaPool *arena = NULL;
/* Require key size to be a multiple of 16 bits. */
- if (!publicExponent || keySizeInBits % 16 != 0) {
+ if (!publicExponent || keySizeInBits % 16 != 0 ||
+ BAD_RSA_KEY_SIZE(keySizeInBits/8, publicExponent->len)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@@ -334,8 +340,7 @@ RSA_PublicKeyOp(RSAPublicKey *key,
modLen = rsa_modulusLen(&key->modulus);
expLen = rsa_modulusLen(&key->publicExponent);
/* 1. Obtain public key (n, e) */
- if (expLen > modLen || modLen > MAX_RSA_MODULUS || expLen > MAX_RSA_EXPONENT) {
- /* exponent should not be greater than modulus */
+ if (BAD_RSA_KEY_SIZE(modLen, expLen)) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
rv = SECFailure;
goto cleanup;
diff --git a/security/nss/lib/freebl/unix_rand.c b/security/nss/lib/freebl/unix_rand.c
index 22f8931b8..f61da8b29 100644
--- a/security/nss/lib/freebl/unix_rand.c
+++ b/security/nss/lib/freebl/unix_rand.c
@@ -833,7 +833,7 @@ for the small amount of entropy it provides.
* is running on.
*/
if (environ != NULL) {
- cp = environ;
+ cp = (const char * const *) environ;
while (*cp) {
RNG_RandomUpdate(*cp, strlen(*cp));
cp++;
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index 2ef0b4434..208638a77 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -850,3 +850,10 @@ NSS_Get_CERT_SignedCrlTemplate;
;+ local:
;+ *;
;+};
+;+NSS_3.10.2 { # NSS 3.10.2 release
+;+ global:
+PK11_TokenKeyGenWithFlags;
+PK11_GenerateKeyPairWithFlags;
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h
index 71f42a44d..0a5ed026c 100644
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -52,11 +52,11 @@ SEC_BEGIN_PROTOS
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>] [<Beta>]"
*/
-#define NSS_VERSION "3.10.1 Beta"
+#define NSS_VERSION "3.10.2"
#define NSS_VMAJOR 3
#define NSS_VMINOR 10
-#define NSS_VPATCH 1
-#define NSS_BETA PR_TRUE
+#define NSS_VPATCH 2
+#define NSS_BETA PR_FALSE
/*
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/pk11auth.c b/security/nss/lib/pk11wrap/pk11auth.c
index 18dc08806..a9bc39943 100644
--- a/security/nss/lib/pk11wrap/pk11auth.c
+++ b/security/nss/lib/pk11wrap/pk11auth.c
@@ -80,7 +80,7 @@ static struct PK11GlobalStruct {
SECStatus
pk11_CheckPassword(PK11SlotInfo *slot,char *pw)
{
- int len = PORT_Strlen(pw);
+ int len = 0;
CK_RV crv;
SECStatus rv;
int64 currtime = PR_Now();
@@ -88,6 +88,11 @@ pk11_CheckPassword(PK11SlotInfo *slot,char *pw)
if (slot->protectedAuthPath) {
len = 0;
pw = NULL;
+ } else if (pw == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ } else {
+ len = PORT_Strlen(pw);
}
PK11_EnterSlotMonitor(slot);
@@ -121,7 +126,7 @@ pk11_CheckPassword(PK11SlotInfo *slot,char *pw)
SECStatus
PK11_CheckUserPassword(PK11SlotInfo *slot,char *pw)
{
- int len = PORT_Strlen(pw);
+ int len = 0;
CK_RV crv;
SECStatus rv;
int64 currtime = PR_Now();
@@ -129,6 +134,11 @@ PK11_CheckUserPassword(PK11SlotInfo *slot,char *pw)
if (slot->protectedAuthPath) {
len = 0;
pw = NULL;
+ } else if (pw == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ } else {
+ len = PORT_Strlen(pw);
}
/* force a logout */
@@ -312,15 +322,23 @@ PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
CK_SESSION_HANDLE rwsession;
CK_RV crv;
SECStatus rv = SECFailure;
- int len = PORT_Strlen(ssopw);
+ int len = 0;
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
- if (rwsession == CK_INVALID_SESSION) return rv;
+ if (rwsession == CK_INVALID_SESSION) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return rv;
+ }
if (slot->protectedAuthPath) {
len = 0;
ssopw = NULL;
+ } else if (ssopw == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ } else {
+ len = PORT_Strlen(ssopw);
}
/* check the password */
@@ -383,7 +401,11 @@ PK11_InitPin(PK11SlotInfo *slot,char *ssopw, char *userpw)
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
- if (rwsession == CK_INVALID_SESSION) goto done;
+ if (rwsession == CK_INVALID_SESSION) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ slot->lastLoginCheck = 0;
+ return rv;
+ }
if (slot->protectedAuthPath) {
len = 0;
@@ -443,6 +465,10 @@ PK11_ChangePW(PK11SlotInfo *slot,char *oldpw, char *newpw)
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
+ if (rwsession == CK_INVALID_SESSION) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return rv;
+ }
crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
(unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
@@ -534,7 +560,34 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
* (3) the password was successful.
*/
while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
+ /* if the token has a protectedAuthPath, the application may have
+ * already issued the C_Login as part of it's pk11_GetPassword call.
+ * In this case the application will tell us what the results were in
+ * the password value (retry or the authentication was successful) so
+ * we can skip our own C_Login call (which would force the token to
+ * try to login again).
+ *
+ * Applications that don't know about protectedAuthPath will return a
+ * password, which we will ignore and trigger the token to
+ * 'authenticate' itself anyway. Hopefully the blinking display on
+ * the reader, or the flashing light under the thumbprint reader will
+ * attract the user's attention */
attempt = PR_TRUE;
+ if (slot->protectedAuthPath) {
+ /* application tried to authenticate and failed. it wants to try
+ * again, continue looping */
+ if (strcmp(password, PK11_PW_RETRY) == 0) {
+ rv = SECWouldBlock;
+ PORT_Free(password);
+ continue;
+ }
+ /* applicaton tried to authenticate and succeeded we're done */
+ if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
+ rv = SECSuccess;
+ PORT_Free(password);
+ break;
+ }
+ }
rv = pk11_CheckPassword(slot,password);
PORT_Memset(password, 0, PORT_Strlen(password));
PORT_Free(password);
diff --git a/security/nss/lib/pk11wrap/pk11load.c b/security/nss/lib/pk11wrap/pk11load.c
index 0906fc5f7..6017361ae 100644
--- a/security/nss/lib/pk11wrap/pk11load.c
+++ b/security/nss/lib/pk11wrap/pk11load.c
@@ -277,6 +277,8 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) {
/* all 2.0 are a priori *not* thread safe */
if (info.cryptokiVersion.minor < 1) mod->isThreadSafe = PR_FALSE;
+ mod->cryptokiVersion = info.cryptokiVersion;
+
/* If we don't have a common name, get it from the PKCS 11 module */
if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) {
diff --git a/security/nss/lib/pk11wrap/pk11nobj.c b/security/nss/lib/pk11wrap/pk11nobj.c
index 4a4f1147a..523e0dafe 100644
--- a/security/nss/lib/pk11wrap/pk11nobj.c
+++ b/security/nss/lib/pk11wrap/pk11nobj.c
@@ -256,11 +256,12 @@ PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
CK_ATTRIBUTE theTemplate[2];
CK_ATTRIBUTE *attrs;
CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
+ CK_BBOOL isKrl = CK_FALSE;
attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++;
if (type != -1) {
- CK_BBOOL isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
+ isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++;
}
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 51a7a0525..51cce7c62 100644
--- a/security/nss/lib/pk11wrap/pk11pub.h
+++ b/security/nss/lib/pk11wrap/pk11pub.h
@@ -236,6 +236,10 @@ PK11SymKey *PK11_KeyGen(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
SECItem *param, int keySize, SECItem *keyid,
PRBool isToken, void *wincx);
+PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot,
+ CK_MECHANISM_TYPE type, SECItem *param,
+ 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);
@@ -345,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 ea6d7012d..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++;
@@ -766,9 +766,131 @@ PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
/*
- * 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. keySize must be 'zero' for fixed key
+ * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute
+ * to be added to the template for the key. PKCS #11 modules fail if you
+ * specify the CKA_VALUE_LEN attribute for keys with fixed length.
+ * 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 opFlags,
+ PK11AttrFlags attrFlags, void *wincx)
+{
+ PK11SymKey *symKey;
+ CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS];
+ CK_ATTRIBUTE *attrs = genTemplate;
+ int count = sizeof(genTemplate)/sizeof(genTemplate[0]);
+ CK_SESSION_HANDLE session;
+ 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 */
+
+ PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size));
+ attrs++;
+ }
+
+ /* Include key id value if provided */
+ if (keyid) {
+ PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++;
+ }
+
+ attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
+ attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
+
+ count = attrs - genTemplate;
+ PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE));
+
+ /* find a slot to generate the key into */
+ /* Only do slot management if this is not a token key */
+ if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) {
+ PK11SlotInfo *bestSlot;
+
+ bestSlot = PK11_GetBestSlot(type,wincx);
+ if (bestSlot == NULL) {
+ PORT_SetError( SEC_ERROR_NO_MODULE );
+ return NULL;
+ }
+
+ symKey = pk11_CreateSymKey(bestSlot, type, !isToken, wincx);
+
+ PK11_FreeSlot(bestSlot);
+ } else {
+ symKey = pk11_CreateSymKey(slot, type, !isToken, wincx);
+ }
+ if (symKey == NULL) return NULL;
+
+ symKey->size = keySize;
+ symKey->origin = PK11_OriginGenerated;
+
+ /* Initialize the Key Gen Mechanism */
+ mechanism.mechanism = PK11_GetKeyGenWithSize(type, keySize);
+ if (mechanism.mechanism == CKM_FAKE_RANDOM) {
+ PORT_SetError( SEC_ERROR_NO_MODULE );
+ return NULL;
+ }
+
+ /* Set the parameters for the key gen if provided */
+ mechanism.pParameter = NULL;
+ mechanism.ulParameterLen = 0;
+ if (param) {
+ mechanism.pParameter = param->data;
+ mechanism.ulParameterLen = param->len;
+ }
+
+ /* Get session and perform locking */
+ if (isToken) {
+ PK11_Authenticate(symKey->slot,PR_TRUE,wincx);
+ session = PK11_GetRWSession(symKey->slot); /* Should always be original slot */
+ symKey->owner = PR_FALSE;
+ } else {
+ session = symKey->session;
+ pk11_EnterKeyMonitor(symKey);
+ }
+
+ crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session,
+ &mechanism, genTemplate, count, &symKey->objectID);
+
+ /* Release lock and session */
+ if (isToken) {
+ PK11_RestoreROSession(symKey->slot, session);
+ } else {
+ pk11_ExitKeyMonitor(symKey);
+ }
+
+ if (crv != CKR_OK) {
+ PK11_FreeSymKey(symKey);
+ PORT_SetError( PK11_MapError(crv) );
+ return NULL;
+ }
+
+ return symKey;
+}
+
+/*
+ * Use the token to generate a key. keySize must be 'zero' for fixed key
+ * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute
+ * to be added to the template for the key. PKCS #11 modules fail if you
+ * specify the CKA_VALUE_LEN attribute for keys with fixed length.
+ * 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.
*/
PK11SymKey *
PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
@@ -821,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;
@@ -1164,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);
}
@@ -1184,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);
}
@@ -1847,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);
@@ -1870,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,
@@ -1907,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);
@@ -1937,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/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c
index 3108d5dbd..5c6998da8 100644
--- a/security/nss/lib/pk11wrap/pk11util.c
+++ b/security/nss/lib/pk11wrap/pk11util.c
@@ -1060,6 +1060,13 @@ SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
CK_RV crv;
PK11SlotInfo *slot;
+ if ((mod->cryptokiVersion.major == 2) &&
+ (mod->cryptokiVersion.minor < 1)) {
+ /* if the module is version 2.0,
+ * C_WaitForSlotEvent() doesn't exist */
+ return secmod_HandleWaitForSlotEvent(mod, flags, latency);
+ }
+
/* first the the PKCS #11 call */
PZ_Lock(mod->refLock);
if (mod->evControlMask & SECMOD_END_WAIT) {
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..cc63eddc7 100644
--- a/security/nss/lib/pk11wrap/secmodt.h
+++ b/security/nss/lib/pk11wrap/secmodt.h
@@ -40,6 +40,7 @@
#include "nssilckt.h"
#include "secoid.h"
#include "secasn1.h"
+#include "pkcs11t.h"
/* find a better home for these... */
extern const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[];
@@ -97,6 +98,7 @@ struct SECMODModuleStr {
int cipherOrder; /* order for cipher operations */
unsigned long evControlMask; /* control the running and shutdown of slot
* events (SECMOD_WaitForAnyTokenEvent) */
+ CK_VERSION cryptokiVersion; /* version of this library */
};
/* evControlMask flags */
@@ -194,6 +196,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 */
@@ -252,6 +389,23 @@ typedef PRBool (PR_CALLBACK *PK11VerifyPasswordFunc)(PK11SlotInfo *slot, void *a
typedef PRBool (PR_CALLBACK *PK11IsLoggedInFunc)(PK11SlotInfo *slot, void *arg);
/*
+ * Special strings the password callback function can return only if
+ * the slot is an protected auth path slot.
+ */
+#define PK11_PW_RETRY "RETRY" /* an failed attempt to authenticate
+ * has already been made, just retry
+ * the operation */
+#define PK11_PW_AUTHENTICATED "AUTH" /* a successful attempt to authenticate
+ * has completed. Continue without
+ * another call to C_Login */
+/* All other non-null values mean that that NSS could call C_Login to force
+ * the authentication. The following define is to aid applications in
+ * documenting that is what it's trying to do */
+#define PK11_PW_TRY "TRY" /* Default: a prompt has been presented
+ * to the user, initiate a C_Login
+ * to authenticate the token */
+
+/*
* PKCS #11 key structures
*/
diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c
index 9e573ad1b..d069846cf 100644
--- a/security/nss/lib/pki/pkistore.c
+++ b/security/nss/lib/pki/pkistore.c
@@ -99,10 +99,12 @@ static PRIntn subject_list_sort(void *v1, void *v2)
NSSCertificate *c2 = (NSSCertificate *)v2;
nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1);
nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2);
- if (dc1->isNewerThan(dc1, dc2)) {
+ if (!dc1) {
+ return dc2 ? 1 : 0;
+ } else if (!dc2) {
return -1;
} else {
- return 1;
+ return dc1->isNewerThan(dc1, dc2) ? -1 : 1;
}
}
diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c
index cbf6d2361..b85e88143 100644
--- a/security/nss/lib/pki/tdcache.c
+++ b/security/nss/lib/pki/tdcache.c
@@ -157,10 +157,12 @@ static PRIntn subject_list_sort(void *v1, void *v2)
NSSCertificate *c2 = (NSSCertificate *)v2;
nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1);
nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2);
- if (dc1->isNewerThan(dc1, dc2)) {
+ if (!dc1) {
+ return dc2 ? 1 : 0;
+ } else if (!dc2) {
return -1;
- } else {
- return 1;
+ } else {
+ return dc1->isNewerThan(dc1, dc2) ? -1 : 1;
}
}
diff --git a/security/nss/lib/smime/cmslocal.h b/security/nss/lib/smime/cmslocal.h
index 78e093c12..666eeb033 100644
--- a/security/nss/lib/smime/cmslocal.h
+++ b/security/nss/lib/smime/cmslocal.h
@@ -333,6 +333,13 @@ NSS_CMSAttributeArray_AddAttr(PLArenaPool *poolp, NSSCMSAttribute ***attrs, NSSC
extern SECStatus
NSS_CMSAttributeArray_SetAttr(PLArenaPool *poolp, NSSCMSAttribute ***attrs, SECOidTag type, SECItem *value, PRBool encoded);
+/*
+ * NSS_CMSSignedData_AddTempCertificate - add temporary certificate references.
+ * They may be needed for signature verification on the data, for example.
+ */
+extern SECStatus
+NSS_CMSSignedData_AddTempCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert);
+
/************************************************************************/
SEC_END_PROTOS
diff --git a/security/nss/lib/smime/cmssigdata.c b/security/nss/lib/smime/cmssigdata.c
index b3b435c23..0ba771d65 100644
--- a/security/nss/lib/smime/cmssigdata.c
+++ b/security/nss/lib/smime/cmssigdata.c
@@ -86,7 +86,7 @@ loser:
void
NSS_CMSSignedData_Destroy(NSSCMSSignedData *sigd)
{
- CERTCertificate **certs, *cert;
+ CERTCertificate **certs, **tempCerts, *cert;
CERTCertificateList **certlists, *certlist;
NSSCMSSignerInfo **signerinfos, *si;
@@ -94,6 +94,7 @@ NSS_CMSSignedData_Destroy(NSSCMSSignedData *sigd)
return;
certs = sigd->certs;
+ tempCerts = sigd->tempCerts;
certlists = sigd->certLists;
signerinfos = sigd->signerInfos;
@@ -102,6 +103,11 @@ NSS_CMSSignedData_Destroy(NSSCMSSignedData *sigd)
CERT_DestroyCertificate (cert);
}
+ if (tempCerts != NULL) {
+ while ((cert = *tempCerts++) != NULL)
+ CERT_DestroyCertificate (cert);
+ }
+
if (certlists != NULL) {
while ((certlist = *certlists++) != NULL)
CERT_DestroyCertificateList (certlist);
@@ -550,6 +556,13 @@ NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb,
goto loser;
}
+ /* save the certs so they don't get destroyed */
+ for (i=0; i < certcount; i++) {
+ CERTCertificate *cert = certArray[i];
+ if (cert)
+ NSS_CMSSignedData_AddTempCertificate(sigd, cert);
+ }
+
if (!keepcerts) {
goto done;
}
@@ -782,6 +795,22 @@ NSS_CMSSignedData_AddCertChain(NSSCMSSignedData *sigd, CERTCertificate *cert)
return rv;
}
+extern SECStatus
+NSS_CMSSignedData_AddTempCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert)
+{
+ CERTCertificate *c;
+ SECStatus rv;
+
+ if (!sigd || !cert) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ c = CERT_DupCertificate(cert);
+ rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->tempCerts), (void *)c);
+ return rv;
+}
+
SECStatus
NSS_CMSSignedData_AddCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert)
{
diff --git a/security/nss/lib/smime/cmst.h b/security/nss/lib/smime/cmst.h
index a1c1bd65a..82f24da14 100644
--- a/security/nss/lib/smime/cmst.h
+++ b/security/nss/lib/smime/cmst.h
@@ -202,6 +202,9 @@ struct NSSCMSSignedDataStr {
SECItem ** digests;
CERTCertificate ** certs;
CERTCertificateList ** certLists;
+ CERTCertificate ** tempCerts; /* temporary certs, needed
+ * for example for signature
+ * verification */
};
#define NSS_CMS_SIGNED_DATA_VERSION_BASIC 1 /* what we *create* */
#define NSS_CMS_SIGNED_DATA_VERSION_EXT 3 /* what we *create* */
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 91c02254f..f9090a925 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -62,6 +62,7 @@
#include "secport.h"
#include "pcert.h"
#include "secrng.h"
+#include "nss.h"
#include "keydbi.h"
@@ -2911,8 +2912,8 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo)
pInfo->cryptokiVersion.major = 2;
pInfo->cryptokiVersion.minor = 11;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
- pInfo->libraryVersion.major = 3;
- pInfo->libraryVersion.minor = 8;
+ pInfo->libraryVersion.major = NSS_VMAJOR;
+ pInfo->libraryVersion.minor = NSS_VMINOR;
PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32);
pInfo->flags = 0;
return CKR_OK;
@@ -2953,8 +2954,8 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
pInfo->flags = CKF_TOKEN_PRESENT;
/* ok we really should read it out of the keydb file. */
/* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
- pInfo->hardwareVersion.major = 3;
- pInfo->hardwareVersion.minor = 8;
+ pInfo->hardwareVersion.major = NSS_VMAJOR;
+ pInfo->hardwareVersion.minor = NSS_VMINOR;
return CKR_OK;
}
diff --git a/security/nss/lib/util/secasn1e.c b/security/nss/lib/util/secasn1e.c
index 778aff08c..db7792cb1 100644
--- a/security/nss/lib/util/secasn1e.c
+++ b/security/nss/lib/util/secasn1e.c
@@ -63,6 +63,14 @@ typedef enum {
needBytes
} sec_asn1e_parse_status;
+typedef enum {
+ hdr_normal = 0, /* encode header normally */
+ hdr_any = 1, /* header already encoded in content */
+ hdr_decoder = 2, /* template only used by decoder. skip it. */
+ hdr_optional = 3, /* optional component, to be omitted */
+ hdr_placeholder = 4 /* place holder for from_buf content */
+} sec_asn1e_hdr_encoding;
+
typedef struct sec_asn1e_state_struct {
SEC_ASN1EncoderContext *top;
const SEC_ASN1Template *theTemplate;
@@ -308,7 +316,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state)
* (tag, optional status, etc.).
*
* NB: ALL the following flags in the subtemplate are disallowed
- * and/or ignored: ECPLICIT, OPTIONAL, INNER< INLINE< POINTER.
+ * and/or ignored: EXPLICIT, OPTIONAL, INNER, INLINE, POINTER.
*/
under_kind = state->theTemplate->kind;
@@ -501,7 +509,8 @@ sec_asn1e_which_choice
static unsigned long
sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
- PRBool disallowStreaming, PRBool *noheaderp)
+ PRBool disallowStreaming, PRBool insideIndefinite,
+ sec_asn1e_hdr_encoding *pHdrException)
{
unsigned long encode_kind, underlying_kind;
PRBool isExplicit, optional, universal, may_stream;
@@ -540,21 +549,27 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
/* Just clear this to get it out of the way; we do not need it here */
encode_kind &= ~SEC_ASN1_DYNAMIC;
+
+ if (encode_kind & SEC_ASN1_NO_STREAM) {
+ disallowStreaming = PR_TRUE;
+ }
encode_kind &= ~SEC_ASN1_NO_STREAM;
- if( encode_kind & SEC_ASN1_CHOICE ) {
- void *src2;
- int indx = sec_asn1e_which_choice(src, theTemplate);
- if( 0 == indx ) {
- /* XXX set an error? "choice not found" */
- /* state->top->status = encodeError; */
- return 0;
- }
+ if (encode_kind & SEC_ASN1_CHOICE) {
+ void *src2;
+ int indx = sec_asn1e_which_choice(src, theTemplate);
+ if (0 == indx) {
+ /* XXX set an error? "choice not found" */
+ /* state->top->status = encodeError; */
+ return 0;
+ }
- src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset);
+ src2 = (void *)
+ ((char *)src - theTemplate->offset + theTemplate[indx].offset);
- return sec_asn1e_contents_length(&theTemplate[indx], src2,
- PR_FALSE, noheaderp);
+ return sec_asn1e_contents_length(&theTemplate[indx], src2,
+ disallowStreaming, insideIndefinite,
+ pHdrException);
}
if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) {
@@ -563,10 +578,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
if (encode_kind & SEC_ASN1_POINTER) {
src = *(void **)src;
if (src == NULL) {
- if (optional)
- *noheaderp = PR_TRUE;
- else
- *noheaderp = PR_FALSE;
+ *pHdrException = optional ? hdr_optional : hdr_normal;
return 0;
}
} else if (encode_kind & SEC_ASN1_INLINE) {
@@ -578,7 +590,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
SECItem* target = (SECItem*)src;
if (!target || !target->data || !target->len) {
/* no valid data to encode subtemplate */
- *noheaderp = PR_TRUE;
+ *pHdrException = hdr_optional;
return 0;
}
} else {
@@ -591,14 +603,17 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
src = (char *)src + theTemplate->offset;
/* recurse to find the length of the subtemplate */
- len = sec_asn1e_contents_length (theTemplate, src, PR_FALSE, noheaderp);
+ len = sec_asn1e_contents_length (theTemplate, src, disallowStreaming,
+ insideIndefinite, pHdrException);
if (len == 0 && optional) {
- *noheaderp = PR_TRUE;
+ *pHdrException = hdr_optional;
} else if (isExplicit) {
- if (*noheaderp) {
- /* Okay, *we* do not want to add in a header, but our caller still does. */
- *noheaderp = PR_FALSE;
- } else {
+ if (*pHdrException == hdr_any) {
+ /* *we* do not want to add in a header,
+ ** but our caller still does.
+ */
+ *pHdrException = hdr_normal;
+ } else if (*pHdrException == hdr_normal) {
/* if the inner content exists, our length is
* len(identifier) + len(length) + len(innercontent)
* XXX we currently assume len(identifier) == 1;
@@ -615,7 +630,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
if (underlying_kind & SEC_ASN1_SAVE) {
/* check that there are no extraneous bits */
PORT_Assert (underlying_kind == SEC_ASN1_SAVE);
- *noheaderp = PR_TRUE;
+ *pHdrException = hdr_decoder;
return 0;
}
@@ -628,18 +643,20 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
underlying_kind &= ~UNEXPECTED_FLAGS;
#undef UNEXPECTED_FLAGS
- if( underlying_kind & SEC_ASN1_CHOICE ) {
- void *src2;
- int indx = sec_asn1e_which_choice(src, theTemplate);
- if( 0 == indx ) {
- /* XXX set an error? "choice not found" */
- /* state->top->status = encodeError; */
- return 0;
- }
+ if (underlying_kind & SEC_ASN1_CHOICE) {
+ void *src2;
+ int indx = sec_asn1e_which_choice(src, theTemplate);
+ if (0 == indx) {
+ /* XXX set an error? "choice not found" */
+ /* state->top->status = encodeError; */
+ return 0;
+ }
- src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset);
- len = sec_asn1e_contents_length(&theTemplate[indx], src2, PR_FALSE,
- noheaderp);
+ src2 = (void *)
+ ((char *)src - theTemplate->offset + theTemplate[indx].offset);
+ len = sec_asn1e_contents_length(&theTemplate[indx], src2,
+ disallowStreaming, insideIndefinite,
+ pHdrException);
} else {
switch (underlying_kind) {
case SEC_ASN1_SEQUENCE_OF:
@@ -660,14 +677,16 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
for (; *group != NULL; group++) {
sub_src = (char *)(*group) + tmpt->offset;
- sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE,
- noheaderp);
+ sub_len = sec_asn1e_contents_length (tmpt, sub_src,
+ disallowStreaming,
+ insideIndefinite,
+ pHdrException);
len += sub_len;
/*
* XXX The 1 below is the presumed length of the identifier;
* to support a high-tag-number this would need to be smarter.
*/
- if (!*noheaderp)
+ if (*pHdrException == hdr_normal)
len += 1 + SEC_ASN1LengthLength (sub_len);
}
}
@@ -683,14 +702,16 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
len = 0;
for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) {
sub_src = (char *)src + tmpt->offset;
- sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE,
- noheaderp);
+ sub_len = sec_asn1e_contents_length (tmpt, sub_src,
+ disallowStreaming,
+ insideIndefinite,
+ pHdrException);
len += sub_len;
/*
* XXX The 1 below is the presumed length of the identifier;
* to support a high-tag-number this would need to be smarter.
*/
- if (!*noheaderp)
+ if (*pHdrException == hdr_normal)
len += 1 + SEC_ASN1LengthLength (sub_len);
}
}
@@ -735,16 +756,23 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
default:
len = ((SECItem *)src)->len;
- if (may_stream && len == 0 && !disallowStreaming)
- len = 1; /* if we're streaming, we may have a secitem w/len 0 as placeholder */
break;
+ } /* end switch */
+
+#ifndef WHAT_PROBLEM_DOES_THIS_SOLVE
+ /* if we're streaming, we may have a secitem w/len 0 as placeholder */
+ if (!len && insideIndefinite && may_stream && !disallowStreaming) {
+ len = 1;
}
- }
+#endif
+ } /* end else */
- if ((len == 0 && optional) || underlying_kind == SEC_ASN1_ANY)
- *noheaderp = PR_TRUE;
+ if (len == 0 && optional)
+ *pHdrException = hdr_optional;
+ else if (underlying_kind == SEC_ASN1_ANY)
+ *pHdrException = hdr_any;
else
- *noheaderp = PR_FALSE;
+ *pHdrException = hdr_normal;
return len;
}
@@ -755,7 +783,8 @@ sec_asn1e_write_header (sec_asn1e_state *state)
{
unsigned long contents_length;
unsigned char tag_number, tag_modifiers;
- PRBool noheader;
+ sec_asn1e_hdr_encoding hdrException = hdr_normal;
+ PRBool indefinite = PR_FALSE;
PORT_Assert (state->place == beforeHeader);
@@ -767,66 +796,79 @@ sec_asn1e_write_header (sec_asn1e_state *state)
return;
}
- if( state->underlying_kind & SEC_ASN1_CHOICE ) {
- int indx = sec_asn1e_which_choice(state->src, state->theTemplate);
- if( 0 == indx ) {
- /* XXX set an error? "choice not found" */
- state->top->status = encodeError;
- return;
- }
-
- state->place = afterChoice;
- state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
- (char *)state->src - state->theTemplate->offset,
- PR_TRUE);
-
- if( (sec_asn1e_state *)NULL != state ) {
- /*
- * Do the "before" field notification.
- */
- sec_asn1e_notify_before (state->top, state->src, state->depth);
- state = sec_asn1e_init_state_based_on_template (state);
- }
-
- return;
+ if (state->underlying_kind & SEC_ASN1_CHOICE) {
+ int indx = sec_asn1e_which_choice(state->src, state->theTemplate);
+ if( 0 == indx ) {
+ /* XXX set an error? "choice not found" */
+ state->top->status = encodeError;
+ return;
+ }
+ state->place = afterChoice;
+ state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
+ (char *)state->src - state->theTemplate->offset,
+ PR_TRUE);
+ if (state) {
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1e_notify_before (state->top, state->src, state->depth);
+ state = sec_asn1e_init_state_based_on_template (state);
+ }
+ return;
}
+ /* The !isString test below is apparently intended to ensure that all
+ ** constructed types receive indefinite length encoding.
+ */
+ indefinite = (PRBool)
+ (state->top->streaming && state->may_stream &&
+ (state->top->from_buf || !state->is_string));
+
/*
- * We are doing a definite-length encoding. First we have to
+ * If we are doing a definite-length encoding, first we have to
* walk the data structure to calculate the entire contents length.
+ * If we are doing an indefinite-length encoding, we still need to
+ * know if the contents is:
+ * optional and to be omitted, or
+ * an ANY (header is pre-encoded), or
+ * a SAVE or some other kind of template used only by the decoder.
+ * So, we call this function either way.
*/
contents_length = sec_asn1e_contents_length (state->theTemplate,
state->src,
state->disallowStreaming,
- &noheader);
+ indefinite,
+ &hdrException);
/*
* We might be told explicitly not to put out a header.
* But it can also be the case, via a pushed subtemplate, that
* sec_asn1e_contents_length could not know that this field is
* really optional. So check for that explicitly, too.
*/
- if (noheader || (contents_length == 0 && state->optional)) {
+ if (hdrException != hdr_normal ||
+ (contents_length == 0 && state->optional)) {
state->place = afterContents;
- if (state->top->streaming && state->may_stream && state->top->from_buf)
- /* we did not find an optional indefinite string, so we don't encode it.
- * However, if TakeFromBuf is on, we stop here anyway to give our caller
- * a chance to intercept at the same point where we would stop if the
- * field were present. */
+ if (state->top->streaming &&
+ state->may_stream &&
+ state->top->from_buf) {
+ /* we did not find an optional indefinite string, so we
+ * don't encode it. However, if TakeFromBuf is on, we stop
+ * here anyway to give our caller a chance to intercept at the
+ * same point where we would stop if the field were present.
+ */
state->top->status = needBytes;
+ }
return;
}
- if (state->top->streaming && state->may_stream
- && (state->top->from_buf || !state->is_string)) {
+ if (indefinite) {
/*
* We need to put out an indefinite-length encoding.
- */
- state->indefinite = PR_TRUE;
- /*
* The only universal types that can be constructed are SETs,
* SEQUENCEs, and strings; so check that it is one of those,
* or that it is not universal (e.g. context-specific).
*/
+ state->indefinite = PR_TRUE;
PORT_Assert ((tag_number == SEC_ASN1_SET)
|| (tag_number == SEC_ASN1_SEQUENCE)
|| ((tag_modifiers & SEC_ASN1_CLASS_MASK) != 0)
diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h
index 783d40911..65c14def0 100644
--- a/security/nss/lib/util/secport.h
+++ b/security/nss/lib/util/secport.h
@@ -37,10 +37,6 @@
/*
* secport.h - portability interfaces for security libraries
*
- * This file abstracts out libc functionality that libsec depends on
- *
- * NOTE - These are not public interfaces
- *
* $Id$
*/
@@ -98,12 +94,6 @@
#include <sys/types.h>
#endif
-#ifdef notdef
-#ifdef XP_MAC
-#include "NSString.h"
-#endif
-#endif
-
#include <ctype.h>
#include <string.h>
#if defined(_WIN32_WCE)