/* * 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 * */ #include "gnutls_int.h" #include #include "errors.h" #include 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; }