From: Nikos Mavrogiannopoulos Date: Fri, 23 Jul 2010 21:48:45 +0000 (+0200) Subject: Better handling of security parameters to key sizes matching (via a single table... X-Git-Tag: gnutls_2_11_3~86 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b12d2b7d3f741e2049dfbb6668503a007c10f543;p=thirdparty%2Fgnutls.git Better handling of security parameters to key sizes matching (via a single table). Added functions to return the security parameter of a private key. --- diff --git a/NEWS b/NEWS index eeb77a5b74..2731aeab97 100644 --- a/NEWS +++ b/NEWS @@ -6,13 +6,15 @@ See the end for copying conditions. * Version 2.11.1 (unreleased) ** libgnutls: Updated documentation and gnutls_pk_params_t mappings -to ECRYPT II recommendations. +to ECRYPT II recommendations. Mappings were moved to a single location +and DSA keys are handled differently (since DSA2 allows for 1024,2048 +and 3072 keys only). ** libgnutls: HMAC-MD5 no longer used by default. ** API and ABI modifications: -No changes since last version. - +gnutls_openpgp_privkey_sec_param: ADDED +gnutls_x509_privkey_sec_param: ADDED * Version 2.11.0 (released 2010-07-22) diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 0bb3d32e5d..dce0a6f3ed 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -30,6 +30,32 @@ #include +typedef struct +{ + const char *name; + gnutls_sec_param_t sec_param; + int bits; /* security level */ + int pk_bits; /* DH, RSA, SRP */ + int dsa_bits; /* bits for DSA. Handled differently since + * choice of key size in DSA is political. + */ + int subgroup_bits; /* subgroup bits */ + int ecc_bits; /* bits for ECC keys */ +} gnutls_sec_params_entry; + +static const gnutls_sec_params_entry sec_params[] = { + {"Weak", GNUTLS_SEC_PARAM_WEAK, 64, 816, 1024, 128, 128}, + {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1248, 1024, 160, 160}, + {"Normal", GNUTLS_SEC_PARAM_NORMAL, 112, 2432, 2048, 224, 224}, + {"Weak", GNUTLS_SEC_PARAM_HIGH, 128, 3248, 3072, 256, 256}, + {"Weak", GNUTLS_SEC_PARAM_ULTRA, 256, 15424, 3072, 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 ; } } + /* Cred type mappings to KX algorithms * FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require @@ -135,8 +161,7 @@ static const gnutls_protocol_t supported_protocols[] = { for(p = sup_versions; p->name != NULL; p++) { b ; } #define GNUTLS_VERSION_ALG_LOOP(a) \ - GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; }) - + GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; }) struct gnutls_cipher_entry { @@ -2293,28 +2318,30 @@ _gnutls_x509_pk_to_oid (gnutls_pk_algorithm_t algorithm) unsigned int gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo, gnutls_sec_param_t param) { +unsigned int ret = 0; - switch(algo) + /* handle DSA differently */ + if (algo == GNUTLS_PK_DSA) { - case GNUTLS_PK_RSA: - case GNUTLS_PK_DSA: - switch(param) - { - case GNUTLS_SEC_PARAM_LOW: - return 1248; - case GNUTLS_SEC_PARAM_HIGH: - return 2432; - case GNUTLS_SEC_PARAM_ULTRA: - return 3248; - case GNUTLS_SEC_PARAM_NORMAL: - default: - return 2432; - } - default: - gnutls_assert(); - return 0; + GNUTLS_SEC_PARAM_LOOP ( if (p->sec_param == param) { ret = p->dsa_bits; break; }); + return ret; } + GNUTLS_SEC_PARAM_LOOP ( if (p->sec_param == param) { ret = p->pk_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 ( if (p->pk_bits >= pk_bits) { ret = p->subgroup_bits; break; }); + + return ret; } /** @@ -2330,36 +2357,11 @@ unsigned int gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo, const char * gnutls_sec_param_get_name (gnutls_sec_param_t param) { - const char *p; +const char* ret = "Unknown"; - switch (param) - { - case GNUTLS_SEC_PARAM_WEAK: - p = "Weak"; - break; - - case GNUTLS_SEC_PARAM_LOW: - p = "Low"; - break; - - case GNUTLS_SEC_PARAM_NORMAL: - p = "Normal"; - break; - - case GNUTLS_SEC_PARAM_HIGH: - p = "High"; - break; - - case GNUTLS_SEC_PARAM_ULTRA: - p = "Ultra"; - break; + GNUTLS_SEC_PARAM_LOOP ( if (p->sec_param == param) { ret = p->name; break; }); - default: - p = "Unknown"; - break; - } - - return p; + return ret; } /** @@ -2377,17 +2379,13 @@ gnutls_sec_param_get_name (gnutls_sec_param_t param) 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_WEAK; - /* currently we ignore algo */ - if (bits >= 15423) - return GNUTLS_SEC_PARAM_ULTRA; - else if (bits >= 3247) - return GNUTLS_SEC_PARAM_HIGH; - else if (bits >= 2431) - return GNUTLS_SEC_PARAM_NORMAL; - else if (bits >= 1248) - return GNUTLS_SEC_PARAM_LOW; - else - return GNUTLS_SEC_PARAM_WEAK; + GNUTLS_SEC_PARAM_LOOP ( + if (p->pk_bits > bits) + { break; } + ret = p->sec_param; + ); + return ret; } diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index a295f18993..ae17f6dd85 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -125,4 +125,6 @@ int _gnutls_cipher_priority (gnutls_session_t session, int _gnutls_kx_priority (gnutls_session_t session, gnutls_kx_algorithm_t algorithm); +unsigned int gnutls_pk_bits_to_subgroup_bits (unsigned int pk_bits); + #endif diff --git a/lib/includes/gnutls/openpgp.h b/lib/includes/gnutls/openpgp.h index d45c81858e..81b73b7c94 100644 --- a/lib/includes/gnutls/openpgp.h +++ b/lib/includes/gnutls/openpgp.h @@ -160,6 +160,8 @@ extern "C" gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, unsigned int *bits); + + gnutls_sec_param_t gnutls_openpgp_privkey_sec_param (gnutls_openpgp_privkey_t key); int gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format, diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 59138982e0..3f07ad435a 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -618,6 +618,7 @@ extern "C" int gnutls_x509_privkey_init (gnutls_x509_privkey_t * key); void gnutls_x509_privkey_deinit (gnutls_x509_privkey_t key); + gnutls_sec_param_t gnutls_x509_privkey_sec_param (gnutls_x509_privkey_t key); int gnutls_x509_privkey_cpy (gnutls_x509_privkey_t dst, gnutls_x509_privkey_t src); int gnutls_x509_privkey_import (gnutls_x509_privkey_t key, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 88c5c25234..b8d39f72b1 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -685,6 +685,8 @@ GNUTLS_2_11 gnutls_x509_crq_get_preferred_hash_algorithm; gnutls_cipher_encrypt2; gnutls_cipher_decrypt2; + gnutls_openpgp_privkey_sec_param; + gnutls_x509_privkey_sec_param; } GNUTLS_2_10; GNUTLS_PRIVATE { diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c index f70cd9387f..865104c000 100644 --- a/lib/nettle/mpi.c +++ b/lib/nettle/mpi.c @@ -396,14 +396,12 @@ inline static int gen_group (mpz_t *prime, mpz_t* generator, unsigned int nbits) /* security level enforcement. * Values for q are selected according to ECRYPT II recommendations. */ - if (nbits <= 1248) { - q_bytes = 160/8; - } else if (nbits <=2432) { - q_bytes = 224/8; - } else if (nbits <= 3248) { - q_bytes = 256/8; - } else { - q_bytes = 512/8; + q_bytes = gnutls_pk_bits_to_subgroup_bits (nbits); + q_bytes/=8; + + if (q_bytes == 0) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; } if (nbits%8 != 0) diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c index 71c17c494a..9be4a2c541 100644 --- a/lib/openpgp/privkey.c +++ b/lib/openpgp/privkey.c @@ -74,6 +74,32 @@ gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key) gnutls_free (key); } +/** + * gnutls_openpgp_privkey_sec_param: + * @key: a key structure + * + * This function will return the security parameter appropriate with + * this private key. + * + * Returns: On success, a valid security parameter is returned otherwise + * %GNUTLS_SEC_PARAM_UNKNOWN is returned. + **/ +gnutls_sec_param_t +gnutls_openpgp_privkey_sec_param (gnutls_openpgp_privkey_t key) +{ +gnutls_pk_algorithm_t algo; +unsigned int bits; + + algo = gnutls_openpgp_privkey_get_pk_algorithm (key, &bits); + if (algo == GNUTLS_PK_UNKNOWN) + { + gnutls_assert(); + return GNUTLS_SEC_PARAM_UNKNOWN; + } + + return gnutls_pk_bits_to_sec_param (algo, bits); +} + /** * gnutls_openpgp_privkey_import: * @key: The structure to store the parsed key. diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 2b8e213829..964ccb3d9e 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -829,6 +829,36 @@ gnutls_x509_privkey_export (gnutls_x509_privkey_t key, output_data, output_data_size); } +/** + * gnutls_x509_privkey_sec_param: + * @key: a key structure + * + * This function will return the security parameter appropriate with + * this private key. + * + * Returns: On success, a valid security parameter is returned otherwise + * %GNUTLS_SEC_PARAM_UNKNOWN is returned. + **/ +gnutls_sec_param_t +gnutls_x509_privkey_sec_param (gnutls_x509_privkey_t key) +{ +int ret; + + switch (key->pk_algorithm) + { + case GNUTLS_PK_RSA: + ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_RSA, _gnutls_mpi_get_nbits(key->params[0]/*m*/)); + break; + case GNUTLS_PK_DSA: + ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_DSA, _gnutls_mpi_get_nbits(key->params[0] /*p*/)); + break; + default: + ret = GNUTLS_SEC_PARAM_UNKNOWN; + } + + return ret; +} + /** * gnutls_x509_privkey_export_rsa_raw: * @key: a structure that holds the rsa parameters diff --git a/src/certtool.c b/src/certtool.c index 579c098d81..107e9ad016 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -1350,6 +1350,7 @@ pgp_privkey_info (void) fprintf (outfile, "\tPublic Key Algorithm: "); cprint = gnutls_pk_algorithm_get_name (ret); fprintf (outfile, "%s\n", cprint ? cprint : "Unknown"); + fprintf (outfile, "\tKey Security Level: %s\n", gnutls_sec_param_get_name(gnutls_openpgp_privkey_sec_param(key))); /* Print the raw public and private keys */ @@ -1678,6 +1679,7 @@ privkey_info (void) cprint = gnutls_pk_algorithm_get_name (ret); fprintf (outfile, "%s\n", cprint ? cprint : "Unknown"); + fprintf (outfile, "\tKey Security Level: %s\n", gnutls_sec_param_get_name(gnutls_x509_privkey_sec_param(key))); /* Print the raw public and private keys */ diff --git a/tests/pathlen/no-ca-or-pathlen.pem b/tests/pathlen/no-ca-or-pathlen.pem index 08c9306add..478a3e18d0 100644 --- a/tests/pathlen/no-ca-or-pathlen.pem +++ b/tests/pathlen/no-ca-or-pathlen.pem @@ -7,7 +7,7 @@ X.509 Certificate Information: Not After: Fri Aug 25 23:59:59 UTC 2000 Subject: O=VeriSign\, Inc.,OU=VeriSign Trust Network,OU=www.verisign.com/repository/RPA Incorp. by Ref.\,LIAB.LTD(c)98,OU=Persona Not Validated,OU=Digital ID Class 1 - Netscape,CN=Simon Josefsson,EMAIL=simon@josefsson.org Subject Public Key Algorithm: RSA - Certificate Security Level: Low + Certificate Security Level: Weak Modulus (bits 1024): c9:0c:ce:8a:fe:71:46:9b:ca:1d:e5:90:12:a5:11:0b c6:2d:c4:33:c6:19:e8:60:59:4e:3f:64:3d:e4:f7:7b