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