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