Ticket #1228: 2.4-tls-group.patch

File 2.4-tls-group.patch, 14.3 KB (added by plaisthos, 18 months ago)
  • README.ec

    diff --git a/README.ec b/README.ec
    index 2f830972..32938017 100644
    a b OpenVPN 2.4.0 and newer automatically initialize ECDH parameters. When ECDSA is 
    1212used for authentication, the curve used for the server certificate will be used
    1313for ECDH too. When autodetection fails (e.g. when using RSA certificates)
    1414OpenVPN lets the crypto library decide if possible, or falls back to the
    15 secp384r1 curve. The list of groups/curves that the crypto library will choose
    16 from can be set with the --tls-groups <grouplist> configuration.
     15secp384r1 curve.
    1716
    1817An administrator can force an OpenVPN/OpenSSL server to use a specific curve
    1918using the --ecdh-curve <curvename> option with one of the curves listed as
    20 available by the --show-groups option. Clients will use the same curve as
     19available by the --show-curves option. Clients will use the same curve as
    2120selected by the server.
    2221
    23 Note that not all curves listed by --show-groups are available for use with TLS;
     22Note that not all curves listed by --show-curves are available for use with TLS;
    2423in that case connecting will fail with a 'no shared cipher' TLS error.
    2524
    2625Authentication (ECDSA)
  • doc/openvpn.8

    diff --git a/doc/openvpn.8 b/doc/openvpn.8
    index b0e4a003..16620062 100644
    a b simply supplied to the crypto library. Please see the OpenSSL and/or mbed TLS 
    49484948documentation for details on the cipher list interpretation.
    49494949
    49504950For OpenSSL, the
    4951 .B \-\-tls\-cipher
     4951.B \-\-tls-cipher
    49524952is used for TLS 1.2 and below. For TLS 1.3 and up, the
    49534953.B \-\-tls\-ciphersuites
    49544954setting is used. mbed TLS has no TLS 1.3 support yet and only the
    4955 .B \-\-tls\-cipher
     4955.B \-\-tls-cipher
    49564956setting is used.
    49574957
    49584958Use
    Use 
    49604960to see a list of TLS ciphers supported by your crypto library.
    49614961
    49624962Warning!
    4963 .B \-\-tls\-groups
    4964 ,
    49654963.B \-\-tls\-cipher
    49664964and
    49674965.B \-\-tls\-ciphersuites
    OpenSSL. 
    49774975The default for \-\-tls\-ciphersuites is to use the crypto library's default.
    49784976.\"*********************************************************
    49794977.TP
    4980 .B \-\-tls\-groups l
    4981 A list
    4982 .B l
    4983 of allowable groups/curves in order of preference.
    4984 
    4985 Set the allowed elictipic curves/groups for the TLS session.
    4986 These groups are  allowed to be used in signatures and key exchange.
    4987 
    4988 mbed TLS currently allows all known curves per default.
    4989 
    4990 OpenSSL 1.1+ restricts the list per default to
    4991 "X25519:secp256r1:X448:secp521r1:secp384r1".
    4992 
    4993 If you use certificates that use non-standard curves, you
    4994 might need to add them here. If you do not force the ecdh curve
    4995 by using
    4996 .B \-\-ecdh\-curve
    4997 , the groups for ecdh will also be picked from this list.
    4998 
    4999 OpenVPN maps the curve name secp256r1 to prime256v1 to allow
    5000 specifying the tls-groups option for mbed TLS and OpenSSL.
    5001 
    5002 Warning: this option not only affects eliptic curve certificates
    5003 but also the key exchange in TLS 1.3 and using this option improperly
    5004 will disable TLS 1.3.
    5005 .\"*********************************************************
    5006 .TP
    50074978.B \-\-tls\-cert\-profile profile
    50084979Set the allowed cryptographic algorithms for certificates according to
    50094980.B profile\fN.
    engines supported by the OpenSSL library. 
    56985669.TP
    56995670.B \-\-show\-curves
    57005671(Standalone)
    5701 Show all available elliptic groups/curves to use with the
     5672Show all available elliptic curves to use with the
    57025673.B \-\-ecdh\-curve
    5703 and
    5704 .B \-\-tls\-groups
    57055674option.
    57065675.\"*********************************************************
    57075676.SS Generate a random key:
  • src/openvpn/misc.c

    diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
    index 2d502ed8..f44c65f6 100644
    a b output_peer_info_env(struct env_set *es, const char *peer_info) 
    16341634    }
    16351635}
    16361636
    1637 int get_num_elements(const char* string, char delimiter)
    1638 {
    1639   int string_len = strlen(string);
    1640 
    1641   ASSERT(0 != string_len);
    1642 
    1643   int element_count = 1;
    1644   /* Get number of ciphers */
    1645   for (int i = 0; i < string_len; i++)
    1646     {
    1647       if (string[i] == delimiter)
    1648         {
    1649           element_count++;
    1650         }
    1651     }
    1652 
    1653   return element_count;
    1654 }
    16551637#endif /* P2MP_SERVER */
  • src/openvpn/misc.h

    diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h
    index c296d0e2..8a34f431 100644
    a b void output_peer_info_env(struct env_set *es, const char *peer_info); 
    314314
    315315#endif /* P2MP_SERVER */
    316316
    317 /**
    318  * Counts the number of delimiter in a string and returns
    319  * their number +1. This is typically used to find out the
    320  * number elements in a cipher string or similar that is separated by : like
    321  *
    322  *   X25519:secp256r1:X448:secp512r1:secp384r1:brainpoolP384r1
    323  *
    324  * @param string        the string to work on
    325  * @param delimiter     the delimiter to count, typically ':'
    326  * @return              number of delimiter found + 1
    327  */
    328 int
    329 get_num_elements(const char* string, char delimiter);
    330317#endif /* ifndef MISC_H */
  • src/openvpn/options.c

    diff --git a/src/openvpn/options.c b/src/openvpn/options.c
    index f46c5e4c..de30fcb0 100644
    a b add_option(struct options *options, 
    76447644        VERIFY_PERMISSION(OPT_P_GENERAL);
    76457645        options->show_tls_ciphers = true;
    76467646    }
    7647     else if ((streq(p[0], "show-curves") || streq(p[0], "show-groups")) && !p[1])
     7647    else if (streq(p[0], "show-curves") && !p[1])
    76487648    {
    76497649        VERIFY_PERMISSION(OPT_P_GENERAL);
    76507650        options->show_curves = true;
    add_option(struct options *options, 
    76527652    else if (streq(p[0], "ecdh-curve") && p[1] && !p[2])
    76537653    {
    76547654        VERIFY_PERMISSION(OPT_P_GENERAL);
    7655         msg(M_WARN, "Consider setting groups/curves in preference with "
    7656             "tls-groups instead of forcing a specific curve with "
    7657             "ecdh-curve.");
    76587655        options->ecdh_curve = p[1];
    76597656    }
    76607657    else if (streq(p[0], "tls-server") && !p[1])
    add_option(struct options *options, 
    78457842        VERIFY_PERMISSION(OPT_P_GENERAL);
    78467843        options->cipher_list_tls13 = p[1];
    78477844    }
    7848     else if (streq(p[0], "tls-groups") && p[1] && !p[2])
    7849     {
    7850         VERIFY_PERMISSION(OPT_P_GENERAL);
    7851         options->tls_groups = p[1];
    7852     }
    78537845    else if (streq(p[0], "crl-verify") && p[1] && ((p[2] && streq(p[2], "dir"))
    78547846                                                   || (p[2] && streq(p[1], INLINE_FILE_TAG) ) || !p[2]) && !p[3])
    78557847    {
  • src/openvpn/options.h

    diff --git a/src/openvpn/options.h b/src/openvpn/options.h
    index 661f6689..f3cafeaf 100644
    a b struct options 
    504504    const char *pkcs12_file;
    505505    const char *cipher_list;
    506506    const char *cipher_list_tls13;
    507     const char *tls_groups;
    508507    const char *tls_cert_profile;
    509508    const char *ecdh_curve;
    510509    const char *tls_verify;
  • src/openvpn/ssl.c

    diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
    index 1228d6f6..7dcd9622 100644
    a b init_ssl(const struct options *options, struct tls_root_ctx *new_ctx) 
    633633    tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
    634634    tls_ctx_restrict_ciphers_tls13(new_ctx, options->cipher_list_tls13);
    635635
    636     /* Set the allow groups/curves for TLS if we want to override them */
    637     if (options->tls_groups)
    638     {
    639         tls_ctx_set_tls_groups(new_ctx, options->tls_groups);
    640     }
    641 
    642636    if (!tls_ctx_set_options(new_ctx, options->ssl_flags))
    643637    {
    644638        goto err;
  • src/openvpn/ssl_backend.h

    diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h
    index 5d0f7f74..c614efa6 100644
    a b void tls_ctx_restrict_ciphers_tls13(struct tls_root_ctx *ctx, const char *cipher 
    200200 */
    201201void tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile);
    202202
    203 /**
    204  * Set the allowed (eliptic curve) group allowed for signatures and
    205  * key exchange.
    206  *
    207  * @param ctx       TLS context to restrict, must be valid.
    208  * @param groups    List of groups that will be allowed, in priority,
    209  *                  separated by :
    210  */
    211 void tls_ctx_set_tls_groups(struct tls_root_ctx *ctx, const char *groups);
    212 
    213203/**
    214204 * Check our certificate notBefore and notAfter fields, and warn if the cert is
    215205 * either not yet valid or has expired.  Note that this is a non-fatal error,
  • src/openvpn/ssl_mbedtls.c

    diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c
    index 7b271382..89b1b67c 100644
    a b tls_ctx_free(struct tls_root_ctx *ctx) 
    185185            free(ctx->allowed_ciphers);
    186186        }
    187187
    188         if (ctx->groups)
    189         {
    190             free(ctx->groups);
    191         }
    192 
    193188        CLEAR(*ctx);
    194189
    195190        ctx->initialised = false;
    void 
    253248tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
    254249{
    255250    char *tmp_ciphers, *tmp_ciphers_orig, *token;
     251    int i, cipher_count;
     252    int ciphers_len;
    256253
    257254    if (NULL == ciphers)
    258255    {
    259256        return; /* Nothing to do */
     257
    260258    }
     259    ciphers_len = strlen(ciphers);
    261260
    262261    ASSERT(NULL != ctx);
     262    ASSERT(0 != ciphers_len);
    263263
    264264    /* Get number of ciphers */
    265     int cipher_count = get_num_elements(ciphers, ':');
     265    for (i = 0, cipher_count = 1; i < ciphers_len; i++)
     266    {
     267        if (ciphers[i] == ':')
     268        {
     269            cipher_count++;
     270        }
     271    }
    266272
    267273    /* Allocate an array for them */
    268274    ALLOC_ARRAY_CLEAR(ctx->allowed_ciphers, int, cipher_count+1)
    269275
    270276    /* Parse allowed ciphers, getting IDs */
    271     int i = 0;
     277    i = 0;
    272278    tmp_ciphers_orig = tmp_ciphers = string_alloc(ciphers, NULL);
    273279
    274280    token = strtok(tmp_ciphers, ":");
    tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile) 
    306312    }
    307313}
    308314
    309 void
    310 tls_ctx_set_tls_groups(struct tls_root_ctx *ctx, const char *groups)
    311 {
    312     ASSERT(NULL != ctx);
    313 
    314     /* Get number of groups */
    315     int groups_count = get_num_elements(groups, ':');
    316 
    317     /* Allocate an array for them */
    318     ALLOC_ARRAY_CLEAR(ctx->groups, mbedtls_ecp_group_id, groups_count + 1)
    319 
    320     /* Parse allowed ciphers, getting IDs */
    321     int i = 0;
    322     char *tmp_groups_orig = string_alloc(groups, NULL);
    323     char *tmp_groups = tmp_groups_orig;
    324 
    325     const char *token = strsep(&tmp_groups_orig, ":");
    326     while (token)
    327     {
    328         const mbedtls_ecp_curve_info *ci =
    329             mbedtls_ecp_curve_info_from_name(token);
    330         if (ci == NULL)
    331         {
    332             msg(M_WARN, "Warning unknown curve/group specified: %s", token);
    333         }
    334         else
    335         {
    336             ctx->groups[i] = ci->grp_id;
    337             i++;
    338         }
    339         token = strsep(&tmp_groups, ":");
    340     }
    341     ctx->groups[i] = MBEDTLS_ECP_DP_NONE;
    342     free(tmp_groups_orig);
    343 }
    344 
    345 
    346315void
    347316tls_ctx_check_cert_time(const struct tls_root_ctx *ctx)
    348317{
    key_state_ssl_init(struct key_state_ssl *ks_ssl, 
    1022991        mbedtls_ssl_conf_ciphersuites(&ks_ssl->ssl_config, ssl_ctx->allowed_ciphers);
    1023992    }
    1024993
    1025     if (ssl_ctx->groups)
    1026     {
    1027         mbedtls_ssl_conf_curves(&ks_ssl->ssl_config, ssl_ctx->groups);
    1028     }
    1029 
    1030994    /* Disable record splitting (for now).  OpenVPN assumes records are sent
    1031995     * unfragmented, and changing that will require thorough review and
    1032996     * testing.  Since OpenVPN is not susceptible to BEAST, we can just
  • src/openvpn/ssl_mbedtls.h

    diff --git a/src/openvpn/ssl_mbedtls.h b/src/openvpn/ssl_mbedtls.h
    index e20cc3c8..dd8ca750 100644
    a b struct tls_root_ctx { 
    8282    struct external_context *external_key; /**< Management external key */
    8383#endif
    8484    int *allowed_ciphers;       /**< List of allowed ciphers for this connection */
    85     mbedtls_ecp_group_id *groups;                /**< List of allowed groups for this connection */
    8685    mbedtls_x509_crt_profile cert_profile; /**< Allowed certificate types */
    8786};
    8887
  • src/openvpn/ssl_openssl.c

    diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
    index b5898d08..4966dd5b 100644
    a b tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile) 
    515515#endif
    516516}
    517517
    518 void
    519 tls_ctx_set_tls_groups(struct tls_root_ctx *ctx, const char *groups)
    520 {
    521     ASSERT(ctx);
    522     /* This method could be as easy as
    523      *  SSL_CTX_set1_groups_list(ctx->ctx, groups)
    524      * but OpenSSL does not like the name secp256r1 for prime256v1
    525      * and as this is one of the more important curve to have
    526      * the same name for OpenSSL and mbedTLS, we do this dance
    527      */
    528 
    529     int groups_count = get_num_elements(groups, ':');
    530 
    531     int *glist;
    532     /* Allocate an array for them */
    533     ALLOC_ARRAY_CLEAR(glist, int, groups_count);
    534 
    535     /* Parse allowed ciphers, getting IDs */
    536     int glistlen = 0;
    537     char *tmp_groups_orig = string_alloc(groups, NULL);
    538     char *tmp_groups = tmp_groups_orig;
    539 
    540     const char *token = strsep(&tmp_groups_orig, ":");
    541     while (token)
    542     {
    543         if (streq(token, "secp256r1"))
    544         {
    545             token = "prime256v1";
    546         }
    547         int nid = OBJ_sn2nid(token);
    548 
    549         if (nid == 0)
    550         {
    551             msg(M_WARN, "Warning unknown curve/group specified: %s", token);
    552         }
    553         else
    554         {
    555             glist[glistlen] = nid;
    556             glistlen++;
    557         }
    558         token = strsep(&tmp_groups, ":");
    559     }
    560 
    561     free(tmp_groups_orig);
    562 
    563     if (!SSL_CTX_set1_groups(ctx->ctx, glist, glistlen))
    564     {
    565         crypto_msg(M_FATAL, "Failed to set allowed TLS group list: %s",
    566                    groups);
    567     }
    568     free(glist);
    569 }
    570 
    571518void
    572519tls_ctx_check_cert_time(const struct tls_root_ctx *ctx)
    573520{
    tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name 
    687634        /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter
    688635         * loading */
    689636        SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
    690 
    691         /* OpenSSL 1.1.0 and newer have always ecdh auto loading enabled,
    692          * so do nothing */
    693 #endif
    694637        return;
     638#endif
    695639#else
    696640        /* For older OpenSSL we have to extract the curve from key on our own */
    697641        EC_KEY *eckey = NULL;
    show_available_curves(void) 
    19801924    ALLOC_ARRAY(curves, EC_builtin_curve, crv_len);
    19811925    if (EC_get_builtin_curves(curves, crv_len))
    19821926    {
    1983         printf("Consider using openssl ecparam -list_curves as\n"
    1984                "alternative to running this command to this command.");
    1985         printf("\nAvailable Elliptic curves/groups:\n");
     1927        printf("Available Elliptic curves:\n");
    19861928        for (n = 0; n < crv_len; n++)
    19871929        {
    19881930            const char *sname;