Changeset a2b4ab6 in mod_gnutls


Ignore:
Timestamp:
Jul 5, 2017, 1:47:32 AM (5 months ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
master
Children:
bd6591f
Parents:
92ac36e
Message:

Use GnuTLS known DH parameters

If the user does not configure the DH parameters to use, mod_gnutls
now estimates the GnuTLS security parameter based on the private key
and uses the matching DH group built into GnuTLS. Using one of the
known DH groups is recommended by the GnuTLS developers.

Using built-in DH groups requires compiling against GnuTLS version
3.5.6 or newer. Otherwise the ffdhe2048 DH group as defined in RFC
7919, Appendix A.1 is the new default, which is the built-in for
security parameter "medium" in current GnuTLS versions.

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_config.c

    r104e881 ra2b4ab6  
    8484}
    8585
    86 /* 2048-bit group parameters from SRP specification */
    87 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
    88         "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
    89         "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
    90         "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
    91         "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
    92         "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
    93         "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
    94         "-----END DH PARAMETERS-----\n";
    95 
    96 /*
    97  * Clean up the various GnuTLS data structures allocated from
     86
     87
     88/**
     89 * Clean up the various GnuTLS data structures allocated by
    9890 * mgs_load_files()
    9991 */
     
    254246#endif
    255247
    256     if (sc->dh_params == NULL)
    257     {
    258         ret = gnutls_dh_params_init(&sc->dh_params);
    259         if (ret < 0) {
    260             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    261                          "GnuTLS: Failed to initialize"
    262                          ": (%d) %s", ret, gnutls_strerror(ret));
    263             ret = -1;
    264             goto cleanup;
    265         }
    266 
    267         /* Load DH parameters */
    268         if (sc->dh_file)
     248    /* Load user provided DH parameters, if any */
     249    if (sc->dh_file)
     250    {
     251        if (sc->dh_params == NULL)
    269252        {
    270             if (load_datum_from_file(spool, sc->dh_file, &data) != 0) {
     253            ret = gnutls_dh_params_init(&sc->dh_params);
     254            if (ret < 0) {
    271255                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    272                              "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file);
     256                             "GnuTLS: Failed to initialize"
     257                             ": (%d) %s", ret, gnutls_strerror(ret));
    273258                ret = -1;
    274259                goto cleanup;
    275260            }
    276 
    277             ret =
    278                 gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
    279                                               GNUTLS_X509_FMT_PEM);
    280             if (ret < 0) {
    281                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    282                              "GnuTLS: Failed to Import "
    283                              "DH params '%s': (%d) %s", sc->dh_file, ret,
    284                              gnutls_strerror(ret));
    285                 ret = -1;
    286                 goto cleanup;
    287             }
    288         } else {
    289             gnutls_datum_t pdata = {
    290                 (void *) static_dh_params,
    291                 sizeof(static_dh_params)
    292             };
    293 
    294             ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &pdata, GNUTLS_X509_FMT_PEM);
    295             if (ret < 0) {
    296                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    297                              "GnuTLS: Unable to generate or load DH Params: (%d) %s",
    298                              ret, gnutls_strerror(ret));
    299                 ret = -1;
    300                 goto cleanup;
    301             }
     261        }
     262
     263        if (load_datum_from_file(spool, sc->dh_file, &data) != 0) {
     264            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     265                         "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file);
     266            ret = -1;
     267            goto cleanup;
     268        }
     269
     270        ret =
     271            gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
     272                                          GNUTLS_X509_FMT_PEM);
     273        if (ret < 0) {
     274            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     275                         "GnuTLS: Failed to Import "
     276                         "DH params '%s': (%d) %s", sc->dh_file, ret,
     277                         gnutls_strerror(ret));
     278            ret = -1;
     279            goto cleanup;
    302280        }
    303281    }
     
    11091087    sc->priorities = NULL;
    11101088    sc->dh_params = NULL;
     1089    sc->dh_file = NULL;
    11111090    sc->ca_list = NULL;
    11121091    sc->ca_list_size = 0;
  • src/gnutls_hooks.c

    r92ac36e ra2b4ab6  
    313313}
    314314
     315
     316
     317#if GNUTLS_VERSION_NUMBER >= 0x030506
     318#define HAVE_KNOWN_DH_GROUPS 1
     319#endif
     320#ifdef HAVE_KNOWN_DH_GROUPS
     321/**
     322 * Try to estimate a GnuTLS security parameter based on the given
     323 * private key. Any errors are logged.
     324 *
     325 * @param s The `server_rec` to use for logging
     326 *
     327 * @param key The private key to use
     328 *
     329 * @return `gnutls_sec_param_t` as returned by
     330 * `gnutls_pk_bits_to_sec_param` for the key properties, or
     331 * GNUTLS_SEC_PARAM_UNKNOWN in case of error
     332 */
     333static gnutls_sec_param_t sec_param_from_privkey(server_rec *server,
     334                                                 gnutls_privkey_t key)
     335{
     336    unsigned int bits = 0;
     337    int pk_algo = gnutls_privkey_get_pk_algorithm(key, &bits);
     338    if (pk_algo < 0)
     339    {
     340        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
     341                     "%s: Could not get private key parameters: %s (%d)",
     342                     __func__, gnutls_strerror(pk_algo), pk_algo);
     343        return GNUTLS_SEC_PARAM_UNKNOWN;
     344    }
     345    return gnutls_pk_bits_to_sec_param(pk_algo, bits);
     346}
     347#else
     348/** ffdhe2048 DH group as defined in RFC 7919, Appendix A.1. This is
     349 * the default DH group if mod_gnutls is compiled agains a GnuTLS
     350 * version that does not provide known DH groups based on security
     351 * parameters (before 3.5.6). */
     352static const char FFDHE2048_PKCS3[] =
     353    "-----BEGIN DH PARAMETERS-----\n"
     354    "MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n"
     355    "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n"
     356    "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n"
     357    "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n"
     358    "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n"
     359    "ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICAQA=\n"
     360    "-----END DH PARAMETERS-----\n";
     361const gnutls_datum_t default_dh_params = {
     362    (void *) FFDHE2048_PKCS3,
     363    sizeof(FFDHE2048_PKCS3)
     364};
     365#endif
     366
     367
     368
     369/**
     370 * Configure the default DH groups to use for the given server. When
     371 * compiled against GnuTLS version 3.5.6 or newer the known DH group
     372 * matching the GnuTLS security parameter estimated from the private
     373 * key is used. Otherwise the ffdhe2048 DH group as defined in RFC
     374 * 7919, Appendix A.1 is the default.
     375 *
     376 * @param server the host to configure
     377 *
     378 * @return `OK` on success, `HTTP_UNAUTHORIZED` otherwise
     379 */
     380static int set_default_dh_param(server_rec *server)
     381{
     382    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     383        ap_get_module_config(server->module_config, &gnutls_module);
     384
     385#ifdef HAVE_KNOWN_DH_GROUPS
     386    gnutls_sec_param_t seclevel = GNUTLS_SEC_PARAM_UNKNOWN;
     387    if (sc->privkey_x509)
     388    {
     389        seclevel = sec_param_from_privkey(server, sc->privkey_x509);
     390        ap_log_error(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, server,
     391                     "%s: GnuTLS security param estimated based on "
     392                     "private key '%s': %s",
     393                     __func__, sc->x509_key_file,
     394                     gnutls_sec_param_get_name(seclevel));
     395    }
     396
     397    if (seclevel == GNUTLS_SEC_PARAM_UNKNOWN)
     398        seclevel = GNUTLS_SEC_PARAM_MEDIUM;
     399    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, server,
     400                 "%s: Setting DH params for security level '%s'.",
     401                 __func__, gnutls_sec_param_get_name(seclevel));
     402
     403    int ret = gnutls_certificate_set_known_dh_params(sc->certs, seclevel);
     404    if (ret < 0)
     405    {
     406        ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, server,
     407                     "%s: setting known DH params failed: %s (%d)",
     408                     __func__, gnutls_strerror(ret), ret);
     409        return HTTP_UNAUTHORIZED;
     410    }
     411    ret = gnutls_anon_set_server_known_dh_params(sc->anon_creds, seclevel);
     412    if (ret < 0)
     413    {
     414        ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, server,
     415                     "%s: setting known DH params failed: %s (%d)",
     416                     __func__, gnutls_strerror(ret), ret);
     417        return HTTP_UNAUTHORIZED;
     418    }
     419#else
     420    int ret = gnutls_dh_params_init(&sc->dh_params);
     421    if (ret < 0)
     422    {
     423        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
     424                     "%s: Failed to initialize DH params structure: "
     425                     "%s (%d)", __func__, gnutls_strerror(ret), ret);
     426        return HTTP_UNAUTHORIZED;
     427    }
     428    ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &default_dh_params,
     429                                        GNUTLS_X509_FMT_PEM);
     430    if (ret < 0)
     431    {
     432        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
     433                     "%s: Failed to import default DH params: %s (%d)",
     434                     __func__, gnutls_strerror(ret), ret);
     435        return HTTP_UNAUTHORIZED;
     436    }
     437
     438    gnutls_certificate_set_dh_params(sc->certs, sc->dh_params);
     439    gnutls_anon_set_server_dh_params(sc->anon_creds, sc->dh_params);
     440#endif
     441
     442    return OK;
     443}
     444
     445
     446
    315447/**
    316448 * Post config hook.
     
    437569        }
    438570
    439         /* Set host DH params */
     571        /* Set host DH params from user configuration or defaults */
    440572        if (sc->dh_params != NULL) {
    441573            gnutls_certificate_set_dh_params(sc->certs, sc->dh_params);
    442574            gnutls_anon_set_server_dh_params(sc->anon_creds, sc->dh_params);
     575        } else {
     576            rv = set_default_dh_param(s);
     577            if (rv != OK)
     578                return rv;
    443579        }
    444580
Note: See TracChangeset for help on using the changeset viewer.