summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornelsonb%netscape.com <devnull@localhost>2003-11-07 08:11:55 +0000
committernelsonb%netscape.com <devnull@localhost>2003-11-07 08:11:55 +0000
commit54466d4bf645d7ec4ca67708db5598426b5b603d (patch)
treeff373d710cdeb200c904638575ae63c4a8d617d2
parent90112e5ca3824162d85d9d87da2dfd1bafe17649 (diff)
downloadnss-hg-54466d4bf645d7ec4ca67708db5598426b5b603d.tar.gz
Backport Bob's fixes for Bugscape bug 53336 to the NSS 3.4 branch.
-rw-r--r--security/nss/lib/freebl/blapit.h10
-rw-r--r--security/nss/lib/softoken/pkcs11.c93
-rw-r--r--security/nss/lib/softoken/pkcs11c.c77
-rw-r--r--security/nss/lib/softoken/pkcs11i.h4
-rw-r--r--security/nss/lib/softoken/pkcs11u.c65
-rw-r--r--security/nss/lib/softoken/rsawrapr.c8
6 files changed, 220 insertions, 37 deletions
diff --git a/security/nss/lib/freebl/blapit.h b/security/nss/lib/freebl/blapit.h
index 0e1b2b0e2..e67941610 100644
--- a/security/nss/lib/freebl/blapit.h
+++ b/security/nss/lib/freebl/blapit.h
@@ -74,6 +74,16 @@
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
/*
+ * these values come from the intial key size limits from the PKCS #11
+ * module. They may be aribitarily adjusted to any value freebl supports
+ * RSA_MAX_MODULUS_BITS is not defined since there is only memory constraints
+ * on the largest RSA Modulus that PKCS #11 or freebl may support.
+ */
+#define RSA_MIN_MODULUS_BITS 128
+#define DH_MIN_P_BITS 128
+#define DH_MAX_P_BITS 1024
+
+/*
* The FIPS 186 algorithm for generating primes P and Q allows only 9
* distinct values for the length of P, and only one value for the
* length of Q.
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index ec708a411..8fb2e32f9 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -251,24 +251,36 @@ static const struct mechanismList mechanisms[] = {
*/
/* ------------------------- RSA Operations ---------------------------*/
- {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,CK_MAX,CKF_GENERATE_KEY_PAIR},PR_TRUE},
- {CKM_RSA_PKCS, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
+ {CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_GENERATE_KEY_PAIR},PR_TRUE},
+ {CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_DUZ_IT_ALL}, PR_TRUE},
#ifdef PK11_RSA9796_SUPPORTED
- {CKM_RSA_9796, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
+ {CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_DUZ_IT_ALL}, PR_TRUE},
#endif
- {CKM_RSA_X_509, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE},
+ {CKM_RSA_X_509, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_DUZ_IT_ALL}, PR_TRUE},
/* -------------- RSA Multipart Signing Operations -------------------- */
- {CKM_MD2_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
- {CKM_MD5_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
- {CKM_SHA1_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE},
+ {CKM_MD2_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_SN_VR}, PR_TRUE},
+ {CKM_MD5_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_SN_VR}, PR_TRUE},
+ {CKM_SHA1_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
+ CKF_SN_VR}, PR_TRUE},
/* ------------------------- DSA Operations --------------------------- */
- {CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}, PR_TRUE},
- {CKM_DSA, {512, 1024, CKF_SN_VR}, PR_TRUE},
- {CKM_DSA_SHA1, {512, 1024, CKF_SN_VR}, PR_TRUE},
+ {CKM_DSA_KEY_PAIR_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
+ CKF_GENERATE_KEY_PAIR}, PR_TRUE},
+ {CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
+ CKF_SN_VR}, PR_TRUE},
+ {CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
+ CKF_SN_VR}, PR_TRUE},
/* -------------------- Diffie Hellman Operations --------------------- */
/* no diffie hellman yet */
- {CKM_DH_PKCS_KEY_PAIR_GEN, {128, 1024, CKF_GENERATE_KEY_PAIR}, PR_TRUE},
- {CKM_DH_PKCS_DERIVE, {128, 1024, CKF_DERIVE}, PR_TRUE},
+ {CKM_DH_PKCS_KEY_PAIR_GEN, {DH_MIN_P_BITS, DH_MAX_P_BITS,
+ CKF_GENERATE_KEY_PAIR}, PR_TRUE},
+ {CKM_DH_PKCS_DERIVE, {DH_MIN_P_BITS, DH_MAX_P_BITS,
+ CKF_DERIVE}, PR_TRUE},
/* ------------------------- RC2 Operations --------------------------- */
{CKM_RC2_KEY_GEN, {1, 128, CKF_GENERATE}, PR_FALSE},
{CKM_RC2_ECB, {1, 128, CKF_EN_DE_WR_UN}, PR_FALSE},
@@ -965,36 +977,61 @@ pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object,
CK_BBOOL derive = CK_FALSE;
CK_BBOOL verify = CK_TRUE;
CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
+ PK11Attribute *attribute;
CK_RV crv;
switch (key_type) {
case CKK_RSA:
- if ( !pk11_hasAttribute(object, CKA_MODULUS)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_MODULUS,
+ RSA_MIN_MODULUS_BITS, 0, 2);
+ if (crv != CKR_OK) {
+ return crv;
}
- if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0);
+ if (crv != CKR_OK) {
+ return crv;
}
pubKeyAttr = CKA_MODULUS;
break;
case CKK_DSA:
- if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_SUBPRIME,
+ DSA_Q_BITS, DSA_Q_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ crv = pk11_ConstrainAttribute(object, CKA_PRIME,
+ DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ crv = pk11_ConstrainAttribute(object, CKA_BASE, 1, DSA_MAX_P_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
}
+ crv = pk11_ConstrainAttribute(object, CKA_VALUE, 1, DSA_MAX_P_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ encrypt = CK_FALSE;
+ recover = CK_FALSE;
+ wrap = CK_FALSE;
+ break;
case CKK_DH:
- if ( !pk11_hasAttribute(object, CKA_PRIME)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_PRIME,
+ DH_MIN_P_BITS, DH_MAX_P_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
}
- if ( !pk11_hasAttribute(object, CKA_BASE)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_BASE, 1, DH_MAX_P_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
}
- if ( !pk11_hasAttribute(object, CKA_VALUE)) {
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = pk11_ConstrainAttribute(object, CKA_VALUE, 1, DH_MAX_P_BITS, 0);
+ if (crv != CKR_OK) {
+ return crv;
}
- if (key_type == CKK_DH) {
- verify = CK_FALSE;
- derive = CK_TRUE;
- }
+ verify = CK_FALSE;
+ derive = CK_TRUE;
encrypt = CK_FALSE;
recover = CK_FALSE;
wrap = CK_FALSE;
diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c
index d4dfc1b75..81a6e73be 100644
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -2999,7 +2999,6 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
}
-
/* NSC_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects. */
CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
@@ -3018,6 +3017,7 @@ CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
int i;
PK11Slot * slot = pk11_SlotFromSessionHandle(hSession);
+ unsigned int bitSize;
/* RSA */
int public_modulus_bits = 0;
@@ -3110,10 +3110,23 @@ CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
crv = CKR_TEMPLATE_INCOMPLETE;
break;
}
+ if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ }
+ if (public_modulus_bits % 2 != 0) {
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ }
/* extract the exponent */
crv=pk11_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
if (crv != CKR_OK) break;
+ bitSize = pk11_GetLengthInBits(pubExp.data, pubExp.len);
+ if (bitSize < 2) {
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ }
crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
pk11_item_expand(&pubExp));
if (crv != CKR_OK) {
@@ -3207,6 +3220,32 @@ kpg_done:
break;
}
+ bitSize = pk11_GetLengthInBits(pqgParam.subPrime.data,
+ pqgParam.subPrime.len);
+ if (bitSize != DSA_Q_BITS) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ PORT_Free(pqgParam.prime.data);
+ PORT_Free(pqgParam.subPrime.data);
+ PORT_Free(pqgParam.base.data);
+ break;
+ }
+ bitSize = pk11_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len);
+ if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ PORT_Free(pqgParam.prime.data);
+ PORT_Free(pqgParam.subPrime.data);
+ PORT_Free(pqgParam.base.data);
+ break;
+ }
+ bitSize = pk11_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
+ if ((bitSize < 1) || (bitSize > DSA_MAX_P_BITS)) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ PORT_Free(pqgParam.prime.data);
+ PORT_Free(pqgParam.subPrime.data);
+ PORT_Free(pqgParam.base.data);
+ break;
+ }
+
/* Generate the key */
rv = DSA_NewKey(&pqgParam, &dsaPriv);
@@ -3245,26 +3284,46 @@ dsagn_done:
if (crv != CKR_OK) break;
crv = pk11_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
if (crv != CKR_OK) {
- PORT_Free(dhParam.prime.data);
- break;
+ PORT_Free(dhParam.prime.data);
+ break;
}
crv = pk11_AddAttributeType(privateKey, CKA_PRIME,
pk11_item_expand(&dhParam.prime));
if (crv != CKR_OK) {
- PORT_Free(dhParam.prime.data);
- PORT_Free(dhParam.base.data);
- break;
+ PORT_Free(dhParam.prime.data);
+ PORT_Free(dhParam.base.data);
+ break;
}
crv = pk11_AddAttributeType(privateKey, CKA_BASE,
pk11_item_expand(&dhParam.base));
- if (crv != CKR_OK) goto dhgn_done;
+ if (crv != CKR_OK) {
+ PORT_Free(dhParam.prime.data);
+ PORT_Free(dhParam.base.data);
+ break;
+ }
+ bitSize = pk11_GetLengthInBits(dhParam.prime.data,dhParam.prime.len);
+ if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ PORT_Free(pqgParam.prime.data);
+ PORT_Free(pqgParam.subPrime.data);
+ PORT_Free(pqgParam.base.data);
+ break;
+ }
+ bitSize = pk11_GetLengthInBits(dhParam.base.data,dhParam.base.len);
+ if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ PORT_Free(pqgParam.prime.data);
+ PORT_Free(pqgParam.subPrime.data);
+ PORT_Free(pqgParam.base.data);
+ break;
+ }
rv = DH_NewKey(&dhParam, &dhPriv);
PORT_Free(dhParam.prime.data);
PORT_Free(dhParam.base.data);
if (rv != SECSuccess) {
- crv = CKR_DEVICE_ERROR;
- break;
+ crv = CKR_DEVICE_ERROR;
+ break;
}
crv=pk11_AddAttributeType(publicKey, CKA_VALUE,
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 391f2f152..b87a5dad7 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -532,6 +532,10 @@ extern CK_RV pk11_AddAttributeType(PK11Object *object, CK_ATTRIBUTE_TYPE type,
CK_ULONG length);
extern CK_RV pk11_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
PK11Object *object, CK_ATTRIBUTE_TYPE type);
+extern unsigned int pk11_GetLengthInBits(unsigned char *buf,
+ unsigned int bufLen);
+extern CK_RV pk11_ConstrainAttribute(PK11Object *object,
+ CK_ATTRIBUTE_TYPE type, int minLength, int maxLength, int minMultiple);
extern PRBool pk11_hasAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type);
extern PRBool pk11_isTrue(PK11Object *object, CK_ATTRIBUTE_TYPE type);
extern void pk11_DeleteAttributeType(PK11Object *object,
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index 6db3996b1..1d48e422b 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -1108,7 +1108,72 @@ pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
return(attribute);
}
+/*
+ * Take a buffer and it's length and return it's true size in bits;
+ */
+unsigned int
+pk11_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
+{
+ unsigned int size = bufLen * 8;
+ int i;
+ /* Get the real length in bytes */
+ for (i=0; i < bufLen; i++) {
+ unsigned char c = *buf++;
+ if (c != 0) {
+ unsigned char m;
+ for (m=0x80; m > 0 ; m = m >> 1) {
+ if ((c & m) != 0) {
+ break;
+ }
+ size--;
+ }
+ break;
+ }
+ size-=8;
+ }
+ return size;
+}
+
+/*
+ * Constrain a big num attribute. to size and padding
+ * minLength means length of the object must be greater than equal to minLength
+ * maxLength means length of the object must be less than equal to maxLength
+ * minMultiple means that object length mod minMultiple must equal 0.
+ * all input sizes are in bits.
+ * if any constraint is '0' that constraint is not checked.
+ */
+CK_RV
+pk11_ConstrainAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type,
+ int minLength, int maxLength, int minMultiple)
+{
+ PK11Attribute *attribute;
+ unsigned int size;
+ unsigned char *ptr;
+ int i,j;
+ attribute = pk11_FindAttribute(object, type);
+ if (!attribute) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ ptr = (unsigned char *) attribute->attrib.pValue;
+ if (ptr == NULL) {
+ pk11_FreeAttribute(attribute);
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ size = pk11_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
+ pk11_FreeAttribute(attribute);
+
+ if ((minLength != 0) && (size < minLength)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ if ((maxLength != 0) && (size > maxLength)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ return CKR_OK;
+}
PRBool
pk11_hasAttributeToken(PK11TokenObject *object)
diff --git a/security/nss/lib/softoken/rsawrapr.c b/security/nss/lib/softoken/rsawrapr.c
index b17d4fc8e..53bbfc35d 100644
--- a/security/nss/lib/softoken/rsawrapr.c
+++ b/security/nss/lib/softoken/rsawrapr.c
@@ -218,6 +218,10 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
*/
padLen = modulusLen - data->len - 3;
PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
+ if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
+ PORT_Free (block);
+ return NULL;
+ }
PORT_Memset (bp,
blockType == RSA_BlockPrivate0
? RSA_BLOCK_PRIVATE0_PAD_OCTET
@@ -240,6 +244,10 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
*/
padLen = modulusLen - data->len - 3;
PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
+ if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
+ PORT_Free (block);
+ return NULL;
+ }
for (i = 0; i < padLen; i++) {
/* Pad with non-zero random data. */
do {