| Index: nss/lib/cryptohi/seckey.c
|
| diff --git a/nss/lib/cryptohi/seckey.c b/nss/lib/cryptohi/seckey.c
|
| index 16d2a499b785ac5a501db9dd05633331b22bbeaf..1fcd4087f0ddece0293f08601139ce9828a99c30 100644
|
| --- a/nss/lib/cryptohi/seckey.c
|
| +++ b/nss/lib/cryptohi/seckey.c
|
| @@ -178,8 +178,8 @@ SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *c
|
| PK11SlotInfo *slot;
|
|
|
| if (!param || !param->base.data || !param->prime.data ||
|
| - param->prime.len < 512/8 || param->base.len == 0 ||
|
| - param->base.len > param->prime.len + 1 ||
|
| + SECKEY_BigIntegerBitLength(¶m->prime) < DH_MIN_P_BITS ||
|
| + param->base.len == 0 || param->base.len > param->prime.len + 1 ||
|
| (param->base.len == 1 && param->base.data[0] == 0)) {
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| return NULL;
|
| @@ -941,61 +941,76 @@ SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
|
| }
|
| }
|
|
|
| -/* returns key strength in bytes (not bits) */
|
| +/* The number of bits in the number from the first non-zero bit onward. */
|
| unsigned
|
| -SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
|
| +SECKEY_BigIntegerBitLength(const SECItem *number)
|
| {
|
| - unsigned char b0;
|
| - unsigned size;
|
| + const unsigned char *p;
|
| + unsigned octets;
|
| + unsigned bits;
|
|
|
| - /* interpret modulus length as key strength */
|
| - if (!pubk)
|
| - goto loser;
|
| - switch (pubk->keyType) {
|
| - case rsaKey:
|
| - if (!pubk->u.rsa.modulus.data) break;
|
| - b0 = pubk->u.rsa.modulus.data[0];
|
| - return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
|
| - case dsaKey:
|
| - if (!pubk->u.dsa.publicValue.data) break;
|
| - b0 = pubk->u.dsa.publicValue.data[0];
|
| - return b0 ? pubk->u.dsa.publicValue.len :
|
| - pubk->u.dsa.publicValue.len - 1;
|
| - case dhKey:
|
| - if (!pubk->u.dh.publicValue.data) break;
|
| - b0 = pubk->u.dh.publicValue.data[0];
|
| - return b0 ? pubk->u.dh.publicValue.len :
|
| - pubk->u.dh.publicValue.len - 1;
|
| - case ecKey:
|
| - /* Get the key size in bits and adjust */
|
| - size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
| - return (size + 7)/8;
|
| - default:
|
| - break;
|
| + if (!number || !number->data) {
|
| + PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| + return 0;
|
| }
|
| -loser:
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - return 0;
|
| +
|
| + p = number->data;
|
| + octets = number->len;
|
| + while (octets > 0 && !*p) {
|
| + ++p;
|
| + --octets;
|
| + }
|
| + if (octets == 0) {
|
| + return 0;
|
| + }
|
| + /* bits = 7..1 because we know at least one bit is set already */
|
| + /* Note: This could do a binary search, but this is faster for keys if we
|
| + * assume that good keys will have the MSB set. */
|
| + for (bits = 7; bits > 0; --bits) {
|
| + if (*p & (1 << bits)) {
|
| + break;
|
| + }
|
| + }
|
| + return octets * 8 + bits - 7;
|
| +}
|
| +
|
| +/* returns key strength in bytes (not bits) */
|
| +unsigned
|
| +SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
|
| +{
|
| + return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
|
| }
|
|
|
| /* returns key strength in bits */
|
| unsigned
|
| SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
|
| {
|
| - unsigned size;
|
| + unsigned bitSize = 0;
|
| +
|
| + if (!pubk) {
|
| + PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| + return 0;
|
| + }
|
| +
|
| + /* interpret modulus length as key strength */
|
| switch (pubk->keyType) {
|
| case rsaKey:
|
| + bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
|
| + break;
|
| case dsaKey:
|
| + bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.publicValue);
|
| + break;
|
| case dhKey:
|
| - return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
|
| + bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.publicValue);
|
| + break;
|
| case ecKey:
|
| - size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
| - return size;
|
| + bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
| + break;
|
| default:
|
| - break;
|
| + PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| + break;
|
| }
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - return 0;
|
| + return bitSize;
|
| }
|
|
|
| /* returns signature length in bytes (not bits) */
|
| @@ -1550,7 +1565,7 @@ SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
|
| * this yet.
|
| */
|
| PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
|
| - PORT_Memset((char *)pvk, 0, sizeof(*pvk));
|
| + PORT_Memset(pvk, 0, sizeof(*pvk));
|
| if(freeit == PR_TRUE) {
|
| PORT_FreeArena(poolp, PR_TRUE);
|
| } else {
|
| @@ -1560,7 +1575,7 @@ SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
|
| SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
|
| SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
|
| SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
|
| - PORT_Memset((char *)pvk, 0, sizeof(*pvk));
|
| + PORT_Memset(pvk, 0, sizeof(*pvk));
|
| if(freeit == PR_TRUE) {
|
| PORT_Free(pvk);
|
| }
|
| @@ -1581,7 +1596,7 @@ SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
|
| * this yet.
|
| */
|
| PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
|
| - PORT_Memset((char *)epki, 0, sizeof(*epki));
|
| + PORT_Memset(epki, 0, sizeof(*epki));
|
| if(freeit == PR_TRUE) {
|
| PORT_FreeArena(poolp, PR_TRUE);
|
| } else {
|
| @@ -1590,7 +1605,7 @@ SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
|
| } else {
|
| SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
|
| SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
|
| - PORT_Memset((char *)epki, 0, sizeof(*epki));
|
| + PORT_Memset(epki, 0, sizeof(*epki));
|
| if(freeit == PR_TRUE) {
|
| PORT_Free(epki);
|
| }
|
| @@ -1889,3 +1904,22 @@ SECKEY_CacheStaticFlags(SECKEYPrivateKey* key)
|
| }
|
| return rv;
|
| }
|
| +
|
| +SECOidTag
|
| +SECKEY_GetECCOid(const SECKEYECParams * params)
|
| +{
|
| + SECItem oid = { siBuffer, NULL, 0};
|
| + SECOidData *oidData = NULL;
|
| +
|
| + /*
|
| + * params->data needs to contain the ASN encoding of an object ID (OID)
|
| + * representing a named curve. Here, we strip away everything
|
| + * before the actual OID and use the OID to look up a named curve.
|
| + */
|
| + if (params->data[0] != SEC_ASN1_OBJECT_ID) return 0;
|
| + oid.len = params->len - 2;
|
| + oid.data = params->data + 2;
|
| + if ((oidData = SECOID_FindOID(&oid)) == NULL) return 0;
|
| +
|
| + return oidData->offset;
|
| +}
|
|
|