Ticket #1228: 2.4-tls-group.patch
File 2.4-tls-group.patch, 14.3 KB (added by , 4 years 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 12 12 used for authentication, the curve used for the server certificate will be used 13 13 for ECDH too. When autodetection fails (e.g. when using RSA certificates) 14 14 OpenVPN 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. 15 secp384r1 curve. 17 16 18 17 An administrator can force an OpenVPN/OpenSSL server to use a specific curve 19 18 using 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 as19 available by the --show-curves option. Clients will use the same curve as 21 20 selected by the server. 22 21 23 Note that not all curves listed by --show- groups are available for use with TLS;22 Note that not all curves listed by --show-curves are available for use with TLS; 24 23 in that case connecting will fail with a 'no shared cipher' TLS error. 25 24 26 25 Authentication (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 4948 4948 documentation for details on the cipher list interpretation. 4949 4949 4950 4950 For OpenSSL, the 4951 .B \-\-tls \-cipher4951 .B \-\-tls-cipher 4952 4952 is used for TLS 1.2 and below. For TLS 1.3 and up, the 4953 4953 .B \-\-tls\-ciphersuites 4954 4954 setting is used. mbed TLS has no TLS 1.3 support yet and only the 4955 .B \-\-tls \-cipher4955 .B \-\-tls-cipher 4956 4956 setting is used. 4957 4957 4958 4958 Use … … Use 4960 4960 to see a list of TLS ciphers supported by your crypto library. 4961 4961 4962 4962 Warning! 4963 .B \-\-tls\-groups4964 ,4965 4963 .B \-\-tls\-cipher 4966 4964 and 4967 4965 .B \-\-tls\-ciphersuites … … OpenSSL. 4977 4975 The default for \-\-tls\-ciphersuites is to use the crypto library's default. 4978 4976 .\"********************************************************* 4979 4977 .TP 4980 .B \-\-tls\-groups l4981 A list4982 .B l4983 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 to4991 "X25519:secp256r1:X448:secp521r1:secp384r1".4992 4993 If you use certificates that use non-standard curves, you4994 might need to add them here. If you do not force the ecdh curve4995 by using4996 .B \-\-ecdh\-curve4997 , the groups for ecdh will also be picked from this list.4998 4999 OpenVPN maps the curve name secp256r1 to prime256v1 to allow5000 specifying the tls-groups option for mbed TLS and OpenSSL.5001 5002 Warning: this option not only affects eliptic curve certificates5003 but also the key exchange in TLS 1.3 and using this option improperly5004 will disable TLS 1.3.5005 .\"*********************************************************5006 .TP5007 4978 .B \-\-tls\-cert\-profile profile 5008 4979 Set the allowed cryptographic algorithms for certificates according to 5009 4980 .B profile\fN. … … engines supported by the OpenSSL library. 5698 5669 .TP 5699 5670 .B \-\-show\-curves 5700 5671 (Standalone) 5701 Show all available elliptic groups/curves to use with the5672 Show all available elliptic curves to use with the 5702 5673 .B \-\-ecdh\-curve 5703 and5704 .B \-\-tls\-groups5705 5674 option. 5706 5675 .\"********************************************************* 5707 5676 .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) 1634 1634 } 1635 1635 } 1636 1636 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 }1655 1637 #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); 314 314 315 315 #endif /* P2MP_SERVER */ 316 316 317 /**318 * Counts the number of delimiter in a string and returns319 * their number +1. This is typically used to find out the320 * number elements in a cipher string or similar that is separated by : like321 *322 * X25519:secp256r1:X448:secp512r1:secp384r1:brainpoolP384r1323 *324 * @param string the string to work on325 * @param delimiter the delimiter to count, typically ':'326 * @return number of delimiter found + 1327 */328 int329 get_num_elements(const char* string, char delimiter);330 317 #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, 7644 7644 VERIFY_PERMISSION(OPT_P_GENERAL); 7645 7645 options->show_tls_ciphers = true; 7646 7646 } 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]) 7648 7648 { 7649 7649 VERIFY_PERMISSION(OPT_P_GENERAL); 7650 7650 options->show_curves = true; … … add_option(struct options *options, 7652 7652 else if (streq(p[0], "ecdh-curve") && p[1] && !p[2]) 7653 7653 { 7654 7654 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.");7658 7655 options->ecdh_curve = p[1]; 7659 7656 } 7660 7657 else if (streq(p[0], "tls-server") && !p[1]) … … add_option(struct options *options, 7845 7842 VERIFY_PERMISSION(OPT_P_GENERAL); 7846 7843 options->cipher_list_tls13 = p[1]; 7847 7844 } 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 }7853 7845 else if (streq(p[0], "crl-verify") && p[1] && ((p[2] && streq(p[2], "dir")) 7854 7846 || (p[2] && streq(p[1], INLINE_FILE_TAG) ) || !p[2]) && !p[3]) 7855 7847 { -
src/openvpn/options.h
diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 661f6689..f3cafeaf 100644
a b struct options 504 504 const char *pkcs12_file; 505 505 const char *cipher_list; 506 506 const char *cipher_list_tls13; 507 const char *tls_groups;508 507 const char *tls_cert_profile; 509 508 const char *ecdh_curve; 510 509 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) 633 633 tls_ctx_restrict_ciphers(new_ctx, options->cipher_list); 634 634 tls_ctx_restrict_ciphers_tls13(new_ctx, options->cipher_list_tls13); 635 635 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 642 636 if (!tls_ctx_set_options(new_ctx, options->ssl_flags)) 643 637 { 644 638 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 200 200 */ 201 201 void tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile); 202 202 203 /**204 * Set the allowed (eliptic curve) group allowed for signatures and205 * 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 213 203 /** 214 204 * Check our certificate notBefore and notAfter fields, and warn if the cert is 215 205 * 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) 185 185 free(ctx->allowed_ciphers); 186 186 } 187 187 188 if (ctx->groups)189 {190 free(ctx->groups);191 }192 193 188 CLEAR(*ctx); 194 189 195 190 ctx->initialised = false; … … void 253 248 tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) 254 249 { 255 250 char *tmp_ciphers, *tmp_ciphers_orig, *token; 251 int i, cipher_count; 252 int ciphers_len; 256 253 257 254 if (NULL == ciphers) 258 255 { 259 256 return; /* Nothing to do */ 257 260 258 } 259 ciphers_len = strlen(ciphers); 261 260 262 261 ASSERT(NULL != ctx); 262 ASSERT(0 != ciphers_len); 263 263 264 264 /* 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 } 266 272 267 273 /* Allocate an array for them */ 268 274 ALLOC_ARRAY_CLEAR(ctx->allowed_ciphers, int, cipher_count+1) 269 275 270 276 /* Parse allowed ciphers, getting IDs */ 271 i nt i= 0;277 i = 0; 272 278 tmp_ciphers_orig = tmp_ciphers = string_alloc(ciphers, NULL); 273 279 274 280 token = strtok(tmp_ciphers, ":"); … … tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile) 306 312 } 307 313 } 308 314 309 void310 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 else335 {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 346 315 void 347 316 tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) 348 317 { … … key_state_ssl_init(struct key_state_ssl *ks_ssl, 1022 991 mbedtls_ssl_conf_ciphersuites(&ks_ssl->ssl_config, ssl_ctx->allowed_ciphers); 1023 992 } 1024 993 1025 if (ssl_ctx->groups)1026 {1027 mbedtls_ssl_conf_curves(&ks_ssl->ssl_config, ssl_ctx->groups);1028 }1029 1030 994 /* Disable record splitting (for now). OpenVPN assumes records are sent 1031 995 * unfragmented, and changing that will require thorough review and 1032 996 * 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 { 82 82 struct external_context *external_key; /**< Management external key */ 83 83 #endif 84 84 int *allowed_ciphers; /**< List of allowed ciphers for this connection */ 85 mbedtls_ecp_group_id *groups; /**< List of allowed groups for this connection */86 85 mbedtls_x509_crt_profile cert_profile; /**< Allowed certificate types */ 87 86 }; 88 87 -
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) 515 515 #endif 516 516 } 517 517 518 void519 tls_ctx_set_tls_groups(struct tls_root_ctx *ctx, const char *groups)520 {521 ASSERT(ctx);522 /* This method could be as easy as523 * SSL_CTX_set1_groups_list(ctx->ctx, groups)524 * but OpenSSL does not like the name secp256r1 for prime256v1525 * and as this is one of the more important curve to have526 * the same name for OpenSSL and mbedTLS, we do this dance527 */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 else554 {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 571 518 void 572 519 tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) 573 520 { … … tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name 687 634 /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter 688 635 * loading */ 689 636 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 #endif694 637 return; 638 #endif 695 639 #else 696 640 /* For older OpenSSL we have to extract the curve from key on our own */ 697 641 EC_KEY *eckey = NULL; … … show_available_curves(void) 1980 1924 ALLOC_ARRAY(curves, EC_builtin_curve, crv_len); 1981 1925 if (EC_get_builtin_curves(curves, crv_len)) 1982 1926 { 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"); 1986 1928 for (n = 0; n < crv_len; n++) 1987 1929 { 1988 1930 const char *sname;