Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postfix/src/tls/   (Postfix Mailserver Version 3.11©)  Datei vom 22.11.2025 mit Größe 12 kB image not shown  

Quelle  tls_dh.c

  Sprache: C
 

/*++
/* NAME
/* tls_dh
/* SUMMARY
/* Diffie-Hellman parameter support
/* SYNOPSIS
/* #define TLS_INTERNAL
/* #include <tls.h>
/*
/* void tls_set_dh_from_file(path)
/* const char *path;
/*
/* void tls_auto_groups(ctx, eecdh, ffdhe)
/* SSL_CTX *ctx;
/* char *eecdh;
/* char *ffdhe;
/*
/* void tls_tmp_dh(ctx, useauto)
/* SSL_CTX *ctx;
/* int useauto;
/* DESCRIPTION
/* This module maintains parameters for Diffie-Hellman key generation.
/*
/* tls_tmp_dh() returns the configured or compiled-in FFDHE
/* group parameters.  The useauto argument enables OpenSSL-builtin group
/* selection in preference to our own compiled-in group.  This may
/* interoperate better with overly strict peers that accept only
/* "standard" groups.
/*
/* tls_set_dh_from_file() overrides compiled-in DH parameters
/* with those specified in the named files. The file format
/* is as expected by the PEM_read_DHparams() routine.
/*
/* tls_auto_groups() enables negotiation of the most preferred key
/* exchange group among those specified by the "eecdh" and "ffdhe"
/* arguments.  The "ffdhe" argument is only used with OpenSSL 3.0
/* and later, and applies to TLS 1.3 and up.
/* DIAGNOSTICS
/* In case of error, tls_set_dh_from_file() logs a warning and
/* ignores the request.
/* LICENSE
/* .ad
/* .fi
/* This software is free. You can do with it whatever you want.
/* The original author kindly requests that you acknowledge
/* the use of his software.
/* AUTHOR(S)
/* Originally written by:
/* Lutz Jaenicke
/* BTU Cottbus
/* Allgemeine Elektrotechnik
/* Universitaetsplatz 3-4
/* D-03044 Cottbus, Germany
/*
/* Updated by:
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/


/* System library. */

#include <sys_defs.h>

#ifdef USE_TLS
#include <stdio.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>

 /*
  * Global library
  */

#include <been_here.h>
#include <mail_params.h>

/* TLS library. */

#define TLS_INTERNAL
#include <tls.h>
#include <openssl/dh.h>
#ifndef OPENSSL_NO_ECDH
#include <openssl/ec.h>
#endif
#if OPENSSL_VERSION_PREREQ(3,0)
#include <openssl/decoder.h>
#endif

/* Application-specific. */

 /*
  * Compiled-in FFDHE (finite-field ephemeral Diffie-Hellman) parameters.
  * Used when no parameters are explicitly loaded from a site-specific file.
  * 
  * With OpenSSL 3.0 and later when no explicit parameter file is specified by
  * the administrator (or the setting is "auto"), we delegate group selection
  * to OpenSSL via SSL_CTX_set_dh_auto(3).
  * 
  * Using an ASN.1 DER encoding avoids the need to explicitly manipulate the
  * internal representation of DH parameter objects.
  * 
  * The FFDHE group is now 2048-bit, as 1024 bits is increasingly considered to
  * weak by clients.  When greater security is required, use EECDH.
  */


 /*-
  * Generated via:
  *   $ openssl dhparam -2 -outform DER 2048 2>/dev/null |
  *     hexdump -ve '/1 "0x%02x, "' | fmt -73
  * TODO: generate at compile-time. But that is no good for the majority of
  * sites that install pre-compiled binaries, and breaks reproducible builds.
  * Instead, generate at installation time and use main.cf configuration.
  */

static unsigned char builtin_der[] = {
    0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xec, 0x02, 0x7b,
    0x74, 0xc6, 0xd4, 0xb4, 0x89, 0x68, 0xfd, 0xbc, 0xe0, 0x82, 0xae, 0xd6,
    0xf1, 0x4d, 0x93, 0xaa, 0x47, 0x07, 0x84, 0x3d, 0x86, 0xf8, 0x47, 0xf7,
    0xdf, 0x08, 0x7b, 0xca, 0x04, 0xa4, 0x72, 0xec, 0x11, 0xe2, 0x38, 0x43,
    0xb7, 0x94, 0xab, 0xaf, 0xe2, 0x85, 0x59, 0x43, 0x4e, 0x71, 0x85, 0xfe,
    0x52, 0x0c, 0xe0, 0x1c, 0xb6, 0xc7, 0xb0, 0x1b, 0x06, 0xb3, 0x4d, 0x1b,
    0x4f, 0xf6, 0x4b, 0x45, 0xbd, 0x1d, 0xb8, 0xe4, 0xa4, 0x48, 0x09, 0x28,
    0x19, 0xd7, 0xce, 0xb1, 0xe5, 0x9a, 0xc4, 0x94, 0x55, 0xde, 0x4d, 0x86,
    0x0f, 0x4c, 0x5e, 0x25, 0x51, 0x6c, 0x96, 0xca, 0xfa, 0xe3, 0x01, 0x69,
    0x82, 0x6c, 0x8f, 0xf5, 0xe7, 0x0e, 0xb7, 0x8e, 0x52, 0xf1, 0xcf, 0x0b,
    0x67, 0x10, 0xd0, 0xb3, 0x77, 0x79, 0xa4, 0xc1, 0xd0, 0x0f, 0x3f, 0xf5,
    0x5c, 0x35, 0xf9, 0x46, 0xd2, 0xc7, 0xfb, 0x97, 0x6d, 0xd5, 0xbe, 0xe4,
    0x8b, 0x5a, 0xf2, 0x88, 0xfa, 0x47, 0xdc, 0xc2, 0x4a, 0x4d, 0x69, 0xd3,
    0x2a, 0xdf, 0x55, 0x6c, 0x5f, 0x71, 0x11, 0x1e, 0x87, 0x03, 0x68, 0xe1,
    0xf4, 0x21, 0x06, 0x63, 0xd9, 0x65, 0xd4, 0x0c, 0x4d, 0xa7, 0x1f, 0x15,
    0x53, 0x3a, 0x50, 0x1a, 0xf5, 0x9b, 0x50, 0x35, 0xe0, 0x16, 0xa1, 0xd7,
    0xe6, 0xbf, 0xd7, 0xd9, 0xd9, 0x53, 0xe5, 0x8b, 0xf8, 0x7b, 0x45, 0x46,
    0xb6, 0xac, 0x50, 0x16, 0x46, 0x42, 0xca, 0x76, 0x38, 0x4b, 0x8e, 0x83,
    0xc6, 0x73, 0x13, 0x9c, 0x03, 0xd1, 0x7a, 0x3d, 0x8d, 0x99, 0x34, 0x10,
    0x79, 0x67, 0x21, 0x23, 0xf9, 0x6f, 0x48, 0x9a, 0xa6, 0xde, 0xbf, 0x7f,
    0x9c, 0x16, 0x53, 0xff, 0xf7, 0x20, 0x96, 0xeb, 0x34, 0xcb, 0x5b, 0x85,
    0x2b, 0x7c, 0x98, 0x00, 0x23, 0x47, 0xce, 0xc2, 0x58, 0x12, 0x86, 0x2c,
    0x57, 0x02, 0x01, 0x02,
};

#if OPENSSL_VERSION_PREREQ(3,0)

/* ------------------------------------- 3.0 API */

static EVP_PKEY *dhp = 0;

/* load_builtin - load compile-time FFDHE group */

static void load_builtin(void)
{
    EVP_PKEY *tmp = 0;
    OSSL_DECODER_CTX *d;
    const unsigned char *endp = builtin_der;
    size_t  dlen = sizeof(builtin_der);

    d = OSSL_DECODER_CTX_new_for_pkey(&tmp, "DER", NULL, "DH",
          OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
          NULL, NULL);
    /* Check decode succeeds and consumes all data (final dlen == 0) */
    if (d && OSSL_DECODER_from_data(d, &endp, &dlen) && tmp && !dlen) {
 dhp = tmp;
    } else {
 EVP_PKEY_free(tmp);
 msg_warn("error loading compiled-in DH parameters");
 tls_print_errors();
    }
    OSSL_DECODER_CTX_free(d);
}

/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */

void    tls_set_dh_from_file(const char *path)
{
    FILE   *fp;
    EVP_PKEY *tmp = 0;
    OSSL_DECODER_CTX *d;

    /*
     * This function is the first to set the DH parameters, but free any
     * prior value just in case the call sequence changes some day.
     */

    if (dhp) {
 EVP_PKEY_free(dhp);
 dhp = 0;
    }
    if (strcmp(path, "auto") == 0)
 return;

    if ((fp = fopen(path, "r")) == 0) {
 msg_warn("error opening DH parameter file \"%s\": %m"
   " -- using compiled-in defaults", path);
 return;
    }
    d = OSSL_DECODER_CTX_new_for_pkey(&tmp, "PEM", NULL, "DH",
          OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
          NULL, NULL);
    if (!d || !OSSL_DECODER_from_fp(d, fp) || !tmp) {
 msg_warn("error decoding DH parameters from file \"%s\""
   " -- using compiled-in defaults", path);
 tls_print_errors();
    } else {
 dhp = tmp;
    }
    OSSL_DECODER_CTX_free(d);
    (void) fclose(fp);
}

/* tls_tmp_dh - configure FFDHE group */

void    tls_tmp_dh(SSL_CTX *ctx, int useauto)
{
    if (!dhp && !useauto)
 load_builtin();
    if (!ctx)
 return;
    if (dhp) {
 EVP_PKEY *tmp = EVP_PKEY_dup(dhp);

 if (tmp && SSL_CTX_set0_tmp_dh_pkey(ctx, tmp) > 0)
     return;
 EVP_PKEY_free(tmp);
 msg_warn("error configuring explicit DH parameters");
 tls_print_errors();
    } else {
 if (SSL_CTX_set_dh_auto(ctx, 1) > 0)
     return;
 msg_warn("error configuring auto DH parameters");
 tls_print_errors();
    }
}

#else     /* OPENSSL_VERSION_PREREQ(3,0) */

/* ------------------------------------- 1.1.1 API */

static DH *dhp = 0;

static void load_builtin(void)
{
    DH     *tmp = 0;
    const unsigned char *endp = builtin_der;

    if (d2i_DHparams(&tmp, &endp, sizeof(builtin_der))
 && sizeof(builtin_der) == endp - builtin_der) {
 dhp = tmp;
    } else {
 DH_free(tmp);
 msg_warn("error loading compiled-in DH parameters");
 tls_print_errors();
    }
}

/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */

void    tls_set_dh_from_file(const char *path)
{
    FILE   *fp;

    /*
     * This function is the first to set the DH parameters, but free any
     * prior value just in case the call sequence changes some day.
     */

    if (dhp) {
 DH_free(dhp);
 dhp = 0;
    }

    /*
     * Forwards compatibility, support "auto" by using the builtin group when
     * OpenSSL is < 3.0 and does not support automatic FFDHE group selection.
     */

    if (strcmp(path, "auto") == 0)
 return;

    if ((fp = fopen(path, "r")) == 0) {
 msg_warn("cannot load DH parameters from file %s: %m"
   " -- using compiled-in defaults", path);
 return;
    }
    if ((dhp = PEM_read_DHparams(fp, 000)) == 0) {
 msg_warn("cannot load DH parameters from file %s"
   " -- using compiled-in defaults", path);
 tls_print_errors();
    }
    (void) fclose(fp);
}

/* tls_tmp_dh - configure FFDHE group */

void    tls_tmp_dh(SSL_CTX *ctx, int useauto)
{
    if (!dhp)
 load_builtin();
    if (!ctx || !dhp || SSL_CTX_set_tmp_dh(ctx, dhp) > 0)
 return;
    msg_warn("error configuring explicit DH parameters");
    tls_print_errors();
}

#endif     /* OPENSSL_VERSION_PREREQ(3,0) */

/* ------------------------------------- Common API */

#define AG_STAT_OK (0)
#define AG_STAT_NO_GROUP (-1)  /* no usable group, may retry */
#define AG_STAT_NO_RETRY (-2)  /* other error, don't retry */

static int setup_auto_groups(SSL_CTX *ctx, const char *origin,
                const char *eecdh,
                const char *ffdhe)
{
#ifndef OPENSSL_NO_ECDH
    SSL_CTX *tmpctx;
    BH_TABLE *seen;
    char   *save;
    char   *groups;
    char   *group;
    static VSTRING *names;

    if ((tmpctx = SSL_CTX_new(TLS_method())) == 0) {
 msg_warn("cannot allocate temp SSL_CTX");
 tls_print_errors();
 return (AG_STAT_NO_RETRY);
    }
    if (!names)
 names = vstring_alloc(sizeof DEF_TLS_EECDH_AUTO +
         sizeof DEF_TLS_FFDHE_AUTO);
    VSTRING_RESET(names);

    /*
     * OpenSSL does not tolerate duplicate groups in the requested list.
     * Deduplicate case-insensitively, just in case OpenSSL some day supports
     * case-insensitive group lookup.  Deduplicate only verified extant
     * groups we're going to ask OpenSSL to use.
     * 
     * OpenSSL 3.3 supports "?<name>" as a syntax for optionally ignoring
     * unsupported groups, so we could skip checking against the throw-away
     * CTX when linked against 3.3 or higher, but the cost savings don't
     * justify the #ifdef overhead for now.
     */

    seen = been_here_init(0, BH_FLAG_FOLD);

#define GROUPS_SEP CHARS_COMMA_SP ":"
#define SETUP_AG_RETURN(val) do { \
 been_here_free(seen); \
 myfree(save); \
 SSL_CTX_free(tmpctx); \
 return (val); \
    } while (0)

    groups = save = concatenate(eecdh, " ", ffdhe, NULL);
    if ((group = mystrtok(&groups, GROUPS_SEP)) == 0) {
 msg_warn("no %s key exchange group - OpenSSL requires at least one",
   origin);
 SETUP_AG_RETURN(AG_STAT_NO_GROUP);
    }
    for (; group != 0; group = mystrtok(&groups, GROUPS_SEP)) {

 /*
  * Validate the group name by trying it as the group for a throw-away
  * SSL context. This way, we can ask for new groups that may not yet
  * be supported by the underlying OpenSSL runtime.  Unsupported
  * groups are silently ignored.
 */

 ERR_set_mark();
 if (SSL_CTX_set1_curves_list(tmpctx, group) > 0 &&
     !been_here_fixed(seen, group)) {
     if (VSTRING_LEN(names) > 0)
  VSTRING_ADDCH(names, ':');
     vstring_strcat(names, group);
 }
 ERR_pop_to_mark();
    }

    if (VSTRING_LEN(names) == 0) {
 /* The names may be case-sensitive */
 msg_warn("none of the %s key exchange groups are supported", origin);
 SETUP_AG_RETURN(AG_STAT_NO_GROUP);
    }
    VSTRING_TERMINATE(names);

    if (SSL_CTX_set1_curves_list(ctx, vstring_str(names)) <= 0) {
 msg_warn("failed to set up the %s key exchange groups", origin);
 tls_print_errors();
 SETUP_AG_RETURN(AG_STAT_NO_RETRY);
    }
    SETUP_AG_RETURN(AG_STAT_OK);
#endif
}

void    tls_auto_groups(SSL_CTX *ctx, const char *eecdh, const char *ffdhe)
{
    char   *def_eecdh = DEF_TLS_EECDH_AUTO;

#if OPENSSL_VERSION_PREREQ(30)
    char   *def_ffdhe = DEF_TLS_FFDHE_AUTO;

#else
    char   *def_ffdhe = "";

    /* Has no effect prior to OpenSSL 3.0 */
    ffdhe = def_ffdhe;
#endif
    const char *origin;

    /* Use OpenSSL defaults */
    if (!*eecdh && !*ffdhe)
 return;

    /*
     * Try the user-specified list first. If that fails (empty list or no
     * known group name), try again with the Postfix defaults. We assume that
     * group selection is mere performance tuning and not security critical.
     * All the groups supported for negotiation should be strong enough.
     */

    for (origin = "configured"/* void */ ; /* void */ ) {
 switch (setup_auto_groups(ctx, origin, eecdh, ffdhe)) {
 case AG_STAT_OK:
     return;
 case AG_STAT_NO_GROUP:
     if (strcmp(eecdh, def_eecdh) != 0
  || strcmp(ffdhe, def_ffdhe) != 0) {
  msg_warn("using Postfix default key exchange groups instead");
  origin = "Postfix default";
  eecdh = def_eecdh;
  ffdhe = def_ffdhe;
  break;
     }
     /* FALLTHROUGH */
 default:
     msg_warn("using OpenSSL default key exchange groups instead");
     return;
 }
    }
}

#ifdef TEST

int     main(int unused_argc, char **unused_argv)
{
    tls_tmp_dh(00);
    return (dhp == 0);
}

#endif

#endif

Messung V0.5 in Prozent
C=81 H=93 G=86

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet am  2026-08-09) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.