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; |
+} |