diff options
Diffstat (limited to 'lib/algorithms/secparams.c')
-rw-r--r-- | lib/algorithms/secparams.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/lib/algorithms/secparams.c b/lib/algorithms/secparams.c new file mode 100644 index 0000000..efd1f47 --- /dev/null +++ b/lib/algorithms/secparams.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2011-2012 Free Software Foundation, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include <algorithms.h> +#include "errors.h" +#include <x509/common.h> + +typedef struct { + const char *name; + gnutls_sec_param_t sec_param; + unsigned int bits; /* security level */ + unsigned int pk_bits; /* DH, RSA, SRP */ + unsigned int dsa_bits; /* bits for DSA. Handled differently since + * choice of key size in DSA is political. + */ + unsigned int subgroup_bits; /* subgroup bits */ + unsigned int ecc_bits; /* bits for ECC keys */ +} gnutls_sec_params_entry; + +static const gnutls_sec_params_entry sec_params[] = { + {"Insecure", GNUTLS_SEC_PARAM_INSECURE, 0, 0, 0, 0, 0}, + {"Export", GNUTLS_SEC_PARAM_EXPORT, 42, 512, 0, 84, 0}, + {"Very weak", GNUTLS_SEC_PARAM_VERY_WEAK, 64, 767, 0, 128, 0}, + {"Weak", GNUTLS_SEC_PARAM_WEAK, 72, 1008, 1008, 160, 160}, +#ifdef ENABLE_FIPS140 + {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160}, + {"Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1024, 1024, 192, 192}, + {"Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 224, 224}, + {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256}, +#else + {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160}, /* ENISA-LEGACY */ + {"Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1776, 2048, 192, 192}, + {"Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 256, 224}, + {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256}, +#endif + {"Ultra", GNUTLS_SEC_PARAM_ULTRA, 192, 8192, 8192, 384, 384}, + {"Future", GNUTLS_SEC_PARAM_FUTURE, 256, 15360, 15360, 512, 512}, + {NULL, 0, 0, 0, 0, 0} +}; + +#define GNUTLS_SEC_PARAM_LOOP(b) \ + { const gnutls_sec_params_entry *p; \ + for(p = sec_params; p->name != NULL; p++) { b ; } } + +/** + * gnutls_sec_param_to_pk_bits: + * @algo: is a public key algorithm + * @param: is a security parameter + * + * When generating private and public key pairs a difficult question + * is which size of "bits" the modulus will be in RSA and the group size + * in DSA. The easy answer is 1024, which is also wrong. This function + * will convert a human understandable security parameter to an + * appropriate size for the specific algorithm. + * + * Returns: The number of bits, or (0). + * + * Since: 2.12.0 + **/ +unsigned int +gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo, + gnutls_sec_param_t param) +{ + unsigned int ret = 0; + + /* handle DSA differently */ + GNUTLS_SEC_PARAM_LOOP( + if (p->sec_param == param) { + if (algo == GNUTLS_PK_DSA) + ret = p->dsa_bits; + else if (IS_EC(algo)||IS_GOSTEC(algo)) + ret = p->ecc_bits; + else + ret = p->pk_bits; + break; + } + ); + return ret; +} + +/** + * gnutls_sec_param_to_symmetric_bits: + * @algo: is a public key algorithm + * @param: is a security parameter + * + * This function will return the number of bits that correspond to + * symmetric cipher strength for the given security parameter. + * + * Returns: The number of bits, or (0). + * + * Since: 3.3.0 + **/ +unsigned int +gnutls_sec_param_to_symmetric_bits(gnutls_sec_param_t param) +{ + unsigned int ret = 0; + + /* handle DSA differently */ + GNUTLS_SEC_PARAM_LOOP( + if (p->sec_param == param) { + ret = p->bits; break; + } + ); + return ret; +} + +/* Returns the corresponding size for subgroup bits (q), + * given the group bits (p). + */ +unsigned int _gnutls_pk_bits_to_subgroup_bits(unsigned int pk_bits) +{ + unsigned int ret = 0; + + GNUTLS_SEC_PARAM_LOOP( + ret = p->subgroup_bits; + if (p->pk_bits >= pk_bits) + break; + ); + return ret; +} + +/* Returns a corresponding SHA algorithm size for the + * public key bits given. It is based on the NIST mappings. + */ +gnutls_digest_algorithm_t _gnutls_pk_bits_to_sha_hash(unsigned int pk_bits) +{ + GNUTLS_SEC_PARAM_LOOP( + if (p->pk_bits >= pk_bits) { + if (p->bits <= 128) + return GNUTLS_DIG_SHA256; + else if (p->bits <= 192) + return GNUTLS_DIG_SHA384; + else + return GNUTLS_DIG_SHA512; + } + ); + return GNUTLS_DIG_SHA256; +} + +/** + * gnutls_sec_param_get_name: + * @param: is a security parameter + * + * Convert a #gnutls_sec_param_t value to a string. + * + * Returns: a pointer to a string that contains the name of the + * specified security level, or %NULL. + * + * Since: 2.12.0 + **/ +const char *gnutls_sec_param_get_name(gnutls_sec_param_t param) +{ + const char *ret = "Unknown"; + + GNUTLS_SEC_PARAM_LOOP( + if (p->sec_param == param) { + ret = p->name; + break; + } + ); + + return ret; +} + +/** + * gnutls_pk_bits_to_sec_param: + * @algo: is a public key algorithm + * @bits: is the number of bits + * + * This is the inverse of gnutls_sec_param_to_pk_bits(). Given an algorithm + * and the number of bits, it will return the security parameter. This is + * a rough indication. + * + * Returns: The security parameter. + * + * Since: 2.12.0 + **/ +gnutls_sec_param_t +gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo, unsigned int bits) +{ + gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_INSECURE; + + if (bits == 0) + return GNUTLS_SEC_PARAM_UNKNOWN; + + if (IS_EC(algo)||IS_GOSTEC(algo)) { + GNUTLS_SEC_PARAM_LOOP( + if (p->ecc_bits > bits) { + break; + } + ret = p->sec_param; + ); + } else { + GNUTLS_SEC_PARAM_LOOP( + if (p->pk_bits > bits) { + break; + } + ret = p->sec_param; + ); + } + + return ret; +} |