Update pre9
This commit is contained in:
@@ -9,6 +9,13 @@
|
||||
|
||||
Changes between 1.1.0h and 1.1.1 [xx XXX xxxx]
|
||||
|
||||
*) Modified the random device based seed sources to keep the relevant
|
||||
file descriptors open rather than reopening them on each access.
|
||||
This allows such sources to operate in a chroot() jail without
|
||||
the associated device nodes being available. This behaviour can be
|
||||
controlled using RAND_keep_random_devices_open().
|
||||
[Paul Dale]
|
||||
|
||||
*) Numerous side-channel attack mitigations have been applied. This may have
|
||||
performance impacts for some algorithms for the benefit of improved
|
||||
security. Specific changes are noted in this change log by their respective
|
||||
|
||||
+35
-9
@@ -24,12 +24,12 @@
|
||||
Every Unix system has its own set of default locations for shared
|
||||
libraries, such as /lib, /usr/lib or possibly /usr/local/lib. If
|
||||
libraries are installed in non-default locations, dynamically linked
|
||||
binaries will not find them and therefore fail to run unless they get a
|
||||
bit of help from a defined runtime shared library search path.
|
||||
binaries will not find them and therefore fail to run, unless they get
|
||||
a bit of help from a defined runtime shared library search path.
|
||||
|
||||
For OpenSSL's application (the 'openssl' command), our configuration
|
||||
scripts do NOT generally set the runtime shared library search path for
|
||||
you. It's therefore advisable to set it explicitly when configuring
|
||||
you. It's therefore advisable to set it explicitly when configuring,
|
||||
unless the libraries are to be installed in directories that you know
|
||||
to be in the default list.
|
||||
|
||||
@@ -42,14 +42,15 @@
|
||||
Possible options to set the runtime shared library search path include
|
||||
the following:
|
||||
|
||||
-Wl,-rpath,/whatever/path
|
||||
-R /whatever/path
|
||||
-rpath /whatever/path
|
||||
-Wl,-rpath,/whatever/path # Linux, *BSD, etc.
|
||||
-R /whatever/path # Solaris
|
||||
-Wl,-R,/whatever/path # AIX (-bsvr4 is passed internally)
|
||||
-Wl,+b,/whatever/path # HP-UX
|
||||
-rpath /whatever/path # Tru64, IRIX
|
||||
|
||||
OpenSSL's configuration scripts recognise all these options and pass
|
||||
them to the Makefile that they build. (In fact, it recognises anything
|
||||
starting with '-Wl,' as a linker option, so for example, HP-UX'
|
||||
'-Wl,+b,/whatever/path' would be used correctly)
|
||||
them to the Makefile that they build. (In fact, all arguments starting
|
||||
with '-Wl,' are recognised as linker options.)
|
||||
|
||||
Please do not use verbatim directories in your runtime shared library
|
||||
search path! Some OpenSSL config targets add an extra directory level
|
||||
@@ -89,3 +90,28 @@
|
||||
|
||||
$ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
|
||||
'-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)'
|
||||
|
||||
It might be worth noting that some/most ELF systems implement support
|
||||
for runtime search path relative to the directory containing current
|
||||
executable, by interpreting $ORIGIN along with some other internal
|
||||
variables. Consult your system documentation.
|
||||
|
||||
Linking your application
|
||||
------------------------
|
||||
|
||||
Third-party applications dynamically linked with OpenSSL (or any other)
|
||||
shared library face exactly the same problem with non-default locations.
|
||||
The OpenSSL config options mentioned above might or might not have bearing
|
||||
on linking of the target application. "Might" means that under some
|
||||
circumstances it would be sufficient to link with OpenSSL shared library
|
||||
"naturally", i.e. with -L/whatever/path -lssl -lcrypto. But there are
|
||||
also cases when you'd have to explicitly specify runtime search path
|
||||
when linking your application. Consult your system documentation and use
|
||||
above section as inspiration...
|
||||
|
||||
Shared OpenSSL builds also install static libraries. Linking with the
|
||||
latter is likely to require special care, because linkers usually look
|
||||
for shared libraries first and tend to remain "blind" to static OpenSSL
|
||||
libraries. Referring to system documentation would suffice, if not for
|
||||
a corner case. On AIX static libraries (in shared build) are named
|
||||
differently, add _a suffix to link with them, e.g. -lcrypto_a.
|
||||
+39
-15
@@ -844,15 +844,29 @@ static void freeandcopy(char **dest, const char *source)
|
||||
*dest = OPENSSL_strdup(source);
|
||||
}
|
||||
|
||||
static int new_session_cb(SSL *S, SSL_SESSION *sess)
|
||||
static int new_session_cb(SSL *s, SSL_SESSION *sess)
|
||||
{
|
||||
BIO *stmp = BIO_new_file(sess_out, "w");
|
||||
|
||||
if (stmp == NULL) {
|
||||
BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
|
||||
} else {
|
||||
PEM_write_bio_SSL_SESSION(stmp, sess);
|
||||
BIO_free(stmp);
|
||||
if (sess_out != NULL) {
|
||||
BIO *stmp = BIO_new_file(sess_out, "w");
|
||||
|
||||
if (stmp == NULL) {
|
||||
BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
|
||||
} else {
|
||||
PEM_write_bio_SSL_SESSION(stmp, sess);
|
||||
BIO_free(stmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Session data gets dumped on connection for TLSv1.2 and below, and on
|
||||
* arrival of the NewSessionTicket for TLSv1.3.
|
||||
*/
|
||||
if (SSL_version(s) == TLS1_3_VERSION) {
|
||||
BIO_printf(bio_c_out,
|
||||
"---\nPost-Handshake New Session Ticket arrived:\n");
|
||||
SSL_SESSION_print(bio_c_out, sess);
|
||||
BIO_printf(bio_c_out, "---\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1919,11 +1933,9 @@ int s_client_main(int argc, char **argv)
|
||||
* come at any time. Therefore we use a callback to write out the session
|
||||
* when we know about it. This approach works for < TLSv1.3 as well.
|
||||
*/
|
||||
if (sess_out != NULL) {
|
||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT
|
||||
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
|
||||
SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
|
||||
}
|
||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT
|
||||
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
|
||||
SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
|
||||
|
||||
if (set_keylog_file(ctx, keylog_file))
|
||||
goto end;
|
||||
@@ -3125,7 +3137,8 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
||||
X509 *peer = NULL;
|
||||
STACK_OF(X509) *sk;
|
||||
const SSL_CIPHER *c;
|
||||
int i;
|
||||
int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
|
||||
long verify_result;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
const COMP_METHOD *comp, *expansion;
|
||||
#endif
|
||||
@@ -3282,7 +3295,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SSL_version(s) == TLS1_3_VERSION) {
|
||||
if (istls13) {
|
||||
switch (SSL_get_early_data_status(s)) {
|
||||
case SSL_EARLY_DATA_NOT_SENT:
|
||||
BIO_printf(bio, "Early data was not sent\n");
|
||||
@@ -3297,9 +3310,20 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* We also print the verify results when we dump session information,
|
||||
* but in TLSv1.3 we may not get that right away (or at all) depending
|
||||
* on when we get a NewSessionTicket. Therefore we print it now as well.
|
||||
*/
|
||||
verify_result = SSL_get_verify_result(s);
|
||||
BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result,
|
||||
X509_verify_cert_error_string(verify_result));
|
||||
} else {
|
||||
/* In TLSv1.3 we do this on arrival of a NewSessionTicket */
|
||||
SSL_SESSION_print(bio, SSL_get_session(s));
|
||||
}
|
||||
|
||||
SSL_SESSION_print(bio, SSL_get_session(s));
|
||||
if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) {
|
||||
BIO_printf(bio, "Keying material exporter:\n");
|
||||
BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
|
||||
|
||||
+4
-2
@@ -2557,7 +2557,8 @@ int speed_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
for (i = 0; i < loopargs_len; i++)
|
||||
RAND_bytes(loopargs[i].buf, 36);
|
||||
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
|
||||
goto end;
|
||||
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
for (testnum = 0; testnum < RSA_NUM; testnum++) {
|
||||
@@ -2653,7 +2654,8 @@ int speed_main(int argc, char **argv)
|
||||
#endif /* OPENSSL_NO_RSA */
|
||||
|
||||
for (i = 0; i < loopargs_len; i++)
|
||||
RAND_bytes(loopargs[i].buf, 36);
|
||||
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
|
||||
goto end;
|
||||
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
for (testnum = 0; testnum < DSA_NUM; testnum++) {
|
||||
|
||||
+1
-1
@@ -916,7 +916,7 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
|
||||
BIGNUM *serial = NULL;
|
||||
|
||||
if (serialfile == NULL) {
|
||||
const char *p = strchr(CAfile, '.');
|
||||
const char *p = strrchr(CAfile, '.');
|
||||
size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile);
|
||||
|
||||
buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer");
|
||||
|
||||
@@ -1012,6 +1012,11 @@ L\$AES_Td
|
||||
.STRINGZ "AES for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
___
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach (split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
|
||||
@@ -1022,8 +1027,12 @@ foreach (split("\n",$code)) {
|
||||
$SIZE_T==4 ? sprintf("extru%s,%d,8,",$1,31-$2)
|
||||
: sprintf("extrd,u%s,%d,8,",$1,63-$2)/e;
|
||||
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/,\*/,/ if ($SIZE_T==4);
|
||||
s/\bbv\b(.*\(%r2\))/bve$1/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
close STDOUT;
|
||||
@@ -200,7 +200,7 @@ static int slg_write(BIO *b, const char *in, int inl)
|
||||
BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
strncpy(buf, in, inl);
|
||||
memcpy(buf, in, inl);
|
||||
buf[inl] = '\0';
|
||||
|
||||
i = 0;
|
||||
|
||||
@@ -984,6 +984,11 @@ sub assemble {
|
||||
ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
|
||||
}
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach (split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
# flip word order in 64-bit mode...
|
||||
@@ -991,7 +996,10 @@ foreach (split("\n",$code)) {
|
||||
# assemble 2.0 instructions in 32-bit mode...
|
||||
s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($BN_SZ==4);
|
||||
|
||||
s/\bbv\b/bve/gm if ($SIZE_T==8);
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
|
||||
+1
-3
@@ -14,6 +14,7 @@
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "internal/refcount.h"
|
||||
#include "internal/ec_int.h"
|
||||
#include "curve448/curve448_lcl.h"
|
||||
|
||||
#if defined(__SUNPRO_C)
|
||||
@@ -636,7 +637,4 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
|
||||
void X25519_public_from_private(uint8_t out_public_value[32],
|
||||
const uint8_t private_key[32]);
|
||||
|
||||
int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
|
||||
const BIGNUM *x, BN_CTX *ctx);
|
||||
|
||||
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
|
||||
+30
-23
@@ -88,11 +88,12 @@ static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
if (dctx) {
|
||||
if (dctx != NULL) {
|
||||
EC_GROUP_free(dctx->gen_group);
|
||||
EC_KEY_free(dctx->co_key);
|
||||
OPENSSL_free(dctx->kdf_ukm);
|
||||
OPENSSL_free(dctx);
|
||||
ctx->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,19 +104,23 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
unsigned int sltmp;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_KEY *ec = ctx->pkey->pkey.ec;
|
||||
const int sig_sz = ECDSA_size(ec);
|
||||
|
||||
if (!sig) {
|
||||
*siglen = ECDSA_size(ec);
|
||||
/* ensure cast to size_t is safe */
|
||||
if (!ossl_assert(sig_sz > 0))
|
||||
return 0;
|
||||
|
||||
if (sig == NULL) {
|
||||
*siglen = (size_t)sig_sz;
|
||||
return 1;
|
||||
} else if (*siglen < (size_t)ECDSA_size(ec)) {
|
||||
}
|
||||
|
||||
if (*siglen < (size_t)sig_sz) {
|
||||
ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dctx->md)
|
||||
type = EVP_MD_type(dctx->md);
|
||||
else
|
||||
type = NID_sha1;
|
||||
type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
|
||||
|
||||
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
|
||||
|
||||
@@ -386,7 +391,8 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (dctx->gen_group == NULL) {
|
||||
ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
@@ -394,10 +400,8 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
ec = EC_KEY_new();
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
ret = EC_KEY_set_group(ec, dctx->gen_group);
|
||||
if (ret)
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
else
|
||||
if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
|
||||
|| !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
|
||||
EC_KEY_free(ec);
|
||||
return ret;
|
||||
}
|
||||
@@ -406,23 +410,26 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
int ret;
|
||||
|
||||
if (ctx->pkey == NULL && dctx->gen_group == NULL) {
|
||||
ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
ec = EC_KEY_new();
|
||||
if (!ec)
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
|
||||
EC_KEY_free(ec);
|
||||
return 0;
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
if (ctx->pkey) {
|
||||
/* Note: if error return, pkey is freed by parent routine */
|
||||
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
|
||||
return 0;
|
||||
} else {
|
||||
if (!EC_KEY_set_group(ec, dctx->gen_group))
|
||||
return 0;
|
||||
}
|
||||
return EC_KEY_generate_key(pkey->pkey.ec);
|
||||
/* Note: if error is returned, we count on caller to free pkey->pkey.ec */
|
||||
if (ctx->pkey != NULL)
|
||||
ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
|
||||
else
|
||||
ret = EC_KEY_set_group(ec, dctx->gen_group);
|
||||
|
||||
return ret ? EC_KEY_generate_key(ec) : 0;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD ec_pkey_meth = {
|
||||
|
||||
@@ -1089,7 +1089,10 @@ SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list
|
||||
SSL_F_CIPHERSUITE_CB:622:ciphersuite_cb
|
||||
SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names
|
||||
SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs
|
||||
SSL_F_CONSTRUCT_STATEFUL_TICKET:636:construct_stateful_ticket
|
||||
SSL_F_CONSTRUCT_STATELESS_TICKET:637:construct_stateless_ticket
|
||||
SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash
|
||||
SSL_F_CREATE_TICKET_PREQUEL:638:create_ticket_prequel
|
||||
SSL_F_CT_MOVE_SCTS:345:ct_move_scts
|
||||
SSL_F_CT_STRICT:349:ct_strict
|
||||
SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add
|
||||
@@ -2541,6 +2544,8 @@ SM2_R_INVALID_ENCODING:104:invalid encoding
|
||||
SM2_R_INVALID_FIELD:105:invalid field
|
||||
SM2_R_NO_PARAMETERS_SET:109:no parameters set
|
||||
SM2_R_USER_ID_TOO_LARGE:106:user id too large
|
||||
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
|
||||
application data after close notify
|
||||
SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake
|
||||
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
|
||||
attempt to reuse session in different context
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Internal EC functions for other submodules: not for application use */
|
||||
|
||||
#ifndef HEADER_OSSL_EC_INTERNAL_H
|
||||
# define HEADER_OSSL_EC_INTERNAL_H
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_EC
|
||||
|
||||
# include <openssl/ec.h>
|
||||
|
||||
/*-
|
||||
* Computes the multiplicative inverse of x in the range
|
||||
* [1,EC_GROUP::order), where EC_GROUP::order is the cardinality of the
|
||||
* subgroup generated by the generator G:
|
||||
*
|
||||
* res := x^(-1) (mod EC_GROUP::order).
|
||||
*
|
||||
* This function expects the following two conditions to hold:
|
||||
* - the EC_GROUP order is prime, and
|
||||
* - x is included in the range [1, EC_GROUP::order).
|
||||
*
|
||||
* This function returns 1 on success, 0 on error.
|
||||
*
|
||||
* If the EC_GROUP order is even, this function explicitly returns 0 as
|
||||
* an error.
|
||||
* In case any of the two conditions stated above is not satisfied,
|
||||
* the correctness of its output is not guaranteed, even if the return
|
||||
* value could still be 1 (as primality testing and a conditional modular
|
||||
* reduction round on the input can be omitted by the underlying
|
||||
* implementations for better SCA properties on regular input values).
|
||||
*/
|
||||
__owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
|
||||
const BIGNUM *x, BN_CTX *ctx);
|
||||
|
||||
# endif /* OPENSSL_NO_EC */
|
||||
#endif
|
||||
@@ -111,4 +111,21 @@ int rand_pool_add_nonce_data(RAND_POOL *pool);
|
||||
*/
|
||||
int rand_pool_add_additional_data(RAND_POOL *pool);
|
||||
|
||||
/*
|
||||
* Initialise the random pool reseeding sources.
|
||||
*
|
||||
* Returns 1 on success and 0 on failure.
|
||||
*/
|
||||
int rand_pool_init(void);
|
||||
|
||||
/*
|
||||
* Finalise the random pool reseeding sources.
|
||||
*/
|
||||
void rand_pool_cleanup(void);
|
||||
|
||||
/*
|
||||
* Control the random pool use of open file descriptors.
|
||||
*/
|
||||
void rand_pool_keep_random_devices_open(int keep);
|
||||
|
||||
#endif
|
||||
@@ -724,6 +724,11 @@ sub assemble {
|
||||
ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
|
||||
}
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach (split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
if ($SIZE_T==4) {
|
||||
@@ -731,7 +736,12 @@ foreach (split("\n",$code)) {
|
||||
s/cmpb,\*/comb,/;
|
||||
s/,\*/,/;
|
||||
}
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
|
||||
|
||||
+17
-4
@@ -255,9 +255,22 @@ L\$done2
|
||||
.PROCEND
|
||||
___
|
||||
}
|
||||
$code =~ s/cmpib,\*/comib,/gm if ($SIZE_T==4);
|
||||
$code =~ s/,\*/,/gm if ($SIZE_T==4);
|
||||
$code =~ s/\bbv\b/bve/gm if ($SIZE_T==8);
|
||||
print $code;
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach(split("\n",$code)) {
|
||||
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/cmpib,\*/comib,/ if ($SIZE_T==4);
|
||||
s/,\*/,/ if ($SIZE_T==4);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
close STDOUT;
|
||||
|
||||
@@ -324,8 +324,13 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
|
||||
if (rand_nonce_lock == NULL)
|
||||
goto err2;
|
||||
|
||||
if (!rand_pool_init())
|
||||
goto err3;
|
||||
|
||||
return 1;
|
||||
|
||||
err3:
|
||||
rand_pool_cleanup();
|
||||
err2:
|
||||
CRYPTO_THREAD_lock_free(rand_meth_lock);
|
||||
rand_meth_lock = NULL;
|
||||
@@ -343,6 +348,7 @@ void rand_cleanup_int(void)
|
||||
|
||||
if (meth != NULL && meth->cleanup != NULL)
|
||||
meth->cleanup();
|
||||
rand_pool_cleanup();
|
||||
RAND_set_rand_method(NULL);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
CRYPTO_THREAD_lock_free(rand_engine_lock);
|
||||
@@ -354,6 +360,15 @@ void rand_cleanup_int(void)
|
||||
rand_nonce_lock = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* RAND_close_seed_files() ensures that any seed file decriptors are
|
||||
* closed after use.
|
||||
*/
|
||||
void RAND_keep_random_devices_open(int keep)
|
||||
{
|
||||
rand_pool_keep_random_devices_open(keep);
|
||||
}
|
||||
|
||||
/*
|
||||
* RAND_poll() reseeds the default RNG using random input
|
||||
*
|
||||
|
||||
+157
-17
@@ -30,6 +30,8 @@
|
||||
|
||||
#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/time.h>
|
||||
|
||||
@@ -154,6 +156,14 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
return rand_pool_entropy_available(pool);
|
||||
}
|
||||
|
||||
void rand_pool_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void rand_pool_keep_random_devices_open(int keep)
|
||||
{
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
# if defined(OPENSSL_RAND_SEED_EGD) && \
|
||||
@@ -240,7 +250,7 @@ int syscall_random(void *buf, size_t buflen)
|
||||
* - Linux since 3.17 with glibc 2.25
|
||||
* - FreeBSD since 12.0 (1200061)
|
||||
*/
|
||||
# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__)
|
||||
# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
|
||||
extern int getentropy(void *bufer, size_t length) __attribute__((weak));
|
||||
|
||||
if (getentropy != NULL)
|
||||
@@ -274,6 +284,134 @@ int syscall_random(void *buf, size_t buflen)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_RAND_SEED_NONE) && defined(OPENSSL_RAND_SEED_DEVRANDOM)
|
||||
static const char *random_device_paths[] = { DEVRANDOM };
|
||||
static struct random_device {
|
||||
int fd;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
mode_t mode;
|
||||
dev_t rdev;
|
||||
} random_devices[OSSL_NELEM(random_device_paths)];
|
||||
static int keep_random_devices_open = 1;
|
||||
|
||||
/*
|
||||
* Verify that the file descriptor associated with the random source is
|
||||
* still valid. The rationale for doing this is the fact that it is not
|
||||
* uncommon for daemons to close all open file handles when daemonizing.
|
||||
* So the handle might have been closed or even reused for opening
|
||||
* another file.
|
||||
*/
|
||||
static int check_random_device(struct random_device * rd)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
return rd->fd != -1
|
||||
&& fstat(rd->fd, &st) != -1
|
||||
&& rd->dev == st.st_dev
|
||||
&& rd->ino == st.st_ino
|
||||
&& ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
|
||||
&& rd->rdev == st.st_rdev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a random device if required and return its file descriptor or -1 on error
|
||||
*/
|
||||
static int get_random_device(size_t n)
|
||||
{
|
||||
struct stat st;
|
||||
struct random_device * rd = &random_devices[n];
|
||||
|
||||
/* reuse existing file descriptor if it is (still) valid */
|
||||
if (check_random_device(rd))
|
||||
return rd->fd;
|
||||
|
||||
/* open the random device ... */
|
||||
if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
|
||||
return rd->fd;
|
||||
|
||||
/* ... and cache its relevant stat(2) data */
|
||||
if (fstat(rd->fd, &st) != -1) {
|
||||
rd->dev = st.st_dev;
|
||||
rd->ino = st.st_ino;
|
||||
rd->mode = st.st_mode;
|
||||
rd->rdev = st.st_rdev;
|
||||
} else {
|
||||
close(rd->fd);
|
||||
rd->fd = -1;
|
||||
}
|
||||
|
||||
return rd->fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a random device making sure it is a random device
|
||||
*/
|
||||
static void close_random_device(size_t n)
|
||||
{
|
||||
struct random_device * rd = &random_devices[n];
|
||||
|
||||
if (check_random_device(rd))
|
||||
close(rd->fd);
|
||||
rd->fd = -1;
|
||||
}
|
||||
|
||||
static void open_random_devices(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(random_devices); i++)
|
||||
(void)get_random_device(i);
|
||||
}
|
||||
|
||||
int rand_pool_init(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(random_devices); i++)
|
||||
random_devices[i].fd = -1;
|
||||
open_random_devices();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rand_pool_cleanup(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(random_devices); i++)
|
||||
close_random_device(i);
|
||||
}
|
||||
|
||||
void rand_pool_keep_random_devices_open(int keep)
|
||||
{
|
||||
if (keep)
|
||||
open_random_devices();
|
||||
else
|
||||
rand_pool_cleanup();
|
||||
keep_random_devices_open = keep;
|
||||
}
|
||||
|
||||
# else /* defined(OPENSSL_RAND_SEED_NONE)
|
||||
* || !defined(OPENSSL_RAND_SEED_DEVRANDOM)
|
||||
*/
|
||||
|
||||
int rand_pool_init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rand_pool_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void rand_pool_keep_random_devices_open(int keep)
|
||||
{
|
||||
}
|
||||
|
||||
# endif /* !defined(OPENSSL_RAND_SEED_NONE)
|
||||
* && defined(OPENSSL_RAND_SEED_DEVRANDOM)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Try the various seeding methods in turn, exit when successful.
|
||||
*
|
||||
@@ -324,30 +462,33 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
|
||||
# ifdef OPENSSL_RAND_SEED_DEVRANDOM
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
if (bytes_needed > 0) {
|
||||
static const char *paths[] = { DEVRANDOM, NULL };
|
||||
FILE *fp;
|
||||
int i;
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; paths[i] != NULL; i++) {
|
||||
if ((fp = fopen(paths[i], "rb")) == NULL)
|
||||
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
|
||||
const int fd = get_random_device(i);
|
||||
|
||||
if (fd == -1)
|
||||
continue;
|
||||
setbuf(fp, NULL);
|
||||
buffer = rand_pool_add_begin(pool, bytes_needed);
|
||||
if (buffer != NULL) {
|
||||
size_t bytes = 0;
|
||||
if (fread(buffer, 1, bytes_needed, fp) == bytes_needed)
|
||||
bytes = bytes_needed;
|
||||
const ssize_t n = read(fd, buffer, bytes_needed);
|
||||
|
||||
rand_pool_add_end(pool, bytes, 8 * bytes);
|
||||
entropy_available = rand_pool_entropy_available(pool);
|
||||
if (n <= 0) {
|
||||
close_random_device(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
rand_pool_add_end(pool, n, 8 * n);
|
||||
}
|
||||
fclose(fp);
|
||||
if (entropy_available > 0)
|
||||
return entropy_available;
|
||||
if (!keep_random_devices_open)
|
||||
close_random_device(i);
|
||||
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
}
|
||||
entropy_available = rand_pool_entropy_available(pool);
|
||||
if (entropy_available > 0)
|
||||
return entropy_available;
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -433,7 +574,6 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get the current time with the highest possible resolution
|
||||
*
|
||||
|
||||
@@ -507,4 +507,17 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
|
||||
return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
|
||||
}
|
||||
|
||||
int rand_pool_init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rand_pool_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void rand_pool_keep_random_devices_open(int keep)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -169,4 +169,17 @@ void RAND_screen(void)
|
||||
}
|
||||
# endif
|
||||
|
||||
int rand_pool_init(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rand_pool_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void rand_pool_keep_random_devices_open(int keep)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -313,9 +313,21 @@ L\$opts
|
||||
.STRINGZ "rc4(4x,`$SZ==1?"char":"int"`)"
|
||||
.STRINGZ "RC4 for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
___
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
$code =~ s/cmpib,\*/comib,/gm if ($SIZE_T==4);
|
||||
$code =~ s/\bbv\b/bve/gm if ($SIZE_T==8);
|
||||
|
||||
print $code;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach(split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/cmpib,\*/comib,/ if ($SIZE_T==4);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
close STDOUT;
|
||||
@@ -260,8 +260,20 @@ $code.=<<___;
|
||||
.STRINGZ "SHA1 block transform for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
___
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
$code =~ s/,\*/,/gm if ($SIZE_T==4);
|
||||
$code =~ s/\bbv\b/bve/gm if ($SIZE_T==8);
|
||||
print $code;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach(split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/,\*/,/ if ($SIZE_T==4);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
close STDOUT;
|
||||
@@ -767,6 +767,11 @@ sub assemble {
|
||||
ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
|
||||
}
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler/) {
|
||||
$gnuas = 1;
|
||||
}
|
||||
|
||||
foreach (split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/ge;
|
||||
|
||||
@@ -790,9 +795,11 @@ foreach (split("\n",$code)) {
|
||||
|
||||
s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($SIZE_T==4);
|
||||
|
||||
s/cmpb,\*/comb,/ if ($SIZE_T==4);
|
||||
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
|
||||
s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
|
||||
s/cmpb,\*/comb,/ if ($SIZE_T==4);
|
||||
s/\bbv\b/bve/ if ($SIZE_T==8);
|
||||
|
||||
print $_,"\n";
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "internal/sm2.h"
|
||||
#include "internal/sm2err.h"
|
||||
#include "internal/ec_int.h" /* ec_group_do_inverse_ord() */
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -133,7 +134,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
|
||||
continue;
|
||||
|
||||
if (!BN_add(s, dA, BN_value_one())
|
||||
|| !BN_mod_inverse(s, s, order, ctx)
|
||||
|| !ec_group_do_inverse_ord(group, s, s, ctx)
|
||||
|| !BN_mod_mul(tmp, dA, r, order, ctx)
|
||||
|| !BN_sub(tmp, k, tmp)
|
||||
|| !BN_mod_mul(s, s, tmp, order, ctx)) {
|
||||
|
||||
@@ -1216,9 +1216,9 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
|
||||
* Last, check that the rest of the extension is a decimal number, at
|
||||
* least one digit long.
|
||||
*/
|
||||
if (!isdigit(*p))
|
||||
if (!ossl_isdigit(*p))
|
||||
return 0;
|
||||
while (isdigit(*p))
|
||||
while (ossl_isdigit(*p))
|
||||
p++;
|
||||
|
||||
# ifdef __VMS
|
||||
@@ -1227,7 +1227,7 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
|
||||
*/
|
||||
if (*p == ';')
|
||||
for (p++; *p != '\0'; p++)
|
||||
if (!isdigit(*p))
|
||||
if (!ossl_isdigit(*p))
|
||||
break;
|
||||
# endif
|
||||
|
||||
|
||||
+13
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
RAND_add, RAND_poll, RAND_seed, RAND_status, RAND_event, RAND_screen
|
||||
RAND_add, RAND_poll, RAND_seed, RAND_status, RAND_event, RAND_screen,
|
||||
RAND_keep_random_devices_open
|
||||
- add randomness to the PRNG or get its status
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@@ -15,6 +16,8 @@ RAND_add, RAND_poll, RAND_seed, RAND_status, RAND_event, RAND_screen
|
||||
void RAND_add(const void *buf, int num, double randomness);
|
||||
void RAND_seed(const void *buf, int num);
|
||||
|
||||
void RAND_keep_random_devices_open(int keep);
|
||||
|
||||
Deprecated:
|
||||
|
||||
#if OPENSSL_API_COMPAT < 0x10100000L
|
||||
@@ -54,6 +57,15 @@ should consider using L<RAND_load_file(3)> instead.
|
||||
|
||||
RAND_seed() is equivalent to RAND_add() with B<randomness> set to B<num>.
|
||||
|
||||
RAND_keep_random_devices_open() is used to control file descriptor
|
||||
usage by the random seed sources. Some seed sources maintain open file
|
||||
descriptors by default, which allows such sources to operate in a
|
||||
chroot(2) jail without the associated device nodes being available. When
|
||||
the B<keep> argument is zero, this call disables the retention of file
|
||||
descriptors. Conversely, a non-zero argument enables the retention of
|
||||
file descriptors. This function is usually called during initialization
|
||||
and it takes effect immediately.
|
||||
|
||||
RAND_event() and RAND_screen() are equivalent to RAND_poll() and exist
|
||||
for compatibility reasons only. See HISTORY section below.
|
||||
|
||||
|
||||
@@ -145,13 +145,39 @@ DTLS connections.
|
||||
|
||||
=item SSL_OP_NO_TICKET
|
||||
|
||||
Normally clients and servers will, where possible, transparently make use
|
||||
of RFC4507bis tickets for stateless session resumption.
|
||||
SSL/TLS supports two mechanisms for resuming sessions: session ids and stateless
|
||||
session tickets.
|
||||
|
||||
If this option is set this functionality is disabled and tickets will
|
||||
not be used by clients or servers.
|
||||
When using session ids a copy of the session information is
|
||||
cached on the server and a unique id is sent to the client. When the client
|
||||
wishes to resume it provides the unique id so that the server can retrieve the
|
||||
session information from its cache.
|
||||
|
||||
This option only applies to TLSv1.2 and below. It is ignored for TLSv1.3.
|
||||
When using stateless session tickets the server uses a session ticket encryption
|
||||
key to encrypt the session information. This encrypted data is sent to the
|
||||
client as a "ticket". When the client wishes to resume it sends the encrypted
|
||||
data back to the server. The server uses its key to decrypt the data and resume
|
||||
the session. In this way the server can operate statelessly - no session
|
||||
information needs to be cached locally.
|
||||
|
||||
The TLSv1.3 protocol only supports tickets and does not directly support session
|
||||
ids. However OpenSSL allows two modes of ticket operation in TLSv1.3: stateful
|
||||
and stateless. Stateless tickets work the same way as in TLSv1.2 and below.
|
||||
Stateful tickets mimic the session id behaviour available in TLSv1.2 and below.
|
||||
The session information is cached on the server and the session id is wrapped up
|
||||
in a ticket and sent back to the client. When the client wishes to resume, it
|
||||
presents a ticket in the same way as for stateless tickets. The server can then
|
||||
extract the session id from the ticket and retrieve the session information from
|
||||
its cache.
|
||||
|
||||
By default OpenSSL will use stateless tickets. The SSL_OP_NO_TICKET option will
|
||||
cause stateless tickets to not be issued. In TLSv1.2 and below this means no
|
||||
ticket gets sent to the client at all. In TLSv1.3 a stateful ticket will be
|
||||
sent. This is a server-side option only.
|
||||
|
||||
In TLSv1.3 it is possible to suppress all tickets (stateful and stateless) from
|
||||
being sent by calling L<SSL_CTX_set_num_tickets(3)> or
|
||||
L<SSL_set_num_tickets(3)>.
|
||||
|
||||
=item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
|
||||
|
||||
|
||||
@@ -226,12 +226,14 @@ was submitted will be ignored). Note that single use tickets are enforced even
|
||||
if a client does not send any early data.
|
||||
|
||||
The replay protection mechanism relies on the internal OpenSSL server session
|
||||
cache (see L<SSL_CTX_set_session_cache_mode(3)>). By default sessions will be
|
||||
added to the cache whenever a session ticket is issued. When a client attempts
|
||||
to resume the session OpenSSL will check for its presence in the internal cache.
|
||||
If it exists then the resumption is allowed and the session is removed from the
|
||||
cache. If it does not exist then the resumption is not allowed and a full
|
||||
handshake will occur.
|
||||
cache (see L<SSL_CTX_set_session_cache_mode(3)>). When replay protection is
|
||||
being used the server will operate as if the SSL_OP_NO_TICKET option had been
|
||||
selected (see L<SSL_CTX_set_options(3)>). Sessions will be added to the cache
|
||||
whenever a session ticket is issued. When a client attempts to resume the
|
||||
session, OpenSSL will check for its presence in the internal cache. If it exists
|
||||
then the resumption is allowed and the session is removed from the cache. If it
|
||||
does not exist then the resumption is not allowed and a full handshake will
|
||||
occur.
|
||||
|
||||
Note that some applications may maintain an external cache of sessions (see
|
||||
L<SSL_CTX_sess_set_new_cb(3)> and similar functions). It is the application's
|
||||
|
||||
@@ -44,6 +44,7 @@ int RAND_priv_bytes(unsigned char *buf, int num);
|
||||
DEPRECATEDIN_1_1_0(int RAND_pseudo_bytes(unsigned char *buf, int num))
|
||||
|
||||
void RAND_seed(const void *buf, int num);
|
||||
void RAND_keep_random_devices_open(int keep);
|
||||
|
||||
# if defined(__ANDROID__) && defined(__NDK_FPABI__)
|
||||
__NDK_FPABI__ /* __attribute__((pcs("aapcs"))) on ARM */
|
||||
|
||||
@@ -1079,8 +1079,8 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
|
||||
# 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
|
||||
# define OpenSSL_add_ssl_algorithms() SSL_library_init()
|
||||
# define SSLeay_add_ssl_algorithms() SSL_library_init()
|
||||
# endif
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_CIPHERSUITE_CB 622
|
||||
# define SSL_F_CONSTRUCT_CA_NAMES 552
|
||||
# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 553
|
||||
# define SSL_F_CONSTRUCT_STATEFUL_TICKET 636
|
||||
# define SSL_F_CONSTRUCT_STATELESS_TICKET 637
|
||||
# define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 539
|
||||
# define SSL_F_CREATE_TICKET_PREQUEL 638
|
||||
# define SSL_F_CT_MOVE_SCTS 345
|
||||
# define SSL_F_CT_STRICT 349
|
||||
# define SSL_F_CUSTOM_EXT_ADD 554
|
||||
@@ -446,6 +449,7 @@ int ERR_load_SSL_strings(void);
|
||||
/*
|
||||
* SSL reason codes.
|
||||
*/
|
||||
# define SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY 291
|
||||
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
|
||||
# define SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE 143
|
||||
|
||||
+62
-38
@@ -1457,40 +1457,6 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case of record types for which we have 'fragment' storage, fill
|
||||
* that so that we can process the data at a fixed place.
|
||||
*/
|
||||
{
|
||||
size_t dest_maxlen = 0;
|
||||
unsigned char *dest = NULL;
|
||||
size_t *dest_len = NULL;
|
||||
|
||||
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
|
||||
dest_maxlen = sizeof(s->rlayer.handshake_fragment);
|
||||
dest = s->rlayer.handshake_fragment;
|
||||
dest_len = &s->rlayer.handshake_fragment_len;
|
||||
}
|
||||
|
||||
if (dest_maxlen > 0) {
|
||||
n = dest_maxlen - *dest_len; /* available space in 'dest' */
|
||||
if (SSL3_RECORD_get_length(rr) < n)
|
||||
n = SSL3_RECORD_get_length(rr); /* available bytes */
|
||||
|
||||
/* now move 'n' bytes: */
|
||||
memcpy(dest + *dest_len,
|
||||
SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n);
|
||||
SSL3_RECORD_add_off(rr, n);
|
||||
SSL3_RECORD_sub_length(rr, n);
|
||||
*dest_len += n;
|
||||
if (SSL3_RECORD_get_length(rr) == 0)
|
||||
SSL3_RECORD_set_read(rr);
|
||||
|
||||
if (*dest_len < dest_maxlen)
|
||||
goto start; /* fragment was too small */
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
|
||||
* (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
|
||||
@@ -1583,12 +1549,70 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
|
||||
* shutdown */
|
||||
s->rwstate = SSL_NOTHING;
|
||||
/*
|
||||
* If we've sent a close_notify but not yet received one back then ditch
|
||||
* anything we read.
|
||||
*/
|
||||
if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) {
|
||||
/*
|
||||
* In TLSv1.3 this could get problematic if we receive a KeyUpdate
|
||||
* message after we sent a close_notify because we're about to ditch it,
|
||||
* so we won't be able to read a close_notify sent afterwards! We don't
|
||||
* support that.
|
||||
*/
|
||||
SSL3_RECORD_set_length(rr, 0);
|
||||
SSL3_RECORD_set_read(rr);
|
||||
return 0;
|
||||
|
||||
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
|
||||
BIO *rbio;
|
||||
|
||||
if ((s->mode & SSL_MODE_AUTO_RETRY) != 0)
|
||||
goto start;
|
||||
|
||||
s->rwstate = SSL_READING;
|
||||
rbio = SSL_get_rbio(s);
|
||||
BIO_clear_retry_flags(rbio);
|
||||
BIO_set_retry_read(rbio);
|
||||
} else {
|
||||
/*
|
||||
* The peer is continuing to send application data, but we have
|
||||
* already sent close_notify. If this was expected we should have
|
||||
* been called via SSL_read() and this would have been handled
|
||||
* above.
|
||||
* No alert sent because we already sent close_notify
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_READ_BYTES,
|
||||
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For handshake data we have 'fragment' storage, so fill that so that we
|
||||
* can process the header at a fixed place. This is done after the
|
||||
* "SHUTDOWN" code above to avoid filling the fragment storage with data
|
||||
* that we're just going to discard.
|
||||
*/
|
||||
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
|
||||
size_t dest_maxlen = sizeof(s->rlayer.handshake_fragment);
|
||||
unsigned char *dest = s->rlayer.handshake_fragment;
|
||||
size_t *dest_len = &s->rlayer.handshake_fragment_len;
|
||||
|
||||
n = dest_maxlen - *dest_len; /* available space in 'dest' */
|
||||
if (SSL3_RECORD_get_length(rr) < n)
|
||||
n = SSL3_RECORD_get_length(rr); /* available bytes */
|
||||
|
||||
/* now move 'n' bytes: */
|
||||
memcpy(dest + *dest_len,
|
||||
SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n);
|
||||
SSL3_RECORD_add_off(rr, n);
|
||||
SSL3_RECORD_sub_length(rr, n);
|
||||
*dest_len += n;
|
||||
if (SSL3_RECORD_get_length(rr) == 0)
|
||||
SSL3_RECORD_set_read(rr);
|
||||
|
||||
if (*dest_len < dest_maxlen)
|
||||
goto start; /* fragment was too small */
|
||||
}
|
||||
|
||||
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
|
||||
|
||||
@@ -24,8 +24,14 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0),
|
||||
"construct_key_exchange_tbs"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATEFUL_TICKET, 0),
|
||||
"construct_stateful_ticket"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATELESS_TICKET, 0),
|
||||
"construct_stateless_ticket"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, 0),
|
||||
"create_synthetic_message_hash"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_TICKET_PREQUEL, 0),
|
||||
"create_ticket_prequel"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CT_MOVE_SCTS, 0), "ct_move_scts"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CT_STRICT, 0), "ct_strict"},
|
||||
{ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_ADD, 0), "custom_ext_add"},
|
||||
@@ -720,6 +726,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY),
|
||||
"application data after close notify"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE),
|
||||
"app data in handshake"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),
|
||||
|
||||
+6
-3
@@ -3435,18 +3435,21 @@ void ssl_update_cache(SSL *s, int mode)
|
||||
&& (!s->hit || SSL_IS_TLS13(s))) {
|
||||
/*
|
||||
* Add the session to the internal cache. In server side TLSv1.3 we
|
||||
* normally don't do this because its a full stateless ticket with only
|
||||
* a dummy session id so there is no reason to cache it, unless:
|
||||
* normally don't do this because by default it's a full stateless ticket
|
||||
* with only a dummy session id so there is no reason to cache it,
|
||||
* unless:
|
||||
* - we are doing early_data, in which case we cache so that we can
|
||||
* detect replays
|
||||
* - the application has set a remove_session_cb so needs to know about
|
||||
* session timeout events
|
||||
* - SSL_OP_NO_TICKET is set in which case it is a stateful ticket
|
||||
*/
|
||||
if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0
|
||||
&& (!SSL_IS_TLS13(s)
|
||||
|| !s->server
|
||||
|| s->max_early_data > 0
|
||||
|| s->session_ctx->remove_session_cb != NULL))
|
||||
|| s->session_ctx->remove_session_cb != NULL
|
||||
|| (s->options & SSL_OP_NO_TICKET) != 0))
|
||||
SSL_CTX_add_session(s->session_ctx, s->session);
|
||||
|
||||
/*
|
||||
|
||||
@@ -2249,6 +2249,8 @@ void ssl_cert_clear_certs(CERT *c);
|
||||
void ssl_cert_free(CERT *c);
|
||||
__owur int ssl_generate_session_id(SSL *s, SSL_SESSION *ss);
|
||||
__owur int ssl_get_new_session(SSL *s, int session);
|
||||
__owur SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
|
||||
size_t sess_id_len);
|
||||
__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello);
|
||||
__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
|
||||
__owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
|
||||
|
||||
+72
-62
@@ -12,6 +12,7 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/engine.h>
|
||||
#include "internal/refcount.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "ssl_locl.h"
|
||||
#include "statem/statem_locl.h"
|
||||
|
||||
@@ -452,6 +453,73 @@ int ssl_get_new_session(SSL *s, int session)
|
||||
return 1;
|
||||
}
|
||||
|
||||
SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
|
||||
size_t sess_id_len)
|
||||
{
|
||||
SSL_SESSION *ret = NULL;
|
||||
int discard;
|
||||
|
||||
if ((s->session_ctx->session_cache_mode
|
||||
& SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) {
|
||||
SSL_SESSION data;
|
||||
|
||||
data.ssl_version = s->version;
|
||||
if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH))
|
||||
return NULL;
|
||||
|
||||
memcpy(data.session_id, sess_id, sess_id_len);
|
||||
data.session_id_length = sess_id_len;
|
||||
|
||||
CRYPTO_THREAD_read_lock(s->session_ctx->lock);
|
||||
ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
|
||||
if (ret != NULL) {
|
||||
/* don't allow other threads to steal it: */
|
||||
SSL_SESSION_up_ref(ret);
|
||||
}
|
||||
CRYPTO_THREAD_unlock(s->session_ctx->lock);
|
||||
if (ret == NULL)
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
}
|
||||
|
||||
if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
|
||||
int copy = 1;
|
||||
|
||||
ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©);
|
||||
|
||||
if (ret != NULL) {
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_cb_hit, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
|
||||
/*
|
||||
* Increment reference count now if the session callback asks us
|
||||
* to do so (note that if the session structures returned by the
|
||||
* callback are shared between threads, it must handle the
|
||||
* reference count itself [i.e. copy == 0], or things won't be
|
||||
* thread-safe).
|
||||
*/
|
||||
if (copy)
|
||||
SSL_SESSION_up_ref(ret);
|
||||
|
||||
/*
|
||||
* Add the externally cached session to the internal cache as
|
||||
* well if and only if we are supposed to.
|
||||
*/
|
||||
if ((s->session_ctx->session_cache_mode &
|
||||
SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) {
|
||||
/*
|
||||
* Either return value of SSL_CTX_add_session should not
|
||||
* interrupt the session resumption process. The return
|
||||
* value is intentionally ignored.
|
||||
*/
|
||||
(void)SSL_CTX_add_session(s->session_ctx, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
|
||||
* connection. It is only called by servers.
|
||||
@@ -504,8 +572,11 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
goto err;
|
||||
case SSL_TICKET_NONE:
|
||||
case SSL_TICKET_EMPTY:
|
||||
if (hello->session_id_len > 0)
|
||||
if (hello->session_id_len > 0) {
|
||||
try_session_cache = 1;
|
||||
ret = lookup_sess_in_cache(s, hello->session_id,
|
||||
hello->session_id_len);
|
||||
}
|
||||
break;
|
||||
case SSL_TICKET_NO_DECRYPT:
|
||||
case SSL_TICKET_SUCCESS:
|
||||
@@ -514,67 +585,6 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
}
|
||||
}
|
||||
|
||||
if (try_session_cache &&
|
||||
ret == NULL &&
|
||||
!(s->session_ctx->session_cache_mode &
|
||||
SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
|
||||
SSL_SESSION data;
|
||||
|
||||
data.ssl_version = s->version;
|
||||
memcpy(data.session_id, hello->session_id, hello->session_id_len);
|
||||
data.session_id_length = hello->session_id_len;
|
||||
|
||||
CRYPTO_THREAD_read_lock(s->session_ctx->lock);
|
||||
ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
|
||||
if (ret != NULL) {
|
||||
/* don't allow other threads to steal it: */
|
||||
SSL_SESSION_up_ref(ret);
|
||||
}
|
||||
CRYPTO_THREAD_unlock(s->session_ctx->lock);
|
||||
if (ret == NULL)
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
}
|
||||
|
||||
if (try_session_cache &&
|
||||
ret == NULL && s->session_ctx->get_session_cb != NULL) {
|
||||
int copy = 1;
|
||||
|
||||
ret = s->session_ctx->get_session_cb(s, hello->session_id,
|
||||
hello->session_id_len,
|
||||
©);
|
||||
|
||||
if (ret != NULL) {
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_cb_hit, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
|
||||
/*
|
||||
* Increment reference count now if the session callback asks us
|
||||
* to do so (note that if the session structures returned by the
|
||||
* callback are shared between threads, it must handle the
|
||||
* reference count itself [i.e. copy == 0], or things won't be
|
||||
* thread-safe).
|
||||
*/
|
||||
if (copy)
|
||||
SSL_SESSION_up_ref(ret);
|
||||
|
||||
/*
|
||||
* Add the externally cached session to the internal cache as
|
||||
* well if and only if we are supposed to.
|
||||
*/
|
||||
if (!
|
||||
(s->session_ctx->session_cache_mode &
|
||||
SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
|
||||
/*
|
||||
* Either return value of SSL_CTX_add_session should not
|
||||
* interrupt the session resumption process. The return
|
||||
* value is intentionally ignored.
|
||||
*/
|
||||
SSL_CTX_add_session(s->session_ctx, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
|
||||
|
||||
+11
-1
@@ -33,6 +33,7 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
|
||||
{
|
||||
size_t i;
|
||||
const char *s;
|
||||
int istls13 = (x->ssl_version == TLS1_3_VERSION);
|
||||
|
||||
if (x == NULL)
|
||||
goto err;
|
||||
@@ -70,7 +71,10 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
|
||||
if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n Master-Key: ") <= 0)
|
||||
if (istls13) {
|
||||
if (BIO_puts(bp, "\n Resumption PSK: ") <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "\n Master-Key: ") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->master_key_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
|
||||
@@ -145,6 +149,12 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
|
||||
x->flags & SSL_SESS_FLAG_EXTMS ? "yes" : "no") <= 0)
|
||||
goto err;
|
||||
|
||||
if (istls13) {
|
||||
if (BIO_printf(bp, " Max Early Data: %u\n",
|
||||
x->ext.max_early_data) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
|
||||
@@ -1009,6 +1009,33 @@ int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
|
||||
SSL_SESSION **sess)
|
||||
{
|
||||
SSL_SESSION *tmpsess = NULL;
|
||||
|
||||
switch (PACKET_remaining(tick)) {
|
||||
case 0:
|
||||
return SSL_TICKET_EMPTY;
|
||||
|
||||
case SSL_MAX_SSL_SESSION_ID_LENGTH:
|
||||
break;
|
||||
|
||||
default:
|
||||
return SSL_TICKET_NO_DECRYPT;
|
||||
}
|
||||
|
||||
tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
|
||||
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
||||
|
||||
if (tmpsess == NULL)
|
||||
return SSL_TICKET_NO_DECRYPT;
|
||||
|
||||
s->ext.ticket_expected = 1;
|
||||
*sess = tmpsess;
|
||||
return SSL_TICKET_SUCCESS;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
@@ -1132,9 +1159,18 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
uint32_t ticket_age = 0, now, agesec, agems;
|
||||
int ret;
|
||||
|
||||
ret = tls_decrypt_ticket(s, PACKET_data(&identity),
|
||||
PACKET_remaining(&identity), NULL, 0,
|
||||
&sess);
|
||||
/*
|
||||
* If we are using anti-replay protection then we behave as if
|
||||
* SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
|
||||
* is no point in using full stateless tickets.
|
||||
*/
|
||||
if ((s->options & SSL_OP_NO_TICKET) != 0
|
||||
|| s->max_early_data > 0)
|
||||
ret = tls_get_stateful_ticket(s, &identity, &sess);
|
||||
else
|
||||
ret = tls_decrypt_ticket(s, PACKET_data(&identity),
|
||||
PACKET_remaining(&identity), NULL, 0,
|
||||
&sess);
|
||||
|
||||
if (ret == SSL_TICKET_EMPTY) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
|
||||
|
||||
+238
-161
@@ -3740,7 +3740,44 @@ int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add,
|
||||
unsigned char *tick_nonce)
|
||||
{
|
||||
/*
|
||||
* Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
|
||||
* unspecified for resumed session (for simplicity).
|
||||
* In TLSv1.3 we reset the "time" field above, and always specify the
|
||||
* timeout.
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u32(pkt,
|
||||
(s->hit && !SSL_IS_TLS13(s))
|
||||
? 0 : s->session->timeout)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!WPACKET_put_bytes_u32(pkt, age_add)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the sub-packet for the actual ticket data */
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
|
||||
unsigned char *tick_nonce)
|
||||
{
|
||||
unsigned char *senc = NULL;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
@@ -3753,14 +3790,197 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
SSL_CTX *tctx = s->session_ctx;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
|
||||
int iv_len;
|
||||
unsigned char tick_nonce[TICKET_NONCE_SIZE];
|
||||
int iv_len, ok = 0;
|
||||
size_t macoffset, macendoffset;
|
||||
|
||||
/* get session encoding length */
|
||||
slen_full = i2d_SSL_SESSION(s->session, NULL);
|
||||
/*
|
||||
* Some length values are 16 bits, so forget it if session is too
|
||||
* long
|
||||
*/
|
||||
if (slen_full == 0 || slen_full > 0xFF00) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
senc = OPENSSL_malloc(slen_full);
|
||||
if (senc == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
hctx = HMAC_CTX_new();
|
||||
if (ctx == NULL || hctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(s->session, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a fresh copy (not shared with other threads) to clean up
|
||||
*/
|
||||
const_p = senc;
|
||||
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
|
||||
if (sess == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
slen = i2d_SSL_SESSION(sess, NULL);
|
||||
if (slen == 0 || slen > slen_full) {
|
||||
/* shouldn't ever happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(sess, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
SSL_SESSION_free(sess);
|
||||
|
||||
/*
|
||||
* Initialize HMAC and cipher contexts. If callback present it does
|
||||
* all the work otherwise use generated values from parent ctx.
|
||||
*/
|
||||
if (tctx->ext.ticket_key_cb) {
|
||||
/* if 0 is returned, write an empty ticket */
|
||||
int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
|
||||
hctx, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
|
||||
/* Put timeout and length */
|
||||
if (!WPACKET_put_bytes_u32(pkt, 0)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
return 1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
} else {
|
||||
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
|
||||
|
||||
iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
if (RAND_bytes(iv, iv_len) <= 0
|
||||
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
|
||||
tctx->ext.secure->tick_aes_key, iv)
|
||||
|| !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
|
||||
sizeof(tctx->ext.secure->tick_hmac_key),
|
||||
EVP_sha256(), NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
memcpy(key_name, tctx->ext.tick_key_name,
|
||||
sizeof(tctx->ext.tick_key_name));
|
||||
}
|
||||
|
||||
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!WPACKET_get_total_written(pkt, &macoffset)
|
||||
/* Output key name */
|
||||
|| !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
|
||||
/* output IV */
|
||||
|| !WPACKET_memcpy(pkt, iv, iv_len)
|
||||
|| !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
|
||||
&encdata1)
|
||||
/* Encrypt session data */
|
||||
|| !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
|
||||
|| !WPACKET_allocate_bytes(pkt, len, &encdata2)
|
||||
|| encdata1 != encdata2
|
||||
|| !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
|
||||
|| !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
|
||||
|| encdata1 + len != encdata2
|
||||
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|
||||
|| !WPACKET_get_total_written(pkt, &macendoffset)
|
||||
|| !HMAC_Update(hctx,
|
||||
(unsigned char *)s->init_buf->data + macoffset,
|
||||
macendoffset - macoffset)
|
||||
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|
||||
|| !HMAC_Final(hctx, macdata1, &hlen)
|
||||
|| hlen > EVP_MAX_MD_SIZE
|
||||
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|
||||
|| macdata1 != macdata2) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Close the sub-packet created by create_ticket_prequel() */
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
|
||||
unsigned char *tick_nonce)
|
||||
{
|
||||
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_memcpy(pkt, s->session->session_id,
|
||||
s->session->session_id_length)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
SSL_CTX *tctx = s->session_ctx;
|
||||
unsigned char tick_nonce[TICKET_NONCE_SIZE];
|
||||
union {
|
||||
unsigned char age_add_c[sizeof(uint32_t)];
|
||||
uint32_t age_add;
|
||||
} age_add_u;
|
||||
|
||||
age_add_u.age_add = 0;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
size_t i, hashlen;
|
||||
uint64_t nonce;
|
||||
@@ -3797,10 +4017,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
cb(s, SSL_CB_HANDSHAKE_START, 1);
|
||||
}
|
||||
/*
|
||||
* If we already sent one NewSessionTicket then we need to take a copy
|
||||
* of it and create a new session from it.
|
||||
* If we already sent one NewSessionTicket, or we resumed then
|
||||
* s->session may already be in a cache and so we must not modify it.
|
||||
* Instead we need to take a copy of it and modify that.
|
||||
*/
|
||||
if (s->sent_tickets != 0) {
|
||||
if (s->sent_tickets != 0 || s->hit) {
|
||||
SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
|
||||
|
||||
if (new_sess == NULL) {
|
||||
@@ -3862,161 +4083,23 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0)
|
||||
goto err;
|
||||
|
||||
/* get session encoding length */
|
||||
slen_full = i2d_SSL_SESSION(s->session, NULL);
|
||||
/*
|
||||
* Some length values are 16 bits, so forget it if session is too
|
||||
* long
|
||||
* If we are using anti-replay protection then we behave as if
|
||||
* SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
|
||||
* is no point in using full stateless tickets.
|
||||
*/
|
||||
if (slen_full == 0 || slen_full > 0xFF00) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
senc = OPENSSL_malloc(slen_full);
|
||||
if (senc == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
hctx = HMAC_CTX_new();
|
||||
if (ctx == NULL || hctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(s->session, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a fresh copy (not shared with other threads) to clean up
|
||||
*/
|
||||
const_p = senc;
|
||||
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
|
||||
if (sess == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
slen = i2d_SSL_SESSION(sess, NULL);
|
||||
if (slen == 0 || slen > slen_full) {
|
||||
/* shouldn't ever happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(sess, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
SSL_SESSION_free(sess);
|
||||
|
||||
/*
|
||||
* Initialize HMAC and cipher contexts. If callback present it does
|
||||
* all the work otherwise use generated values from parent ctx.
|
||||
*/
|
||||
if (tctx->ext.ticket_key_cb) {
|
||||
/* if 0 is returned, write an empty ticket */
|
||||
int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
|
||||
hctx, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
|
||||
/* Put timeout and length */
|
||||
if (!WPACKET_put_bytes_u32(pkt, 0)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
return 1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
if (((s->options & SSL_OP_NO_TICKET) != 0 || s->max_early_data > 0)
|
||||
&& SSL_IS_TLS13(s)) {
|
||||
if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
} else {
|
||||
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
|
||||
|
||||
iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
if (RAND_bytes(iv, iv_len) <= 0
|
||||
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
|
||||
tctx->ext.secure->tick_aes_key, iv)
|
||||
|| !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
|
||||
sizeof(tctx->ext.secure->tick_hmac_key),
|
||||
EVP_sha256(), NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
memcpy(key_name, tctx->ext.tick_key_name,
|
||||
sizeof(tctx->ext.tick_key_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
|
||||
* unspecified for resumed session (for simplicity).
|
||||
* In TLSv1.3 we reset the "time" field above, and always specify the
|
||||
* timeout.
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u32(pkt,
|
||||
(s->hit && !SSL_IS_TLS13(s))
|
||||
? 0 : s->session->timeout)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& (!WPACKET_put_bytes_u32(pkt, age_add_u.age_add)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, tick_nonce,
|
||||
TICKET_NONCE_SIZE)))
|
||||
/* Now the actual ticket data */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &macoffset)
|
||||
/* Output key name */
|
||||
|| !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
|
||||
/* output IV */
|
||||
|| !WPACKET_memcpy(pkt, iv, iv_len)
|
||||
|| !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
|
||||
&encdata1)
|
||||
/* Encrypt session data */
|
||||
|| !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
|
||||
|| !WPACKET_allocate_bytes(pkt, len, &encdata2)
|
||||
|| encdata1 != encdata2
|
||||
|| !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
|
||||
|| !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
|
||||
|| encdata1 + len != encdata2
|
||||
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|
||||
|| !WPACKET_get_total_written(pkt, &macendoffset)
|
||||
|| !HMAC_Update(hctx,
|
||||
(unsigned char *)s->init_buf->data + macoffset,
|
||||
macendoffset - macoffset)
|
||||
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|
||||
|| !HMAC_Final(hctx, macdata1, &hlen)
|
||||
|| hlen > EVP_MAX_MD_SIZE
|
||||
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|
||||
|| macdata1 != macdata2
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
} else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
|
||||
tick_nonce)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!tls_construct_extensions(s, pkt,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
@@ -4033,15 +4116,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
s->next_ticket_nonce++;
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
|
||||
}
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
OPENSSL_free(senc);
|
||||
|
||||
return 1;
|
||||
err:
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+21
-5
@@ -1396,7 +1396,8 @@ static int create_sctp_socks(int *ssock, int *csock)
|
||||
static HANDSHAKE_RESULT *do_handshake_internal(
|
||||
SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
|
||||
const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra,
|
||||
SSL_SESSION *session_in, SSL_SESSION **session_out)
|
||||
SSL_SESSION *session_in, SSL_SESSION *serv_sess_in,
|
||||
SSL_SESSION **session_out, SSL_SESSION **serv_sess_out)
|
||||
{
|
||||
PEER server, client;
|
||||
BIO *client_to_server = NULL, *server_to_client = NULL;
|
||||
@@ -1452,10 +1453,14 @@ static HANDSHAKE_RESULT *do_handshake_internal(
|
||||
|
||||
configure_handshake_ssl(server.ssl, client.ssl, extra);
|
||||
if (session_in != NULL) {
|
||||
SSL_SESSION_get_id(serv_sess_in, &sess_id_len);
|
||||
/* In case we're testing resumption without tickets. */
|
||||
if (!TEST_true(SSL_CTX_add_session(server_ctx, session_in))
|
||||
if ((sess_id_len > 0
|
||||
&& !TEST_true(SSL_CTX_add_session(server_ctx,
|
||||
serv_sess_in)))
|
||||
|| !TEST_true(SSL_set_session(client.ssl, session_in)))
|
||||
goto err;
|
||||
sess_id_len = 0;
|
||||
}
|
||||
|
||||
ret->result = SSL_TEST_INTERNAL_ERROR;
|
||||
@@ -1657,6 +1662,16 @@ static HANDSHAKE_RESULT *do_handshake_internal(
|
||||
|
||||
if (session_out != NULL)
|
||||
*session_out = SSL_get1_session(client.ssl);
|
||||
if (serv_sess_out != NULL) {
|
||||
SSL_SESSION *tmp = SSL_get_session(server.ssl);
|
||||
|
||||
/*
|
||||
* We create a fresh copy that is not in the server session ctx linked
|
||||
* list.
|
||||
*/
|
||||
if (tmp != NULL)
|
||||
*serv_sess_out = SSL_SESSION_dup(tmp);
|
||||
}
|
||||
|
||||
if (SSL_get_server_tmp_key(client.ssl, &tmp_key)) {
|
||||
ret->tmp_key_type = pkey_type(tmp_key);
|
||||
@@ -1699,11 +1714,11 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
|
||||
const SSL_TEST_CTX *test_ctx)
|
||||
{
|
||||
HANDSHAKE_RESULT *result;
|
||||
SSL_SESSION *session = NULL;
|
||||
SSL_SESSION *session = NULL, *serv_sess = NULL;
|
||||
|
||||
result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
|
||||
test_ctx, &test_ctx->extra,
|
||||
NULL, &session);
|
||||
NULL, NULL, &session, &serv_sess);
|
||||
if (result == NULL
|
||||
|| test_ctx->handshake_mode != SSL_TEST_HANDSHAKE_RESUME
|
||||
|| result->result == SSL_TEST_INTERNAL_ERROR)
|
||||
@@ -1718,8 +1733,9 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
|
||||
/* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
|
||||
result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
|
||||
test_ctx, &test_ctx->resume_extra,
|
||||
session, NULL);
|
||||
session, serv_sess, NULL, NULL);
|
||||
end:
|
||||
SSL_SESSION_free(session);
|
||||
SSL_SESSION_free(serv_sess);
|
||||
return result;
|
||||
}
|
||||
@@ -90,6 +90,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[0-resumption-client]
|
||||
@@ -126,6 +127,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[1-resumption-client]
|
||||
@@ -162,6 +164,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[2-resumption-client]
|
||||
@@ -198,6 +201,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[3-resumption-client]
|
||||
@@ -234,6 +238,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[4-resumption-client]
|
||||
@@ -270,6 +275,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[5-resumption-client]
|
||||
@@ -306,6 +312,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[6-resumption-client]
|
||||
@@ -342,6 +349,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[7-resumption-client]
|
||||
@@ -378,6 +386,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[8-resumption-client]
|
||||
@@ -414,6 +423,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[9-resumption-client]
|
||||
@@ -450,6 +460,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[10-resumption-client]
|
||||
@@ -486,6 +497,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[11-resumption-client]
|
||||
@@ -522,6 +534,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[12-resumption-client]
|
||||
@@ -558,6 +571,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[13-resumption-client]
|
||||
@@ -594,6 +608,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[14-resumption-client]
|
||||
@@ -630,6 +645,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[15-resumption-client]
|
||||
@@ -666,6 +682,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[16-resumption-client]
|
||||
@@ -702,6 +719,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[17-resumption-client]
|
||||
@@ -738,6 +756,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[18-resumption-client]
|
||||
@@ -774,6 +793,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[19-resumption-client]
|
||||
@@ -810,6 +830,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[20-resumption-client]
|
||||
@@ -846,6 +867,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[21-resumption-client]
|
||||
@@ -882,6 +904,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[22-resumption-client]
|
||||
@@ -918,6 +941,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[23-resumption-client]
|
||||
@@ -954,6 +978,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[24-resumption-client]
|
||||
@@ -990,6 +1015,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[25-resumption-client]
|
||||
@@ -1026,6 +1052,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[26-resumption-client]
|
||||
@@ -1062,6 +1089,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[27-resumption-client]
|
||||
@@ -1098,6 +1126,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[28-resumption-client]
|
||||
@@ -1134,6 +1163,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[29-resumption-client]
|
||||
@@ -1170,6 +1200,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[30-resumption-client]
|
||||
@@ -1206,6 +1237,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = TLSv1.3
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[31-resumption-client]
|
||||
|
||||
@@ -41,6 +41,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[0-resumption-client]
|
||||
@@ -78,6 +79,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[1-resumption-client]
|
||||
@@ -115,6 +117,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[2-resumption-client]
|
||||
@@ -152,6 +155,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[3-resumption-client]
|
||||
@@ -189,6 +193,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[4-resumption-client]
|
||||
@@ -226,6 +231,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[5-resumption-client]
|
||||
@@ -263,6 +269,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1.2
|
||||
Options = SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[6-resumption-client]
|
||||
@@ -300,6 +307,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
MaxProtocol = DTLSv1.2
|
||||
Options = -SessionTicket
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[7-resumption-client]
|
||||
|
||||
@@ -210,6 +210,7 @@ sub generate_resumption_tests {
|
||||
},
|
||||
"resume_server" => {
|
||||
"MaxProtocol" => $protocols[$resume_protocol],
|
||||
"Options" => $ticket,
|
||||
},
|
||||
"test" => {
|
||||
"ExpectedProtocol" => $protocols[$resume_protocol],
|
||||
|
||||
+132
-1
@@ -1062,7 +1062,8 @@ static int execute_test_session(int maxprot, int use_int_cache,
|
||||
sess2 = NULL;
|
||||
|
||||
SSL_CTX_set_max_proto_version(sctx, maxprot);
|
||||
SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
|
||||
if (maxprot == TLS1_2_VERSION)
|
||||
SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
|
||||
new_called = remove_called = get_called = 0;
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
|
||||
NULL, NULL))
|
||||
@@ -4971,6 +4972,135 @@ static int test_ticket_callbacks(int tst)
|
||||
return testresult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test bi-directional shutdown.
|
||||
* Test 0: TLSv1.2
|
||||
* Test 1: TLSv1.2, server continues to read/write after client shutdown
|
||||
* Test 2: TLSv1.3, no pending NewSessionTicket messages
|
||||
* Test 3: TLSv1.3, pending NewSessionTicket messages
|
||||
* Test 4: TLSv1.3, server continues to read/write after client shutdown, client
|
||||
* reads it
|
||||
* Test 5: TLSv1.3, server continues to read/write after client shutdown, client
|
||||
* doesn't read it
|
||||
*/
|
||||
static int test_shutdown(int tst)
|
||||
{
|
||||
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||
SSL *clientssl = NULL, *serverssl = NULL;
|
||||
int testresult = 0;
|
||||
char msg[] = "A test message";
|
||||
char buf[80];
|
||||
size_t written, readbytes;
|
||||
|
||||
#ifdef OPENSSL_NO_TLS1_2
|
||||
if (tst == 0)
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef OPENSSL_NO_TLS1_3
|
||||
if (tst != 0)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
|
||||
TLS_client_method(),
|
||||
TLS1_VERSION,
|
||||
(tst <= 1) ? TLS1_2_VERSION
|
||||
: TLS1_3_VERSION,
|
||||
&sctx, &cctx, cert, privkey))
|
||||
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||
NULL, NULL)))
|
||||
goto end;
|
||||
|
||||
if (tst == 3) {
|
||||
if (!TEST_true(create_bare_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
} else if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_int_eq(SSL_shutdown(clientssl), 0))
|
||||
goto end;
|
||||
|
||||
if (tst >= 4) {
|
||||
/*
|
||||
* Reading on the server after the client has sent close_notify should
|
||||
* fail and provide SSL_ERROR_ZERO_RETURN
|
||||
*/
|
||||
if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|
||||
|| !TEST_int_eq(SSL_get_error(serverssl, 0),
|
||||
SSL_ERROR_ZERO_RETURN)
|
||||
|| !TEST_int_eq(SSL_get_shutdown(serverssl),
|
||||
SSL_RECEIVED_SHUTDOWN)
|
||||
/*
|
||||
* Even though we're shutdown on receive we should still be
|
||||
* able to write.
|
||||
*/
|
||||
|| !TEST_true(SSL_write(serverssl, msg, sizeof(msg)))
|
||||
|| !TEST_int_eq(SSL_shutdown(serverssl), 1))
|
||||
goto end;
|
||||
if (tst == 4) {
|
||||
/* Should still be able to read data from server */
|
||||
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf),
|
||||
&readbytes))
|
||||
|| !TEST_size_t_eq(readbytes, sizeof(msg))
|
||||
|| !TEST_int_eq(memcmp(msg, buf, readbytes), 0))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Writing on the client after sending close_notify shouldn't be possible */
|
||||
if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written)))
|
||||
goto end;
|
||||
|
||||
if (tst < 4) {
|
||||
/*
|
||||
* For these tests the client has sent close_notify but it has not yet
|
||||
* been received by the server. The server has not sent close_notify
|
||||
* yet.
|
||||
*/
|
||||
if (!TEST_int_eq(SSL_shutdown(serverssl), 0)
|
||||
/*
|
||||
* Writing on the server after sending close_notify shouldn't
|
||||
* be possible.
|
||||
*/
|
||||
|| !TEST_false(SSL_write_ex(serverssl, msg, sizeof(msg), &written))
|
||||
|| !TEST_int_eq(SSL_shutdown(clientssl), 1)
|
||||
|| !TEST_int_eq(SSL_shutdown(serverssl), 1))
|
||||
goto end;
|
||||
} else if (tst == 4) {
|
||||
/*
|
||||
* In this test the client has sent close_notify and it has been
|
||||
* received by the server which has responded with a close_notify. The
|
||||
* client needs to read the close_notify sent by the server.
|
||||
*/
|
||||
if (!TEST_int_eq(SSL_shutdown(clientssl), 1))
|
||||
goto end;
|
||||
} else {
|
||||
/*
|
||||
* tst == 5
|
||||
*
|
||||
* The client has sent close_notify and is expecting a close_notify
|
||||
* back, but instead there is application data first. The shutdown
|
||||
* should fail with a fatal error.
|
||||
*/
|
||||
if (!TEST_int_eq(SSL_shutdown(clientssl), -1)
|
||||
|| !TEST_int_eq(SSL_get_error(clientssl, -1), SSL_ERROR_SSL))
|
||||
goto end;
|
||||
}
|
||||
|
||||
testresult = 1;
|
||||
|
||||
end:
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(cert = test_get_argument(0))
|
||||
@@ -5068,6 +5198,7 @@ int setup_tests(void)
|
||||
ADD_ALL_TESTS(test_ssl_pending, 2);
|
||||
ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data));
|
||||
ADD_ALL_TESTS(test_ticket_callbacks, 12);
|
||||
ADD_ALL_TESTS(test_shutdown, 6);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+22
-4
@@ -680,12 +680,14 @@ int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
|
||||
/*
|
||||
* Create an SSL connection, but does not ready any post-handshake
|
||||
* NewSessionTicket messages.
|
||||
*/
|
||||
int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
|
||||
{
|
||||
int retc = -1, rets = -1, err, abortctr = 0, i;
|
||||
int retc = -1, rets = -1, err, abortctr = 0;
|
||||
int clienterr = 0, servererr = 0;
|
||||
unsigned char buf;
|
||||
size_t readbytes;
|
||||
int isdtls = SSL_is_dtls(serverssl);
|
||||
|
||||
do {
|
||||
@@ -738,6 +740,22 @@ int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
|
||||
}
|
||||
} while (retc <=0 || rets <= 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an SSL connection including any post handshake NewSessionTicket
|
||||
* messages.
|
||||
*/
|
||||
int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
|
||||
{
|
||||
int i;
|
||||
unsigned char buf;
|
||||
size_t readbytes;
|
||||
|
||||
if (!create_bare_ssl_connection(serverssl, clientssl, want))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We attempt to read some data on the client side which we expect to fail.
|
||||
* This will ensure we have received the NewSessionTicket in TLSv1.3 where
|
||||
|
||||
@@ -18,6 +18,7 @@ int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
|
||||
char *privkeyfile);
|
||||
int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
|
||||
SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio);
|
||||
int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want);
|
||||
int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want);
|
||||
void shutdown_ssl_connection(SSL *serverssl, SSL *clientssl);
|
||||
|
||||
|
||||
@@ -4568,3 +4568,4 @@ EVP_PKEY_get_raw_private_key 4519 1_1_1 EXIST::FUNCTION:
|
||||
EVP_PKEY_asn1_set_get_priv_key 4520 1_1_1 EXIST::FUNCTION:
|
||||
EVP_PKEY_asn1_set_get_pub_key 4521 1_1_1 EXIST::FUNCTION:
|
||||
EVP_PKEY_set_alias_type 4522 1_1_1 EXIST::FUNCTION:
|
||||
RAND_keep_random_devices_open 4523 1_1_1 EXIST::FUNCTION:
|
||||
Reference in New Issue
Block a user