Add functions returning security bits. Add functions to return the "bits of security" for various public key algorithms. Based on SP800-57.
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 5fff226..f317204 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c
@@ -462,3 +462,10 @@ { ameth->pkey_ctrl = pkey_ctrl; } + +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits)(const EVP_PKEY *pk)) + { + ameth->pkey_security_bits = pkey_security_bits; + } +
diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h index a1035cd..023934b 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h
@@ -122,6 +122,7 @@ int (*pkey_size)(const EVP_PKEY *pk); int (*pkey_bits)(const EVP_PKEY *pk); + int (*pkey_security_bits)(const EVP_PKEY *pk); int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen);
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index b3518cb..f4c8cc0 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h
@@ -420,6 +420,7 @@ int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); int BN_num_bits(const BIGNUM *a); int BN_num_bits_word(BN_ULONG l); +int BN_security_bits(int L, int N); BIGNUM *BN_new(void); void BN_init(BIGNUM *); void BN_clear_free(BIGNUM *a);
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 72da073..b1e224b 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c
@@ -880,3 +880,28 @@ } #undef BN_CONSTTIME_SWAP } + +/* Bits of security, see SP800-57 */ + +int BN_security_bits(int L, int N) + { + int secbits, bits; + if (L >= 15360) + secbits = 256; + else if (L >= 7690) + secbits = 192; + else if (L >= 3072) + secbits = 128; + else if (L >= 2048) + secbits = 112; + else if (L >= 1024) + secbits = 80; + else + return 0; + if (N == -1) + return secbits; + bits = N / 2; + if (bits < 80) + return 0; + return bits >= secbits ? secbits : bits; + }
diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c index 0b8e567..455c560 100644 --- a/crypto/cmac/cm_ameth.c +++ b/crypto/cmac/cm_ameth.c
@@ -87,7 +87,7 @@ 0,0,0, cmac_size, - 0, + 0, 0, 0,0,0,0,0,0,0, cmac_key_free,
diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h index 0cbb32e..8e8f87d 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h
@@ -202,6 +202,7 @@ void DH_free(DH *dh); int DH_up_ref(DH *dh); int DH_size(const DH *dh); +int DH_security_bits(const DH *dh); int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); int DH_set_ex_data(DH *d, int idx, void *arg);
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 2b0035c..ce1edcb 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c
@@ -448,6 +448,11 @@ return BN_num_bits(pkey->pkey.dh->p); } +static int dh_security_bits(const EVP_PKEY *pkey) + { + return DH_security_bits(pkey->pkey.dh); + } + static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { if ( BN_cmp(a->pkey.dh->p,b->pkey.dh->p) || @@ -620,6 +625,7 @@ int_dh_size, dh_bits, + dh_security_bits, dh_param_decode, dh_param_encode, @@ -653,6 +659,7 @@ int_dh_size, dh_bits, + dh_security_bits, dh_param_decode, dh_param_encode,
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 7aef080..83b3dc5 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c
@@ -245,3 +245,15 @@ { return(BN_num_bytes(dh->p)); } + +int DH_security_bits(const DH *dh) + { + int N; + if (dh->q) + N = BN_num_bits(dh->q); + else if (dh->length) + N = dh->length; + else + N = -1; + return BN_security_bits(BN_num_bits(dh->p), N); + }
diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h index 6010a95..add452b 100644 --- a/crypto/dsa/dsa.h +++ b/crypto/dsa/dsa.h
@@ -234,6 +234,7 @@ /* "up" the DSA object's reference count */ int DSA_up_ref(DSA *r); int DSA_size(const DSA *); +int DSA_security_bits(const DSA *d); /* next 4 return -1 on error */ int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp); int DSA_sign(int type,const unsigned char *dgst,int dlen,
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 6b1d52f..aa3f55e 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c
@@ -368,6 +368,11 @@ return BN_num_bits(pkey->pkey.dsa->p); } +static int dsa_security_bits(const EVP_PKEY *pkey) + { + return DSA_security_bits(pkey->pkey.dsa); + } + static int dsa_missing_parameters(const EVP_PKEY *pkey) { DSA *dsa; @@ -696,6 +701,7 @@ int_dsa_size, dsa_bits, + dsa_security_bits, dsa_param_decode, dsa_param_encode,
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index c9b25a0..b78fadd 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c
@@ -272,6 +272,11 @@ return(CRYPTO_get_ex_data(&d->ex_data,idx)); } +int DSA_security_bits(const DSA *d) + { + return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); + } + #ifndef OPENSSL_NO_DH DH *DSA_dup_DH(const DSA *r) {
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index f024f90..ae9d531 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c
@@ -395,6 +395,22 @@ return ret; } +static int ec_security_bits(const EVP_PKEY *pkey) + { + int ecbits = ec_bits(pkey); + if (ecbits >= 512) + return 256; + if (ecbits >= 384) + return 192; + if (ecbits >= 256) + return 128; + if (ecbits >= 224) + return 112; + if (ecbits >= 160) + return 80; + return ecbits / 2; + } + static int ec_missing_parameters(const EVP_PKEY *pkey) { if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) @@ -659,6 +675,7 @@ int_ec_size, ec_bits, + ec_security_bits, eckey_param_decode, eckey_param_encode,
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 94d1dc8..ea92aa2 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h
@@ -957,6 +957,7 @@ int EVP_PKEY_id(const EVP_PKEY *pkey); int EVP_PKEY_base_id(const EVP_PKEY *pkey); int EVP_PKEY_bits(EVP_PKEY *pkey); +int EVP_PKEY_security_bits(const EVP_PKEY *pkey); int EVP_PKEY_size(EVP_PKEY *pkey); int EVP_PKEY_set_type(EVP_PKEY *pkey,int type); int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); @@ -1115,6 +1116,9 @@ int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2)); +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits)(const EVP_PKEY *pk)); + #define EVP_PKEY_OP_UNDEFINED 0 #define EVP_PKEY_OP_PARAMGEN (1<<1)
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 109188c..42a8be1 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c
@@ -89,6 +89,15 @@ return 0; } +int EVP_PKEY_security_bits(const EVP_PKEY *pkey) + { + if (pkey == NULL) + return 0; + if (!pkey->ameth || !pkey->ameth->pkey_security_bits) + return -2; + return pkey->ameth->pkey_security_bits(pkey); + } + int EVP_PKEY_size(EVP_PKEY *pkey) { if (pkey && pkey->ameth && pkey->ameth->pkey_size)
diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c index e03f24a..a6aa793 100644 --- a/crypto/hmac/hm_ameth.c +++ b/crypto/hmac/hm_ameth.c
@@ -152,7 +152,7 @@ 0,0,0, hmac_size, - 0, + 0, 0, 0,0,0,0,0,0,0, hmac_key_free,
diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index 41a052a..543deaf 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h
@@ -307,6 +307,7 @@ RSA * RSA_new(void); RSA * RSA_new_method(ENGINE *engine); int RSA_size(const RSA *rsa); +int RSA_security_bits(const RSA *rsa); /* Deprecated version */ #ifndef OPENSSL_NO_DEPRECATED
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 929193b..04d9f62 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c
@@ -170,6 +170,11 @@ return BN_num_bits(pkey->pkey.rsa->n); } +static int rsa_security_bits(const EVP_PKEY *pkey) + { + return RSA_security_bits(pkey->pkey.rsa); + } + static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); @@ -993,6 +998,7 @@ int_rsa_size, rsa_bits, + rsa_security_bits, 0,0,0,0,0,0,
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 9e3f7da..ba277ca 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c
@@ -320,3 +320,8 @@ r->bignum_data=p; return(1); } + +int RSA_security_bits(const RSA *rsa) + { + return BN_security_bits(BN_num_bits(rsa->n), -1); + }