From 2514fa79acba998c2a8d4e5a8288a5b3ae990377 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sat, 18 Jan 2014 14:51:40 +0000 Subject: [PATCH] Add functions returning security bits. Add functions to return the "bits of security" for various public key algorithms. Based on SP800-57. --- crypto/asn1/ameth_lib.c | 7 +++++++ crypto/asn1/asn1_locl.h | 1 + crypto/bn/bn.h | 1 + crypto/bn/bn_lib.c | 25 +++++++++++++++++++++++++ crypto/cmac/cm_ameth.c | 2 +- crypto/dh/dh.h | 1 + crypto/dh/dh_ameth.c | 7 +++++++ crypto/dh/dh_lib.c | 12 ++++++++++++ crypto/dsa/dsa.h | 1 + crypto/dsa/dsa_ameth.c | 6 ++++++ crypto/dsa/dsa_lib.c | 5 +++++ crypto/ec/ec_ameth.c | 17 +++++++++++++++++ crypto/evp/evp.h | 4 ++++ crypto/evp/p_lib.c | 9 +++++++++ crypto/hmac/hm_ameth.c | 2 +- crypto/rsa/rsa.h | 1 + crypto/rsa/rsa_ameth.c | 6 ++++++ crypto/rsa/rsa_lib.c | 5 +++++ 18 files changed, 110 insertions(+), 2 deletions(-) diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 5fff226120..f317204d9c 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -462,3 +462,10 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, { 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 a1035cd46e..023934bb2b 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h @@ -122,6 +122,7 @@ struct evp_pkey_asn1_method_st 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 b3518cb3ba..f4c8cc0124 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -420,6 +420,7 @@ int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); 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 72da0735fd..b1e224bb4d 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -880,3 +880,28 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) } #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 0b8e5670b0..455c5602d9 100644 --- a/crypto/cmac/cm_ameth.c +++ b/crypto/cmac/cm_ameth.c @@ -87,7 +87,7 @@ const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = 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 0cbb32e336..8e8f87dfdc 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h @@ -202,6 +202,7 @@ DH * DH_new(void); 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 2b0035cd0a..ce1edcb0d9 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -448,6 +448,11 @@ static int dh_bits(const EVP_PKEY *pkey) 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 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = int_dh_size, dh_bits, + dh_security_bits, dh_param_decode, dh_param_encode, @@ -653,6 +659,7 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = 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 7aef080e7a..83b3dc50c1 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -245,3 +245,15 @@ int DH_size(const DH *dh) { 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 6010a954f0..add452b27c 100644 --- a/crypto/dsa/dsa.h +++ b/crypto/dsa/dsa.h @@ -234,6 +234,7 @@ void DSA_free (DSA *r); /* "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 6b1d52fab2..aa3f55e218 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -368,6 +368,11 @@ static int dsa_bits(const EVP_PKEY *pkey) 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 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 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 c9b25a0561..b78fadd467 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -272,6 +272,11 @@ void *DSA_get_ex_data(DSA *d, int idx) 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 f024f90497..ae9d5319a3 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -395,6 +395,22 @@ static int ec_bits(const EVP_PKEY *pkey) 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 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = 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 94d1dc863b..ea92aa28d8 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -957,6 +957,7 @@ int EVP_PKEY_type(int type); 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 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, 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 109188c45b..42a8be1bb8 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -89,6 +89,15 @@ int EVP_PKEY_bits(EVP_PKEY *pkey) 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 e03f24aeda..a6aa793110 100644 --- a/crypto/hmac/hm_ameth.c +++ b/crypto/hmac/hm_ameth.c @@ -152,7 +152,7 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = 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 41a052a3ee..543deaf572 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -307,6 +307,7 @@ struct rsa_st 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 929193b4fa..04d9f62dd0 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -170,6 +170,11 @@ static int rsa_bits(const EVP_PKEY *pkey) 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 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = 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 9e3f7dafcd..ba277cacd8 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -320,3 +320,8 @@ int RSA_memory_lock(RSA *r) r->bignum_data=p; return(1); } + +int RSA_security_bits(const RSA *rsa) + { + return BN_security_bits(BN_num_bits(rsa->n), -1); + } -- 2.39.2