From no-reply at appveyor.com Thu Feb 1 03:06:19 2018 From: no-reply at appveyor.com (AppVeyor) Date: Thu, 01 Feb 2018 03:06:19 +0000 Subject: [openssl-commits] Build failed: openssl master.15309 Message-ID: <20180201030619.1.2FC1019E484A7181@appveyor.com> An HTML attachment was scrubbed... URL: From levitte at openssl.org Thu Feb 1 06:12:47 2018 From: levitte at openssl.org (Richard Levitte) Date: Thu, 01 Feb 2018 06:12:47 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517465567.548516.18086.nullmailer@dev.openssl.org> The branch master has been updated via 4e525a0b4db2b11bee15a485b6ed6622ca8948f1 (commit) via 71bb86f0dc72c49d9efc098a71a6654004a2035a (commit) via 39556e63ef6c079d144b07d7f492152abf9efe77 (commit) from 3cb413da197c26c4520cbf08e5d4542637a90a4e (commit) - Log ----------------------------------------------------------------- commit 4e525a0b4db2b11bee15a485b6ed6622ca8948f1 Author: Richard Levitte Date: Wed Jan 31 22:08:12 2018 +0100 ocsp.c doesn't free the whole output chain, maybe causing a memory leak Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5224) commit 71bb86f0dc72c49d9efc098a71a6654004a2035a Author: Richard Levitte Date: Sun Jan 28 09:49:46 2018 +0100 Make sure that apps/openssl prefixes its output with '# ' during tests The reason to do this is that some output might start with an 'ok', which TAP catches and takes for TAP output. The TAP compatible way is to make all output it shouldn't catch look like comments. We do this by setting the environment variable HARNESS_OSSL_PREFIX during tests. When that is set, apps/openssl uses BIO_f_linebuffer and sets its prefix to the content of that environment variable. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5224) commit 39556e63ef6c079d144b07d7f492152abf9efe77 Author: Richard Levitte Date: Tue Jan 30 22:03:27 2018 +0100 Add an apps internal BIO filter for prefixing output lines Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5224) ----------------------------------------------------------------------- Summary of changes: apps/apps.c | 20 +++++- apps/apps.h | 16 ++++- apps/bf_prefix.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++ apps/build.info | 2 +- apps/ocsp.c | 2 +- apps/openssl.c | 1 + util/perl/OpenSSL/Test.pm | 4 +- 7 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 apps/bf_prefix.c diff --git a/apps/apps.c b/apps/apps.c index 834cedd..0438bdb 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -2428,14 +2428,26 @@ BIO *dup_bio_in(int format) BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); } +static BIO_METHOD *prefix_method = NULL; + BIO *dup_bio_out(int format) { BIO *b = BIO_new_fp(stdout, BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); + void *prefix = NULL; + #ifdef OPENSSL_SYS_VMS if (istext(format)) b = BIO_push(BIO_new(BIO_f_linebuffer()), b); #endif + + if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { + if (prefix_method == NULL) + prefix_method = apps_bf_prefix(); + b = BIO_push(BIO_new(prefix_method), b); + BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix); + } + return b; } @@ -2450,6 +2462,12 @@ BIO *dup_bio_err(int format) return b; } +void destroy_prefix_method() +{ + BIO_meth_free(prefix_method); + prefix_method = NULL; +} + void unbuffer(FILE *fp) { /* diff --git a/apps/apps.h b/apps/apps.h index a740ad4..daaef36 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -48,6 +48,20 @@ extern const unsigned char tls13_aes128gcmsha256_id[]; extern const unsigned char tls13_aes256gcmsha384_id[]; extern BIO_ADDR *ourpeer; +BIO_METHOD *apps_bf_prefix(void); +/* + * The control used to set the prefix with BIO_ctrl() + * We make it high enough so the chance of ever clashing with the BIO library + * remains unlikely for the foreseeable future and beyond. + */ +#define PREFIX_CTRL_SET_PREFIX (1 << 15) +/* + * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we + * need to destroy at some point. When created internally, it's stored + * in an internal pointer which can be freed with the following function + */ +void destroy_prefix_method(void); + BIO *dup_bio_in(int format); BIO *dup_bio_out(int format); BIO *dup_bio_err(int format); diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c new file mode 100644 index 0000000..4d5e3a3 --- /dev/null +++ b/apps/bf_prefix.c @@ -0,0 +1,176 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten); +static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); +static int prefix_puts(BIO *b, const char *str); +static int prefix_gets(BIO *b, char *str, int size); +static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); +static int prefix_create(BIO *b); +static int prefix_destroy(BIO *b); +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static BIO_METHOD *prefix_meth = NULL; + +BIO_METHOD *apps_bf_prefix(void) +{ + if (prefix_meth == NULL) { + if ((prefix_meth = + BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL + || !BIO_meth_set_create(prefix_meth, prefix_create) + || !BIO_meth_set_destroy(prefix_meth, prefix_destroy) + || !BIO_meth_set_write_ex(prefix_meth, prefix_write) + || !BIO_meth_set_read_ex(prefix_meth, prefix_read) + || !BIO_meth_set_puts(prefix_meth, prefix_puts) + || !BIO_meth_set_gets(prefix_meth, prefix_gets) + || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl) + || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) { + BIO_meth_free(prefix_meth); + prefix_meth = NULL; + } + } + return prefix_meth; +} + +typedef struct prefix_ctx_st { + char *prefix; + int linestart; /* flag to indicate we're at the line start */ +} PREFIX_CTX; + +static int prefix_create(BIO *b) +{ + PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + + ctx->prefix = NULL; + ctx->linestart = 1; + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + return 1; +} + +static int prefix_destroy(BIO *b) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + OPENSSL_free(ctx->prefix); + OPENSSL_free(ctx); + return 1; +} + +static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) +{ + return BIO_read_ex(BIO_next(b), in, size, numread); +} + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + return 0; + + /* If no prefix is set or if it's empty, we've got nothing to do here */ + if (ctx->prefix == NULL || *ctx->prefix == '\0') { + /* We do note if what comes next will be a new line, though */ + if (outl > 0) + ctx->linestart = (out[outl-1] == '\n'); + return BIO_write_ex(BIO_next(b), out, outl, numwritten); + } + + *numwritten = 0; + + while (*out != '\0') { + size_t i; + char c; + + /* If we know that we're at the start of the line, output the prefix */ + if (ctx->linestart) { + size_t dontcare; + + if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), + &dontcare)) + return 0; + ctx->linestart = 0; + } + + /* Now, go look for the next LF, or the end of the string */ + for (i = 0; (c = out[i]) != '\n' && c != '\0'; i++) + continue; + if (c == '\n') + i++; + + /* Output what we found so far */ + while (i > 0) { + size_t num = 0; + + if (!BIO_write_ex(BIO_next(b), out, i, &num)) + return 0; + out += num; + *numwritten += num; + i -= num; + } + + /* If we found a LF, what follows is a new line, so take note */ + if (c == '\n') + ctx->linestart = 1; + } + + return 1; +} + +static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 0; + + switch (cmd) { + case PREFIX_CTRL_SET_PREFIX: + { + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + break; + + OPENSSL_free(ctx->prefix); + ctx->prefix = OPENSSL_strdup((const char *)ptr); + ret = ctx->prefix != NULL; + } + break; + default: + if (BIO_next(b) != NULL) + ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); + break; + } + return ret; +} + +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + return BIO_callback_ctrl(BIO_next(b), cmd, fp); +} + +static int prefix_gets(BIO *b, char *buf, int size) +{ + return BIO_gets(BIO_next(b), buf, size); +} + +static int prefix_puts(BIO *b, const char *str) +{ + return BIO_write(b, str, strlen(str)); +} diff --git a/apps/build.info b/apps/build.info index 4a36ab5..e724373 100644 --- a/apps/build.info +++ b/apps/build.info @@ -8,7 +8,7 @@ s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c); our @apps_lib_src = - ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c), + ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c), split(/\s+/, $target{apps_aux_src}) ); our @apps_init_src = split(/\s+/, $target{apps_init_src}); "" -} diff --git a/apps/ocsp.c b/apps/ocsp.c index 122aee6..bd16a5b 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -730,7 +730,7 @@ redo_accept: free_index(rdb); BIO_free_all(cbio); BIO_free_all(acbio); - BIO_free(out); + BIO_free_all(out); OCSP_REQUEST_free(req); OCSP_RESPONSE_free(resp); OCSP_BASICRESP_free(bs); diff --git a/apps/openssl.c b/apps/openssl.c index fe1eabd..fffa05e 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -93,6 +93,7 @@ static int apps_startup() static void apps_shutdown() { destroy_ui_method(); + destroy_prefix_method(); } static char *make_config_name() diff --git a/util/perl/OpenSSL/Test.pm b/util/perl/OpenSSL/Test.pm index 4afbf85..e363a48 100644 --- a/util/perl/OpenSSL/Test.pm +++ b/util/perl/OpenSSL/Test.pm @@ -1,4 +1,4 @@ -# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -476,7 +476,9 @@ sub run { } close $pipe; } else { + $ENV{HARNESS_OSSL_PREFIX} = "# "; system("$prefix$cmd"); + delete $ENV{HARNESS_OSSL_PREFIX}; } $e = ($? & 0x7f) ? ($? & 0x7f)|0x80 : ($? >> 8); $r = $hooks{exit_checker}->($e); From builds at travis-ci.org Thu Feb 1 06:46:17 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 06:46:17 +0000 Subject: [openssl-commits] Broken: openssl/openssl#16019 (master - 4e525a0) In-Reply-To: Message-ID: <5a72b7b96a71c_43fc6302ba56c772945@9cde2705-86f2-43ab-a9e0-15a89b8526cf.mail> Build Update for openssl/openssl ------------------------------------- Build: #16019 Status: Broken Duration: 32 minutes and 42 seconds Commit: 4e525a0 (master) Author: Richard Levitte Message: ocsp.c doesn't free the whole output chain, maybe causing a memory leak Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5224) View the changeset: https://github.com/openssl/openssl/compare/3cb413da197c...4e525a0b4db2 View the full build log and details: https://travis-ci.org/openssl/openssl/builds/335965776?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From osslsanity at gmail.com Thu Feb 1 09:19:45 2018 From: osslsanity at gmail.com (osslsanity at gmail.com) Date: Thu, 1 Feb 2018 09:19:45 +0000 (UTC) Subject: [openssl-commits] Jenkins build is back to normal : master_mips #365 In-Reply-To: <124278280.317.1517390295998.JavaMail.jenkins@ip-172-31-34-99> References: <124278280.317.1517390295998.JavaMail.jenkins@ip-172-31-34-99> Message-ID: <581252309.319.1517476785348.JavaMail.jenkins@ip-172-31-34-99> See From osslsanity at gmail.com Thu Feb 1 09:23:45 2018 From: osslsanity at gmail.com (osslsanity at gmail.com) Date: Thu, 1 Feb 2018 09:23:45 +0000 (UTC) Subject: [openssl-commits] Jenkins build is back to normal : master_mips_noasm #365 In-Reply-To: <212967360.318.1517390488998.JavaMail.jenkins@ip-172-31-34-99> References: <212967360.318.1517390488998.JavaMail.jenkins@ip-172-31-34-99> Message-ID: <1379815588.320.1517477025737.JavaMail.jenkins@ip-172-31-34-99> See From matt at openssl.org Thu Feb 1 10:43:58 2018 From: matt at openssl.org (Matt Caswell) Date: Thu, 01 Feb 2018 10:43:58 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517481838.084825.18118.nullmailer@dev.openssl.org> The branch master has been updated via 848a950b715fa73070a9d1638e7630acfb0dfa4d (commit) from 4e525a0b4db2b11bee15a485b6ed6622ca8948f1 (commit) - Log ----------------------------------------------------------------- commit 848a950b715fa73070a9d1638e7630acfb0dfa4d Author: Matt Caswell Date: Wed Jan 31 09:53:51 2018 +0000 Fix some instances of the wrong alert type being sent In a few places we sent an internal_error alert instead of a decode_error. Fixes #5213 Fixes #5214 Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5219) ----------------------------------------------------------------------- Summary of changes: ssl/statem/extensions_clnt.c | 9 +++++++-- ssl/statem/statem_clnt.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index dbb8812..5441e98 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -1273,7 +1273,7 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - unsigned int ecpointformats_len; + size_t ecpointformats_len; PACKET ecptformatlist; if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { @@ -1283,8 +1283,13 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, } if (!s->hit) { ecpointformats_len = PACKET_remaining(&ecptformatlist); - s->session->ext.ecpointformats_len = 0; + if (ecpointformats_len == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH); + return 0; + } + s->session->ext.ecpointformats_len = 0; OPENSSL_free(s->session->ext.ecpointformats); s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len); if (s->session->ext.ecpointformats == NULL) { diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 8a33386..e79bd7b 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2452,7 +2452,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) PACKET sigalgs; if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); return MSG_PROCESS_ERROR; @@ -2484,7 +2484,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) } if (PACKET_remaining(pkt) != 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); return MSG_PROCESS_ERROR; From builds at travis-ci.org Thu Feb 1 11:19:25 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 11:19:25 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16021 (master - 848a950) In-Reply-To: Message-ID: <5a72f7bd92296_43f99fdf20f7c88176d@6f1e7807-ba31-4302-beba-07cf17cd0e30.mail> Build Update for openssl/openssl ------------------------------------- Build: #16021 Status: Still Failing Duration: 34 minutes and 36 seconds Commit: 848a950 (master) Author: Matt Caswell Message: Fix some instances of the wrong alert type being sent In a few places we sent an internal_error alert instead of a decode_error. Fixes #5213 Fixes #5214 Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5219) View the changeset: https://github.com/openssl/openssl/compare/4e525a0b4db2...848a950b715f View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336041110?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Thu Feb 1 16:39:35 2018 From: no-reply at appveyor.com (AppVeyor) Date: Thu, 01 Feb 2018 16:39:35 +0000 Subject: [openssl-commits] Build failed: openssl master.15316 Message-ID: <20180201163935.1.D594E03B6E8DA49F@appveyor.com> An HTML attachment was scrubbed... URL: From matt at openssl.org Thu Feb 1 17:19:33 2018 From: matt at openssl.org (Matt Caswell) Date: Thu, 01 Feb 2018 17:19:33 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517505573.209120.19402.nullmailer@dev.openssl.org> The branch master has been updated via e43e6b1951de931ca500c6964496e76651332f5e (commit) via 658e4879c50dff23c040c681656843a50002e403 (commit) via 88834998dda00a713abe3a17d6caebba2f70318d (commit) via 9d75dce3e1f94be6006500089491cb3284f70d06 (commit) via 633a8829ffc01952aed1f5040d481a5eeef1670c (commit) from 848a950b715fa73070a9d1638e7630acfb0dfa4d (commit) - Log ----------------------------------------------------------------- commit e43e6b1951de931ca500c6964496e76651332f5e Author: Todd Short Date: Wed Jan 31 16:36:27 2018 -0500 Fix some minor code nits Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) commit 658e4879c50dff23c040c681656843a50002e403 Author: Todd Short Date: Wed Jan 31 16:34:20 2018 -0500 Fix doc nits Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) commit 88834998dda00a713abe3a17d6caebba2f70318d Author: Todd Short Date: Wed Jan 31 16:20:52 2018 -0500 Free pha_dgst in SSL_clear() Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) commit 9d75dce3e1f94be6006500089491cb3284f70d06 Author: Todd Short Date: Mon Dec 18 16:52:28 2017 -0500 Add TLSv1.3 post-handshake authentication (PHA) Add SSL_verify_client_post_handshake() for servers to initiate PHA Add SSL_force_post_handshake_auth() for clients that don't have certificates initially configured, but use a certificate callback. Update SSL_CTX_set_verify()/SSL_set_verify() mode: * Add SSL_VERIFY_POST_HANDSHAKE to postpone client authentication until after the initial handshake. * Update SSL_VERIFY_CLIENT_ONCE now only sends out one CertRequest regardless of when the certificate authentication takes place; either initial handshake, re-negotiation, or post-handshake authentication. Add 'RequestPostHandshake' and 'RequirePostHandshake' SSL_CONF options that add the SSL_VERIFY_POST_HANDSHAKE to the 'Request' and 'Require' options Add support to s_client: * Enabled automatically when cert is configured * Can be forced enabled via -force_pha Add support to s_server: * Use 'c' to invoke PHA in s_server * Remove some dead code Update documentation Update unit tests: * Illegal use of PHA extension * TLSv1.3 certificate tests DTLS and TLS behave ever-so-slightly differently. So, when DTLS1.3 is implemented, it's PHA support state machine may need to be different. Add a TODO and a #error Update handshake context to deal with PHA. The handshake context for TLSv1.3 post-handshake auth is up through the ClientFinish message, plus the CertificateRequest message. Subsequent Certificate, CertificateVerify, and Finish messages are based on this handshake context (not the Certificate message per se, but it's included after the hash). KeyUpdate, NewSessionTicket, and prior Certificate Request messages are not included in post-handshake authentication. After the ClientFinished message is processed, save off the digest state for future post-handshake authentication. When post-handshake auth occurs, copy over the saved handshake context into the "main" handshake digest. This effectively discards the any KeyUpdate or NewSessionTicket messages and any prior post-handshake authentication. This, of course, assumes that the ID-22 did not mean to include any previous post-handshake authentication into the new handshake transcript. This is implied by section 4.4.1 that lists messages only up to the first ClientFinished. Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) commit 633a8829ffc01952aed1f5040d481a5eeef1670c Author: Todd Short Date: Fri Jan 19 10:43:19 2018 -0500 Remove bad comments Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) ----------------------------------------------------------------------- Summary of changes: apps/s_cb.c | 1 + apps/s_client.c | 9 + apps/s_server.c | 24 +- crypto/err/openssl.txt | 17 +- doc/man1/s_client.pod | 6 + doc/man3/SSL_CONF_cmd.pod | 12 + doc/man3/SSL_CTX_set_verify.pod | 67 +++- include/openssl/ssl.h | 5 +- include/openssl/sslerr.h | 12 + include/openssl/tls1.h | 1 + ssl/ssl_conf.c | 7 +- ssl/ssl_err.c | 19 ++ ssl/ssl_lib.c | 57 ++++ ssl/ssl_locl.h | 22 ++ ssl/statem/extensions.c | 16 + ssl/statem/extensions_clnt.c | 42 +++ ssl/statem/extensions_cust.c | 1 + ssl/statem/extensions_srvr.c | 14 + ssl/statem/statem_clnt.c | 78 ++++- ssl/statem/statem_lib.c | 111 +++++-- ssl/statem/statem_locl.h | 10 +- ssl/statem/statem_srvr.c | 121 ++++++- ssl/t1_trce.c | 3 +- test/build.info | 2 +- test/handshake_helper.c | 60 +++- test/recipes/70-test_tls13messages.t | 7 +- test/recipes/80-test_ssl_new.t | 3 +- test/ssl-tests/26-tls13_client_auth.conf | 476 ++++++++++++++++++++++++++++ test/ssl-tests/26-tls13_client_auth.conf.in | 293 +++++++++++++++++ test/ssl_test_ctx.c | 8 + test/ssl_test_ctx.h | 7 +- test/sslapitest.c | 60 ++++ util/libssl.num | 2 + util/perl/TLSProxy/Message.pm | 1 + util/perl/checkhandshake.pm | 3 +- 35 files changed, 1489 insertions(+), 88 deletions(-) create mode 100644 test/ssl-tests/26-tls13_client_auth.conf create mode 100644 test/ssl-tests/26-tls13_client_auth.conf.in diff --git a/apps/s_cb.c b/apps/s_cb.c index 575fb04..8d51d74 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -666,6 +666,7 @@ static STRINT_PAIR tlsext_types[] = { {"psk", TLSEXT_TYPE_psk}, {"psk kex modes", TLSEXT_TYPE_psk_kex_modes}, {"certificate authorities", TLSEXT_TYPE_certificate_authorities}, + {"post handshake auth", TLSEXT_TYPE_post_handshake_auth}, {NULL} }; diff --git a/apps/s_client.c b/apps/s_client.c index 774345e..ca2bd0d 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -602,6 +602,7 @@ typedef enum OPTION_choice { OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, + OPT_FORCE_PHA, OPT_R_ENUM } OPTION_CHOICE; @@ -788,6 +789,7 @@ const OPTIONS s_client_options[] = { #endif {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, + {"force_pha", OPT_FORCE_PHA, '-', "Force-enable post-handshake-authentication"}, {NULL, OPT_EOF, 0x00, NULL} }; @@ -958,6 +960,7 @@ int s_client_main(int argc, char **argv) int isdtls = 0; #endif char *psksessf = NULL; + int force_pha = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -1469,6 +1472,9 @@ int s_client_main(int argc, char **argv) case OPT_EARLY_DATA: early_data_file = opt_arg(); break; + case OPT_FORCE_PHA: + force_pha = 1; + break; } } if (count4or6 >= 2) { @@ -1904,6 +1910,9 @@ int s_client_main(int argc, char **argv) if (con == NULL) goto end; + if (force_pha) + SSL_force_post_handshake_auth(con); + if (sess_in != NULL) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); diff --git a/apps/s_server.c b/apps/s_server.c index f124b12..a0e72b3 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -2480,9 +2480,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) printf("SSL_do_handshake -> %d\n", i); i = 0; /* 13; */ continue; - /* - * strcpy(buf,"server side RE-NEGOTIATE\n"); - */ } if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) { SSL_set_verify(con, @@ -2493,10 +2490,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) printf("SSL_do_handshake -> %d\n", i); i = 0; /* 13; */ continue; - /* - * strcpy(buf,"server side RE-NEGOTIATE asking for client - * cert\n"); - */ } if ((buf[0] == 'K' || buf[0] == 'k') && ((buf[1] == '\n') || (buf[1] == '\r'))) { @@ -2507,10 +2500,19 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) printf("SSL_do_handshake -> %d\n", i); i = 0; continue; - /* - * strcpy(buf,"server side RE-NEGOTIATE asking for client - * cert\n"); - */ + } + if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_set_verify(con, SSL_VERIFY_PEER, NULL); + i = SSL_verify_client_post_handshake(con); + if (i == 0) { + printf("Failed to initiate request\n"); + ERR_print_errors(bio_err); + } else { + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + } + continue; } if (buf[0] == 'P') { static const char *str = "Lets print some clear text\n"; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index ed706da..fb3be57 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1192,6 +1192,7 @@ SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1:205:SSL_use_RSAPrivateKey_ASN1 SSL_F_SSL_USE_RSAPRIVATEKEY_FILE:206:SSL_use_RSAPrivateKey_file SSL_F_SSL_VALIDATE_CT:400:ssl_validate_ct SSL_F_SSL_VERIFY_CERT_CHAIN:207:ssl_verify_cert_chain +SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE:616:SSL_verify_client_post_handshake SSL_F_SSL_WRITE:208:SSL_write SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data SSL_F_SSL_WRITE_EARLY_FINISH:527:* @@ -1205,6 +1206,10 @@ SSL_F_TLS13_ENC:609:tls13_enc SSL_F_TLS13_FINAL_FINISH_MAC:605:tls13_final_finish_mac SSL_F_TLS13_GENERATE_SECRET:591:tls13_generate_secret SSL_F_TLS13_HKDF_EXPAND:561:tls13_hkdf_expand +SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA:617:\ + tls13_restore_handshake_digest_for_pha +SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA:618:\ + tls13_save_handshake_digest_for_pha SSL_F_TLS13_SETUP_KEY_BLOCK:441:tls13_setup_key_block SSL_F_TLS1_CHANGE_CIPHER_STATE:209:tls1_change_cipher_state SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS:341:* @@ -1247,6 +1252,8 @@ SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN:549:tls_construct_ctos_maxfragmentlen SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding +SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH:619:\ + tls_construct_ctos_post_handshake_auth SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate @@ -1315,6 +1322,7 @@ SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats SSL_F_TLS_PARSE_CTOS_EMS:570:tls_parse_ctos_ems SSL_F_TLS_PARSE_CTOS_KEY_SHARE:463:tls_parse_ctos_key_share SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen +SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH:620:tls_parse_ctos_post_handshake_auth SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate @@ -2446,6 +2454,7 @@ SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:151:error in received cipher list SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN:204:error setting tlsa base domain SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE:194:exceeds max fragment size SSL_R_EXCESSIVE_MESSAGE_SIZE:152:excessive message size +SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async @@ -2466,7 +2475,9 @@ SSL_R_INVALID_CCS_MESSAGE:260:invalid ccs message SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg SSL_R_INVALID_COMMAND:280:invalid command SSL_R_INVALID_COMPRESSION_ALGORITHM:341:invalid compression algorithm +SSL_R_INVALID_CONFIG:283:invalid config SSL_R_INVALID_CONFIGURATION_NAME:113:invalid configuration name +SSL_R_INVALID_CONTEXT:282:invalid context SSL_R_INVALID_CT_VALIDATION_TYPE:212:invalid ct validation type SSL_R_INVALID_KEY_UPDATE_TYPE:120:invalid key update type SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data @@ -2495,6 +2506,7 @@ SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION:209:missing supported groups extension SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary +SSL_R_NOT_SERVER:284:not server SSL_R_NO_APPLICATION_PROTOCOL:235:no application protocol SSL_R_NO_CERTIFICATES_RETURNED:176:no certificates returned SSL_R_NO_CERTIFICATE_ASSIGNED:177:no certificate assigned @@ -2534,6 +2546,7 @@ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:199:peer did not return a certificate SSL_R_PEM_NAME_BAD_PREFIX:391:pem name bad prefix SSL_R_PEM_NAME_TOO_SHORT:392:pem name too short SSL_R_PIPELINE_FAILURE:406:pipeline failure +SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR:278:post handshake auth encoding err SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown SSL_R_PSK_IDENTITY_NOT_FOUND:223:psk identity not found SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb @@ -2545,6 +2558,8 @@ SSL_R_RECORD_TOO_SMALL:298:record too small SSL_R_RENEGOTIATE_EXT_TOO_LONG:335:renegotiate ext too long SSL_R_RENEGOTIATION_ENCODING_ERR:336:renegotiation encoding err SSL_R_RENEGOTIATION_MISMATCH:337:renegotiation mismatch +SSL_R_REQUEST_PENDING:285:request pending +SSL_R_REQUEST_SENT:286:request sent SSL_R_REQUIRED_CIPHER_MISSING:215:required cipher missing SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING:342:\ required compression algorithm missing diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod index 1d9dd39..4f0f01c 100644 --- a/doc/man1/s_client.pod +++ b/doc/man1/s_client.pod @@ -118,6 +118,7 @@ B B [B<-ctlogfile>] [B<-keylogfile file>] [B<-early_data file>] +[B<-force_pha>] [B] =head1 DESCRIPTION @@ -621,6 +622,11 @@ Reads the contents of the specified file and attempts to send it as early data to the server. This will only work with resumed sessions that support early data and when the server accepts the early data. +=item B<-force_pha> + +For TLSv1.3 only, always send the Post-Handshake Authentication extension, +whether or not a certificate has been provided via B<-cert>. + =item B<[target]> Rather than providing B<-connect>, the target hostname and optional port may diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod index 06b98bd..27317e0 100644 --- a/doc/man3/SSL_CONF_cmd.pod +++ b/doc/man3/SSL_CONF_cmd.pod @@ -435,6 +435,18 @@ occurs if the client does not present a certificate. Servers only. B requests a certificate from a client only on the initial connection: not when renegotiating. Servers only. +B configures the connection to support requests but does +not require a certificate from the client post-handshake. A certificate will +not be requested during the initial handshake. The server application must +provide a mechanism to request a certificate post-handshake. Servers only. +TLSv1.3 only. + +B configures the connection to support requests and +requires a certificate from the client post-handshake: an error occurs if the +client does not present a certificate. A certificate will not be requested +during the initial handshake. The server application must provide a mechanism +to request a certificate post-handshake. Servers only. TLSv1.3 only. + =item B, B A file or directory of certificates in PEM format whose names are used as the diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 9e634dd..89760f4 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -5,7 +5,9 @@ SSL_get_ex_data_X509_STORE_CTX_idx, SSL_CTX_set_verify, SSL_set_verify, SSL_CTX_set_verify_depth, SSL_set_verify_depth, -SSL_verify_cb +SSL_verify_cb, +SSL_verify_client_post_handshake, +SSL_force_post_handshake_auth - set peer certificate verification parameters =head1 SYNOPSIS @@ -15,11 +17,14 @@ SSL_verify_cb typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback); - void SSL_set_verify(SSL *s, int mode, SSL_verify_cb verify_callback); + void SSL_set_verify(SSL *ssl, int mode, SSL_verify_cb verify_callback); SSL_get_ex_data_X509_STORE_CTX_idx(void); void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); - void SSL_set_verify_depth(SSL *s, int depth); + void SSL_set_verify_depth(SSL *ssl, int depth); + + int SSL_verify_client_post_handshake(SSL *ssl); + void SSL_force_post_handshake_auth(SSL *ssl); =head1 DESCRIPTION @@ -43,6 +48,16 @@ verification that shall be allowed for B. SSL_set_verify_depth() sets the maximum B for the certificate chain verification that shall be allowed for B. +SSL_force_post_handshake_auth() forces the Post-Handshake Authentication +extension to be added to the ClientHello regardless of certificate configuration +at the time of the initial handshake, such that post-handshake authentication +can be requested by the server. A certificate callback will need to be set via +SSL_CTX_set_client_cert_cb() if no certificate is provided at initialization. + +SSL_verify_client_post_handshake() causes a CertificateRequest message to be +sent by a server on the given B connection. The SSL_VERIFY_PEER flag must +be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional. + =head1 NOTES The verification of certificates can be controlled by a set of logically @@ -69,7 +84,8 @@ fails, the TLS/SSL handshake is immediately terminated with an alert message containing the reason for the verification failure. The behaviour can be controlled by the additional -SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE flags. +SSL_VERIFY_FAIL_IF_NO_PEER_CERT, SSL_VERIFY_CLIENT_ONCE and +SSL_VERIFY_POST_HANDSHAKE flags. B the server certificate is verified. If the verification process fails, the TLS/SSL handshake is @@ -87,9 +103,22 @@ B ignored =item SSL_VERIFY_CLIENT_ONCE -B only request a client certificate on the initial TLS/SSL -handshake. Do not ask for a client certificate again in case of a -renegotiation. This flag must be used together with SSL_VERIFY_PEER. +B only request a client certificate once during the +connection. Do not ask for a client certificate again during +renegotiation or post-authentication if a certificate was requested +during the initial handshake. This flag must be used together with +SSL_VERIFY_PEER. + +B ignored + +=item SSL_VERIFY_POST_HANDSHAKE + +B the server will not send a client certificate request +during the initial handshake, but will send the request via +SSL_verify_client_post_handshake(). This allows the SSL_CTX or SSL +to be configured for post-handshake peer verification before the +handshake occurs. This flag must be used together with +SSL_VERIFY_PEER. TLSv1.3 only; no effect on pre-TLSv1.3 connections. B ignored @@ -154,6 +183,20 @@ Its return value is identical to B, so that any verification failure will lead to a termination of the TLS/SSL handshake with an alert message, if SSL_VERIFY_PEER is set. +After calling SSL_force_post_handshake_auth(), the client will need to add a +certificate or certificate callback to its configuration before it can +successfully authenticate. This must be called before SSL_connect(). + +SSL_verify_client_post_handshake() requires that verify flags have been +previously set, and that a client sent the post-handshake authentication +extension. When the client returns a certificate the verify callback will be +invoked. A write operation must take place for the Certificate Request to be +sent to the client, this can be done with SSL_do_handshake() or SSL_write_ex(). +Only one certificate request may be outstanding at any time. + +When post-handshake authentication occurs, a refreshed NewSessionTicket +message is sent to the client. + =head1 BUGS In client mode, it is not checked whether the SSL_VERIFY_PEER flag @@ -165,6 +208,10 @@ required. The SSL*_set_verify*() functions do not provide diagnostic information. +The SSL_verify_client_post_handshake() function returns 1 if the request +succeeded, and 0 if the request failed. The error stack can be examined +to determine the failure reason. + =head1 EXAMPLES The following code sequence realizes an example B function @@ -288,8 +335,14 @@ L, L, L, L, +L, L +=head1 HISTORY + +The SSL_VERIFY_POST_HANDSHAKE option, and the SSL_verify_client_post_handshake() +and SSL_force_post_handshake_auth() functions were added in OpenSSL 1.1.1. + =head1 COPYRIGHT Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 97d2e46..9c45b90 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1052,13 +1052,14 @@ size_t SSL_get_finished(const SSL *s, void *buf, size_t count); size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); /* - * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options are + * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are * 'ored' with SSL_VERIFY_PEER if they are desired */ # define SSL_VERIFY_NONE 0x00 # define SSL_VERIFY_PEER 0x01 # define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 # define SSL_VERIFY_CLIENT_ONCE 0x04 +# define SSL_VERIFY_POST_HANDSHAKE 0x08 # define OpenSSL_add_ssl_algorithms() SSL_library_init() # if OPENSSL_API_COMPAT < 0x10100000L @@ -1850,6 +1851,8 @@ int SSL_renegotiate(SSL *s); int SSL_renegotiate_abbreviated(SSL *s); __owur int SSL_renegotiate_pending(SSL *s); int SSL_shutdown(SSL *s); +__owur int SSL_verify_client_post_handshake(SSL *s); +void SSL_force_post_handshake_auth(SSL *s); __owur const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx); __owur const SSL_METHOD *SSL_get_ssl_method(SSL *s); diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index ec81ba3..a84a62d 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -241,6 +241,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 # define SSL_F_SSL_VALIDATE_CT 400 # define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +# define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 616 # define SSL_F_SSL_WRITE 208 # define SSL_F_SSL_WRITE_EARLY_DATA 526 # define SSL_F_SSL_WRITE_EARLY_FINISH 527 @@ -254,6 +255,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS13_FINAL_FINISH_MAC 605 # define SSL_F_TLS13_GENERATE_SECRET 591 # define SSL_F_TLS13_HKDF_EXPAND 561 +# define SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA 617 +# define SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA 618 # define SSL_F_TLS13_SETUP_KEY_BLOCK 441 # define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 # define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS 341 @@ -295,6 +298,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 549 # define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471 # define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472 +# define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 619 # define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501 # define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509 # define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473 @@ -358,6 +362,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PARSE_CTOS_EMS 570 # define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 463 # define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN 571 +# define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 620 # define SSL_F_TLS_PARSE_CTOS_PSK 505 # define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464 @@ -522,6 +527,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN 204 # define SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE 194 # define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +# define SSL_R_EXTENSION_NOT_RECEIVED 279 # define SSL_R_EXTRA_DATA_IN_MESSAGE 153 # define SSL_R_EXT_LENGTH_MISMATCH 163 # define SSL_R_FAILED_TO_INIT_ASYNC 405 @@ -542,7 +548,9 @@ int ERR_load_SSL_strings(void); # define SSL_R_INVALID_CERTIFICATE_OR_ALG 238 # define SSL_R_INVALID_COMMAND 280 # define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +# define SSL_R_INVALID_CONFIG 283 # define SSL_R_INVALID_CONFIGURATION_NAME 113 +# define SSL_R_INVALID_CONTEXT 282 # define SSL_R_INVALID_CT_VALIDATION_TYPE 212 # define SSL_R_INVALID_KEY_UPDATE_TYPE 120 # define SSL_R_INVALID_MAX_EARLY_DATA 174 @@ -571,6 +579,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_MISSING_TMP_DH_KEY 171 # define SSL_R_MISSING_TMP_ECDH_KEY 311 # define SSL_R_NOT_ON_RECORD_BOUNDARY 182 +# define SSL_R_NOT_SERVER 284 # define SSL_R_NO_APPLICATION_PROTOCOL 235 # define SSL_R_NO_CERTIFICATES_RETURNED 176 # define SSL_R_NO_CERTIFICATE_ASSIGNED 177 @@ -608,6 +617,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_PEM_NAME_BAD_PREFIX 391 # define SSL_R_PEM_NAME_TOO_SHORT 392 # define SSL_R_PIPELINE_FAILURE 406 +# define SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR 278 # define SSL_R_PROTOCOL_IS_SHUTDOWN 207 # define SSL_R_PSK_IDENTITY_NOT_FOUND 223 # define SSL_R_PSK_NO_CLIENT_CB 224 @@ -619,6 +629,8 @@ int ERR_load_SSL_strings(void); # define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335 # define SSL_R_RENEGOTIATION_ENCODING_ERR 336 # define SSL_R_RENEGOTIATION_MISMATCH 337 +# define SSL_R_REQUEST_PENDING 285 +# define SSL_R_REQUEST_SENT 286 # define SSL_R_REQUIRED_CIPHER_MISSING 215 # define SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING 342 # define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 345 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 434e327..1253352 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -146,6 +146,7 @@ extern "C" { # define TLSEXT_TYPE_cookie 44 # define TLSEXT_TYPE_psk_kex_modes 45 # define TLSEXT_TYPE_certificate_authorities 47 +# define TLSEXT_TYPE_post_handshake_auth 49 # define TLSEXT_TYPE_signature_algorithms_cert 50 # define TLSEXT_TYPE_key_share 51 diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 0cd8ace..cb4ff8d 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -386,7 +386,12 @@ static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value) SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER), SSL_FLAG_VFY_SRV("Require", SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), - SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE) + SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), + SSL_FLAG_VFY_SRV("RequestPostHandshake", + SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE), + SSL_FLAG_VFY_SRV("RequirePostHandshake", + SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT), }; if (value == NULL) return -3; diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 746678c..f0bde60 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -351,6 +351,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VALIDATE_CT, 0), "ssl_validate_ct"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CERT_CHAIN, 0), "ssl_verify_cert_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, 0), + "SSL_verify_client_post_handshake"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE, 0), "SSL_write"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_DATA, 0), "SSL_write_early_data"}, @@ -369,6 +371,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_GENERATE_SECRET, 0), "tls13_generate_secret"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_HKDF_EXPAND, 0), "tls13_hkdf_expand"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, 0), + "tls13_restore_handshake_digest_for_pha"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, 0), + "tls13_save_handshake_digest_for_pha"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SETUP_KEY_BLOCK, 0), "tls13_setup_key_block"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHANGE_CIPHER_STATE, 0), @@ -441,6 +447,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_ctos_npn"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, 0), "tls_construct_ctos_padding"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH, 0), + "tls_construct_ctos_post_handshake_auth"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK, 0), "tls_construct_ctos_psk"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, 0), @@ -557,6 +565,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_ctos_key_share"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, 0), "tls_parse_ctos_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH, 0), + "tls_parse_ctos_post_handshake_auth"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK, 0), "tls_parse_ctos_psk"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, 0), "tls_parse_ctos_psk_kex_modes"}, @@ -832,6 +842,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "exceeds max fragment size"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXCESSIVE_MESSAGE_SIZE), "excessive message size"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXTENSION_NOT_RECEIVED), + "extension not received"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXTRA_DATA_IN_MESSAGE), "extra data in message"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXT_LENGTH_MISMATCH), @@ -868,8 +880,10 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "invalid command"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMPRESSION_ALGORITHM), "invalid compression algorithm"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONFIG), "invalid config"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONFIGURATION_NAME), "invalid configuration name"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONTEXT), "invalid context"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CT_VALIDATION_TYPE), "invalid ct validation type"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_KEY_UPDATE_TYPE), @@ -919,6 +933,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "missing tmp ecdh key"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY), "not on record boundary"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_SERVER), "not server"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_APPLICATION_PROTOCOL), "no application protocol"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATES_RETURNED), @@ -978,6 +993,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "pem name bad prefix"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEM_NAME_TOO_SHORT), "pem name too short"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PIPELINE_FAILURE), "pipeline failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR), + "post handshake auth encoding err"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PROTOCOL_IS_SHUTDOWN), "protocol is shutdown"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_IDENTITY_NOT_FOUND), @@ -996,6 +1013,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "renegotiation encoding err"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATION_MISMATCH), "renegotiation mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUEST_PENDING), "request pending"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUEST_SENT), "request sent"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_CIPHER_MISSING), "required cipher missing"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING), diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 270d4de..68a9b19 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -614,6 +614,9 @@ int SSL_clear(SSL *s) s->key_update = SSL_KEY_UPDATE_NONE; + EVP_MD_CTX_free(s->pha_dgst); + s->pha_dgst = NULL; + /* Reset DANE verification result state */ s->dane.mdpth = -1; s->dane.pdpth = -1; @@ -1186,6 +1189,8 @@ void SSL_free(SSL *s) OPENSSL_free(s->ext.alpn); OPENSSL_free(s->ext.tls13_cookie); OPENSSL_free(s->clienthello); + OPENSSL_free(s->pha_context); + EVP_MD_CTX_free(s->pha_dgst); sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free); @@ -5318,3 +5323,55 @@ int SSL_stateless(SSL *s) return 0; } + +void SSL_force_post_handshake_auth(SSL *ssl) +{ + ssl->pha_forced = 1; +} + +int SSL_verify_client_post_handshake(SSL *ssl) +{ + if (!SSL_IS_TLS13(ssl)) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_WRONG_SSL_VERSION); + return 0; + } + if (!ssl->server) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_NOT_SERVER); + return 0; + } + + if (!SSL_is_init_finished(ssl)) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_STILL_IN_INIT); + return 0; + } + + switch (ssl->post_handshake_auth) { + case SSL_PHA_NONE: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_EXTENSION_NOT_RECEIVED); + return 0; + default: + case SSL_PHA_EXT_SENT: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, ERR_R_INTERNAL_ERROR); + return 0; + case SSL_PHA_EXT_RECEIVED: + break; + case SSL_PHA_REQUEST_PENDING: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_PENDING); + return 0; + case SSL_PHA_REQUESTED: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_SENT); + return 0; + } + + ssl->post_handshake_auth = SSL_PHA_REQUEST_PENDING; + + /* checks verify_mode and algorithm_auth */ + if (!send_certificate_request(ssl)) { + ssl->post_handshake_auth = SSL_PHA_EXT_RECEIVED; /* restore on error */ + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_INVALID_CONFIG); + return 0; + } + + ossl_statem_set_in_init(ssl, 1); + return 1; +} diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6afd009..221d5b9 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -402,6 +402,15 @@ #define CERT_PRIVATE_KEY 2 */ +/* Post-Handshake Authentication state */ +typedef enum { + SSL_PHA_NONE = 0, + SSL_PHA_EXT_SENT, /* client-side only: extension sent */ + SSL_PHA_EXT_RECEIVED, /* server-side only: extension received */ + SSL_PHA_REQUEST_PENDING, /* server-side only: request pending */ + SSL_PHA_REQUESTED /* request received by client, or sent by server */ +} SSL_PHA_STATE; + /* CipherSuite length. SSLv3 and all TLS versions. */ # define TLS_CIPHER_LEN 2 /* used to hold info on the particular ciphers used */ @@ -702,6 +711,7 @@ typedef enum tlsext_index_en { TLSEXT_IDX_signed_certificate_timestamp, TLSEXT_IDX_extended_master_secret, TLSEXT_IDX_signature_algorithms_cert, + TLSEXT_IDX_post_handshake_auth, TLSEXT_IDX_signature_algorithms, TLSEXT_IDX_supported_versions, TLSEXT_IDX_psk_kex_modes, @@ -1334,6 +1344,14 @@ struct ssl_st { int renegotiate; /* If sending a KeyUpdate is pending */ int key_update; + /* Post-handshake authentication state */ + SSL_PHA_STATE post_handshake_auth; + int pha_forced; + uint8_t* pha_context; + size_t pha_context_len; + int certreqs_sent; + EVP_MD_CTX *pha_dgst; /* this is just the digest through ClientFinished */ + # ifndef OPENSSL_NO_SRP /* ctx for SRP authentication */ SRP_CTX srp_ctx; @@ -2535,6 +2553,10 @@ __owur int srp_generate_server_master_secret(SSL *s); __owur int srp_generate_client_master_secret(SSL *s); __owur int srp_verify_server_param(SSL *s); +/* statem/statem_srvr.c */ + +__owur int send_certificate_request(SSL *s); + /* statem/extensions_cust.c */ custom_ext_method *custom_ext_find(const custom_ext_methods *exts, diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 5ad86f2..daf43c6 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -55,6 +55,7 @@ static int init_srtp(SSL *s, unsigned int context); static int final_sig_algs(SSL *s, unsigned int context, int sent); static int final_early_data(SSL *s, unsigned int context, int sent); static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); +static int init_post_handshake_auth(SSL *s, unsigned int context); /* Structure to define a built-in extension */ typedef struct extensions_definition_st { @@ -290,6 +291,14 @@ static const EXTENSION_DEFINITION ext_defs[] = { NULL, NULL, NULL }, { + TLSEXT_TYPE_post_handshake_auth, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY, + init_post_handshake_auth, + tls_parse_ctos_post_handshake_auth, NULL, + NULL, tls_construct_ctos_post_handshake_auth, + NULL, + }, + { TLSEXT_TYPE_signature_algorithms, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, init_sig_algs, tls_parse_ctos_sig_algs, @@ -1653,3 +1662,10 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent) return 1; } + +static int init_post_handshake_auth(SSL *s, unsigned int context) +{ + s->post_handshake_auth = SSL_PHA_NONE; + + return 1; +} diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 5441e98..6286242 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -1133,6 +1133,48 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, #endif } +EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + if (!s->pha_forced) { + int i, n = 0; + + /* check for cert, if present, we can do post-handshake auth */ + if (s->cert == NULL) + return EXT_RETURN_NOT_SENT; + + for (i = 0; i < SSL_PKEY_NUM; i++) { + if (s->cert->pkeys[i].x509 != NULL + && s->cert->pkeys[i].privatekey != NULL) + n++; + } + + /* no identity certificates, so no extension */ + if (n == 0) + return EXT_RETURN_NOT_SENT; + } + + /* construct extension - 0 length, no contents */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->post_handshake_auth = SSL_PHA_EXT_SENT; + + return EXT_RETURN_SENT; +#else + return EXT_RETURN_NOT_SENT; +#endif +} + + /* * Parse the server's renegotiation binding and abort if it's not right */ diff --git a/ssl/statem/extensions_cust.c b/ssl/statem/extensions_cust.c index 0a23630..60a7c37 100644 --- a/ssl/statem/extensions_cust.c +++ b/ssl/statem/extensions_cust.c @@ -525,6 +525,7 @@ int SSL_extension_supported(unsigned int ext_type) case TLSEXT_TYPE_early_data: case TLSEXT_TYPE_certificate_authorities: case TLSEXT_TYPE_psk: + case TLSEXT_TYPE_post_handshake_auth: return 1; default: return 0; diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index 0a7bac4..27ff5a5 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -1161,6 +1161,20 @@ err: return 0; } +int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH, + SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR); + return 0; + } + + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + + return 1; +} + /* * Add the server's renegotiation binding */ diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index e79bd7b..f224da6 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -160,6 +160,26 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt) st->hand_state = TLS_ST_CR_KEY_UPDATE; return 1; } + if (mt == SSL3_MT_CERTIFICATE_REQUEST) { +#if DTLS_MAX_VERSION != DTLS1_2_VERSION +# error TODO(DTLS1.3): Restore digest for PHA before adding message. +#endif + if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) { + s->post_handshake_auth = SSL_PHA_REQUESTED; + /* + * In TLS, this is called before the message is added to the + * digest. In DTLS, this is expected to be called after adding + * to the digest. Either move the digest restore, or add the + * message here after the swap, or do it after the clientFinished? + */ + if (!tls13_restore_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return 0; + } + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } + } break; } @@ -382,6 +402,17 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s) ERR_R_INTERNAL_ERROR); return WRITE_TRAN_ERROR; + case TLS_ST_CR_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + st->hand_state = TLS_ST_CW_CERT; + return WRITE_TRAN_CONTINUE; + } + /* Shouldn't happen - same as default case */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + case TLS_ST_CR_FINISHED: if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY || s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING) @@ -798,11 +829,17 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst) return WORK_MORE_B; if (SSL_IS_TLS13(s)) { - if (!s->method->ssl3_enc->change_cipher_state(s, - SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + if (!tls13_save_handshake_digest_for_pha(s)) { /* SSLfatal() already called */ return WORK_ERROR; } + if (s->post_handshake_auth != SSL_PHA_REQUESTED) { + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } } break; @@ -2399,9 +2436,11 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) OPENSSL_free(s->s3->tmp.ctype); s->s3->tmp.ctype = NULL; s->s3->tmp.ctype_len = 0; + OPENSSL_free(s->pha_context); + s->pha_context = NULL; - /* TODO(TLS1.3) need to process request context, for now ignore */ - if (!PACKET_get_length_prefixed_1(pkt, &reqctx)) { + if (!PACKET_get_length_prefixed_1(pkt, &reqctx) || + !PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); @@ -3357,8 +3396,12 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst) } s->rwstate = SSL_NOTHING; } - if (ssl3_check_client_certificate(s)) + if (ssl3_check_client_certificate(s)) { + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + return WORK_FINISHED_STOP; + } return WORK_FINISHED_CONTINUE; + } /* Fall through to WORK_MORE_B */ wst = WORK_MORE_B; @@ -3403,6 +3446,8 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst) } } + if (s->post_handshake_auth == SSL_PHA_REQUESTED) + return WORK_FINISHED_STOP; return WORK_FINISHED_CONTINUE; } @@ -3414,14 +3459,19 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst) int tls_construct_client_certificate(SSL *s, WPACKET *pkt) { - /* - * TODO(TLS1.3): For now we must put an empty context. Needs to be filled in - * later - */ - if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); - return 0; + if (SSL_IS_TLS13(s)) { + if (s->pha_context == NULL) { + /* no context available, add 0-length context */ + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } + } else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } } if (!ssl3_output_cert_chain(s, pkt, (s->s3->tmp.cert_req == 2) ? NULL diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 87ce280..f57f33c 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use @@ -43,12 +43,15 @@ int ssl3_do_write(SSL *s, int type) /* * should not be done for 'Hello Request's, but in that case we'll * ignore the result anyway + * TLS1.3 KeyUpdate and NewSessionTicket do not need to be added */ - if (!ssl3_finish_mac(s, - (unsigned char *)&s->init_buf->data[s->init_off], - written)) - return -1; - + if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET + && s->statem.hand_state != TLS_ST_CW_KEY_UPDATE + && s->statem.hand_state != TLS_ST_SW_KEY_UPDATE)) + if (!ssl3_finish_mac(s, + (unsigned char *)&s->init_buf->data[s->init_off], + written)) + return -1; if (written == s->init_num) { if (s->msg_callback) s->msg_callback(1, s->version, type, s->init_buf->data, @@ -504,7 +507,7 @@ int tls_construct_finished(SSL *s, WPACKET *pkt) size_t slen; /* This is a real handshake so make sure we clean it up at the end */ - if (!s->server) + if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED) s->statem.cleanuphand = 1; /* @@ -741,8 +744,14 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) /* This is a real handshake so make sure we clean it up at the end */ - if (s->server) - s->statem.cleanuphand = 1; + if (s->server) { + if (s->post_handshake_auth != SSL_PHA_REQUESTED) + s->statem.cleanuphand = 1; + if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + } /* * In TLSv1.3 a Finished message signals a key change so the end of the @@ -801,7 +810,8 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) */ if (SSL_IS_TLS13(s)) { if (s->server) { - if (!s->method->ssl3_enc->change_cipher_state(s, + if (s->post_handshake_auth != SSL_PHA_REQUESTED && + !s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; @@ -1021,6 +1031,10 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop) s->init_num = 0; } + if (SSL_IS_TLS13(s) && !s->server + && s->post_handshake_auth == SSL_PHA_REQUESTED) + s->post_handshake_auth = SSL_PHA_EXT_SENT; + if (s->statem.cleanuphand) { /* skipped if we just sent a HelloRequest */ s->renegotiate = 0; @@ -1237,18 +1251,24 @@ int tls_get_message_body(SSL *s, size_t *len) /* * We defer feeding in the HRR until later. We'll do it as part of * processing the message + * The TLsv1.3 handshake transcript stops at the ClientFinished + * message. */ #define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2) - if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO - || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE - || memcmp(hrrrandom, - s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET, - SSL3_RANDOM_SIZE) != 0) { - if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, - s->init_num + SSL3_HM_HEADER_LENGTH)) { - /* SSLfatal() already called */ - *len = 0; - return 0; + /* KeyUpdate and NewSessionTicket do not need to be added */ + if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET + && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) { + if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO + || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE + || memcmp(hrrrandom, + s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET, + SSL3_RANDOM_SIZE) != 0) { + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH)) { + /* SSLfatal() already called */ + *len = 0; + return 0; + } } } if (s->msg_callback) @@ -2208,3 +2228,54 @@ size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs, *ptbs = tbs; return tbslen; } + +/* + * Saves the current handshake digest for Post-Handshake Auth, + * Done after ClientFinished is processed, done exactly once + */ +int tls13_save_handshake_digest_for_pha(SSL *s) +{ + if (s->pha_dgst == NULL) { + if (!ssl3_digest_cached_records(s, 1)) + /* SSLfatal() already called */ + return 0; + + s->pha_dgst = EVP_MD_CTX_new(); + if (s->pha_dgst == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->pha_dgst, + s->s3->handshake_dgst)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + return 1; +} + +/* + * Restores the Post-Handshake Auth handshake digest + * Done just before sending/processing the Cert Request + */ +int tls13_restore_handshake_digest_for_pha(SSL *s) +{ + if (s->pha_dgst == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst, + s->pha_dgst)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h index f16d3cb..af081eb 100644 --- a/ssl/statem/statem_locl.h +++ b/ssl/statem/statem_locl.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -235,6 +235,8 @@ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, @@ -365,6 +367,9 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt, size_t chainidx); EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context, @@ -411,3 +416,6 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_handle_alpn(SSL *s); + +int tls13_save_handshake_digest_for_pha(SSL *s); +int tls13_restore_handshake_digest_for_pha(SSL *s); diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 51b6ce9..812780a 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -107,6 +107,13 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt) */ if (s->early_data_state == SSL_EARLY_DATA_READING) break; + + if (mt == SSL3_MT_CERTIFICATE + && s->post_handshake_auth == SSL_PHA_REQUESTED) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + if (mt == SSL3_MT_KEY_UPDATE) { st->hand_state = TLS_ST_SR_KEY_UPDATE; return 1; @@ -325,16 +332,22 @@ static int send_server_key_exchange(SSL *s) * 1: Yes * 0: No */ -static int send_certificate_request(SSL *s) +int send_certificate_request(SSL *s) { if ( /* don't request cert unless asked for it: */ s->verify_mode & SSL_VERIFY_PEER /* + * don't request if post-handshake-only unless doing + * post-handshake in TLSv1.3: + */ + && (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE) + || s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) + /* * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert - * during re-negotiation: + * a second time: */ - && (s->s3->tmp.finish_md_len == 0 || + && (s->certreqs_sent < 1 || !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) /* * never request cert in anonymous ciphersuites (see @@ -388,6 +401,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) st->hand_state = TLS_ST_SW_KEY_UPDATE; return WRITE_TRAN_CONTINUE; } + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + st->hand_state = TLS_ST_SW_CERT_REQ; + return WRITE_TRAN_CONTINUE; + } /* Try to read from the client instead */ return WRITE_TRAN_FINISHED; @@ -423,7 +440,12 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) return WRITE_TRAN_CONTINUE; case TLS_ST_SW_CERT_REQ: - st->hand_state = TLS_ST_SW_CERT; + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + s->post_handshake_auth = SSL_PHA_REQUESTED; + st->hand_state = TLS_ST_OK; + } else { + st->hand_state = TLS_ST_SW_CERT; + } return WRITE_TRAN_CONTINUE; case TLS_ST_SW_CERT: @@ -450,6 +472,8 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) * and give the application the opportunity to delay sending the * session ticket? */ + if (s->post_handshake_auth == SSL_PHA_REQUESTED) + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; st->hand_state = TLS_ST_SW_SESSION_TICKET; return WRITE_TRAN_CONTINUE; @@ -863,6 +887,13 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) } break; + case TLS_ST_SW_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + if (statem_flush(s) != 1) + return WORK_MORE_A; + } + break; + case TLS_ST_SW_KEY_UPDATE: if (statem_flush(s) != 1) return WORK_MORE_A; @@ -2702,12 +2733,30 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) int tls_construct_certificate_request(SSL *s, WPACKET *pkt) { if (SSL_IS_TLS13(s)) { - /* TODO(TLS1.3) for now send empty request context */ - if (!WPACKET_put_bytes_u8(pkt, 0)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, - ERR_R_INTERNAL_ERROR); - return 0; + /* Send random context when doing post-handshake auth */ + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + OPENSSL_free(s->pha_context); + s->pha_context_len = 32; + if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL + || ssl_randbytes(s, s->pha_context, s->pha_context_len) <= 0 + || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* reset the handshake hash back to just after the ClientFinished */ + if (!tls13_restore_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return 0; + } + } else { + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } } if (!tls_construct_extensions(s, pkt, @@ -2748,6 +2797,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } done: + s->certreqs_sent++; s->s3->tmp.cert_request = 1; return 1; } @@ -3396,11 +3446,12 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) int i; MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; X509 *x = NULL; - unsigned long l, llen; + unsigned long l; const unsigned char *certstart, *certbytes; STACK_OF(X509) *sk = NULL; PACKET spkt, context; size_t chainidx; + SSL_SESSION *new_sess = NULL; if ((sk = sk_X509_new_null()) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, @@ -3408,10 +3459,16 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) goto err; } - /* TODO(TLS1.3): For now we ignore the context. We need to verify this */ - if ((SSL_IS_TLS13(s) && !PACKET_get_length_prefixed_1(pkt, &context)) - || !PACKET_get_net_3(pkt, &llen) - || !PACKET_get_sub_packet(pkt, &spkt, llen) + if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context) + || (s->pha_context == NULL && PACKET_remaining(&context) != 0) + || (s->pha_context != NULL && + !PACKET_equal(&context, s->pha_context, s->pha_context_len)))) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_INVALID_CONTEXT); + goto err; + } + + if (!PACKET_get_length_prefixed_3(pkt, &spkt) || PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH); @@ -3516,6 +3573,35 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) } } + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. Here, we need to do this every time + * a new certificate is received via post-handshake authentication, as the + * session may have already gone into the session cache. + */ + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + int m = s->session_ctx->session_cache_mode; + + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (m & SSL_SESS_CACHE_SERVER) { + /* + * Remove the old session from the cache. We carry on if this fails + */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + X509_free(s->session->peer); s->session->peer = sk_X509_shift(sk); s->session->verify_result = s->verify_result; @@ -3523,6 +3609,9 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) sk_X509_pop_free(s->session->peer_chain, X509_free); s->session->peer_chain = sk; + if (new_sess != NULL) + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + /* * Freeze the handshake buffer. For #endif +#include "../ssl/ssl_locl.h" #include "internal/sockets.h" #include "internal/nelem.h" #include "handshake_helper.h" @@ -674,6 +675,8 @@ static void configure_handshake_ssl(SSL *server, SSL *client, if (extra->client.servername != SSL_TEST_SERVERNAME_NONE) SSL_set_tlsext_host_name(client, ssl_servername_name(extra->client.servername)); + if (extra->client.force_pha) + SSL_force_post_handshake_auth(client); } /* The status for each connection phase. */ @@ -848,7 +851,9 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer) || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER || test_ctx->handshake_mode - == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT)) { + == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT + || test_ctx->handshake_mode + == SSL_TEST_HANDSHAKE_POST_HANDSHAKE_AUTH)) { peer->status = PEER_TEST_FAILURE; return; } @@ -929,6 +934,25 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer) if (peer->status != PEER_SUCCESS) peer->status = PEER_ERROR; return; + } else if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_POST_HANDSHAKE_AUTH) { + if (SSL_is_server(peer->ssl)) { + /* Make the server believe it's received the extension */ + if (test_ctx->extra.server.force_pha) + peer->ssl->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + ret = SSL_verify_client_post_handshake(peer->ssl); + if (!ret) { + peer->status = PEER_ERROR; + return; + } + } + do_handshake_step(peer); + /* + * This is a one step handshake. We shouldn't get anything other than + * PEER_SUCCESS + */ + if (peer->status != PEER_SUCCESS) + peer->status = PEER_ERROR; + return; } /* @@ -1004,25 +1028,41 @@ typedef enum { CONNECTION_DONE } connect_phase_t; + +static int renegotiate_op(const SSL_TEST_CTX *test_ctx) +{ + switch (test_ctx->handshake_mode) { + case SSL_TEST_HANDSHAKE_RENEG_SERVER: + case SSL_TEST_HANDSHAKE_RENEG_CLIENT: + return 1; + default: + return 0; + } +} +static int post_handshake_op(const SSL_TEST_CTX *test_ctx) +{ + switch (test_ctx->handshake_mode) { + case SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT: + case SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER: + case SSL_TEST_HANDSHAKE_POST_HANDSHAKE_AUTH: + return 1; + default: + return 0; + } +} + static connect_phase_t next_phase(const SSL_TEST_CTX *test_ctx, connect_phase_t phase) { switch (phase) { case HANDSHAKE: - if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER - || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT - || test_ctx->handshake_mode - == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT - || test_ctx->handshake_mode - == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER) + if (renegotiate_op(test_ctx) || post_handshake_op(test_ctx)) return RENEG_APPLICATION_DATA; return APPLICATION_DATA; case RENEG_APPLICATION_DATA: return RENEG_SETUP; case RENEG_SETUP: - if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER - || test_ctx->handshake_mode - == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT) + if (post_handshake_op(test_ctx)) return APPLICATION_DATA; return RENEG_HANDSHAKE; case RENEG_HANDSHAKE: diff --git a/test/recipes/70-test_tls13messages.t b/test/recipes/70-test_tls13messages.t index fc70b4f..4190ab5 100644 --- a/test/recipes/70-test_tls13messages.t +++ b/test/recipes/70-test_tls13messages.t @@ -89,6 +89,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf"); checkhandshake::DEFAULT_EXTENSIONS], [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK, checkhandshake::PSK_CLI_EXTENSION], + [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_POST_HANDSHAKE_AUTH, + checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION], [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, checkhandshake::DEFAULT_EXTENSIONS], @@ -123,6 +125,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf"); checkhandshake::DEFAULT_EXTENSIONS], [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK, checkhandshake::PSK_CLI_EXTENSION], + [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_POST_HANDSHAKE_AUTH, + checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION], [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, checkhandshake::DEFAULT_EXTENSIONS], @@ -214,7 +218,8 @@ $proxy->clientflags("-cert ".srctop_file("apps", "server.pem")); $proxy->serverflags("-Verify 5"); $proxy->start(); checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE, - checkhandshake::DEFAULT_EXTENSIONS, + checkhandshake::DEFAULT_EXTENSIONS | + checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION, "Client auth handshake test"); #Test 7: Server name handshake (no client request) diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index d1388d9..be03388 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -28,7 +28,7 @@ map { s/\^// } @conf_files if $^O eq "VMS"; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 25; # = scalar @conf_srcs +plan tests => 26; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. @@ -96,6 +96,7 @@ my %skip = ( && disabled("tls1_2")) || disabled("srp"), "24-padding.conf" => disabled("tls1_3"), "25-cipher.conf" => disabled("ec") || disabled("tls1_2"), + "26-tls13_client_auth.conf" => disabled("tls1_3"), ); foreach my $conf (@conf_files) { diff --git a/test/ssl-tests/26-tls13_client_auth.conf b/test/ssl-tests/26-tls13_client_auth.conf new file mode 100644 index 0000000..f769b12 --- /dev/null +++ b/test/ssl-tests/26-tls13_client_auth.conf @@ -0,0 +1,476 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 14 + +test-0 = 0-server-auth-TLSv1.3 +test-1 = 1-client-auth-TLSv1.3-request +test-2 = 2-client-auth-TLSv1.3-require-fail +test-3 = 3-client-auth-TLSv1.3-require +test-4 = 4-client-auth-TLSv1.3-require-non-empty-names +test-5 = 5-client-auth-TLSv1.3-noroot +test-6 = 6-client-auth-TLSv1.3-request-post-handshake +test-7 = 7-client-auth-TLSv1.3-require-fail-post-handshake +test-8 = 8-client-auth-TLSv1.3-require-post-handshake +test-9 = 9-client-auth-TLSv1.3-require-non-empty-names-post-handshake +test-10 = 10-client-auth-TLSv1.3-noroot-post-handshake +test-11 = 11-client-auth-TLSv1.3-request-force-client-post-handshake +test-12 = 12-client-auth-TLSv1.3-request-force-server-post-handshake +test-13 = 13-client-auth-TLSv1.3-request-force-both-post-handshake +# =========================================================== + +[0-server-auth-TLSv1.3] +ssl_conf = 0-server-auth-TLSv1.3-ssl + +[0-server-auth-TLSv1.3-ssl] +server = 0-server-auth-TLSv1.3-server +client = 0-server-auth-TLSv1.3-client + +[0-server-auth-TLSv1.3-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[0-server-auth-TLSv1.3-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-0] +ExpectedResult = Success + + +# =========================================================== + +[1-client-auth-TLSv1.3-request] +ssl_conf = 1-client-auth-TLSv1.3-request-ssl + +[1-client-auth-TLSv1.3-request-ssl] +server = 1-client-auth-TLSv1.3-request-server +client = 1-client-auth-TLSv1.3-request-client + +[1-client-auth-TLSv1.3-request-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = Request + +[1-client-auth-TLSv1.3-request-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-1] +ExpectedResult = Success + + +# =========================================================== + +[2-client-auth-TLSv1.3-require-fail] +ssl_conf = 2-client-auth-TLSv1.3-require-fail-ssl + +[2-client-auth-TLSv1.3-require-fail-ssl] +server = 2-client-auth-TLSv1.3-require-fail-server +client = 2-client-auth-TLSv1.3-require-fail-client + +[2-client-auth-TLSv1.3-require-fail-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = Require + +[2-client-auth-TLSv1.3-require-fail-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-2] +ExpectedResult = ServerFail +ExpectedServerAlert = HandshakeFailure + + +# =========================================================== + +[3-client-auth-TLSv1.3-require] +ssl_conf = 3-client-auth-TLSv1.3-require-ssl + +[3-client-auth-TLSv1.3-require-ssl] +server = 3-client-auth-TLSv1.3-require-server +client = 3-client-auth-TLSv1.3-require-client + +[3-client-auth-TLSv1.3-require-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +ClientSignatureAlgorithms = PSS+SHA256 +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = Request + +[3-client-auth-TLSv1.3-require-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-3] +ExpectedClientCANames = empty +ExpectedClientCertType = RSA +ExpectedClientSignHash = SHA256 +ExpectedClientSignType = RSA-PSS +ExpectedResult = Success + + +# =========================================================== + +[4-client-auth-TLSv1.3-require-non-empty-names] +ssl_conf = 4-client-auth-TLSv1.3-require-non-empty-names-ssl + +[4-client-auth-TLSv1.3-require-non-empty-names-ssl] +server = 4-client-auth-TLSv1.3-require-non-empty-names-server +client = 4-client-auth-TLSv1.3-require-non-empty-names-client + +[4-client-auth-TLSv1.3-require-non-empty-names-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +ClientCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +ClientSignatureAlgorithms = PSS+SHA256 +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = Request + +[4-client-auth-TLSv1.3-require-non-empty-names-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-4] +ExpectedClientCANames = ${ENV::TEST_CERTS_DIR}/root-cert.pem +ExpectedClientCertType = RSA +ExpectedClientSignHash = SHA256 +ExpectedClientSignType = RSA-PSS +ExpectedResult = Success + + +# =========================================================== + +[5-client-auth-TLSv1.3-noroot] +ssl_conf = 5-client-auth-TLSv1.3-noroot-ssl + +[5-client-auth-TLSv1.3-noroot-ssl] +server = 5-client-auth-TLSv1.3-noroot-server +client = 5-client-auth-TLSv1.3-noroot-client + +[5-client-auth-TLSv1.3-noroot-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = Require + +[5-client-auth-TLSv1.3-noroot-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-5] +ExpectedResult = ServerFail +ExpectedServerAlert = UnknownCA + + +# =========================================================== + +[6-client-auth-TLSv1.3-request-post-handshake] +ssl_conf = 6-client-auth-TLSv1.3-request-post-handshake-ssl + +[6-client-auth-TLSv1.3-request-post-handshake-ssl] +server = 6-client-auth-TLSv1.3-request-post-handshake-server +client = 6-client-auth-TLSv1.3-request-post-handshake-client + +[6-client-auth-TLSv1.3-request-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = RequestPostHandshake + +[6-client-auth-TLSv1.3-request-post-handshake-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-6] +ExpectedResult = ServerFail +HandshakeMode = PostHandshakeAuth + + +# =========================================================== + +[7-client-auth-TLSv1.3-require-fail-post-handshake] +ssl_conf = 7-client-auth-TLSv1.3-require-fail-post-handshake-ssl + +[7-client-auth-TLSv1.3-require-fail-post-handshake-ssl] +server = 7-client-auth-TLSv1.3-require-fail-post-handshake-server +client = 7-client-auth-TLSv1.3-require-fail-post-handshake-client + +[7-client-auth-TLSv1.3-require-fail-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = RequirePostHandshake + +[7-client-auth-TLSv1.3-require-fail-post-handshake-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-7] +ExpectedResult = ServerFail +HandshakeMode = PostHandshakeAuth + + +# =========================================================== + +[8-client-auth-TLSv1.3-require-post-handshake] +ssl_conf = 8-client-auth-TLSv1.3-require-post-handshake-ssl + +[8-client-auth-TLSv1.3-require-post-handshake-ssl] +server = 8-client-auth-TLSv1.3-require-post-handshake-server +client = 8-client-auth-TLSv1.3-require-post-handshake-client + +[8-client-auth-TLSv1.3-require-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +ClientSignatureAlgorithms = PSS+SHA256 +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = RequestPostHandshake + +[8-client-auth-TLSv1.3-require-post-handshake-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-8] +ExpectedClientCANames = empty +ExpectedClientCertType = RSA +ExpectedClientSignHash = SHA256 +ExpectedClientSignType = RSA-PSS +ExpectedResult = Success +HandshakeMode = PostHandshakeAuth + + +# =========================================================== + +[9-client-auth-TLSv1.3-require-non-empty-names-post-handshake] +ssl_conf = 9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-ssl + +[9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-ssl] +server = 9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-server +client = 9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-client + +[9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +ClientCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +ClientSignatureAlgorithms = PSS+SHA256 +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem +VerifyMode = RequestPostHandshake + +[9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-9] +ExpectedClientCANames = ${ENV::TEST_CERTS_DIR}/root-cert.pem +ExpectedClientCertType = RSA +ExpectedClientSignHash = SHA256 +ExpectedClientSignType = RSA-PSS +ExpectedResult = Success +HandshakeMode = PostHandshakeAuth + + +# =========================================================== + +[10-client-auth-TLSv1.3-noroot-post-handshake] +ssl_conf = 10-client-auth-TLSv1.3-noroot-post-handshake-ssl + +[10-client-auth-TLSv1.3-noroot-post-handshake-ssl] +server = 10-client-auth-TLSv1.3-noroot-post-handshake-server +client = 10-client-auth-TLSv1.3-noroot-post-handshake-client + +[10-client-auth-TLSv1.3-noroot-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = RequirePostHandshake + +[10-client-auth-TLSv1.3-noroot-post-handshake-client] +Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-10] +ExpectedResult = ServerFail +ExpectedServerAlert = UnknownCA +HandshakeMode = PostHandshakeAuth + + +# =========================================================== + +[11-client-auth-TLSv1.3-request-force-client-post-handshake] +ssl_conf = 11-client-auth-TLSv1.3-request-force-client-post-handshake-ssl + +[11-client-auth-TLSv1.3-request-force-client-post-handshake-ssl] +server = 11-client-auth-TLSv1.3-request-force-client-post-handshake-server +client = 11-client-auth-TLSv1.3-request-force-client-post-handshake-client + +[11-client-auth-TLSv1.3-request-force-client-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = RequestPostHandshake + +[11-client-auth-TLSv1.3-request-force-client-post-handshake-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-11] +ExpectedResult = Success +HandshakeMode = PostHandshakeAuth +client = 11-client-auth-TLSv1.3-request-force-client-post-handshake-client-extra + +[11-client-auth-TLSv1.3-request-force-client-post-handshake-client-extra] +ForcePHA = Yes + + +# =========================================================== + +[12-client-auth-TLSv1.3-request-force-server-post-handshake] +ssl_conf = 12-client-auth-TLSv1.3-request-force-server-post-handshake-ssl + +[12-client-auth-TLSv1.3-request-force-server-post-handshake-ssl] +server = 12-client-auth-TLSv1.3-request-force-server-post-handshake-server +client = 12-client-auth-TLSv1.3-request-force-server-post-handshake-client + +[12-client-auth-TLSv1.3-request-force-server-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = RequestPostHandshake + +[12-client-auth-TLSv1.3-request-force-server-post-handshake-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-12] +ExpectedResult = ClientFail +HandshakeMode = PostHandshakeAuth +server = 12-client-auth-TLSv1.3-request-force-server-post-handshake-server-extra + +[12-client-auth-TLSv1.3-request-force-server-post-handshake-server-extra] +ForcePHA = Yes + + +# =========================================================== + +[13-client-auth-TLSv1.3-request-force-both-post-handshake] +ssl_conf = 13-client-auth-TLSv1.3-request-force-both-post-handshake-ssl + +[13-client-auth-TLSv1.3-request-force-both-post-handshake-ssl] +server = 13-client-auth-TLSv1.3-request-force-both-post-handshake-server +client = 13-client-auth-TLSv1.3-request-force-both-post-handshake-client + +[13-client-auth-TLSv1.3-request-force-both-post-handshake-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +VerifyMode = RequestPostHandshake + +[13-client-auth-TLSv1.3-request-force-both-post-handshake-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-13] +ExpectedResult = Success +HandshakeMode = PostHandshakeAuth +server = 13-client-auth-TLSv1.3-request-force-both-post-handshake-server-extra +client = 13-client-auth-TLSv1.3-request-force-both-post-handshake-client-extra + +[13-client-auth-TLSv1.3-request-force-both-post-handshake-server-extra] +ForcePHA = Yes + +[13-client-auth-TLSv1.3-request-force-both-post-handshake-client-extra] +ForcePHA = Yes + + diff --git a/test/ssl-tests/26-tls13_client_auth.conf.in b/test/ssl-tests/26-tls13_client_auth.conf.in new file mode 100644 index 0000000..6da4168 --- /dev/null +++ b/test/ssl-tests/26-tls13_client_auth.conf.in @@ -0,0 +1,293 @@ +# -*- mode: perl; -*- +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +## Test TLSv1.3 certificate authentication +## Similar to 04-client_auth.conf.in output, but specific for +## TLSv1.3 and post-handshake authentication + +use strict; +use warnings; + +package ssltests; +use OpenSSL::Test::Utils; + +our @tests = ( + { + name => "server-auth-TLSv1.3", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "Success", + }, + }, + { + name => "client-auth-TLSv1.3-request", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "Request", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "Success", + }, + }, + { + name => "client-auth-TLSv1.3-require-fail", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "Require", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "ServerFail", + "ExpectedServerAlert" => "HandshakeFailure", + }, + }, + { + name => "client-auth-TLSv1.3-require", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "ClientSignatureAlgorithms" => "PSS+SHA256", + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "Request", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "Success", + "ExpectedClientCertType" => "RSA", + "ExpectedClientSignType" => "RSA-PSS", + "ExpectedClientSignHash" => "SHA256", + "ExpectedClientCANames" => "empty" + }, + }, + { + name => "client-auth-TLSv1.3-require-non-empty-names", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "ClientSignatureAlgorithms" => "PSS+SHA256", + "ClientCAFile" => test_pem("root-cert.pem"), + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "Request", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "Success", + "ExpectedClientCertType" => "RSA", + "ExpectedClientSignType" => "RSA-PSS", + "ExpectedClientSignHash" => "SHA256", + "ExpectedClientCANames" => test_pem("root-cert.pem"), + }, + }, + { + name => "client-auth-TLSv1.3-noroot", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "Require", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "ServerFail", + "ExpectedServerAlert" => "UnknownCA", + }, + }, + { + name => "client-auth-TLSv1.3-request-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "RequestPostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "ServerFail", + "HandshakeMode" => "PostHandshakeAuth", + }, + }, + { + name => "client-auth-TLSv1.3-require-fail-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "RequirePostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "ServerFail", + "HandshakeMode" => "PostHandshakeAuth", + }, + }, + { + name => "client-auth-TLSv1.3-require-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "ClientSignatureAlgorithms" => "PSS+SHA256", + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "RequestPostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "Success", + "HandshakeMode" => "PostHandshakeAuth", + "ExpectedClientCertType" => "RSA", + "ExpectedClientSignType" => "RSA-PSS", + "ExpectedClientSignHash" => "SHA256", + "ExpectedClientCANames" => "empty" + }, + }, + { + name => "client-auth-TLSv1.3-require-non-empty-names-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "ClientSignatureAlgorithms" => "PSS+SHA256", + "ClientCAFile" => test_pem("root-cert.pem"), + "VerifyCAFile" => test_pem("root-cert.pem"), + "VerifyMode" => "RequestPostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "Success", + "HandshakeMode" => "PostHandshakeAuth", + "ExpectedClientCertType" => "RSA", + "ExpectedClientSignType" => "RSA-PSS", + "ExpectedClientSignHash" => "SHA256", + "ExpectedClientCANames" => test_pem("root-cert.pem"), + }, + }, + { + name => "client-auth-TLSv1.3-noroot-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "RequirePostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Certificate" => test_pem("ee-client-chain.pem"), + "PrivateKey" => test_pem("ee-key.pem"), + }, + test => { + "ExpectedResult" => "ServerFail", + "HandshakeMode" => "PostHandshakeAuth", + "ExpectedServerAlert" => "UnknownCA", + }, + }, + { + name => "client-auth-TLSv1.3-request-force-client-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "RequestPostHandshake", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + extra => { + "ForcePHA" => "Yes", + }, + }, + test => { + "ExpectedResult" => "Success", + "HandshakeMode" => "PostHandshakeAuth", + }, + }, + { + name => "client-auth-TLSv1.3-request-force-server-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "RequestPostHandshake", + extra => { + "ForcePHA" => "Yes", + }, + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "ClientFail", + "HandshakeMode" => "PostHandshakeAuth", + }, + }, + { + name => "client-auth-TLSv1.3-request-force-both-post-handshake", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyMode" => "RequestPostHandshake", + extra => { + "ForcePHA" => "Yes", + }, + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + extra => { + "ForcePHA" => "Yes", + }, + }, + test => { + "ExpectedResult" => "Success", + "HandshakeMode" => "PostHandshakeAuth", + }, + }, +); diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index 897b31e..1f7db2e 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -369,6 +369,7 @@ static const test_enum ssl_handshake_modes[] = { {"RenegotiateClient", SSL_TEST_HANDSHAKE_RENEG_CLIENT}, {"KeyUpdateServer", SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER}, {"KeyUpdateClient", SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT}, + {"PostHandshakeAuth", SSL_TEST_HANDSHAKE_POST_HANDSHAKE_AUTH}, }; __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value) @@ -622,6 +623,11 @@ __owur static int parse_expected_client_ca_names(SSL_TEST_CTX *test_ctx, IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_cipher) +/* Client and Server ForcePHA */ + +IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CLIENT_CONF, client, force_pha) +IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, force_pha) + /* Known test options and their corresponding parse methods. */ /* Top-level options. */ @@ -676,6 +682,7 @@ static const ssl_test_client_option ssl_test_client_options[] = { { "SRPUser", &parse_client_srp_user }, { "SRPPassword", &parse_client_srp_password }, { "MaxFragmentLenExt", &parse_max_fragment_len_mode }, + { "ForcePHA", &parse_client_force_pha }, }; /* Nested server options. */ @@ -692,6 +699,7 @@ static const ssl_test_server_option ssl_test_server_options[] = { { "CertStatus", &parse_certstatus }, { "SRPUser", &parse_server_srp_user }, { "SRPPassword", &parse_server_srp_password }, + { "ForcePHA", &parse_server_force_pha }, }; SSL_TEST_CTX *SSL_TEST_CTX_new() diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 2d7b0c2..0ec87ce 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -73,7 +73,8 @@ typedef enum { SSL_TEST_HANDSHAKE_RENEG_SERVER, SSL_TEST_HANDSHAKE_RENEG_CLIENT, SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER, - SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT + SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT, + SSL_TEST_HANDSHAKE_POST_HANDSHAKE_AUTH } ssl_handshake_mode_t; typedef enum { @@ -107,6 +108,8 @@ typedef struct { char *reneg_ciphers; char *srp_user; char *srp_password; + /* Forced PHA */ + int force_pha; } SSL_TEST_CLIENT_CONF; typedef struct { @@ -122,6 +125,8 @@ typedef struct { /* An SRP user known to the server. */ char *srp_user; char *srp_password; + /* Forced PHA */ + int force_pha; } SSL_TEST_SERVER_CONF; typedef struct { diff --git a/test/sslapitest.c b/test/sslapitest.c index a338578..b655fe7 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -3306,6 +3306,65 @@ end: return testresult; } +#ifndef OPENSSL_NO_TLS1_3 +static int test_pha_key_update(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + &sctx, &cctx, cert, privkey))) + return 0; + + if (!TEST_true(SSL_CTX_set_min_proto_version(sctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_max_proto_version(sctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_min_proto_version(cctx, TLS1_3_VERSION)) + || !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_3_VERSION))) + goto end; + + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + SSL_force_post_handshake_auth(clientssl); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_set_verify(serverssl, SSL_VERIFY_PEER, NULL); + if (!TEST_true(SSL_verify_client_post_handshake(serverssl))) + goto end; + + if (!TEST_true(SSL_key_update(clientssl, SSL_KEY_UPDATE_NOT_REQUESTED))) + goto end; + + /* Start handshake on the server */ + if (!TEST_int_eq(SSL_do_handshake(serverssl), 1)) + goto end; + + /* Starts with SSL_connect(), but it's really just SSL_do_handshake() */ + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; +} +#endif + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) @@ -3352,6 +3411,7 @@ int setup_tests(void) ADD_TEST(test_tls13_psk); ADD_ALL_TESTS(test_custom_exts, 5); ADD_TEST(test_stateless); + ADD_TEST(test_pha_key_update); #else ADD_ALL_TESTS(test_custom_exts, 3); #endif diff --git a/util/libssl.num b/util/libssl.num index abaa5bf..866ff53 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -474,3 +474,5 @@ SSL_CTX_set_tlsext_max_fragment_length 474 1_1_1 EXIST::FUNCTION: SSL_set_tlsext_max_fragment_length 475 1_1_1 EXIST::FUNCTION: SSL_SESSION_get_max_fragment_length 476 1_1_1 EXIST::FUNCTION: SSL_stateless 477 1_1_1 EXIST::FUNCTION: +SSL_verify_client_post_handshake 478 1_1_1 EXIST::FUNCTION: +SSL_force_post_handshake_auth 479 1_1_1 EXIST::FUNCTION: diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index eea272f..0311490 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -79,6 +79,7 @@ use constant { EXT_SUPPORTED_VERSIONS => 43, EXT_COOKIE => 44, EXT_PSK_KEX_MODES => 45, + EXT_POST_HANDSHAKE_AUTH => 49, EXT_SIG_ALGS_CERT => 50, EXT_RENEGOTIATE => 65281, EXT_NPN => 13172, diff --git a/util/perl/checkhandshake.pm b/util/perl/checkhandshake.pm index e1667d5..2f4a296 100644 --- a/util/perl/checkhandshake.pm +++ b/util/perl/checkhandshake.pm @@ -53,7 +53,8 @@ use constant { KEY_SHARE_SRV_EXTENSION => 0x00020000, PSK_KEX_MODES_EXTENSION => 0x00040000, KEY_SHARE_HRR_EXTENSION => 0x00080000, - SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000 + SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000, + POST_HANDSHAKE_AUTH_CLI_EXTENSION => 0x00200000 }; our @handmessages = (); From no-reply at appveyor.com Thu Feb 1 18:15:57 2018 From: no-reply at appveyor.com (AppVeyor) Date: Thu, 01 Feb 2018 18:15:57 +0000 Subject: [openssl-commits] Build completed: openssl master.15317 Message-ID: <20180201181557.1.331CCF3C25E4847F@appveyor.com> An HTML attachment was scrubbed... URL: From levitte at openssl.org Thu Feb 1 18:17:31 2018 From: levitte at openssl.org (Richard Levitte) Date: Thu, 01 Feb 2018 18:17:31 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517509051.246215.10490.nullmailer@dev.openssl.org> The branch master has been updated via 34544072e9bccd4dad958ebeb3caadbb5c5106d0 (commit) from e43e6b1951de931ca500c6964496e76651332f5e (commit) - Log ----------------------------------------------------------------- commit 34544072e9bccd4dad958ebeb3caadbb5c5106d0 Author: Richard Levitte Date: Thu Feb 1 10:35:59 2018 +0100 VMS: MMS wants a space before the target / dependecies separator So as not to be mixed up with a device specification... Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/5234) ----------------------------------------------------------------------- Summary of changes: Configurations/descrip.mms.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configurations/descrip.mms.tmpl b/Configurations/descrip.mms.tmpl index 7d8b348..bfeee77 100644 --- a/Configurations/descrip.mms.tmpl +++ b/Configurations/descrip.mms.tmpl @@ -553,7 +553,7 @@ configdata.pm : $(SRCDIR)Configure $(SRCDIR)config.com {- join(" ", @{$config{bu @ WRITE SYS$OUTPUT "*************************************************" @ PIPE ( EXIT %X10000000 ) -reconfigure reconf: +reconfigure reconf : perl configdata.pm -r -v {- From rsalz at openssl.org Thu Feb 1 18:18:51 2018 From: rsalz at openssl.org (Rich Salz) Date: Thu, 01 Feb 2018 18:18:51 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517509131.425188.12569.nullmailer@dev.openssl.org> The branch master has been updated via 67c836e860c735cf1b039ef52973237fd26b74d6 (commit) from 34544072e9bccd4dad958ebeb3caadbb5c5106d0 (commit) - Log ----------------------------------------------------------------- commit 67c836e860c735cf1b039ef52973237fd26b74d6 Author: Rich Salz Date: Thu Feb 1 13:18:32 2018 -0500 Shorten output by a line Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/5238) ----------------------------------------------------------------------- Summary of changes: Configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configure b/Configure index cad25bb..a994876 100755 --- a/Configure +++ b/Configure @@ -939,7 +939,7 @@ if ($target eq "HASH") { exit 0; } -print "Configuring OpenSSL version $config{version} ($config{version_num})\n"; +print "Configuring OpenSSL version $config{version} ($config{version_num}) "; print "for $target\n"; # Backward compatibility? From rsalz at openssl.org Thu Feb 1 18:23:21 2018 From: rsalz at openssl.org (Rich Salz) Date: Thu, 01 Feb 2018 18:23:21 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517509401.196692.17544.nullmailer@dev.openssl.org> The branch master has been updated via 3c5a61dd0f9d9a9eac098419bcaf47d1c296ca81 (commit) from 67c836e860c735cf1b039ef52973237fd26b74d6 (commit) - Log ----------------------------------------------------------------- commit 3c5a61dd0f9d9a9eac098419bcaf47d1c296ca81 Author: Michael Richardson Date: Thu Feb 1 13:22:48 2018 -0500 Add OPENSSL_VERSION_AT_LEAST added macro to create version number use the macro to build OPENSSL_VERSION_AT_LEAST(maj,min,fix) so that customers of libssl (such as ruby-openssl) do not need to be so aware of openssl version numbers. includes updates to ssl(7) and OPENSSL_VERSION_NUMBER(3) man page Reviewed-by: Richard Levitte Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5212) ----------------------------------------------------------------------- Summary of changes: doc/man3/OPENSSL_VERSION_NUMBER.pod | 5 +++++ doc/man7/ssl.pod | 6 ++++++ include/openssl/opensslv.h | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/doc/man3/OPENSSL_VERSION_NUMBER.pod b/doc/man3/OPENSSL_VERSION_NUMBER.pod index 6eca113..d5842c0 100644 --- a/doc/man3/OPENSSL_VERSION_NUMBER.pod +++ b/doc/man3/OPENSSL_VERSION_NUMBER.pod @@ -47,6 +47,11 @@ number was therefore 0x0090581f. OpenSSL_version_num() returns the version number. +The macro OPENSSL_VERSION_AT_LEAST(major,minor) can be used at compile +time test if the current version is at least as new as the version provided. +The arguments major, minor and fix correspond to the version information +as given above. + OpenSSL_version() returns different strings depending on B: =over 4 diff --git a/doc/man7/ssl.pod b/doc/man7/ssl.pod index 724fc78..066b325 100644 --- a/doc/man7/ssl.pod +++ b/doc/man7/ssl.pod @@ -89,6 +89,12 @@ includes both more private SSL headers and headers from the B library. Whenever you need hard-core details on the internals of the SSL API, look inside this header file. +OPENSSL_VERSION_AT_LEAST(major,minor) can be +used in C<#if> statements in order to determine which version of the library is +being used. This can be used to either enable optional features at compile +time, or work around issues with a previous version. +See L. + =item B Unused. Present for backwards compatibility only. diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index c6e15a5..420a1c9 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -42,6 +42,11 @@ extern "C" { # define OPENSSL_VERSION_NUMBER 0x10101000L # define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1-dev xx XXX xxxx" +#define OPENSSL_MAKE_VERSION(maj,min,fix,patch) ((0x10000000L)+((maj&0xff)<<20)+((min&0xff)<<12)+((fix&0xff)<<4)+patch) + +/* use this for #if tests, should never depend upon fix/patch */ +#define OPENSSL_VERSION_AT_LEAST(maj,min) (OPENSSL_MAKE_VERSION(maj,min, 0, 0) >= OPENSSL_VERSION_NUMBER) + /*- * The macros below are to be used for shared library (.so, .dll, ...) * versioning. That kind of versioning works a bit differently between From builds at travis-ci.org Thu Feb 1 17:53:47 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 17:53:47 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16024 (master - e43e6b1) In-Reply-To: Message-ID: <5a73542b210cf_43f99ee3fba70146079@6f1e7807-ba31-4302-beba-07cf17cd0e30.mail> Build Update for openssl/openssl ------------------------------------- Build: #16024 Status: Still Failing Duration: 33 minutes and 21 seconds Commit: e43e6b1 (master) Author: Todd Short Message: Fix some minor code nits Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) View the changeset: https://github.com/openssl/openssl/compare/848a950b715f...e43e6b1951de View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336201545?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From rsalz at openssl.org Thu Feb 1 18:27:43 2018 From: rsalz at openssl.org (Rich Salz) Date: Thu, 01 Feb 2018 18:27:43 +0000 Subject: [openssl-commits] [openssl] OpenSSL_1_1_0-stable update Message-ID: <1517509663.057882.22619.nullmailer@dev.openssl.org> The branch OpenSSL_1_1_0-stable has been updated via d8adfdcd2e5de23f3e1d1a1d10c2fda6f4a65c4a (commit) from d4577a1474cd67afbfa5a48729c979180144b9d6 (commit) - Log ----------------------------------------------------------------- commit d8adfdcd2e5de23f3e1d1a1d10c2fda6f4a65c4a Author: Michael Richardson Date: Thu Feb 1 13:22:48 2018 -0500 Add OPENSSL_VERSION_AT_LEAST added macro to create version number use the macro to build OPENSSL_VERSION_AT_LEAST(maj,min,fix) so that customers of libssl (such as ruby-openssl) do not need to be so aware of openssl version numbers. includes updates to ssl(7) and OPENSSL_VERSION_NUMBER(3) man page Reviewed-by: Richard Levitte Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5212) (cherry picked from commit 3c5a61dd0f9d9a9eac098419bcaf47d1c296ca81) ----------------------------------------------------------------------- Summary of changes: doc/crypto/OPENSSL_VERSION_NUMBER.pod | 5 +++++ doc/ssl/ssl.pod | 6 ++++++ include/openssl/opensslv.h | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/doc/crypto/OPENSSL_VERSION_NUMBER.pod b/doc/crypto/OPENSSL_VERSION_NUMBER.pod index 9cc1ed1..6e23abf 100644 --- a/doc/crypto/OPENSSL_VERSION_NUMBER.pod +++ b/doc/crypto/OPENSSL_VERSION_NUMBER.pod @@ -47,6 +47,11 @@ number was therefore 0x0090581f. OpenSSL_version_num() returns the version number. +The macro OPENSSL_VERSION_AT_LEAST(major,minor) can be used at compile +time test if the current version is at least as new as the version provided. +The arguments major, minor and fix correspond to the version information +as given above. + OpenSSL_version() returns different strings depending on B: =over 4 diff --git a/doc/ssl/ssl.pod b/doc/ssl/ssl.pod index daee30d..3b17ec1 100644 --- a/doc/ssl/ssl.pod +++ b/doc/ssl/ssl.pod @@ -91,6 +91,12 @@ includes both more private SSL headers and headers from the B library. Whenever you need hard-core details on the internals of the SSL API, look inside this header file. +OPENSSL_VERSION_AT_LEAST(major,minor) can be +used in C<#if> statements in order to determine which version of the library is +being used. This can be used to either enable optional features at compile +time, or work around issues with a previous version. +See L. + =item B Unused. Present for backwards compatibility only. diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index 47cb0bf..a7a0136 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -46,6 +46,11 @@ extern "C" { # define OPENSSL_VERSION_TEXT "OpenSSL 1.1.0h-dev xx XXX xxxx" # endif +#define OPENSSL_MAKE_VERSION(maj,min,fix,patch) ((0x10000000L)+((maj&0xff)<<20)+((min&0xff)<<12)+((fix&0xff)<<4)+patch) + +/* use this for #if tests, should never depend upon fix/patch */ +#define OPENSSL_VERSION_AT_LEAST(maj,min) (OPENSSL_MAKE_VERSION(maj,min, 0, 0) >= OPENSSL_VERSION_NUMBER) + /*- * The macros below are to be used for shared library (.so, .dll, ...) * versioning. That kind of versioning works a bit differently between From builds at travis-ci.org Thu Feb 1 18:48:26 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 18:48:26 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16027 (master - 3454407) In-Reply-To: Message-ID: <5a7360fa7a8be_43f99ee3fba701544139@6f1e7807-ba31-4302-beba-07cf17cd0e30.mail> Build Update for openssl/openssl ------------------------------------- Build: #16027 Status: Still Failing Duration: 30 minutes and 3 seconds Commit: 3454407 (master) Author: Richard Levitte Message: VMS: MMS wants a space before the target / dependecies separator So as not to be mixed up with a device specification... Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/5234) View the changeset: https://github.com/openssl/openssl/compare/e43e6b1951de...34544072e9bc View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336224446?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at travis-ci.org Thu Feb 1 19:03:12 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 19:03:12 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16028 (master - 67c836e) In-Reply-To: Message-ID: <5a73647067208_43f99f0a24468156613e@6f1e7807-ba31-4302-beba-07cf17cd0e30.mail> Build Update for openssl/openssl ------------------------------------- Build: #16028 Status: Still Failing Duration: 38 minutes and 36 seconds Commit: 67c836e (master) Author: Rich Salz Message: Shorten output by a line Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/5238) View the changeset: https://github.com/openssl/openssl/compare/34544072e9bc...67c836e860c7 View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336224843?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at travis-ci.org Thu Feb 1 19:17:05 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 19:17:05 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16029 (master - 3c5a61d) In-Reply-To: Message-ID: <5a7367b1c4b72_43fc62c152070182417@9cde2705-86f2-43ab-a9e0-15a89b8526cf.mail> Build Update for openssl/openssl ------------------------------------- Build: #16029 Status: Still Failing Duration: 37 minutes and 32 seconds Commit: 3c5a61d (master) Author: Michael Richardson Message: Add OPENSSL_VERSION_AT_LEAST added macro to create version number use the macro to build OPENSSL_VERSION_AT_LEAST(maj,min,fix) so that customers of libssl (such as ruby-openssl) do not need to be so aware of openssl version numbers. includes updates to ssl(7) and OPENSSL_VERSION_NUMBER(3) man page Reviewed-by: Richard Levitte Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5212) View the changeset: https://github.com/openssl/openssl/compare/67c836e860c7...3c5a61dd0f9d View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336226632?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From appro at openssl.org Thu Feb 1 20:46:11 2018 From: appro at openssl.org (Andy Polyakov) Date: Thu, 01 Feb 2018 20:46:11 +0000 Subject: [openssl-commits] [openssl] OpenSSL_1_1_0-stable update Message-ID: <1517517971.036272.31057.nullmailer@dev.openssl.org> The branch OpenSSL_1_1_0-stable has been updated via 723183b5640e9b047acac189c7c7fb78575522d4 (commit) via 0b9373ce3c2d39d9a88634913b8191ad4f7a453c (commit) from d8adfdcd2e5de23f3e1d1a1d10c2fda6f4a65c4a (commit) - Log ----------------------------------------------------------------- commit 723183b5640e9b047acac189c7c7fb78575522d4 Author: David Benjamin Date: Tue Jan 23 13:57:10 2018 -0500 Don't leak the exponent bit width in BN_mod_exp_mont_consttime. The exponent here is one of d, dmp1, or dmq1 for RSA. This value and its bit length are both secret. The only public upper bound is the bit width of the corresponding modulus (RSA n, p, and q, respectively). Although BN_num_bits is constant-time (sort of; see bn_correct_top notes in preceding patch), this does not fix the root problem, which is that the windows are based on the minimal bit width, not the upper bound. We could use BN_num_bits(m), but BN_mod_exp_mont_consttime is public API and may be called with larger exponents. Instead, use all top*BN_BITS2 bits in the BIGNUM. This is still sensitive to the long-standing bn_correct_top leak, but we need to fix that regardless. This may cause us to do a handful of extra multiplications for RSA keys which are just above a whole number of words, but that is not a standard RSA key size. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) (cherry picked from commit 39eeb64f59ff838f976ad305de7d15747d47a41c) commit 0b9373ce3c2d39d9a88634913b8191ad4f7a453c Author: David Benjamin Date: Tue Jan 23 13:46:53 2018 -0500 Make BN_num_bits_word constant-time. (This patch was written by Andy Polyakov. I only wrote the commit message. Mistakes in the analysis are my fault.) BN_num_bits, by way of BN_num_bits_word, currently leaks the most-significant word of its argument via branching and memory access pattern. BN_num_bits is called on RSA prime factors in various places. These have public bit lengths, but all bits beyond the high bit are secret. This fully resolves those cases. There are a few places where BN_num_bits is called on an input where the bit length is also secret. This does *not* fully resolve those cases as we still only look at the top word. Today, that is guaranteed to be non-zero, but only because of the long-standing bn_correct_top timing leak. Once that is fixed, a constant-time BN_num_bits on such inputs must count bits on each word. Instead, those cases should not call BN_num_bits at all. In particular, BN_mod_exp_mont_consttime uses the exponent bit width to pick windows, but it should be using the maximum bit width. The next patch will fix this. Thanks to Dinghao Wu, Danfeng Zhang, Shuai Wang, Pei Wang, and Xiao Liu for reporting this issue. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) (cherry picked from commit 972c87dfc7e765bd28a4964519c362f0d3a58ca4) ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_exp.c | 6 ++- crypto/bn/bn_lib.c | 107 ++++++++++++++++++++--------------------------------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 7ebaeb0..8073368 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -633,7 +633,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, top = m->top; - bits = BN_num_bits(p); + /* + * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + * whether the top bits are zero. + */ + bits = p->top * BN_BITS2; if (bits == 0) { /* x**0 mod 1 is still zero. */ if (BN_is_one(m)) { diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index b8d4468..6081e88 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -88,74 +88,47 @@ const BIGNUM *BN_value_one(void) int BN_num_bits_word(BN_ULONG l) { - static const unsigned char bits[256] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - }; - -#if defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffffffff00000000L) { - if (l & 0xffff000000000000L) { - if (l & 0xff00000000000000L) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000L) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -#else -# ifdef SIXTY_FOUR_BIT - if (l & 0xffffffff00000000LL) { - if (l & 0xffff000000000000LL) { - if (l & 0xff00000000000000LL) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000LL) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -# endif -#endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffff0000L) { - if (l & 0xff000000L) - return (bits[(int)(l >> 24L)] + 24); - else - return (bits[(int)(l >> 16L)] + 16); - } else + BN_ULONG x, mask; + int bits = (l != 0); + +#if BN_BITS2 > 32 + x = l >> 32; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 32 & mask; + l ^= (x ^ l) & mask; #endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xff00L) - return (bits[(int)(l >> 8)] + 8); - else -#endif - return (bits[(int)(l)]); - } - } + + x = l >> 16; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 16 & mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 8 & mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 4 & mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 2 & mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 1 & mask; + + return bits; } int BN_num_bits(const BIGNUM *a) From appro at openssl.org Thu Feb 1 20:46:11 2018 From: appro at openssl.org (Andy Polyakov) Date: Thu, 01 Feb 2018 20:46:11 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517517971.131544.31080.nullmailer@dev.openssl.org> The branch master has been updated via 39eeb64f59ff838f976ad305de7d15747d47a41c (commit) via 972c87dfc7e765bd28a4964519c362f0d3a58ca4 (commit) from 3c5a61dd0f9d9a9eac098419bcaf47d1c296ca81 (commit) - Log ----------------------------------------------------------------- commit 39eeb64f59ff838f976ad305de7d15747d47a41c Author: David Benjamin Date: Tue Jan 23 13:57:10 2018 -0500 Don't leak the exponent bit width in BN_mod_exp_mont_consttime. The exponent here is one of d, dmp1, or dmq1 for RSA. This value and its bit length are both secret. The only public upper bound is the bit width of the corresponding modulus (RSA n, p, and q, respectively). Although BN_num_bits is constant-time (sort of; see bn_correct_top notes in preceding patch), this does not fix the root problem, which is that the windows are based on the minimal bit width, not the upper bound. We could use BN_num_bits(m), but BN_mod_exp_mont_consttime is public API and may be called with larger exponents. Instead, use all top*BN_BITS2 bits in the BIGNUM. This is still sensitive to the long-standing bn_correct_top leak, but we need to fix that regardless. This may cause us to do a handful of extra multiplications for RSA keys which are just above a whole number of words, but that is not a standard RSA key size. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) commit 972c87dfc7e765bd28a4964519c362f0d3a58ca4 Author: David Benjamin Date: Tue Jan 23 13:46:53 2018 -0500 Make BN_num_bits_word constant-time. (This patch was written by Andy Polyakov. I only wrote the commit message. Mistakes in the analysis are my fault.) BN_num_bits, by way of BN_num_bits_word, currently leaks the most-significant word of its argument via branching and memory access pattern. BN_num_bits is called on RSA prime factors in various places. These have public bit lengths, but all bits beyond the high bit are secret. This fully resolves those cases. There are a few places where BN_num_bits is called on an input where the bit length is also secret. This does *not* fully resolve those cases as we still only look at the top word. Today, that is guaranteed to be non-zero, but only because of the long-standing bn_correct_top timing leak. Once that is fixed, a constant-time BN_num_bits on such inputs must count bits on each word. Instead, those cases should not call BN_num_bits at all. In particular, BN_mod_exp_mont_consttime uses the exponent bit width to pick windows, but it should be using the maximum bit width. The next patch will fix this. Thanks to Dinghao Wu, Danfeng Zhang, Shuai Wang, Pei Wang, and Xiao Liu for reporting this issue. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_exp.c | 6 ++- crypto/bn/bn_lib.c | 107 ++++++++++++++++++++--------------------------------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 69970e6..b786bf0 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -623,7 +623,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, top = m->top; - bits = BN_num_bits(p); + /* + * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + * whether the top bits are zero. + */ + bits = p->top * BN_BITS2; if (bits == 0) { /* x**0 mod 1 is still zero. */ if (BN_is_one(m)) { diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index b9f19d8..57fe452 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -88,74 +88,47 @@ const BIGNUM *BN_value_one(void) int BN_num_bits_word(BN_ULONG l) { - static const unsigned char bits[256] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - }; - -#if defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffffffff00000000L) { - if (l & 0xffff000000000000L) { - if (l & 0xff00000000000000L) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000L) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -#else -# ifdef SIXTY_FOUR_BIT - if (l & 0xffffffff00000000LL) { - if (l & 0xffff000000000000LL) { - if (l & 0xff00000000000000LL) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000LL) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -# endif -#endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffff0000L) { - if (l & 0xff000000L) - return (bits[(int)(l >> 24L)] + 24); - else - return (bits[(int)(l >> 16L)] + 16); - } else -#endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xff00L) - return (bits[(int)(l >> 8)] + 8); - else + BN_ULONG x, mask; + int bits = (l != 0); + +#if BN_BITS2 > 32 + x = l >> 32; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 32 & mask; + l ^= (x ^ l) & mask; #endif - return (bits[(int)(l)]); - } - } + + x = l >> 16; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 16 & mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 8 & mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 4 & mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 2 & mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 1 & mask; + + return bits; } int BN_num_bits(const BIGNUM *a) From appro at openssl.org Thu Feb 1 20:48:11 2018 From: appro at openssl.org (Andy Polyakov) Date: Thu, 01 Feb 2018 20:48:11 +0000 Subject: [openssl-commits] [openssl] OpenSSL_1_0_2-stable update Message-ID: <1517518091.502376.2105.nullmailer@dev.openssl.org> The branch OpenSSL_1_0_2-stable has been updated via 4981e6fc1da4aec6775fc248643c91dd1e87e0b7 (commit) via 66509ddbd00179e8be58d54cf5576fb6b74d0131 (commit) from d498e526832bd6c50238f3dc0bcac9375179926e (commit) - Log ----------------------------------------------------------------- commit 4981e6fc1da4aec6775fc248643c91dd1e87e0b7 Author: David Benjamin Date: Tue Jan 23 13:57:10 2018 -0500 Don't leak the exponent bit width in BN_mod_exp_mont_consttime. The exponent here is one of d, dmp1, or dmq1 for RSA. This value and its bit length are both secret. The only public upper bound is the bit width of the corresponding modulus (RSA n, p, and q, respectively). Although BN_num_bits is constant-time (sort of; see bn_correct_top notes in preceding patch), this does not fix the root problem, which is that the windows are based on the minimal bit width, not the upper bound. We could use BN_num_bits(m), but BN_mod_exp_mont_consttime is public API and may be called with larger exponents. Instead, use all top*BN_BITS2 bits in the BIGNUM. This is still sensitive to the long-standing bn_correct_top leak, but we need to fix that regardless. This may cause us to do a handful of extra multiplications for RSA keys which are just above a whole number of words, but that is not a standard RSA key size. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) (cherry picked from commit 39eeb64f59ff838f976ad305de7d15747d47a41c) commit 66509ddbd00179e8be58d54cf5576fb6b74d0131 Author: David Benjamin Date: Tue Jan 23 13:46:53 2018 -0500 Make BN_num_bits_word constant-time. (This patch was written by Andy Polyakov. I only wrote the commit message. Mistakes in the analysis are my fault.) BN_num_bits, by way of BN_num_bits_word, currently leaks the most-significant word of its argument via branching and memory access pattern. BN_num_bits is called on RSA prime factors in various places. These have public bit lengths, but all bits beyond the high bit are secret. This fully resolves those cases. There are a few places where BN_num_bits is called on an input where the bit length is also secret. This does *not* fully resolve those cases as we still only look at the top word. Today, that is guaranteed to be non-zero, but only because of the long-standing bn_correct_top timing leak. Once that is fixed, a constant-time BN_num_bits on such inputs must count bits on each word. Instead, those cases should not call BN_num_bits at all. In particular, BN_mod_exp_mont_consttime uses the exponent bit width to pick windows, but it should be using the maximum bit width. The next patch will fix this. Thanks to Dinghao Wu, Danfeng Zhang, Shuai Wang, Pei Wang, and Xiao Liu for reporting this issue. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) (cherry picked from commit 972c87dfc7e765bd28a4964519c362f0d3a58ca4) ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_exp.c | 6 ++- crypto/bn/bn_lib.c | 107 ++++++++++++++++++++--------------------------------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index c4b63e4..9fc545a 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -727,7 +727,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, top = m->top; - bits = BN_num_bits(p); + /* + * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + * whether the top bits are zero. + */ + bits = p->top * BN_BITS2; if (bits == 0) { /* x**0 mod 1 is still zero. */ if (BN_is_one(m)) { diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 10b78f5..27b9bdb 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -144,74 +144,47 @@ const BIGNUM *BN_value_one(void) int BN_num_bits_word(BN_ULONG l) { - static const unsigned char bits[256] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - }; - -#if defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffffffff00000000L) { - if (l & 0xffff000000000000L) { - if (l & 0xff00000000000000L) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000L) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -#else -# ifdef SIXTY_FOUR_BIT - if (l & 0xffffffff00000000LL) { - if (l & 0xffff000000000000LL) { - if (l & 0xff00000000000000LL) { - return (bits[(int)(l >> 56)] + 56); - } else - return (bits[(int)(l >> 48)] + 48); - } else { - if (l & 0x0000ff0000000000LL) { - return (bits[(int)(l >> 40)] + 40); - } else - return (bits[(int)(l >> 32)] + 32); - } - } else -# endif -#endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xffff0000L) { - if (l & 0xff000000L) - return (bits[(int)(l >> 24L)] + 24); - else - return (bits[(int)(l >> 16L)] + 16); - } else + BN_ULONG x, mask; + int bits = (l != 0); + +#if BN_BITS2 > 32 + x = l >> 32; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 32 & mask; + l ^= (x ^ l) & mask; #endif - { -#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) - if (l & 0xff00L) - return (bits[(int)(l >> 8)] + 8); - else -#endif - return (bits[(int)(l)]); - } - } + + x = l >> 16; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 16 & mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 8 & mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 4 & mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 2 & mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 1 & mask; + + return bits; } int BN_num_bits(const BIGNUM *a) From appro at openssl.org Thu Feb 1 20:53:10 2018 From: appro at openssl.org (Andy Polyakov) Date: Thu, 01 Feb 2018 20:53:10 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517518390.319396.7805.nullmailer@dev.openssl.org> The branch master has been updated via f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09 (commit) from 39eeb64f59ff838f976ad305de7d15747d47a41c (commit) - Log ----------------------------------------------------------------- commit f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09 Author: David Benjamin Date: Wed Jan 31 14:47:41 2018 -0500 Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. Reviewed-by: Andy Polyakov Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5228) ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_mont.c | 57 +++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 2119bfa..6357c60 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -101,6 +101,11 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) r->top = max; n0 = mont->n0[0]; + /* + * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On + * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| + * includes |carry| which is stored separately. + */ for (carry = 0, i = 0; i < nl; i++, rp++) { v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); v = (v + carry + rp[nl]) & BN_MASK2; @@ -115,46 +120,24 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ret->neg = r->neg; rp = ret->d; - ap = &(r->d[nl]); -# define BRANCH_FREE 1 -# if BRANCH_FREE - { - BN_ULONG *nrp; - size_t m; + /* + * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap| + * includes |carry| which is stored separately. + */ + ap = &(r->d[nl]); - v = bn_sub_words(rp, ap, np, nl) - carry; - /* - * if subtraction result is real, then trick unconditional memcpy - * below to perform in-place "refresh" instead of actual copy. - */ - m = (0 - (size_t)v); - nrp = - (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m)); - - for (i = 0, nl -= 4; i < nl; i += 4) { - BN_ULONG t1, t2, t3, t4; - - t1 = nrp[i + 0]; - t2 = nrp[i + 1]; - t3 = nrp[i + 2]; - ap[i + 0] = 0; - t4 = nrp[i + 3]; - ap[i + 1] = 0; - rp[i + 0] = t1; - ap[i + 2] = 0; - rp[i + 1] = t2; - ap[i + 3] = 0; - rp[i + 2] = t3; - rp[i + 3] = t4; - } - for (nl += 4; i < nl; i++) - rp[i] = nrp[i], ap[i] = 0; + /* + * |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v| + * cannot be -1. That would imply the subtraction did not fit in |nl| words, + * and we know at most one subtraction is needed. + */ + v = bn_sub_words(rp, ap, np, nl) - carry; + v = 0 - v; + for (i = 0; i < nl; i++) { + rp[i] = (v & ap[i]) | (~v & rp[i]); + ap[i] = 0; } -# else - if (bn_sub_words(rp, ap, np, nl) - carry) - memcpy(rp, ap, nl * sizeof(BN_ULONG)); -# endif bn_correct_top(r); bn_correct_top(ret); bn_check_top(ret); From appro at openssl.org Thu Feb 1 20:54:06 2018 From: appro at openssl.org (Andy Polyakov) Date: Thu, 01 Feb 2018 20:54:06 +0000 Subject: [openssl-commits] [openssl] OpenSSL_1_1_0-stable update Message-ID: <1517518446.382803.9324.nullmailer@dev.openssl.org> The branch OpenSSL_1_1_0-stable has been updated via db91094a49b370acf03cf6adfcacf2256b8bd153 (commit) from 723183b5640e9b047acac189c7c7fb78575522d4 (commit) - Log ----------------------------------------------------------------- commit db91094a49b370acf03cf6adfcacf2256b8bd153 Author: David Benjamin Date: Wed Jan 31 14:47:41 2018 -0500 Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. Reviewed-by: Andy Polyakov Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5228) (cherry picked from commit f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09) ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_mont.c | 57 +++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 90e1ba2..65889bf 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -101,6 +101,11 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) r->top = max; n0 = mont->n0[0]; + /* + * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On + * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| + * includes |carry| which is stored separately. + */ for (carry = 0, i = 0; i < nl; i++, rp++) { v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); v = (v + carry + rp[nl]) & BN_MASK2; @@ -115,46 +120,24 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ret->neg = r->neg; rp = ret->d; - ap = &(r->d[nl]); -# define BRANCH_FREE 1 -# if BRANCH_FREE - { - BN_ULONG *nrp; - size_t m; + /* + * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap| + * includes |carry| which is stored separately. + */ + ap = &(r->d[nl]); - v = bn_sub_words(rp, ap, np, nl) - carry; - /* - * if subtraction result is real, then trick unconditional memcpy - * below to perform in-place "refresh" instead of actual copy. - */ - m = (0 - (size_t)v); - nrp = - (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m)); - - for (i = 0, nl -= 4; i < nl; i += 4) { - BN_ULONG t1, t2, t3, t4; - - t1 = nrp[i + 0]; - t2 = nrp[i + 1]; - t3 = nrp[i + 2]; - ap[i + 0] = 0; - t4 = nrp[i + 3]; - ap[i + 1] = 0; - rp[i + 0] = t1; - ap[i + 2] = 0; - rp[i + 1] = t2; - ap[i + 3] = 0; - rp[i + 2] = t3; - rp[i + 3] = t4; - } - for (nl += 4; i < nl; i++) - rp[i] = nrp[i], ap[i] = 0; + /* + * |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v| + * cannot be -1. That would imply the subtraction did not fit in |nl| words, + * and we know at most one subtraction is needed. + */ + v = bn_sub_words(rp, ap, np, nl) - carry; + v = 0 - v; + for (i = 0; i < nl; i++) { + rp[i] = (v & ap[i]) | (~v & rp[i]); + ap[i] = 0; } -# else - if (bn_sub_words(rp, ap, np, nl) - carry) - memcpy(rp, ap, nl * sizeof(BN_ULONG)); -# endif bn_correct_top(r); bn_correct_top(ret); bn_check_top(ret); From levitte at openssl.org Thu Feb 1 21:09:45 2018 From: levitte at openssl.org (Richard Levitte) Date: Thu, 01 Feb 2018 21:09:45 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517519385.037469.25934.nullmailer@dev.openssl.org> The branch master has been updated via 03cb2cc9e53f7ca7539069a388d2767fffa7cf66 (commit) from f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09 (commit) - Log ----------------------------------------------------------------- commit 03cb2cc9e53f7ca7539069a388d2767fffa7cf66 Author: Richard Levitte Date: Thu Feb 1 21:28:59 2018 +0100 Fix of prefix bio filter (bf_prefix.c): rely on the given length The assumption that the received buffer has to be NUL-terminated was faulty. Fault found in #5224 Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5239) ----------------------------------------------------------------------- Summary of changes: apps/bf_prefix.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c index 4d5e3a3..bae3c91 100644 --- a/apps/bf_prefix.c +++ b/apps/bf_prefix.c @@ -96,7 +96,7 @@ static int prefix_write(BIO *b, const char *out, size_t outl, *numwritten = 0; - while (*out != '\0') { + while (outl > 0) { size_t i; char c; @@ -111,7 +111,7 @@ static int prefix_write(BIO *b, const char *out, size_t outl, } /* Now, go look for the next LF, or the end of the string */ - for (i = 0; (c = out[i]) != '\n' && c != '\0'; i++) + for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) continue; if (c == '\n') i++; @@ -123,6 +123,7 @@ static int prefix_write(BIO *b, const char *out, size_t outl, if (!BIO_write_ex(BIO_next(b), out, i, &num)) return 0; out += num; + outl -= num; *numwritten += num; i -= num; } From builds at travis-ci.org Thu Feb 1 21:17:58 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 21:17:58 +0000 Subject: [openssl-commits] Errored: openssl/openssl#16033 (master - 39eeb64) In-Reply-To: Message-ID: <5a738404abf0a_43f99f4c6d1f81777512@6f1e7807-ba31-4302-beba-07cf17cd0e30.mail> Build Update for openssl/openssl ------------------------------------- Build: #16033 Status: Errored Duration: 24 minutes and 13 seconds Commit: 39eeb64 (master) Author: David Benjamin Message: Don't leak the exponent bit width in BN_mod_exp_mont_consttime. The exponent here is one of d, dmp1, or dmq1 for RSA. This value and its bit length are both secret. The only public upper bound is the bit width of the corresponding modulus (RSA n, p, and q, respectively). Although BN_num_bits is constant-time (sort of; see bn_correct_top notes in preceding patch), this does not fix the root problem, which is that the windows are based on the minimal bit width, not the upper bound. We could use BN_num_bits(m), but BN_mod_exp_mont_consttime is public API and may be called with larger exponents. Instead, use all top*BN_BITS2 bits in the BIGNUM. This is still sensitive to the long-standing bn_correct_top leak, but we need to fix that regardless. This may cause us to do a handful of extra multiplications for RSA keys which are just above a whole number of words, but that is not a standard RSA key size. Reviewed-by: Paul Dale Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5154) View the changeset: https://github.com/openssl/openssl/compare/3c5a61dd0f9d...39eeb64f59ff View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336282420?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at travis-ci.org Thu Feb 1 21:34:37 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 21:34:37 +0000 Subject: [openssl-commits] Errored: openssl/openssl#16036 (OpenSSL_1_1_0-stable - db91094) In-Reply-To: Message-ID: <5a73887ade5e4_43f89e30efeb41801074@e51d55cc-c6be-4a36-be0f-ddf49f2909b7.mail> Build Update for openssl/openssl ------------------------------------- Build: #16036 Status: Errored Duration: 19 minutes and 18 seconds Commit: db91094 (OpenSSL_1_1_0-stable) Author: David Benjamin Message: Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. Reviewed-by: Andy Polyakov Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5228) (cherry picked from commit f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09) View the changeset: https://github.com/openssl/openssl/compare/723183b5640e...db91094a49b3 View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336285391?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at travis-ci.org Thu Feb 1 21:40:37 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 21:40:37 +0000 Subject: [openssl-commits] Still Failing: openssl/openssl#16035 (master - f345b1f) In-Reply-To: Message-ID: <5a7389e2d8d68_43f89ed5174101811263@e51d55cc-c6be-4a36-be0f-ddf49f2909b7.mail> Build Update for openssl/openssl ------------------------------------- Build: #16035 Status: Still Failing Duration: 34 minutes and 25 seconds Commit: f345b1f (master) Author: David Benjamin Message: Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. Reviewed-by: Andy Polyakov Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5228) View the changeset: https://github.com/openssl/openssl/compare/39eeb64f59ff...f345b1f39d9b View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336285052?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at travis-ci.org Thu Feb 1 22:18:23 2018 From: builds at travis-ci.org (Travis CI) Date: Thu, 01 Feb 2018 22:18:23 +0000 Subject: [openssl-commits] Errored: openssl/openssl#16038 (master - 03cb2cc) In-Reply-To: Message-ID: <5a73922f2af99_43fcf7691c064114080@ddecd48c-d6f6-40cf-986a-99b8fb90cde8.mail> Build Update for openssl/openssl ------------------------------------- Build: #16038 Status: Errored Duration: 39 minutes and 30 seconds Commit: 03cb2cc (master) Author: Richard Levitte Message: Fix of prefix bio filter (bf_prefix.c): rely on the given length The assumption that the received buffer has to be NUL-terminated was faulty. Fault found in #5224 Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5239) View the changeset: https://github.com/openssl/openssl/compare/f345b1f39d9b...03cb2cc9e53f View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336291165?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From matt at openssl.org Fri Feb 2 10:06:37 2018 From: matt at openssl.org (Matt Caswell) Date: Fri, 02 Feb 2018 10:06:37 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517565997.863123.30763.nullmailer@dev.openssl.org> The branch master has been updated via 22da44fce9ca198d9115e2852e6f9a0183e56886 (commit) from 03cb2cc9e53f7ca7539069a388d2767fffa7cf66 (commit) - Log ----------------------------------------------------------------- commit 22da44fce9ca198d9115e2852e6f9a0183e56886 Author: Matt Caswell Date: Thu Feb 1 17:40:17 2018 +0000 Document SSL_OP_ENABLE_MIDDLEBOX_COMPAT Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5237) ----------------------------------------------------------------------- Summary of changes: doc/man3/SSL_CTX_set_options.pod | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod index ba9a95f..0d51077 100644 --- a/doc/man3/SSL_CTX_set_options.pod +++ b/doc/man3/SSL_CTX_set_options.pod @@ -189,6 +189,15 @@ those clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server cipher list; but still allows other clients to use AES and other ciphers. Requires B. +=item SSL_OP_ENABLE_MIDDLEBOX_COMPAT + +If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This +has the effect of making TLSv1.3 look more like TLSv1.2 so that middleboxes that +do not understand TLSv1.3 will not drop the connection. Regardless of whether +this option is set or not CCS messages received from the peer will always be +ignored in TLSv1.3. This option is set by default. To switch it off use +SSL_clear_options(). A future version of OpenSSL may not set this by default. + =back The following options no longer have any effect but their identifiers are From builds at travis-ci.org Fri Feb 2 10:39:01 2018 From: builds at travis-ci.org (Travis CI) Date: Fri, 02 Feb 2018 10:39:01 +0000 Subject: [openssl-commits] Passed: openssl/openssl#16047 (master - 22da44f) In-Reply-To: Message-ID: <5a743fc44317e_43fa28f04b6606897b2@e3a217df-7e6b-497f-9547-ac4ea8da33a1.mail> Build Update for openssl/openssl ------------------------------------- Build: #16047 Status: Passed Duration: 31 minutes and 27 seconds Commit: 22da44f (master) Author: Matt Caswell Message: Document SSL_OP_ENABLE_MIDDLEBOX_COMPAT Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5237) View the changeset: https://github.com/openssl/openssl/compare/03cb2cc9e53f...22da44fce9ca View the full build log and details: https://travis-ci.org/openssl/openssl/builds/336485681?utm_source=email&utm_medium=notification -- You can configure recipients for build notifications in your .travis.yml file. See https://docs.travis-ci.com/user/notifications -------------- next part -------------- An HTML attachment was scrubbed... URL: From levitte at openssl.org Fri Feb 2 11:43:40 2018 From: levitte at openssl.org (Richard Levitte) Date: Fri, 02 Feb 2018 11:43:40 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517571820.789431.20831.nullmailer@dev.openssl.org> The branch master has been updated via 50ea9d2b3521467a11559be41dcf05ee05feabd6 (commit) from 22da44fce9ca198d9115e2852e6f9a0183e56886 (commit) - Log ----------------------------------------------------------------- commit 50ea9d2b3521467a11559be41dcf05ee05feabd6 Author: Richard Levitte Date: Fri Feb 2 10:33:41 2018 +0100 Have configdata.pm also display the contents of %target Reviewed-by: Andy Polyakov (Merged from https://github.com/openssl/openssl/pull/5243) ----------------------------------------------------------------------- Summary of changes: Configure | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Configure b/Configure index a994876..22d42fb 100755 --- a/Configure +++ b/Configure @@ -2331,6 +2331,7 @@ unless (caller) { my $dump = undef; my $cmdline = undef; my $options = undef; + my $target = undef; my $envvars = undef; my $makevars = undef; my $buildparams = undef; @@ -2341,6 +2342,7 @@ unless (caller) { GetOptions('dump|d' => \$dump, 'command-line|c' => \$cmdline, 'options|o' => \$options, + 'target|t' => \$target, 'environment|e' => \$envvars, 'make-variables|m' => \$makevars, 'build-parameters|b' => \$buildparams, @@ -2350,7 +2352,7 @@ unless (caller) { 'man' => \$man) or die "Errors in command line arguments\n"; - unless ($dump || $cmdline || $options || $envvars || $makevars + unless ($dump || $cmdline || $options || $target || $envvars || $makevars || $buildparams || $reconf || $verbose || $help || $man) { print STDERR <<"_____"; You must give at least one option. @@ -2399,6 +2401,21 @@ _____ } } } + if ($dump || $target) { + print "\nConfig target attributes:\n\n"; + foreach (sort keys %target) { + next if $_ =~ m|^_| || $_ eq 'template'; + my $quotify = sub { + map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_; + }; + print ' ', $_, ' => '; + if (ref($target{$_}) eq "ARRAY") { + print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; + } else { + print $quotify->($target{$_}), ",\n" + } + } + } if ($dump || $envvars) { print "\nRecorded environment:\n\n"; foreach (sort keys %{$config{perlenv}}) { @@ -2509,7 +2526,8 @@ Print the manual page and exit. =item B<--dump> | B<-d> Print all relevant configuration data. This is equivalent to B<--command-line> -B<--options> B<--environment> B<--make-variables> B<--build-parameters>. +B<--options> B<--target> B<--environment> B<--make-variables> +B<--build-parameters>. =item B<--command-line> | B<-c> @@ -2520,6 +2538,10 @@ Print the current configuration command line. Print the features, both enabled and disabled, and display defined macro and skipped directories where applicable. +=item B<--target> | B<-t> + +Print the config attributes for this config target. + =item B<--environment> | B<-e> Print the environment variables and their values at the time of configuration. From appro at openssl.org Fri Feb 2 22:15:41 2018 From: appro at openssl.org (Andy Polyakov) Date: Fri, 02 Feb 2018 22:15:41 +0000 Subject: [openssl-commits] [openssl] OpenSSL_1_0_2-stable update Message-ID: <1517609741.295032.12721.nullmailer@dev.openssl.org> The branch OpenSSL_1_0_2-stable has been updated via 48081cf988fc8f50215a2b18babd6a7859defd36 (commit) from 4981e6fc1da4aec6775fc248643c91dd1e87e0b7 (commit) - Log ----------------------------------------------------------------- commit 48081cf988fc8f50215a2b18babd6a7859defd36 Author: Andy Polyakov Date: Thu Feb 1 22:03:59 2018 +0100 Fix timing leak in BN_from_montgomery_word. BN_from_montgomery_word doesn't have a constant memory access pattern. Replace the pointer trick with a constant-time select. There is, of course, still the bn_correct_top leak pervasive in BIGNUM itself. See also https://boringssl-review.googlesource.com/22904 from BoringSSL. (backport from f345b1f39d9b4e4c9ef07e7522e9b2a870c9ca09 signed off by David Benjamin ) Reviewed-by: Kurt Roeckx ----------------------------------------------------------------------- Summary of changes: crypto/bn/bn_mont.c | 75 ++++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 55 deletions(-) diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 94e7a8f..49cf51a 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -207,26 +207,13 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) r->top = max; n0 = mont->n0[0]; -# ifdef BN_COUNT - fprintf(stderr, "word BN_from_montgomery_word %d * %d\n", nl, nl); -# endif + /* + * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On + * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| + * includes |carry| which is stored separately. + */ for (carry = 0, i = 0; i < nl; i++, rp++) { -# ifdef __TANDEM - { - long long t1; - long long t2; - long long t3; - t1 = rp[0] * (n0 & 0177777); - t2 = 037777600000l; - t2 = n0 & t2; - t3 = rp[0] & 0177777; - t2 = (t3 * t2) & BN_MASK2; - t1 = t1 + t2; - v = bn_mul_add_words(rp, np, nl, (BN_ULONG)t1); - } -# else v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); -# endif v = (v + carry + rp[nl]) & BN_MASK2; carry |= (v != rp[nl]); carry &= (v <= rp[nl]); @@ -239,46 +226,24 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ret->neg = r->neg; rp = ret->d; - ap = &(r->d[nl]); -# define BRANCH_FREE 1 -# if BRANCH_FREE - { - BN_ULONG *nrp; - size_t m; + /* + * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap| + * includes |carry| which is stored separately. + */ + ap = &(r->d[nl]); - v = bn_sub_words(rp, ap, np, nl) - carry; - /* - * if subtraction result is real, then trick unconditional memcpy - * below to perform in-place "refresh" instead of actual copy. - */ - m = (0 - (size_t)v); - nrp = - (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m)); - - for (i = 0, nl -= 4; i < nl; i += 4) { - BN_ULONG t1, t2, t3, t4; - - t1 = nrp[i + 0]; - t2 = nrp[i + 1]; - t3 = nrp[i + 2]; - ap[i + 0] = 0; - t4 = nrp[i + 3]; - ap[i + 1] = 0; - rp[i + 0] = t1; - ap[i + 2] = 0; - rp[i + 1] = t2; - ap[i + 3] = 0; - rp[i + 2] = t3; - rp[i + 3] = t4; - } - for (nl += 4; i < nl; i++) - rp[i] = nrp[i], ap[i] = 0; + /* + * |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v| + * cannot be -1. That would imply the subtraction did not fit in |nl| words, + * and we know at most one subtraction is needed. + */ + v = bn_sub_words(rp, ap, np, nl) - carry; + v = 0 - v; + for (i = 0; i < nl; i++) { + rp[i] = (v & ap[i]) | (~v & rp[i]); + ap[i] = 0; } -# else - if (bn_sub_words(rp, ap, np, nl) - carry) - memcpy(rp, ap, nl * sizeof(BN_ULONG)); -# endif bn_correct_top(r); bn_correct_top(ret); bn_check_top(ret); From matt at openssl.org Sat Feb 3 00:01:38 2018 From: matt at openssl.org (Matt Caswell) Date: Sat, 03 Feb 2018 00:01:38 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517616098.230569.17667.nullmailer@dev.openssl.org> The branch master has been updated via 1f5878b8e25a785dde330bf485e6ed5a6ae09a1a (commit) via b1a51abb935163cbb0b0089ad9ee8ff174341bbd (commit) via 2221ec10ab2771d7effad839392c88f35cde04a3 (commit) from 50ea9d2b3521467a11559be41dcf05ee05feabd6 (commit) - Log ----------------------------------------------------------------- commit 1f5878b8e25a785dde330bf485e6ed5a6ae09a1a Author: Tatsuhiro Tsujikawa Date: Sun Jan 21 11:30:36 2018 +0900 Make sure that exporting keying material is allowed Reviewed-by: Rich Salz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4944) commit b1a51abb935163cbb0b0089ad9ee8ff174341bbd Author: Tatsuhiro Tsujikawa Date: Thu Jan 18 15:39:45 2018 +0900 Remove generation of exporter master secret on client application traffic Reviewed-by: Rich Salz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4944) commit 2221ec10ab2771d7effad839392c88f35cde04a3 Author: Tatsuhiro Tsujikawa Date: Sat Dec 16 16:46:18 2017 +0900 Generate exporter_master_secret after server Finished Reviewed-by: Rich Salz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4944) ----------------------------------------------------------------------- Summary of changes: ssl/statem/statem.c | 10 ++++++++++ ssl/statem/statem.h | 1 + ssl/tls13_enc.c | 25 ++++++++++++------------- test/tls13secretstest.c | 5 +++++ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 45cb9ab..95c369a 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -941,3 +941,13 @@ int ossl_statem_app_data_allowed(SSL *s) return 0; } + +/* + * This function returns 1 if TLS exporter is ready to export keying + * material, or 0 if otherwise. + */ +int ossl_statem_export_allowed(SSL *s) +{ + return s->s3->previous_server_finished_len != 0 + && s->statem.hand_state != TLS_ST_SW_FINISHED; +} diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h index e8d9174..3242c78 100644 --- a/ssl/statem/statem.h +++ b/ssl/statem/statem.h @@ -132,6 +132,7 @@ __owur int ossl_statem_skip_early_data(SSL *s); void ossl_statem_check_finish_init(SSL *s, int send); void ossl_statem_set_hello_verify_done(SSL *s); __owur int ossl_statem_app_data_allowed(SSL *s); +__owur int ossl_statem_export_allowed(SSL *s); /* Flush the write BIO */ int statem_flush(SSL *s); diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index fe817f8..05355fb 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -562,16 +562,6 @@ int tls13_change_cipher_state(SSL *s, int which) goto err; } s->session->master_key_length = hashlen; - - /* Now we create the exporter master secret */ - if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, - exporter_master_secret, - sizeof(exporter_master_secret) - 1, - hash, hashlen, s->exporter_master_secret, - hashlen)) { - /* SSLfatal() already called */ - goto err; - } } if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher, @@ -581,9 +571,18 @@ int tls13_change_cipher_state(SSL *s, int which) goto err; } - if (label == server_application_traffic) + if (label == server_application_traffic) { memcpy(s->server_app_traffic_secret, secret, hashlen); - else if (label == client_application_traffic) + /* Now we create the exporter master secret */ + if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, + exporter_master_secret, + sizeof(exporter_master_secret) - 1, + hash, hashlen, s->exporter_master_secret, + hashlen)) { + /* SSLfatal() already called */ + goto err; + } + } else if (label == client_application_traffic) memcpy(s->client_app_traffic_secret, secret, hashlen); if (!ssl_log_secret(s, log_label, secret, hashlen)) { @@ -667,7 +666,7 @@ int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen, unsigned int hashsize, datalen; int ret = 0; - if (ctx == NULL || !SSL_is_init_finished(s)) + if (ctx == NULL || !ossl_statem_export_allowed(s)) goto err; if (!use_context) diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c index 16542c4..f08b5d3 100644 --- a/test/tls13secretstest.c +++ b/test/tls13secretstest.c @@ -212,6 +212,11 @@ void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file, { } +int ossl_statem_export_allowed(SSL *s) +{ + return 1; +} + /* End of mocked out code */ static int test_secret(SSL *s, unsigned char *prk, From rsalz at openssl.org Sat Feb 3 23:24:09 2018 From: rsalz at openssl.org (Rich Salz) Date: Sat, 03 Feb 2018 23:24:09 +0000 Subject: [openssl-commits] [tools] master update Message-ID: <1517700249.074535.13354.nullmailer@dev.openssl.org> The branch master has been updated via 27296557068a17464f17533d89d4fa6f3555b909 (commit) from bb40e3e6bcd68b3ba9ba4e71751d9f8e630f63cf (commit) - Log ----------------------------------------------------------------- commit 27296557068a17464f17533d89d4fa6f3555b909 Author: Rich Salz Date: Sat Feb 3 18:23:50 2018 -0500 Add our release tools ----------------------------------------------------------------------- Summary of changes: release-tools/MKRELEASE.md | 168 +++++++++++++++ release-tools/README.md | 320 +++++++++++++++++++++++++++++ release-tools/do-copyright-year | 40 ++++ release-tools/do-release.pl | 209 +++++++++++++++++++ release-tools/mkrelease.pl | 427 +++++++++++++++++++++++++++++++++++++++ release-tools/release-check.pl | 215 ++++++++++++++++++++ release-tools/release-date.pl | 64 ++++++ release-tools/release-git.pl | 164 +++++++++++++++ release-tools/release-update.pl | 153 ++++++++++++++ release-tools/release-version.pl | 179 ++++++++++++++++ 10 files changed, 1939 insertions(+) create mode 100644 release-tools/MKRELEASE.md create mode 100644 release-tools/README.md create mode 100755 release-tools/do-copyright-year create mode 100644 release-tools/do-release.pl create mode 100644 release-tools/mkrelease.pl create mode 100644 release-tools/release-check.pl create mode 100644 release-tools/release-date.pl create mode 100644 release-tools/release-git.pl create mode 100644 release-tools/release-update.pl create mode 100644 release-tools/release-version.pl diff --git a/release-tools/MKRELEASE.md b/release-tools/MKRELEASE.md new file mode 100644 index 0000000..04d6dc7 --- /dev/null +++ b/release-tools/MKRELEASE.md @@ -0,0 +1,168 @@ +# Documentation on the mkrelease.pl script + +This file provides an overview of the mkrelease.pl script, and how to +configure some of its parameters (by setting environment variables). +It is normally run by following the process in README.md and should be +run in a pristine directgory of the branch to be released, which must +be a stable branch. + +The script handles most of the processes involved in making a release +including: + +1. Doing `make update` +2. Changing version numbers in various files +3. Tagging release +4. Making the tarballs, .md5, .sha1, .sha256 and .gpg files +5. Creating the signed email announcement, including hashes of release +6. Uploading files to dev.openssl.org +7. Updating the version for next release + +If you plan to make an actual release make sure your GPG key is included +in the [OMC list](https://www.openssl.org/community/omc.html) on the website +and in the file doc/fingerprints.txt of *all* active branches. + +The script mkrelease.pl calls the files release-check.pl, release-date.pl, +release-git.pl, release-update.pl and release-version.pl, which are expected +to all be in the same directory. + +You are advised to clone a fresh repository. Unless you specify `--no-clean` +the release process will run `git clean -x -d -f` +*WARNING* this will delete ALL untracked files from the current branch. + +From the branch directory if you run: + + perl /path/to/mkrelease.pl --reviewer=name + +It should perform all of the above steps and commit changes locally. You can +then sanity check these with `git log` before pushing them to the public repo. + +## Environment Variables + +- OPENSSL
+ Path to openssl utility to use. Default is `openssl`. + +- OPENSSL_TAR
+ The tar command to use when creating the tarball. Default is `tar`. + +- OPENSSL_GPG
+ The gpg command to use when signing a tarball or announcement. + The default is `gpg` which will use gpg with the default key. + If you wish to use a different, key set OPENSSL_GPG to include + appropriate options. + +- OPENSSL_GPG_TAR
+ Command to use to sign a tarball. + The default is: `$OPENSSL_GPG --use-agent -sba` + +- OPENSSL_GPG_ANNOUNCE
+ The command to use to sign a tarball. + The default is: `$OPENSSL_GPG --use-agent -sta --clearsign` + +- OPENSSL_SCP
+ The command to use to upload files. + The default is `scp` + +- OPENSSL_SCP_HOST
+ The host (and optional username) needed to upload files. + The default is `dev.openssl.org`, but you might want to change this to + `username at dev.openssl.org` + +- OPENSSL_SCP_DIR
+ The directory to upload files to. + Normally this wont be changed from the default which is + `$OPENSSL_SCP_HOST:~openssl/dist/new` + This is a holding area on dev.openssl.org where distributions are uploaded + temporarily before being moved to the web and ftp directories. + +For local testing, you can do something like this: + + export OPENSSL_SCP=cp + export OPENSSL_SCP_DIR="$HOME/testdir" + +## Options + +- `--revert`
+ Remove all local changes from repository and delete any release tag. This + returns the local tree to the same state as before a release attempt was + made. + +- `--reviewer=name`
+ Add reviewer `name` to list of reviewers in commit message. Any valid + name for checking OMC membership will work. + This option may be used multiple times; at least one is required. + +- `--enter-pre`
+ Instead of making a full release enter pre-release state. This by itself + will not produce a release it will just change version numbers and commit + the changes. Subsequent releases on this branch will be pre-release + versions. This option should NOT be used if the branch is already in + pre-release state. + +- `--leave-pre`
+ For a branch in pre-release state, leave pre-release and make a full release. + +- `--label=label`
+ Add the textual label `label` to the version string, where `label` must be + one of `alpha` or `beta`. While in pre-release state a label *must* be + provided. + +- `--no-upload`
+ Do not attempt to upload release files to dev.openssl.org + +- `--no-clean`
+ Do not clean untracked files from directory. Warning: if you use this option + you can end up with extraneous files in the distribution tarball. + +- `--no-update`
+ Do not perform a `make update`. + +- `--verbose`
+ Be more verbose at what is going on + +- `--debug`
+ Include debug output to describe all actions in detail + +- `--git-info`
+ Just print out details of all git branch information and exit + +- `--git-branch-info`
+ Print out details of the currently detected branch and exit + +- `--branch-version=version`
+ Use branch `version` instead of the one autodetected for the current branch. + This option is not normally needed. + +# The do-release script + +The do-release.pl script copies distributions from the temporary holding area +to the http and ftp areas. It it intended to be run as the `openssl` user on +dev.openssl.org. + +It does the following: + +1. Copy OpenSSL release files from the holding area to the http and ftp + locations: currently /v/openssl/www/source and /v/openssl/ftp/source +2. Move OpenSSL release files from holding area to ~openssl/dist/old By + doing this the script wont try and make a release again with old files. +3. Mail the release message. This is sent to openssl-dev openssl-users and + openssl-announce (it needs to be approved in openssl-announce). The + subject line is `OpenSSL version xxx released`. + +## do-release options + +- `--copy`
+ Copy files to http and ftp directories. **You will have to manually move + the OLD files to old/ directories.** + +- `--move`
+ Move files from holding area to ~openssl/dist/old + +- `--mail`
+ Send out announcement email: if this option is not given, the command you + need to call to send the release mail will be printed out. + +- `--full-release`
+ Perform all operations for a release (copy, move and mail). + +Note: because several of these options are irreversible they have to be +explicitly included. diff --git a/release-tools/README.md b/release-tools/README.md new file mode 100644 index 0000000..7b3767e --- /dev/null +++ b/release-tools/README.md @@ -0,0 +1,320 @@ +# HOW TO MAKE A RELEASE + +This file documents how to make an OpenSSL release. Please fix any +errors you find while doing, or just after, your next release! + +Releases are done by one person, with a second person acting as the +reviewer and additional tester. + +## Pre-requisites + +Have a local clone of the website repo: + + openssl-git at git.openssl.org:openssl-web.git + +Make sure you can sudo to the openssl user on dev.openssl.org; this is +usually done by being in the openssl group. For example, ssh to the +server and run this command: + + sudo -u openssl id + +## Setup + +The day before the release, freeze the main repository. This locks out +everyone but the named user, who is doing the release, from doing any pushes. +Someone other than the person doing the release should run the command. +For example: + + ssh openssl-git at git.openssl.org freeze openssl NAME + +## Making the tarball and announcements + +This section generates the tarball and announcements locally. It makes +no changes which cannot be easily undone. You will have to repeat this +section for each version being released, so it is often easier to have +separate copies: + + git clone openssl-git at git.openssl.org:openssl.git rel-102 + cd rel-102 + git branch --track OpenSSL_1_0_2-stable origin/OpenSSL_1_0_2-stable + git checkout OpenSSL_1_0_2-stable + +Make sure that the CHANGES and NEWS files have been updated and reviewed. +NEWS should contain a summary of any changes for the release, and for a +security release is (often just a list of the CVEs addressed. You should also +update NEWS in the master branch to include details of all releases. Just +update the NEWS bullet points - do not change the release date, keep it as +**under development**. + +Add any security fixes to the tree. Commit them but *do not push*. + +Make sure that the copyrights are updated. This script will update +the copyright markers and commit the changes (where $HERE stands for +the directory where this README is): + + $HERE/do-copyright-year + +Perform the local automated release steps. This can normally be done with: + + perl $HERE/mkrelease.pl --reviewer=NAME + +Alternatively, to use the openssl-team PGP key: + + export OPENSSL_GPG_KEYID=8B3D79F5 + perl $HERE/mkrelease.pl --reviewer=NAME + +See $HERE/MKRELEASE.md for details of the options to mkrelease.pl. +This will leave a handful of files in the parent directory of where +you extracted the release. +See below for details of how to do perform this step manually if you want +to or have to. + +Verify that the results of the script are sensible. Check +the commits the automated release process has performed, using for example +`git log`. Check the signed announcement RELEASE.asc file. Maybe check +that the tarball length and hashes match in the .md5, .sha1, and review +the announcment file. *Do not push* changes to the public repo at this stage. + +Both the person doing the release and the reviewer should sanity-check the +release at this point. Checks to consider include the following: + +- Builds and make test passes on multiple plaforms - Linux, Windows, etc. +- Builds from tarball + +Send the auto-generated commits to the reviewer and await their +1. +Repeat from the begining of this section if you need to release +multiple versions. + +## Website updates + +The changes in this section should be made in your copy of the web repo. + +Update the news/newsflash.txt file. This normally is one or two lines. Just +copy and paste existing announcements making minor changes for the date and +version number as necessary. + +Update the news/vulnerabilities.xml file if appropriate. + +If there is a Security Advisory then copy it into the news/secadv directory. + +Commit your changes, but *do not push* them to the website. + +## Publishing the release + +*BE CAREFUL* This section makes everything visible and is therefore +largely irreversible. If you are performing a dry run then DO NOT +perform any steps in this section. + +Check that release has been uploaded properly. The release tarballs and +associated files should be in ~openssl/dist/new. They should be owned by the +openssl userid and world-readable. + +Copy the tarballs to appropriate directories. This can be +done using the do-release.pl script. See MKRELEASE.md for a description of +the options. For example: + + sudo -u openssl perl ~openssl/do-release.pl --copy --move + +This will copy the relevant files to the website and move them from +~openssl/dist/new to ~openssl/dist/old so they will not seen by a subsequent +release. Alternatively if you want to perform one release at a time or copy/move +the files manually, see below. + +The do-release.pl script will display the commands you will need to issue to +send the announcement emails later. Keep a note of those commands for future +reference. + +Verify that the tarballs are available via FTP: + + ftp://ftp.openssl.org/source/ + +And that they are ready for the website: + + ls /var/www/openssl/source + +Push your local changes made above to the public repo. You will +typically want to sanity check this with: + + git push -n + +Push new tags to public repo. Again sanity check with: + + git push --tags -n + +to make sure no local tags were pushed. + +## Updating the website + +Push the website changes you made earlier to the OpenSSL website repo. When +you do this, the website will get updated and a script to flush the Akamai CDN +cache will be run. You can look at things on www-origin.openssl.org; the +CDN-hosted www.openssl.org should only be a few minutes delayed. + +Verify that the release notes, which are built from the CHANGES file in the +release, have been updated. This is done automatically by the commit-hook, but +if you see a problem, try the following steps: + + cd /var/www/openssl + sudo -u openssl -H make relupd + sudo -u openssl ./bin/purge-one-hour + +Wait for a while for the Akamai flush to work (normally within a few minutes). +Have a look at the website and news announcement at: + + https://www.openssl.org/ + https://www.openssl.org/news/ + +Check the download page has updated properly: + + https://www.openssl.org/source/ + +Check the notes look sensible at: + + https://www.openssl.org/news/news.html + +Also check the notes here: + + https://www.openssl.org/news/openssl-1.0.2-notes.html + https://www.openssl.org/news/openssl-1.1.0-notes.html + +## Send the announcement mail + +Send out the announcements. Generic release announcement messages will be +created automatically by the build script and the commands you need to use to +send them were displayed when you executed do-release.pl above. +These should normally be sent from the openssl account. These are sent to +openssl-users, openssl-project, and openssl-announce. + +If do-release.pl was used with `--move` be sure to move the +announcement text files away from the staging directory after they have been +sent. This is done as follows (with VERSION replaced with the version of +OpenSSL to announce): + + sudo -u openssl \ + mv ~openssl/dist/new/openssl-VERSION.txt.asc ~openssl/dist/old + +Send out the Security Advisory if there is one. Copy the file to the +openssl user home directory, and then do the following + + sudo -u openssl gpg -u 8B3D79F5 --clearsign secadv_FILENAME + sudo -u openssl mutt -s "OpenSSL Security Advisory" \ + openssl-project openssl-users openssl-announce + <~openssl/secadv_FILENAME.txt.asc + +Approve the openssl-announce email. Go to + +and approve the messages. +The administration password needed for approval is held in /opt/mailman/README +on mta.openssl.org + +Check the mailing list messages have arrived. + +## Finish + +Unfreeze the repository. + + ssh openssl-git at git.openssl.org unfreeze openssl + +If this release includes security fixes with a CVE then you should inform +MITRE about them. See the instructions at the top of cvepool.txt in bureau. + +Check mailing lists over the next few hours for reports of any success +or failure. If necessary fix these and in the worst case make another +release. + +# MANUAL PROCESS + +If for some reason you cannot use, or do not trust, release script +mkrelease.pl then you can perform the release manually. This is difficult to +get right so you should avoid it if possible. + +Check what the automated release did for previous releases. This is the best +way to get a feel for what happens. You can do this by checking the commit +logs before a release tag for example: + + git log --reverse 0d7717f..ebe2219 + +The first two commits are security fixes. The third commit is (as the log +message implies) an update of the NEWS file. The next commit which has the +automated log message "Prepare for 1.0.1g release" includes the steps +necessary to make the release. + +## Manually building the release files + +Do a `make update`. If necessary commit. You can push this commit to +the repo so you have as few local changes as possible. Note that even if +"make update" does not make any visible changes it can still update timestamps +on some files which avoid some problems with builds (e.g. if the source files +are all made read only). + +Update NEWS, README and CHANGES. These should contain the date and +the correct version in the appropriate format. + +Update crypto/opensslv.h which contains the version. This contains the +version number in the appropriate formats. For OPENSSL_VERSION_NUMBER and +normal (not pre) releases you change the last digit from 0 (meaning -dev) +to f (meaning release). Change the text forms in OPENSSL_VERSION_TEXT for +normal and FIPS builds. + +Double-check that the version is right. If you mess up the syntax you can end +up with the wrong release number or worse break compilation. + +Commit the changes you made so far, and check that the logs look sensible. + +Make a local tag; the public repo requires annotated tags: + + git tag -s -m "OpenSSL 1.0.2L release tag" OpenSSL_1_0_2L + +or if you want to use the openssl-team key: + + git tag -u 8B3D79F5 -m "OpenSSL 1.0.2L release tag" OpenSSL_1_0_2L + +Make the release tarball. You do this with: + + make dist + +Create .sha1, .sha256 and .asc files manually. You can use: + + openssl sha1 + openssl sha256 + +Create .sha1, .sha256 and .asc files manually. You can use the openssl sha1 and +sha256 commands, obviously. Sign the tarball: + + gpg -sba opensslversion.tar.gz + +or if you want to use the openssl-team key: + + gpg -u 8B3D79F5 -sba opensslversion.tar.gz + +Create an announcement file. You can use an existing one as a +template for example something in ~openssl/dist/old/ update the version +numbers, tarball size and hashes. Sign announcement with: + + gpg -sta --clearsign announce.txt + +or if you want to use the openssl-team key: + + gpg -u 8B3D79F5 -sta --clearsign announce.txt + +Prepare for next development version by updating CHANGES, NEWS, README +crypto/opensslv.h and openssl.spec. The automated scripts use the comment +message `Prepare for 1.0.1h-dev`. + +Be absolutely *certain* you did not make any mistakes, so check +several times preferably by different people. + +Upload tarballs to dev.openssl.org + +## Manually releasing the files + +If you do not want to use do-release.pl, you can manually perform +the steps necessary for the release. This is (fortunately) much simpler +than the manual release process above. + +Copy release files to web source directory. The four files (tarball, +sha1, .sha256 and .asc) need to be manually copied to /var/www/openssl/source +Also move any outdated releases to /var/www/openssl/source/old/SUBDIR + +Copy files to ftp source directory, /srv/ftp/source. +Also move any oudated releases to /srv/ftp/source/old/SUBDIR diff --git a/release-tools/do-copyright-year b/release-tools/do-copyright-year new file mode 100755 index 0000000..59b9235 --- /dev/null +++ b/release-tools/do-copyright-year @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +this_year=`date +%Y` +some_year="[12][0-9][0-9][0-9]" +year_range="(${some_year})(-${some_year})?" + +copyright_owner="The OpenSSL Project" +copyright="Copyright .*${year_range} .*${copyright_owner}" + +# sed_script: +# for all lines that contain ${copyright} : { +# replace years yyyy-zzzz (or year yyyy) by yyyy-${this_year} +# replace repeated years yyyy-yyyy by yyyy +# } +ss=/tmp/sed$$ +cat <$ss +/${copyright}/ { +s|${year_range}|\1-${this_year}| +s|(${some_year})-\1|\1| +} +EOF + +NYD=`date +%Y-01-01` +echo Updating copryight +git diff-tree -r --name-only `git rev-list -1 --before=$NYD HEAD`..HEAD \ + | while read FILE ; do + sed -E -f /tmp/sed$$ "$FILE" >/tmp/$$ + mv /tmp/$$ "$FILE" + git add "$FILE" +done +echo Committing change locally. +git commit -m 'Update copyright year' +rm -f $ss diff --git a/release-tools/do-release.pl b/release-tools/do-release.pl new file mode 100644 index 0000000..1725055 --- /dev/null +++ b/release-tools/do-release.pl @@ -0,0 +1,209 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +my $homedir = glob("~openssl"); +my $tmpdir = $ENV{"OPENSSL_TMP_DIR"} // $homedir . "/dist/new"; +my $olddir = $ENV{"OPENSSL_OLD_DIR"} // $homedir . "/dist/old"; +my $srcdir = $ENV{"OPENSSL_SRC_DIR"} // "/var/www/openssl/source"; +my $ftpdir = $ENV{"OPENSSL_FTP_DIR"} // "/srv/ftp/source"; +my $mail = $ENV{"OPENSSL_MAIL"} // "mutt -s SUBJECT RECIP < BODY"; + +my $do_mail = 0; +my $do_copy = 0; +my $do_move = 0; +my $mail_only = 0; + +foreach (@ARGV) { + if (/--tmpdir=(.*)$/) { + $tmpdir = $1; + } elsif (/^--copy$/) { + $do_copy = 1; + } + elsif (/^--move$/) { + $do_move = 1; + } elsif (/^--mail$/) { + $do_mail = 1; + } elsif (/^--mail-only$/) { + $mail_only = 1; + $do_mail = 1; + } elsif (/^--full-release$/) { + $do_mail = 1; + $do_copy = 1; + $do_move = 1; + } else { + print STDERR "Unknown command line argument $_"; + exit 1; + } +} + +if ( getpwuid($<) ne "openssl" && !exists $ENV{"OPENSSL_RELEASE_TEST"} ) { + print "This script must be run as the \"openssl\" user\n"; + exit 1; +} + +die "Can't find distribution directory $tmpdir" unless -d $tmpdir; +die "Can't find old distribution directory $olddir" unless -d $olddir; +die "Can't find source directory $srcdir" unless -d $srcdir; +die "Can't find ftp directory $ftpdir" unless -d $ftpdir; + +my @versions; +my @series; +my @files = glob("$tmpdir/*.txt.asc"); + +foreach (@files) { + if (/^.*\/openssl-(\d+\.\d+\.\d+[a-z]*-pre\d+)\..*$/) { + push @versions, $1; + } elsif (/^.*\/openssl-(\d+\.\d+\.\d+[a-z]*)\..*$/) { + push @versions, $1; + } else { + die "Unexpected filename $_"; + } +} +foreach (@versions) { + if (/^(\d+\.\d+\.\d+)[a-z]*$/) { + my $serie = $1; + push @series, $serie unless grep /^$serie/, @series; + } +} +die "No distribution in temp directory!" if ( scalar @versions == 0 ); +print "OpenSSL versions to be released:\n"; +foreach (@versions) { + print "$_\n"; +} +print "OK? (y/n)\n"; +$_ = ; +exit 1 unless /^y/i; + +my @distfiles; +my @announce; + +foreach (@versions) { + push @distfiles, "openssl-$_.tar.gz"; + push @distfiles, "openssl-$_.tar.gz.sha1"; + push @distfiles, "openssl-$_.tar.gz.sha256"; + push @distfiles, "openssl-$_.tar.gz.asc"; + push @announce, "openssl-$_.txt.asc"; +} + +$do_copy = 0 if $mail_only; + +my $bad = 0; +if ($do_copy) { + foreach (@distfiles) { + if ( !-f "$tmpdir/$_" ) { + print STDERR "File $_ not found in temp directory!\n"; + $bad = 1; + } + if ( -e "$srcdir/$_" ) { + print STDERR "File $_ already present in source directory!\n"; + $bad = 1; + } + if ( -e "$ftpdir/$_" ) { + print STDERR "File $_ already present in ftp directory!\n"; + $bad = 1; + } + if ( -e "$olddir/$_" ) { + print STDERR + "File $_ already present in old distributions directory!\n"; + $bad = 1; + } + } +} + +exit 1 if $bad; + +print "Directory sanity check OK\n"; + +print "Starting release for OpenSSL @versions\n"; + +if ($do_copy) { + foreach (@distfiles) { + system("cp $tmpdir/$_ $srcdir/$_"); + die "Error copying $_ to source directory!" if $?; + system("cp $tmpdir/$_ $ftpdir/$_"); + die "Error copying $_ to ftp directory!" if $?; + } + print "Copied distributions files to source and ftp directories\n"; + foreach my $serie (@series) { + my $tomove_oldsrc = "$srcdir/old/$serie"; + my @tomove_src = + map { + my $x = $_; + $x =~ s|.*/||g; + grep( /^$x$/, @distfiles ) ? () : $x + } + grep { -f $_ } + glob("$srcdir/openssl-$serie.tar.gz $srcdir/openssl-$serie?.tar.gz"); + my $tomove_oldftp = "$ftpdir/old/$serie"; + my @tomove_ftp = + map { + my $x = $_; + $x =~ s|.*/||g; + grep( /^$x$/, @distfiles ) ? () : $x + } + grep { -f $_ } + glob("$ftpdir/openssl-$serie.tar.gz $ftpdir/openssl-$serie?.tar.gz"); + + mkdir $tomove_oldsrc + or die "Couldn't mkdir $tomove_oldsrc : $!" + if !-d $tomove_oldsrc; + mkdir $tomove_oldftp + or die "Couldn't mkdir $tomove_oldftp : $!" + if !-d $tomove_oldftp; + foreach (@tomove_src) { + system("mv $srcdir/$_* $tomove_oldsrc/"); + die "Error moving $_* to old source directory!" if $?; + } + foreach (@tomove_ftp) { + system("mv $ftpdir/$_* $tomove_oldftp/"); + die "Error moving $_* to old ftp directory!" if $?; + } + } + print + "Moved old distributions files to source/old and ftp/old directories\n"; +} +else { + print "Test mode: no files copied\n"; +} + +foreach (@versions) { + my $announce = "openssl-$_.txt.asc"; + my $annversion = $_; + $annversion =~ s/-pre(\d+$)/ pre release $1/; + my $annmail = $mail; + $annmail =~ s/SUBJECT/"OpenSSL version $annversion published"/; + $annmail =~ s/RECIP/openssl-project openssl-users openssl-announce/; + $annmail =~ s|BODY|$tmpdir/$announce|; + + if ($do_mail) { + print "Sending announcement email for OpenSSL $_...\n"; + system("$annmail"); + die "Error sending announcement email!" if $?; + print "Don't forget to authorise the openssl-announce email.\n"; + push @distfiles, $announce if $do_move; + } else { + print "Announcement email not sent automatically\n"; + print "\nSend announcement mail manually with command:\n\n$annmail\n\n"; + print +"When done, move the announcement file away with command:\n\nmv $tmpdir/$announce $olddir/$announce\n\n" + if $do_move; + } +} + +if ($do_move) { + foreach (@distfiles) { + rename( "$tmpdir/$_", "$olddir/$_" ) || die "Can't move $_: $!"; + } + print "Moved distribution files to old directory\n"; +} + +print "Successful!\n"; + diff --git a/release-tools/mkrelease.pl b/release-tools/mkrelease.pl new file mode 100644 index 0000000..4012e4d --- /dev/null +++ b/release-tools/mkrelease.pl @@ -0,0 +1,427 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# OpenSSL release generation script. + +use strict; +use warnings; +use File::Basename; +use lib dirname(__FILE__); +use Module::Load::Conditional qw(can_load); +can_load(modules => { 'OpenSSL::Query::DB' => undef }); +use OpenSSL::Query::REST; + +require "release-check.pl"; +require "release-date.pl"; +require "release-git.pl"; +require "release-update.pl"; +require "release-version.pl"; + +our $debug = 0; +our $verbose = 0; +my @reviewers; +my @openssl_branches; +my $revert; +my $pre; +my $info_only; +my $branch_info_only; +my $no_clean; +my $no_update; +my $no_release; +my $no_upload; +my $bversion; +my $ok; +my $label; + +#Determine include path +our $includepath; +if ( -e "crypto/opensslv.h" ) { + $includepath = "crypto"; +} +else { + $includepath = "include/openssl"; +} + +sub print_git_info { + my ( $rinfo, $branch, $s ) = @_; + my $version = openssl_git_expected_version( $rinfo, $branch ); + my $last = openssl_git_last_release( $rinfo, $branch ); + my $last_full = openssl_git_last_release( $rinfo, $branch, 1, 1 ); + + # Auto detect pre release if we haven't forced it. + $pre = $version =~ /-pre/ unless defined $pre; + my $next = openssl_version_next( $version, $pre ); + + print "${s}Branch version: $branch\n"; + print "${s}Last release: $last\n"; + print "${s}Last full release: $last_full\n"; + print "${s}Current version: $version\n"; + print "${s}Next release: $next\n"; +} + +sub print_branch_info { + my ($rinfo) = @_; + my ( $rtags, $rbranches ) = @$rinfo; + print "All Branch details:\n"; + foreach (@$rbranches) { + print "\n"; + print_git_info( $rinfo, $_, "\t" ); + } + print "\n"; +} + +# Initialise git version tables, OMC database. +my $gitinfo = openssl_git_init(); +my $query = OpenSSL::Query->new(); + +foreach (@ARGV) { + if (/^--git-info$/) { + $info_only = 1; + } elsif (/^--branch-version=(.*)$/) { + $bversion = $1; + } elsif (/^--git-branch-info/) { + $branch_info_only = 1; + } elsif (/^--no-clean/) { + $no_clean = 1; + } elsif (/^--no-release/) { + $no_release = 1; + } elsif (/^--no-update/) { + $no_update = 1; + } elsif (/^--no-upload/) { + $no_upload = 1; + } elsif (/^--revert/) { + $revert = 1; + } elsif (/^--leave-pre/) { + $pre = 0; + } elsif (/^--enter-pre/) { + $pre = 1; + } elsif (/^--debug/) { + $debug = 1; + $verbose = 1; + } elsif (/^--verbose/) { + $verbose = 1; + } elsif (/^--reviewer=(.*)$/) { + my $r = $1; + my $rname = $query->find_person_tag($r, 'rev'); + die "Unknown reviewer $1" unless $rname; + push @reviewers, $rname; + } elsif (/^--label=(.*)$/) { + $label = $1; + if ( $label ne "alpha" && $label ne "beta" ) { + die "Invalid label"; + } + } else { + print "Uknown option $_\n"; + exit 1; + } +} + +if ($revert) { + $_ = openssl_git_current_branch(); + print "Reverting to repository version for $_\n"; + system("git reset --hard origin/$_"); + die "Error reverting!!" if $?; + openssl_git_delete_local_tags($_); + exit 0; +} + +$bversion = openssl_git_branch_version() unless defined $bversion; + +if ($info_only) { + print_git_info( $gitinfo, $bversion, "" ); + exit 0; +} + +if ($branch_info_only) { + print_branch_info($gitinfo); + exit 0; +} + +die "No reviewer set!" unless @reviewers; + +print "Current branch version is $bversion\n"; + +if ( openssl_git_check_changes() ) { + print "ERROR: unstaged changes in current branch!\n"; + exit 1; +} + +my $expected_version = openssl_git_expected_version( $gitinfo, $bversion ); + +# If this is first pre release there will be no releases from this branch +# So set expected version to pre1-dev as we can't detect this from +# tags. + +if ( $expected_version !~ /-pre/ && openssl_check_first_pre() ) { + $expected_version =~ s/-dev/-pre1-dev/; +} + +# Auto detect pre release if we haven't forced it. +$pre = $expected_version =~ /-pre/ unless defined $pre; + +if ( !$pre && defined $label ) { + die "Not a pre-release but a label has been defined"; +} +if ( $pre && !defined $label ) { + die "This is a pre-release but a label has not been defined"; +} + +my $last_version = openssl_git_last_release( $gitinfo, $bversion, 1, 1 ); +my $last_branch_release = openssl_git_last_release( $gitinfo, $bversion, 1 ); +my $next_version = openssl_version_next( $expected_version, $pre ); + +print "Branch feature version: $bversion\n"; +print "Last release on this branch: $last_branch_release\n"; +print "Current branch version $expected_version\n"; +print "Next release version $next_version\n"; +print "Last full release version $last_version\n"; + +$ok = openssl_check_all( $expected_version, $last_version ); + +print "Branch sanity check: " . ( $ok ? "OK" : "NOT OK" ) . "\n"; + +if ( $ok == 0 ) { + print "Sanity check failed, cannot continue\n"; + exit 1; +} + +if ( !$no_clean ) { + print "Cleaning directory\n"; + system("git clean -x -d -f"); + die "Error cleaning directory" if $?; +} + +openssl_git_make_update(@reviewers) unless $no_update; + +$expected_version = openssl_version_next( $expected_version, $pre ); + +my $date = openssl_current_date() unless $expected_version =~ /-pre1-dev/; + +print "Updating versions to $expected_version\n"; + +openssl_update_all( $expected_version, $date, $label ); + +$ok = openssl_check_all( $expected_version, $last_version, $date ); + +print "Changes sanity check: " . ( $ok ? "OK" : "NOT OK" ) . "\n"; + +if ( $ok == 0 ) { + print "Release sanity check failed, cannot continue\n"; + exit 1; +} + +print "Committing changes:\n"; + +# If we changed from -dev to -pre1-dev a dev version is +# entering pre release. Just commit changes without a release. + +if ( $expected_version =~ /pre1-dev/ ) { + my $main_version = $expected_version; + $main_version =~ s/-pre1-dev//; + openssl_git_commit( "OpenSSL $main_version is now in pre release", + @reviewers ); + die "Error comitting changes!" if $?; + print "Version set to $expected_version, exiting\n"; + exit 0; +} + +openssl_git_commit( "Prepare for $expected_version release", @reviewers ); +die "Error comitting release changes!" if $?; + +my $tag = "OpenSSL_$expected_version"; +my $tagkey = + defined( $ENV{OPENSSL_GPG_KEYID} ) ? " -u $ENV{OPENSSL_GPG_KEYID}" : " -s"; + +$tag =~ tr/\./_/; + +print + "Tagging release with tag $tag (you will need to provide a pass phrase)\n"; + +system("git tag$tagkey -m \"OpenSSL $expected_version release tag\" $tag"); +die "Error tagging release!" if $?; + +my $TAR = defined( $ENV{OPENSSL_TAR} ) ? "TAR=$ENV{OPENSSL_TAR}" : ""; + +if ( !$no_release ) { + print "Generating release tarball.\n"; + my $openssl = $ENV{"OPENSSL"} // "openssl"; + my $gpgkeyid = + defined( $ENV{OPENSSL_GPG_KEYID} ) ? " -u $ENV{OPENSSL_GPG_KEYID}" : ""; + my $gpg = $ENV{"OPENSSL_GPG"} // "gpg$gpgkeyid"; + my $gpgtar = $ENV{"OPENSSL_GPG_TAR"} // "$gpg --use-agent -sba"; + my $gpgann = $ENV{"OPENSSL_GPG_ANNOUNCE"} + // "$gpg --use-agent -sta --clearsign"; + my $tarfile = "openssl-${expected_version}.tar.gz"; + system("(./config; make $TAR dist) >../$tarfile.log 2>&1"); + die "Error generating release!" if $?; + die "Can't find tarball!!" unless -f "../$tarfile"; + + my $length = -s "../$tarfile"; + print "Creating hash files\n"; + my $sha1hash = `$openssl sha1 < ../$tarfile`; + chomp $sha1hash; + $sha1hash =~ s/^.*=\s//; + die "invalid hash" unless $sha1hash =~ /[0-9a-f]{20}/; + my $sha256hash = `$openssl sha256 < ../$tarfile`; + chomp $sha256hash; + $sha256hash =~ s/^.*=\s//; + die "invalid hash" unless $sha256hash =~ /[0-9a-f]{20}/; + open OUT, ">../$tarfile.sha1"; + print OUT $sha1hash . "\n"; + close OUT; + open OUT, ">../$tarfile.sha256"; + print OUT $sha256hash . "\n"; + close OUT; + print "Creating PGP signature:\n"; + unlink("../${tarfile}.asc"); + system("$gpgtar ../$tarfile"); + die "Error creating signature" if $?; + + my $anntxt = "../openssl-${expected_version}.txt"; + + open OUT, ">$anntxt"; + if ( $expected_version =~ /-pre/ ) { + + # Note the variable name is the same length as the real + # version so the announcement can be made to look pretty. + # If we ever go to pre10 it will be one character longer... + my $openssl_ver = $expected_version; + $openssl_ver =~ s/^(.*)-pre(\d+)$/$1 pre release $2/; + my $fvers = $expected_version; + $fvers =~ s/-pre\d+//; + print OUT <) { + if (/^.*OpenSSL\s+(\S+)\s+(\([[:alpha:]]+\)\s+)?(.*)$/) { + check_str( "README version", $version, $1, \$ok ); + if ( defined $indate ) { + check_str( "README date", $date, $3, \$ok ); + } + close IN; + return $ok; + } + } + close IN; + print STDERR "Invalid syntax in README\n"; + return 0; +} + +sub openssl_check_NEWS { + my ( $version, $prev, $indate ) = @_; + my $date = openssl_date( $version =~ /-pre/ ? undef : $indate ); + my $ok = 1; + if ( $date =~ /XXX/ ) { + if ( $version =~ /-pre/ ) { + $date = "in pre-release"; + } else { + $date = "under development"; + } + } + $version =~ s/-dev$//; + $version =~ s/-pre.*$//; + open( IN, "NEWS" ) || die "Can't open NEWS"; + + while () { + if ( +/^ Major changes between OpenSSL (\S+) and OpenSSL (\S+)\s+\[0?(.*)\]/ + ) + { + check_str( "NEWS previous version", $prev, $1, \$ok ); + check_str( "NEWS version", $version, $2, \$ok ); + check_str( "NEWS date", $date, $3, \$ok ); + close IN; + return $ok; + } + } + close IN; + print STDERR "Invalid syntax in NEWS\n"; + return 0; +} + +sub openssl_check_CHANGES { + my ( $version, $prev, $indate ) = @_; + my $date = openssl_date( $version =~ /-pre/ ? undef : $indate ); + my $ok = 1; + $version =~ s/-dev$//; + $version =~ s/-pre.*$//; + open( IN, "CHANGES" ) || die "Can't open CHANGES"; + + while () { + if (/^ Changes between (\S+) and (\S+)\s+\[0?(.*)\]/) { + check_str( "CHANGES previous version", $prev, $1, \$ok ); + check_str( "CHANGES version", $version, $2, \$ok ); + check_str( "CHANGES date", $date, $3, \$ok ); + close IN; + return $ok; + } + } + close IN; + print STDERR "Invalid syntax in CHANGES\n"; + return 0; +} + +sub openssl_check_version_h { + my ( $version, $indate ) = @_; + my ( $hex_done, $fips_done, $version_done ); + my $hexversion = openssl_version_hex($version); + my $ok = 1; + my $version_fips = $version . "-fips"; + $version_fips =~ s/-dev-fips/-fips-dev/; + my $date = openssl_date($indate); + open( IN, "$main::includepath/opensslv.h" ) || die "Can't open opensslv.h"; + + while () { + if (/OPENSSL_VERSION_NUMBER\s+(0x[0-9a-f]+)L/) { + check_str( "opensslv.h: HEX version", $hexversion, $1, \$ok ); + $hex_done = 1; + } elsif ( +/OPENSSL_VERSION_TEXT\s+\"OpenSSL (\S*fips\S*)\s+(\([[:alpha:]]+\)\s+)?(.*)\"/ + ) + { + check_str( "opensslv.h: FIPS version", $version_fips, $1, \$ok ); + check_str( "opensslv.h: FIPS date", $date, $3, \$ok ); + $fips_done = 1; + } elsif ( +/OPENSSL_VERSION_TEXT\s+\"OpenSSL (\S*)\s+(\([[:alpha:]]+\)\s+)?(.*)\"/ + ) + { + check_str( "opensslv.h: version", $version, $1, \$ok ); + check_str( "opensslv.h: date", $date, $3, \$ok ); + $version_done = 1; + } + if ( $hex_done && $fips_done && $version_done ) { + close IN; + return $ok; + } + } + print STDERR "Invalid syntax in opensslv.h\n"; + close IN; + return 0; +} + +sub openssl_check_spec { + my ($version) = @_; + my $ok = 1; + $version =~ s/-dev$//; + $version =~ s/-pre.*$//; + open( IN, "openssl.spec" ) || die "Can't open openssl.spec"; + while () { + if (/^Version:\s+(\S+)$/) { + check_str( "openssl.spec version", $version, $1, \$ok ); + close IN; + return $ok; + } + } + close IN; + print STDERR "Invalid syntax in README\n"; + return 0; +} + +sub print_ok { + my ( $file, $ok ) = @_; + print "File: $file " . ( $ok ? "OK" : "NOT OK!!" ) . "\n" + if ($main::verbose); +} + +sub openssl_check_all { + my ( $version, $last_version, $date ) = @_; + + my $readme_ok = openssl_check_README( $version, $date ); + + print_ok( "README", $readme_ok ); + + my $changes_ok = openssl_check_CHANGES( $version, $last_version, $date ); + + print_ok( "CHANGES", $changes_ok ); + + my $news_ok = openssl_check_NEWS( $version, $last_version, $date ); + + print_ok( "NEWS", $news_ok ); + + my $v_h_ok = openssl_check_version_h( $version, $date ); + + print_ok( "opensslv.h", $v_h_ok ); + + # Newer versions don't have openssl.spec + my $spec_ok = 1; + if ( -f "openssl.spec" ) { + $spec_ok = openssl_check_spec($version); + + print_ok( "openssl.spec", $spec_ok ); + } + + return $readme_ok && $changes_ok && $news_ok && $v_h_ok && $spec_ok; +} + +# If there are no tagged releases for the current version +# and we are in pre release mode then either we are just entering +# pre release and the next version will be pre1-dev or we are already +# at pre1-dev and we need to do a release of pre1. +# Check opensslv.h to determine which + +sub openssl_check_first_pre { + open( IN, "$main::includepath/opensslv.h" ) || die "Can't open opensslv.h"; + + while () { + if (/OPENSSL_VERSION_TEXT\s+\"OpenSSL \S*\s+.*\"/) { + close IN; + + # Ignore -fips in string + s/-fips//; + return /pre1-dev/; + } + } + close IN; + die "Invalid sysntax in opensslv.h"; +} + +return 1; diff --git a/release-tools/release-date.pl b/release-tools/release-date.pl new file mode 100644 index 0000000..c5b5c38 --- /dev/null +++ b/release-tools/release-date.pl @@ -0,0 +1,64 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Return date into a form suitable for the FAQ, version file and +# CHANGES file entries. Optionally can be passed date in the form +# mm/dd/yyyy + +sub openssl_date { + my ($datestr) = @_; + my ( $mday, $mon, $year ); + + if ( defined $datestr ) { + if ( $datestr =~ /(\d+)\/(\d+)\/(\d+)/ ) { + $mday = $1; + $mon = $2; + $year = $3; + $mon--; + } else { + die "Invalid date syntax $datestr, expecting mm/dd/yyyy"; + } + } else { + return ( "xx XXX xxxx", undef, undef ) if wantarray; + return "xx XXX xxxx"; + } + + my $mdsuff; + if ( $mday % 10 > 0 && $mday % 10 <= 3 && ( $mday < 10 || $mday > 20 ) ) { + my @mday_ord = qw(st nd rd); + $mdsuff = $mday_ord[ $mday % 10 - 1 ]; + } else { + $mdsuff = "th"; + } + + my @mnames = + qw(January February March April May June July August September October November December); + + my $mname = $mnames[$mon]; + my $mname_short = substr $mname, 0, 3; + + my $date_ch = sprintf "%d %s %d", $mday, $mname_short, $year; + return $date_ch unless wantarray; + my $date_ab = sprintf "%s %d%s, %d", $mname_short, $mday, $mdsuff, $year; + my $date_full = sprintf "%-9s %2d%s, %d", $mname, $mday, $mdsuff, $year; + + return ( $date_ch, $date_ab, $date_full ); + +} + +# Return current date in dd/mm/yyyy format suitable to passing into +# openssl_date(). + +sub openssl_current_date { + my ( $mday, $mon, $year ) = (localtime)[ 3 .. 5 ]; + $year += 1900; + $mon++; + return "$mday/$mon/$year"; +} + +return 1; diff --git a/release-tools/release-git.pl b/release-tools/release-git.pl new file mode 100644 index 0000000..2b6ac1a --- /dev/null +++ b/release-tools/release-git.pl @@ -0,0 +1,164 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +# OpenSSL git version utilities. + +# Retrieve list of branches and release tags in a reference usable by other +# functions. + +sub openssl_git_init { + my @tmpbranches = + grep { chomp; s|^\s+origin/OpenSSL_(\w*\d)-stable$|$1|; } `git branch -r`; + die "Error retrieving branch details!" if $?; + + # Create initial dev version entry: lowest possible version for + # branch which will be accurate if no releases have take place. + my @branches; + foreach ( sort @tmpbranches ) { + tr/_/\./; + next if /^0/ && $_ ne "0.9.8"; + push @branches, $_; + } + + # Create list of tags + my @rtags = grep { chomp; s/OpenSSL_(\d.*)$/$1/; } `git tag`; + die "Error retrieving tag details!" if $?; + my @tags; + foreach (@rtags) { + + # Skip if tag has - and it isn't pre + next if ( /-/ && !/-pre\d+$/ ); + tr/_/\./; + next if /^0/ && !/^0.9.8/; + push @tags, $_; + } + my $aref = [ \@tags, \@branches ]; + return $aref; +} + +# Return last release number on supplied branch. +# If $nopre is set, skip pre releases, if $prev set +# return last release on previous branch if no release +# on current branch. + +sub openssl_git_last_release { + my ( $rinfo, $branch, $nopre, $prev ) = @_; + my ( $rtag, $rbranch ) = @$rinfo; + my $brhex = openssl_version_branch_hex($branch); + my $rv = ""; + my $rvhex = ""; + foreach (@$rtag) { + next if ( $nopre && /-pre/ ); + my $taghex = openssl_version_hex($_); + my $tagbhex = openssl_version_branch_hex($_); + + # Is tag for current branch? + if ( $tagbhex ne $brhex ) { + + # Discard if only want current branch or greater + # than current branch + next if ( !$prev || $tagbhex gt $brhex ); + } + + # If release is later than last value replace. + if ( $taghex gt $rvhex ) { + $rv = $_; + $rvhex = openssl_version_hex($rv); + } + } + return $rv eq "" ? "none" : $rv; +} + +sub openssl_git_current_branch { + + # Current branch + $_ = `git rev-parse --abbrev-ref HEAD`; + die "Can't get current branch!" if $?; + chomp; + return $_; +} + +sub openssl_git_branch_version { + ($_) = @_; + $_ = openssl_git_current_branch() unless defined $_; + die "Unexpected branch name $_" unless s/OpenSSL_//; + tr /_/\./; + die "Unexpected branch name $_" unless s/-stable$//; + return $_; +} + +sub openssl_git_expected_version { + my ( $rinfo, $branch ) = @_; + $branch = openssl_git_major_version() unless defined $branch; + my $rv = openssl_git_last_release( $rinfo, $branch ); + return $branch .= "-dev" if $rv eq "none"; + return openssl_version_next($rv); +} + +sub openssl_git_check_changes { + + # For some reason this is unreliable if you use --quiet ... + system("git diff --exit-code >/dev/null"); + return 0 if $? == 0; + return 1 if $? == 256; + die "Unexpected status $?"; +} + +sub openssl_git_make_update { + print "Configuring system\n"; + system("perl Configure gcc >/dev/null 2>&1"); + die "Error configuring system" if $?; + + print "Doing make update\n"; + system("make update >/dev/null 2>&1"); + die "make update error" if $?; + if ( openssl_git_check_changes() ) { + print "Source modified, committing changes\n"; + openssl_git_commit( "make update", @_ ); + die "Error committing update" if $?; + } else { + print "No changes\n"; + } + system("find . -name Makefile.save -exec rm \\\{\\\} \\\;"); + die "Error removing Makefile.save files" if $?; +} + +sub openssl_git_delete_local_tags { + my ($branch) = @_; + $branch =~ s/-stable//; + my @tags = grep { chomp; } `git tag -l $branch\*`; + my @rtags = + grep { chomp; s|^.*refs/tags/||; } `git ls-remote --tags origin`; + my %rtaghash; + foreach (@rtags) { + $rtaghash{$_} = 1; + } + foreach (@tags) { + if ( !defined $rtaghash{$_} ) { + print "Deleting local tag $_\n" if $main::verbose; + system("git tag -d $_"); + } + } +} + +sub openssl_git_commit { + my @args = ( "git", "commit", "-a" ); + my ( $message, @reviewers ) = @_; + $message .= "\n\n"; + foreach (@reviewers) { + $message .= "Reviewed-by: $_\n"; + } + push @args, "-m", "$message"; + system(@args); + die "Error committing update" if $?; +} + +return 1; diff --git a/release-tools/release-update.pl b/release-tools/release-update.pl new file mode 100644 index 0000000..a8d5687 --- /dev/null +++ b/release-tools/release-update.pl @@ -0,0 +1,153 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +sub openssl_update_file { + my $fref = pop @_; + my $file = pop @_; + my $file_new = $file . ".new"; + my $finished = 0; + open( IN, "$file" ) || die "Can't open $file"; + open( OUT, ">$file_new" ) || die "Can't open $file_new"; + while () { + $finished = &$fref(@_) unless $finished; + print OUT; + } + close IN; + close OUT; + unlink $file; + rename $file_new, $file; + print "Updated $file\n" if $main::verbose; +} + +sub openssl_update_README { + my ( $version, $indate, $label ) = @_; + my $date = openssl_date($indate); + my $update = sub { + if (/^.*OpenSSL/) { + $_ = " OpenSSL $version"; + $_ .= " $label" if ( defined $label ); + $_ .= " $date" if ( defined $indate ); + $_ .= "\n"; + return 1; + } + return 0; + }; + openssl_update_file( @_, "README", $update ); +} + +sub openssl_update_CHANGES { + my ( $version, $indate ) = @_; + my $date = openssl_date($indate); + $version =~ s/-dev//; + my $update = sub { + if (/^ Changes between \S+ and (\S+)\s+\[0?(.*)\]/) { + my $chversion = $1; + my $chdate = $2; + if ( defined $indate ) { + s/$chdate/$date/; + } else { + my $newchanges = < 1 || length $NN > 2 || length $FF > 2 ) { + die "Invalid version syntax"; + } + + my ( $PP, $S ); + + if ( $rest eq "" ) { + $PP = "00"; + $S = "f"; + } else { + $S = ""; + if ( $rest =~ s/-dev$// ) { + $S = "0"; + } + + # Note pre release development versions of the form -preX-dev + # version is same for pre release and development versions + # So check for -preX after we have stripped off any + # -dev above. + if ( $rest =~ s/-pre([\d]+)$// ) { + $S = sprintf "%x", $1; + } + + # No -dev or -pre, must be release + $S = "f" if $S eq ""; + + if ( $rest eq "" ) { + $PP = "00"; + } elsif ( $rest =~ /^z([a-z]$)/ ) { + $PP = sprintf "%02x", ord($1) - ord("a") + 26; + } elsif ( $rest =~ /(^[a-z]$)/ ) { + $PP = sprintf "%02x", ord($1) - ord("a") + 1; + } else { + die "Invalid version syntax: \"$ov\""; + } + } + + if ( length $S > 1 || length $PP > 2 ) { + die "Invalid version syntax"; + } + + return "0x$M$NN$FF$PP$S"; + +} + +# Convert hex format to string +# Usage is version_str($hex_version), returns version as a string. + +sub openssl_version_str { + my ($hexversion) = @_; + my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion; + die "Bad hex version $hexversion" if $chk ne "0x" || $S eq ""; + my $version_str = hex($M) . "." . hex($NN) . "." . hex($FF); + + if ( $PP ne "00" ) { + my $hex_PP = hex($PP); + if ( $hex_PP > 25 ) { + $version_str .= "z"; + $hex_PP -= 25; + } + $version_str .= chr( $hex_PP + ord("a") - 1 ); + } + + if ( $S eq "0" ) { + $version_str .= "-dev"; + } elsif ( $S ne "f" ) { + $version_str .= "-pre" . hex($S); + } + + return $version_str; + +} + +# Given a hex number work out the next version. +# Usage is openssl_next_version($version, $pre, $dev) +# $pre indicates whether we should use pre releases +# $dev indicates we should use a development version. + +sub openssl_version_next { + my ( $version, $pre, $dev ) = @_; + my $hexversion = openssl_version_hex($version); + my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion; + die "Invalid syntax $version" if $S eq ""; + + # If $pre or $dev not set work out what we want. + $dev = $version !~ /-dev/ unless defined $dev; + $pre = $version =~ /-pre/ unless defined $pre; + + # If we want a release then just need to get rid of "-dev" part. + # + if ( $dev == 0 ) { + die "Expecting a development version!!" if $version !~ /-dev/; + + # NB version number is identical for pre and pre development. + # So just strip out "-dev" part. + $version =~ s/-dev//; + + # Special case: if we are going from X.Y.Z-dev and using pre releases + # next version is X.Y.Z-pre1-dev and this wont be a release, + # just changing version numbers for beginning of pre releases. + $version .= "-pre1-dev" if $pre && $S eq "0"; + + # If moving out of pre release return full release + $version =~ s/-pre.*$// unless $pre; + return $version; + } + die "Not expecting a development version!!" if $version =~ /-dev/; + + # If a pre release we need to increment the pre release portion + if ( $pre != 0 ) { + + # Hex version can only handle 14 pre releases. + die "Can't go past pre release 14!!" if ( $S eq "e" ); + + # Must be a pre release or development version. + die "Can't go from release to pre release!!" if $S eq "f"; + $S = sprintf "%x", hex($S) + 1; + $hexversion =~ s/.$/$S/; + $version = openssl_version_str($hexversion); + $version .= "-dev" if $dev; + return $version; + } + + # If last version pre release and not doing pre releases any more then switch + # to full release. + return openssl_version_str("0x$M$NN$FF${PP}f") if ( $version =~ /pre/ ); + + # Otherwise need to increment letter value if not a pre release. + $PP = sprintf "%02x", hex($PP) + 1; + die "Invalid letter version!!" if ( length $PP > 2 ); + return openssl_version_str("0x$M$NN$FF${PP}0"); +} + +# Return hex branch version belongs to. +# So "1.0.1a-pre2-dev" returns hex of "1.0.1" for example. + +sub openssl_version_branch_hex { + my ($version) = @_; + my $hexversion = openssl_version_hex($version); + my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion; + die "Invalid syntax $version" if $S eq ""; + return "0x$M$NN${FF}00F"; +} + +return 1; From scan-admin at coverity.com Sun Feb 4 07:19:07 2018 From: scan-admin at coverity.com (scan-admin at coverity.com) Date: Sun, 04 Feb 2018 07:19:07 +0000 (UTC) Subject: [openssl-commits] Coverity Scan: Analysis completed for openssl/openssl Message-ID: <5a76b3eac0e58_24b4eed4f1898287@node1.mail> Your request for analysis of openssl/openssl has been completed successfully. The results are available at https://u2389337.ct.sendgrid.net/wf/click?upn=08onrYu34A-2BWcWUl-2F-2BfV0V05UPxvVjWch-2Bd2MGckcRakUl6QyjujEohY7rPpoYUEcf-2B75FkFkxwwFKGZV8c1xA-3D-3D_19DGMz38yO7VfzGQuXkecdlEmzBoDG4v8Dvyanv-2F1I3xqTV-2FmJ0QLslqpaRYLBAT1W7vvWtl5tODhabX6C7NaR7tTQAIK-2BbNsWEjbIF2CQjiOl1VwDRVsdE16NH-2BlF2myNiFWe8TbHA2yAwz5H-2BcEmGc451voUb0GPWFUTj0V0s09j1z-2FigzJcQ7V36kIKk9JaxOa2EYAPAUslw9PTt3SRBnj7ByBqqBROoLnLaY-2BzY-3D Build ID: 198977 Analysis Summary: New defects found: 0 Defects eliminated: 0 From scan-admin at coverity.com Sun Feb 4 07:46:00 2018 From: scan-admin at coverity.com (scan-admin at coverity.com) Date: Sun, 04 Feb 2018 07:46:00 +0000 (UTC) Subject: [openssl-commits] Coverity Scan: Analysis completed for OpenSSL-1.0.2 Message-ID: <5a76ba37cd704_25a07ed4f18982a5@node1.mail> Your request for analysis of OpenSSL-1.0.2 has been completed successfully. The results are available at https://u2389337.ct.sendgrid.net/wf/click?upn=08onrYu34A-2BWcWUl-2F-2BfV0V05UPxvVjWch-2Bd2MGckcRakUl6QyjujEohY7rPpoYUEeuRTZVWU4ku8PUBnVPw8PQ-3D-3D_19DGMz38yO7VfzGQuXkecdlEmzBoDG4v8Dvyanv-2F1I2yRVzD6q7CfeDpKdxq0kyGp9zeN-2Bp1P2tla476FyCX5K1iS-2FUSx-2BYg67N0bBTFP7OlIW1NVyxZAR1jtEe9U1vN6BvcArqKgcTPvwGCSy4ZR57hpjB5FlYMrtDvAfxMwWEkJzxfXO-2FxSraJvmngb-2BKOsO9zWFVpgkJ8lG-2BpLgBc6KHXekWu82SWxGvQvKNGdCM-3D Build ID: 198982 Analysis Summary: New defects found: 0 Defects eliminated: 0 From no-reply at appveyor.com Sun Feb 4 10:28:52 2018 From: no-reply at appveyor.com (AppVeyor) Date: Sun, 04 Feb 2018 10:28:52 +0000 Subject: [openssl-commits] Build failed: openssl master.15362 Message-ID: <20180204102852.1.69C36AAA1620DDFF@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Sun Feb 4 14:59:15 2018 From: no-reply at appveyor.com (AppVeyor) Date: Sun, 04 Feb 2018 14:59:15 +0000 Subject: [openssl-commits] Build completed: openssl master.15363 Message-ID: <20180204145915.1.A5506B04FD5E11D2@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Sun Feb 4 19:17:45 2018 From: no-reply at appveyor.com (AppVeyor) Date: Sun, 04 Feb 2018 19:17:45 +0000 Subject: [openssl-commits] Build failed: openssl master.15370 Message-ID: <20180204191745.1.7D909CB181DF89E1@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Sun Feb 4 19:50:57 2018 From: no-reply at appveyor.com (AppVeyor) Date: Sun, 04 Feb 2018 19:50:57 +0000 Subject: [openssl-commits] Build completed: openssl master.15371 Message-ID: <20180204195057.1.1B6D6122C221DD61@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Mon Feb 5 06:16:13 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 06:16:13 +0000 Subject: [openssl-commits] Build failed: openssl master.15375 Message-ID: <20180205061613.1.F0CD97C635B9C615@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Mon Feb 5 09:33:34 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 09:33:34 +0000 Subject: [openssl-commits] Build failed: openssl master.15376 Message-ID: <20180205093334.1.D1EC5552B2439AF3@appveyor.com> An HTML attachment was scrubbed... URL: From matt at openssl.org Mon Feb 5 10:10:56 2018 From: matt at openssl.org (Matt Caswell) Date: Mon, 05 Feb 2018 10:10:56 +0000 Subject: [openssl-commits] [tools] master update Message-ID: <1517825456.039972.31067.nullmailer@dev.openssl.org> The branch master has been updated via 7823d374c6841eac48a7baf1f2955eb962b5305d (commit) from 27296557068a17464f17533d89d4fa6f3555b909 (commit) - Log ----------------------------------------------------------------- commit 7823d374c6841eac48a7baf1f2955eb962b5305d Author: Matt Caswell Date: Fri Dec 8 10:13:21 2017 +0000 Add an option to not add yourself as a reviewer Every now and then I need to merge a commit that I did not author or review (someone else has done those things). This adds an option to addrev to enable you to add the "Reviewed by" headers without also adding yourself. Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/6) ----------------------------------------------------------------------- Summary of changes: review-tools/addrev | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/review-tools/addrev b/review-tools/addrev index 6b3d64a..fdf2aa5 100755 --- a/review-tools/addrev +++ b/review-tools/addrev @@ -9,6 +9,7 @@ my $list_reviewers = 0; my $help = 0; my $haveprnum = 0; my $trivial = 0; +my $useself = 1; my $my_email; @@ -23,6 +24,8 @@ foreach (@ARGV) { $args .= "--trivial "; } elsif (/^--verbose$/) { $args .= "--verbose "; + } elsif (/^--noself$/) { + $useself = 0; } elsif (/^--myemail=(.+)$/) { $my_email = $1; } elsif (/^--nopr$/) { @@ -56,11 +59,13 @@ if ($help) { die "Need either --prnum or --nopr flag" unless $haveprnum; -if (!defined $my_email) { - $my_email = `git config --get user.email`; -} +if ($useself) { + if (!defined $my_email) { + $my_email = `git config --get user.email`; + } -$args .= "--myemail=$my_email "; + $args .= "--myemail=$my_email "; +} system("git filter-branch -f --tag-name-filter cat --msg-filter \"gitaddrev $args\" $filterargs"); From matt at openssl.org Mon Feb 5 10:57:32 2018 From: matt at openssl.org (Matt Caswell) Date: Mon, 05 Feb 2018 10:57:32 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517828252.679241.3214.nullmailer@dev.openssl.org> The branch master has been updated via 1c4b15458670aea5d3849d4b57b8c0ce34a54fbe (commit) from 1f5878b8e25a785dde330bf485e6ed5a6ae09a1a (commit) - Log ----------------------------------------------------------------- commit 1c4b15458670aea5d3849d4b57b8c0ce34a54fbe Author: Matt Caswell Date: Fri Feb 2 10:17:06 2018 +0000 Add MiddleboxCompat option to SSL_CONF_cmd man page Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5244) ----------------------------------------------------------------------- Summary of changes: doc/man3/SSL_CONF_cmd.pod | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod index 27317e0..5179e29 100644 --- a/doc/man3/SSL_CONF_cmd.pod +++ b/doc/man3/SSL_CONF_cmd.pod @@ -420,6 +420,12 @@ B: In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means that there will be no forward secrecy for the resumed session. Equivalent to B. +B: If set then dummy Change Cipher Spec (CCS) messages are sent +in TLSv1.3. This has the effect of making TLSv1.3 look more like TLSv1.2 so that +middleboxes that do not understand TLSv1.3 will not drop the connection. This +option is set by default. A future version of OpenSSL may not set this by +default. Equivalent to B. + =item B The B argument is a comma separated list of flags to set. From no-reply at appveyor.com Mon Feb 5 11:54:26 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 11:54:26 +0000 Subject: [openssl-commits] Build completed: openssl master.15377 Message-ID: <20180205115426.1.4A82B649A0AE5A09@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Mon Feb 5 13:14:28 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 13:14:28 +0000 Subject: [openssl-commits] Build failed: openssl master.15379 Message-ID: <20180205131428.1.908951674F5CDE5B@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Mon Feb 5 14:21:19 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 14:21:19 +0000 Subject: [openssl-commits] Build completed: openssl master.15380 Message-ID: <20180205142119.1.895793A33B863565@appveyor.com> An HTML attachment was scrubbed... URL: From no-reply at appveyor.com Mon Feb 5 14:45:24 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 14:45:24 +0000 Subject: [openssl-commits] Build failed: openssl master.15381 Message-ID: <20180205144524.1.7BB37C6D9FED2049@appveyor.com> An HTML attachment was scrubbed... URL: From mark at openssl.org Mon Feb 5 15:01:34 2018 From: mark at openssl.org (Mark J. Cox) Date: Mon, 05 Feb 2018 15:01:34 +0000 Subject: [openssl-commits] [web] master update Message-ID: <1517842894.308333.3284.nullmailer@dev.openssl.org> The branch master has been updated via 8ba74cf7cecf400ff776874e4165e5c66653095a (commit) via 11b53fcc49c27a3adaa5282fb2567d084fae8f09 (commit) from f7d3fb4dbadf9235d05d806b974b21b5a8f96487 (commit) - Log ----------------------------------------------------------------- commit 8ba74cf7cecf400ff776874e4165e5c66653095a Author: Mark J. Cox Date: Mon Feb 5 15:00:47 2018 +0000 Based on discussions with Mitre, over this field that isn't yet defined, but is unlikely to be machine parsable (looking at all the published ones to date). They'd like "Fixed in" and "Affects", so let's give that both in a nice text format for the description and the vulnerability affects sections. commit 11b53fcc49c27a3adaa5282fb2567d084fae8f09 Author: Mark J. Cox Date: Mon Feb 5 14:57:10 2018 +0000 CVE-2004-0081 was missing the 'fixed in 0.9.6d' line, causing it to not get included on the list of 0.9.6 issues and fail json validation. ----------------------------------------------------------------------- Summary of changes: bin/vulnxml2json.py | 23 ++++++++++++----------- news/vulnerabilities.xml | 2 ++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/bin/vulnxml2json.py b/bin/vulnxml2json.py index 41afbf8..b905da1 100755 --- a/bin/vulnxml2json.py +++ b/bin/vulnxml2json.py @@ -23,14 +23,16 @@ neverreleased = "1.0.0h,"; # Location of CVE JSON schema (default, can use local file etc) default_cve_schema = "https://raw.githubusercontent.com/CVEProject/automation-working-group/master/cve_json_schema/CVE_JSON_4.0_min_public.schema" -def merge_affects(issue): +def merge_affects(issue,base): # let's merge the affects into a nice list which is better for Mitre text but we have to take into account our stange lettering scheme prev = "" anext = "" alist = list() vlist = list() for affects in issue.getElementsByTagName('affects'): # so we can sort them - vlist.append(affects.getAttribute("version")) + version = affects.getAttribute("version") + if (not base or base in version): + vlist.append(version) for ver in sorted(vlist): # print "version %s (last was %s, next was %s)" %(ver,prev,anext) if (ver != anext): @@ -110,18 +112,17 @@ for issue in issues: if refs: cve['references'] = { "reference_data": refs } - allaffects = list() - for affects in issue.getElementsByTagName('affects'): - allaffects.append({ "version_value":"openssl-"+affects.getAttribute("version")}) + vv = list() + for affects in issue.getElementsByTagName('fixed'): + text = "Fixed in OpenSSL %s (Affected %s)" %(affects.getAttribute('version'),merge_affects(issue,affects.getAttribute("base"))) + # Let's condense into a list form since the format of this field is 'free text' at the moment, not machine readable (as per mail with George Theall) + vv.append({"version_value":text}) + # Mitre want the fixed/affected versions in the text too + desc += " "+text+"." - cve['affects'] = { "vendor" : { "vendor_data" : [ { "vendor_name": "OpenSSL", "product": { "product_data" : [ { "product_name": "OpenSSL", "version": { "version_data" : allaffects}}]}}]}} - - # Mitre want the fixed/affected versions in the text too - - desc += " (Affects "+merge_affects(issue)+")." + cve['affects'] = { "vendor" : { "vendor_data" : [ { "vendor_name": "OpenSSL", "product": { "product_data" : [ { "product_name": "OpenSSL", "version": { "version_data" : vv}}]}}]}} # Mitre want newlines and excess spaces stripped - desc = re.sub('[\n ]+',' ', desc) cve['description'] = { "description_data": [ { "lang":"eng", "value": desc} ] } diff --git a/news/vulnerabilities.xml b/news/vulnerabilities.xml index 80786e1..6e4c717 100644 --- a/news/vulnerabilities.xml +++ b/news/vulnerabilities.xml @@ -4638,6 +4638,8 @@ OpenSSL library in such a way as to cause a crash. + + From no-reply at appveyor.com Mon Feb 5 16:30:42 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 16:30:42 +0000 Subject: [openssl-commits] Build failed: openssl OpenSSL_1_1_0-stable.15382 Message-ID: <20180205163042.1.84CB08C361BDB9C8@appveyor.com> An HTML attachment was scrubbed... URL: From rsalz at openssl.org Mon Feb 5 16:38:02 2018 From: rsalz at openssl.org (Rich Salz) Date: Mon, 05 Feb 2018 16:38:02 +0000 Subject: [openssl-commits] [web] master update Message-ID: <1517848682.997083.17849.nullmailer@dev.openssl.org> The branch master has been updated via 2cef09be2a43e95dcd9f35695716a797e12cce3b (commit) from 8ba74cf7cecf400ff776874e4165e5c66653095a (commit) - Log ----------------------------------------------------------------- commit 2cef09be2a43e95dcd9f35695716a797e12cce3b Author: Rich Salz Date: Mon Feb 5 11:37:59 2018 -0500 Typo in directory name ----------------------------------------------------------------------- Summary of changes: {.well_known => .well-known}/security.txt | 0 {.well_known => .well-known}/security.txt.asc | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {.well_known => .well-known}/security.txt (100%) rename {.well_known => .well-known}/security.txt.asc (100%) diff --git a/.well_known/security.txt b/.well-known/security.txt similarity index 100% rename from .well_known/security.txt rename to .well-known/security.txt diff --git a/.well_known/security.txt.asc b/.well-known/security.txt.asc similarity index 100% rename from .well_known/security.txt.asc rename to .well-known/security.txt.asc From no-reply at appveyor.com Mon Feb 5 16:54:32 2018 From: no-reply at appveyor.com (AppVeyor) Date: Mon, 05 Feb 2018 16:54:32 +0000 Subject: [openssl-commits] Build completed: openssl master.15383 Message-ID: <20180205165432.1.76F0D3D02130A647@appveyor.com> An HTML attachment was scrubbed... URL: From matthias.st.pierre at ncp-e.com Mon Feb 5 19:06:27 2018 From: matthias.st.pierre at ncp-e.com (matthias.st.pierre at ncp-e.com) Date: Mon, 05 Feb 2018 19:06:27 +0000 Subject: [openssl-commits] [openssl] master update Message-ID: <1517857587.830646.5928.nullmailer@dev.openssl.org> The branch master has been updated via f61f62ea13470a00ae8be691d62abec97f94f0ee (commit) via 1648338ba1a63c19c7bae32170cd1d825b48eaee (commit) via 58351fbd02e9960af199df99f6f003419c1487a4 (commit) from 1c4b15458670aea5d3849d4b57b8c0ce34a54fbe (commit) - Log ----------------------------------------------------------------- commit f61f62ea13470a00ae8be691d62abec97f94f0ee Author: Dr. Matthias St. Pierre Date: Sat Feb 3 22:33:19 2018 +0100 Use RAND_DRBG_bytes() for RAND_bytes() and RAND_priv_bytes() The functions RAND_bytes() and RAND_priv_bytes() are now both based on a common implementation using RAND_DRBG_bytes() (if the default OpenSSL rand method is active). This not only simplifies the code but also has the advantage that additional input from a high precision timer is added on every generate call if the timer is available. Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5251) commit 1648338ba1a63c19c7bae32170cd1d825b48eaee Author: Dr. Matthias St. Pierre Date: Sat Feb 3 22:32:47 2018 +0100 Fix size limitation of RAND_DRBG_bytes() When comparing the implementations of drbg_bytes() and RAND_DRBG_bytes(), it was noticed that the former split the buffer into chunks when calling RAND_DRBG_generate() to circumvent the size limitation of the buffer to outlen <= drb->max_request. This loop was missing in RAND_DRBG_bytes(), so it was adopted from drbg_bytes(). Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5251) commit 58351fbd02e9960af199df99f6f003419c1487a4 Author: Dr. Matthias St. Pierre Date: Sat Feb 3 21:13:19 2018 +0100 drbg_bytes: remove check for DRBG_UNINITIALIZED state This check not only prevented the automatic reinstantiation of the DRBG, which is implemented in RAND_DRBG_generate(), but also prevented an error message from being generated in the case of failure. Reviewed-by: Kurt Roeckx (Merged from https://github.com/openssl/openssl/pull/5251) ----------------------------------------------------------------------- Summary of changes: crypto/rand/drbg_lib.c | 33 ++++++++++++++++----------------- crypto/rand/rand_lib.c | 4 ++-- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index cb2f9e8..4404e4f 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -546,10 +546,22 @@ int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen) { unsigned char *additional = NULL; size_t additional_len; + size_t chunk; size_t ret; additional_len = rand_drbg_get_additional_data(&additional, drbg->max_adinlen); - ret = RAND_DRBG_generate(drbg, out, outlen, 0, additional, additional_len); + + for ( ; outlen > 0; outlen -= chunk, out += chunk) { + chunk = outlen; + if (chunk > drbg->max_request) + chunk = drbg->max_request; + ret = RAND_DRBG_generate(drbg, out, chunk, 0, additional, additional_len); + if (!ret) + goto err; + } + ret = 1; + +err: if (additional_len != 0) OPENSSL_secure_clear_free(additional, additional_len); @@ -764,29 +776,16 @@ void rand_drbg_cleanup_int(void) /* Implements the default OpenSSL RAND_bytes() method */ static int drbg_bytes(unsigned char *out, int count) { - int ret = 0; - size_t chunk; + int ret; RAND_DRBG *drbg = RAND_DRBG_get0_public(); if (drbg == NULL) return 0; CRYPTO_THREAD_write_lock(drbg->lock); - if (drbg->state == DRBG_UNINITIALISED) - goto err; - - for ( ; count > 0; count -= chunk, out += chunk) { - chunk = count; - if (chunk > drbg->max_request) - chunk = drbg->max_request; - ret = RAND_DRBG_generate(drbg, out, chunk, 0, NULL, 0); - if (!ret) - goto err; - } - ret = 1; - -err: + ret = RAND_DRBG_bytes(drbg, out, count); CRYPTO_THREAD_unlock(drbg->lock); + return ret; } diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 20ac583..e82a63e 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -719,7 +719,7 @@ int RAND_priv_bytes(unsigned char *buf, int num) /* We have to lock the DRBG before generating bits from it. */ CRYPTO_THREAD_write_lock(drbg->lock); - ret = RAND_DRBG_generate(drbg, buf, num, 0, NULL, 0); + ret = RAND_DRBG_bytes(drbg, buf, num); CRYPTO_THREAD_unlock(drbg->lock); return ret; } From no-reply at appveyor.com Tue Feb 6 01:53:48 2018 From: no-reply at appveyor.com (AppVeyor) Date: Tue, 06 Feb 2018 01:53:48 +0000 Subject: [openssl-commits] Build failed: openssl master.15389 Message-ID: <20180206015348.1.DE293A829AED39C5@appveyor.com> An HTML attachment was scrubbed... URL: From mark at openssl.org Tue Feb 6 09:01:34 2018 From: mark at openssl.org (Mark J. Cox) Date: Tue, 06 Feb 2018 09:01:34 +0000 Subject: [openssl-commits] [web] master update Message-ID: <1517907694.623038.24207.nullmailer@dev.openssl.org> The branch master has been updated via 93624a912c2c58b247062aed08492ef988df292e (commit) via e18f270d1a141d407f43cc6eea82d860210180e7 (commit) from 2cef09be2a43e95dcd9f35695716a797e12cce3b (commit) - Log ----------------------------------------------------------------- commit 93624a912c2c58b247062aed08492ef988df292e Merge: e18f270 2cef09b Author: Mark J. Cox Date: Tue Feb 6 09:01:10 2018 +0000 Merge branch 'master' of git.openssl.org:openssl-web commit e18f270d1a141d407f43cc6eea82d860210180e7 Author: Mark J. Cox Date: Tue Feb 6 09:00:32 2018 +0000 When an issue affects more than one release list the releases latest first ----------------------------------------------------------------------- Summary of changes: bin/mk-cvepage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mk-cvepage b/bin/mk-cvepage index 4a6f942..8dbb864 100755 --- a/bin/mk-cvepage +++ b/bin/mk-cvepage @@ -115,7 +115,7 @@ for issue in sorted(issues, key=lambda x: (x.getAttribute('public'), x.getElemen allissues += "