You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
10 KiB
241 lines
10 KiB
diff -up openssl-1.0.1e/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod.logjam openssl-1.0.1e/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod |
|
--- openssl-1.0.1e/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod.logjam 2013-02-11 16:02:48.000000000 +0100 |
|
+++ openssl-1.0.1e/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod 2015-05-25 11:37:08.893049771 +0200 |
|
@@ -12,12 +12,10 @@ SSL_CTX_set_tmp_dh_callback, SSL_CTX_set |
|
DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); |
|
long SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh); |
|
|
|
- void SSL_set_tmp_dh_callback(SSL_CTX *ctx, |
|
+ void SSL_set_tmp_dh_callback(SSL *ctx, |
|
DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); |
|
long SSL_set_tmp_dh(SSL *ssl, DH *dh) |
|
|
|
- DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); |
|
- |
|
=head1 DESCRIPTION |
|
|
|
SSL_CTX_set_tmp_dh_callback() sets the callback function for B<ctx> to be |
|
@@ -50,24 +48,25 @@ even if he gets hold of the normal (cert |
|
only used for signing. |
|
|
|
In order to perform a DH key exchange the server must use a DH group |
|
-(DH parameters) and generate a DH key. The server will always generate a new |
|
-DH key during the negotiation, when the DH parameters are supplied via |
|
-callback and/or when the SSL_OP_SINGLE_DH_USE option of |
|
-L<SSL_CTX_set_options(3)|SSL_CTX_set_options(3)> is set. It will |
|
-immediately create a DH key, when DH parameters are supplied via |
|
-SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set. In this case, |
|
+(DH parameters) and generate a DH key. |
|
+The server will always generate a new DH key during the negotiation |
|
+if either the DH parameters are supplied via callback or the |
|
+SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set (or both). |
|
+It will immediately create a DH key if DH parameters are supplied via |
|
+SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set. |
|
+In this case, |
|
it may happen that a key is generated on initialization without later |
|
being needed, while on the other hand the computer time during the |
|
negotiation is being saved. |
|
|
|
If "strong" primes were used to generate the DH parameters, it is not strictly |
|
necessary to generate a new key for each handshake but it does improve forward |
|
-secrecy. If it is not assured, that "strong" primes were used (see especially |
|
-the section about DSA parameters below), SSL_OP_SINGLE_DH_USE must be used |
|
-in order to prevent small subgroup attacks. Always using SSL_OP_SINGLE_DH_USE |
|
-has an impact on the computer time needed during negotiation, but it is not |
|
-very large, so application authors/users should consider to always enable |
|
-this option. |
|
+secrecy. If it is not assured that "strong" primes were used, |
|
+SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup |
|
+attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the |
|
+computer time needed during negotiation, but it is not very large, so |
|
+application authors/users should consider always enabling this option. |
|
+The option is required to implement perfect forward secrecy (PFS). |
|
|
|
As generating DH parameters is extremely time consuming, an application |
|
should not generate the parameters on the fly but supply the parameters. |
|
@@ -75,82 +74,62 @@ DH parameters can be reused, as the actu |
|
the negotiation. The risk in reusing DH parameters is that an attacker |
|
may specialize on a very often used DH group. Applications should therefore |
|
generate their own DH parameters during the installation process using the |
|
-openssl L<dhparam(1)|dhparam(1)> application. In order to reduce the computer |
|
-time needed for this generation, it is possible to use DSA parameters |
|
-instead (see L<dhparam(1)|dhparam(1)>), but in this case SSL_OP_SINGLE_DH_USE |
|
-is mandatory. |
|
+openssl L<dhparam(1)|dhparam(1)> application. This application |
|
+guarantees that "strong" primes are used. |
|
|
|
-Application authors may compile in DH parameters. Files dh512.pem, |
|
-dh1024.pem, dh2048.pem, and dh4096 in the 'apps' directory of current |
|
+Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current |
|
version of the OpenSSL distribution contain the 'SKIP' DH parameters, |
|
which use safe primes and were generated verifiably pseudo-randomly. |
|
These files can be converted into C code using the B<-C> option of the |
|
-L<dhparam(1)|dhparam(1)> application. |
|
-Authors may also generate their own set of parameters using |
|
-L<dhparam(1)|dhparam(1)>, but a user may not be sure how the parameters were |
|
-generated. The generation of DH parameters during installation is therefore |
|
-recommended. |
|
+L<dhparam(1)|dhparam(1)> application. Generation of custom DH |
|
+parameters during installation should still be preferred to stop an |
|
+attacker from specializing on a commonly used group. Files dh1024.pem |
|
+and dh512.pem contain old parameters that must not be used by |
|
+applications. |
|
|
|
An application may either directly specify the DH parameters or |
|
-can supply the DH parameters via a callback function. The callback approach |
|
-has the advantage, that the callback may supply DH parameters for different |
|
-key lengths. |
|
- |
|
-The B<tmp_dh_callback> is called with the B<keylength> needed and |
|
-the B<is_export> information. The B<is_export> flag is set, when the |
|
-ephemeral DH key exchange is performed with an export cipher. |
|
+can supply the DH parameters via a callback function. |
|
+ |
|
+Previous versions of the callback used B<is_export> and B<keylength> |
|
+parameters to control parameter generation for export and non-export |
|
+cipher suites. Modern servers that do not support export ciphersuites |
|
+are advised to either use SSL_CTX_set_tmp_dh() in combination with |
|
+SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore |
|
+B<keylength> and B<is_export> and simply supply at least 2048-bit |
|
+parameters in the callback. |
|
|
|
=head1 EXAMPLES |
|
|
|
-Handle DH parameters for key lengths of 512 and 1024 bits. (Error handling |
|
+Setup DH parameters with a key length of 2048 bits. (Error handling |
|
partly left out.) |
|
|
|
- ... |
|
- /* Set up ephemeral DH stuff */ |
|
- DH *dh_512 = NULL; |
|
- DH *dh_1024 = NULL; |
|
- FILE *paramfile; |
|
+ Command-line parameter generation: |
|
+ $ openssl dhparam -out dh_param_2048.pem 2048 |
|
|
|
+ Code for setting up parameters during server initialization: |
|
+ |
|
+ ... |
|
+ SSL_CTX ctx = SSL_CTX_new(); |
|
... |
|
- /* "openssl dhparam -out dh_param_512.pem -2 512" */ |
|
- paramfile = fopen("dh_param_512.pem", "r"); |
|
+ |
|
+ /* Set up ephemeral DH parameters. */ |
|
+ DH *dh_2048 = NULL; |
|
+ FILE *paramfile; |
|
+ paramfile = fopen("dh_param_2048.pem", "r"); |
|
if (paramfile) { |
|
- dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); |
|
+ dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); |
|
fclose(paramfile); |
|
+ } else { |
|
+ /* Error. */ |
|
} |
|
- /* "openssl dhparam -out dh_param_1024.pem -2 1024" */ |
|
- paramfile = fopen("dh_param_1024.pem", "r"); |
|
- if (paramfile) { |
|
- dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); |
|
- fclose(paramfile); |
|
+ if (dh_2048 == NULL) { |
|
+ /* Error. */ |
|
} |
|
- ... |
|
- |
|
- /* "openssl dhparam -C -2 512" etc... */ |
|
- DH *get_dh512() { ... } |
|
- DH *get_dh1024() { ... } |
|
- |
|
- DH *tmp_dh_callback(SSL *s, int is_export, int keylength) |
|
- { |
|
- DH *dh_tmp=NULL; |
|
- |
|
- switch (keylength) { |
|
- case 512: |
|
- if (!dh_512) |
|
- dh_512 = get_dh512(); |
|
- dh_tmp = dh_512; |
|
- break; |
|
- case 1024: |
|
- if (!dh_1024) |
|
- dh_1024 = get_dh1024(); |
|
- dh_tmp = dh_1024; |
|
- break; |
|
- default: |
|
- /* Generating a key on the fly is very costly, so use what is there */ |
|
- setup_dh_parameters_like_above(); |
|
- } |
|
- return(dh_tmp); |
|
+ if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) { |
|
+ /* Error. */ |
|
} |
|
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); |
|
+ ... |
|
|
|
=head1 RETURN VALUES |
|
|
|
diff -up openssl-1.0.1e/ssl/ssl_err.c.logjam openssl-1.0.1e/ssl/ssl_err.c |
|
--- openssl-1.0.1e/ssl/ssl_err.c.logjam 2015-05-25 11:38:29.834858712 +0200 |
|
+++ openssl-1.0.1e/ssl/ssl_err.c 2015-05-25 11:42:01.041578905 +0200 |
|
@@ -361,6 +361,7 @@ static ERR_STRING_DATA SSL_str_reasons[] |
|
{ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG) ,"data length too long"}, |
|
{ERR_REASON(SSL_R_DECRYPTION_FAILED) ,"decryption failed"}, |
|
{ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"}, |
|
+{ERR_REASON(SSL_R_DH_KEY_TOO_SMALL) ,"dh key too small"}, |
|
{ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"}, |
|
{ERR_REASON(SSL_R_DIGEST_CHECK_FAILED) ,"digest check failed"}, |
|
{ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG) ,"dtls message too big"}, |
|
diff -up openssl-1.0.1e/ssl/ssl.h.logjam openssl-1.0.1e/ssl/ssl.h |
|
--- openssl-1.0.1e/ssl/ssl.h.logjam 2015-05-25 11:38:29.834858712 +0200 |
|
+++ openssl-1.0.1e/ssl/ssl.h 2015-05-25 11:40:42.482823220 +0200 |
|
@@ -2289,6 +2289,7 @@ void ERR_load_SSL_strings(void); |
|
#define SSL_R_DATA_LENGTH_TOO_LONG 146 |
|
#define SSL_R_DECRYPTION_FAILED 147 |
|
#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 |
|
+#define SSL_R_DH_KEY_TOO_SMALL 372 |
|
#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 |
|
#define SSL_R_DIGEST_CHECK_FAILED 149 |
|
#define SSL_R_DTLS_MESSAGE_TOO_BIG 334 |
|
diff -up openssl-1.0.1e/ssl/s3_clnt.c.logjam openssl-1.0.1e/ssl/s3_clnt.c |
|
--- openssl-1.0.1e/ssl/s3_clnt.c.logjam 2015-05-25 11:38:29.833858690 +0200 |
|
+++ openssl-1.0.1e/ssl/s3_clnt.c 2015-05-25 11:51:05.845754562 +0200 |
|
@@ -3277,24 +3277,34 @@ int ssl3_check_cert_and_algorithm(SSL *s |
|
} |
|
#endif |
|
#ifndef OPENSSL_NO_DH |
|
- if ((alg_k & SSL_kEDH) && |
|
- !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) |
|
+ if ((alg_k & SSL_kEDH) && dh == NULL) |
|
{ |
|
- SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); |
|
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR); |
|
goto f_err; |
|
} |
|
- else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) |
|
+ if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) |
|
{ |
|
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); |
|
goto f_err; |
|
} |
|
#ifndef OPENSSL_NO_DSA |
|
- else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) |
|
+ if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) |
|
{ |
|
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); |
|
goto f_err; |
|
} |
|
#endif |
|
+ /* Check DHE only: static DH not implemented. */ |
|
+ if (alg_k & SSL_kEDH) |
|
+ { |
|
+ int dh_size = BN_num_bits(dh->p); |
|
+ if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) |
|
+ || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) |
|
+ { |
|
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); |
|
+ goto f_err; |
|
+ } |
|
+ } |
|
#endif |
|
|
|
if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
|
|
|