diff options
author | nelsonb%netscape.com <devnull@localhost> | 2003-11-07 08:11:55 +0000 |
---|---|---|
committer | nelsonb%netscape.com <devnull@localhost> | 2003-11-07 08:11:55 +0000 |
commit | 54466d4bf645d7ec4ca67708db5598426b5b603d (patch) | |
tree | ff373d710cdeb200c904638575ae63c4a8d617d2 | |
parent | 90112e5ca3824162d85d9d87da2dfd1bafe17649 (diff) | |
download | nss-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.h | 10 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11.c | 93 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11c.c | 77 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11i.h | 4 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11u.c | 65 | ||||
-rw-r--r-- | security/nss/lib/softoken/rsawrapr.c | 8 |
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 { |