Latest update - pre9
This commit is contained in:
@@ -9,6 +9,16 @@
|
||||
|
||||
Changes between 1.1.0h and 1.1.1 [xx XXX xxxx]
|
||||
|
||||
*) s390x assembly pack: add (improved) hardware-support for the following
|
||||
cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb,
|
||||
aes-cfb/cfb8, aes-ecb.
|
||||
[Patrick Steuer]
|
||||
|
||||
*) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
|
||||
parameter is no longer accepted, as it leads to a corrupt table. NULL
|
||||
pem_str is reserved for alias entries only.
|
||||
[Richard Levitte]
|
||||
|
||||
*) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
|
||||
step for prime curves. The new implementation is based on formulae from
|
||||
differential addition-and-doubling in homogeneous projective coordinates
|
||||
|
||||
@@ -93,8 +93,8 @@ GENERATED={- # common0.tmpl provides @generated
|
||||
@generated) -}
|
||||
|
||||
INSTALL_LIBS={- join(" ", map { quotify1(lib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBS={- join(" ", map { quotify1(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; quotify1(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBS={- join(" ", map { quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_ENGINES={- join(" ", map { quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_ENGINEPDBS={- join(" ", map { local $dsoext = ".pdb"; quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_PROGRAMS={- join(" ", map { quotify1($_.$exeext) } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -}
|
||||
|
||||
@@ -1034,11 +1034,12 @@ if ($d) {
|
||||
$target = $t;
|
||||
}
|
||||
}
|
||||
|
||||
&usage if !$table{$target} || $table{$target}->{template};
|
||||
|
||||
$config{target} = $target;
|
||||
my %target = resolve_config($target);
|
||||
|
||||
&usage if (!%target || $target{template});
|
||||
|
||||
foreach (keys %target_attr_translate) {
|
||||
$target{$target_attr_translate{$_}} = $target{$_}
|
||||
if $target{$_};
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
put together one-size-fits-all instructions. You might
|
||||
have to pass more flags or set up environment variables
|
||||
to actually make it work. Android and iOS cases are
|
||||
discussed in corresponding Configurations/10-main.cf
|
||||
sections. But there are cases when this option alone is
|
||||
discussed in corresponding Configurations/15-*.conf
|
||||
files. But there are cases when this option alone is
|
||||
sufficient. For example to build the mingw64 target on
|
||||
Linux "--cross-compile-prefix=x86_64-w64-mingw32-"
|
||||
works. Naturally provided that mingw packages are
|
||||
@@ -157,10 +157,12 @@
|
||||
"--cross-compile-prefix=mipsel-linux-gnu-" suffices
|
||||
in such case. Needless to mention that you have to
|
||||
invoke ./Configure, not ./config, and pass your target
|
||||
name explicitly.
|
||||
name explicitly. Also, note that --openssldir refers
|
||||
to target's file system, not one you are building on.
|
||||
|
||||
--debug
|
||||
Build OpenSSL with debugging symbols.
|
||||
Build OpenSSL with debugging symbols and zero optimization
|
||||
level.
|
||||
|
||||
--libdir=DIR
|
||||
The name of the directory under the top of the installation
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@
|
||||
One can engage clang by adjusting PATH to cover NDK's clang. Just keep
|
||||
in mind that if you miss it, Configure will try to use gcc... Also,
|
||||
PATH would need even further adjustment to cover unprefixed, yet
|
||||
target-specific, ar and ranlib (or not, if you use binutils-multiarch
|
||||
on your Linux).
|
||||
target-specific, ar and ranlib. It's possible that you don't need to
|
||||
bother, if binutils-multiarch is installed on your Linux system.
|
||||
|
||||
Running tests (on Linux)
|
||||
------------------------
|
||||
|
||||
@@ -216,6 +216,18 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* One of the following must be true:
|
||||
*
|
||||
* pem_str == NULL AND ASN1_PKEY_ALIAS is set
|
||||
* pem_str != NULL AND ASN1_PKEY_ALIAS is clear
|
||||
*
|
||||
* Anything else is an error and may lead to a corrupt ASN1 method table
|
||||
*/
|
||||
if (!((pem_str == NULL && (flags & ASN1_PKEY_ALIAS) != 0)
|
||||
|| (pem_str != NULL && (flags & ASN1_PKEY_ALIAS) == 0)))
|
||||
goto err;
|
||||
|
||||
if (pem_str) {
|
||||
ameth->pem_str = OPENSSL_strdup(pem_str);
|
||||
if (!ameth->pem_str)
|
||||
|
||||
@@ -883,8 +883,6 @@ static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name)
|
||||
htmp.params = NULL;
|
||||
|
||||
idx = sk_MIME_HEADER_find(hdrs, &htmp);
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
return sk_MIME_HEADER_value(hdrs, idx);
|
||||
}
|
||||
|
||||
@@ -896,8 +894,6 @@ static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name)
|
||||
param.param_name = (char *)name;
|
||||
param.param_value = NULL;
|
||||
idx = sk_MIME_PARAM_find(hdr->params, ¶m);
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
return sk_MIME_PARAM_value(hdr->params, idx);
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -58,8 +58,10 @@ int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_AUX *aux;
|
||||
int *lck, ret;
|
||||
CRYPTO_REF_COUNT *lck;
|
||||
CRYPTO_RWLOCK **lock;
|
||||
int ret = -1;
|
||||
|
||||
if ((it->itype != ASN1_ITYPE_SEQUENCE)
|
||||
&& (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
|
||||
return 0;
|
||||
@@ -68,25 +70,34 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
|
||||
return 0;
|
||||
lck = offset2ptr(*pval, aux->ref_offset);
|
||||
lock = offset2ptr(*pval, aux->ref_lock);
|
||||
if (op == 0) {
|
||||
*lck = 1;
|
||||
|
||||
switch (op) {
|
||||
case 0:
|
||||
*lck = ret = 1;
|
||||
*lock = CRYPTO_THREAD_lock_new();
|
||||
if (*lock == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (CRYPTO_atomic_add(lck, op, &ret, *lock) < 0)
|
||||
break;
|
||||
case 1:
|
||||
if (!CRYPTO_UP_REF(lck, &ret, *lock))
|
||||
return -1;
|
||||
break;
|
||||
case -1:
|
||||
if (!CRYPTO_DOWN_REF(lck, &ret, *lock))
|
||||
return -1; /* failed */
|
||||
#ifdef REF_PRINT
|
||||
fprintf(stderr, "%p:%4d:%s\n", it, *lck, it->sname);
|
||||
fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname);
|
||||
#endif
|
||||
REF_ASSERT_ISNT(ret < 0);
|
||||
if (ret == 0) {
|
||||
CRYPTO_THREAD_lock_free(*lock);
|
||||
*lock = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,8 +63,7 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
|
||||
if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
|
||||
|| !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s))
|
||||
|| !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
|
||||
|| (context_len > 0
|
||||
&& !EVP_DigestUpdate(hashctx, context, context_len)))
|
||||
|| !EVP_DigestUpdate(hashctx, context, context_len))
|
||||
return C448_FAILURE;
|
||||
|
||||
return C448_SUCCESS;
|
||||
@@ -161,8 +160,7 @@ c448_error_t c448_ed448_sign(
|
||||
|| !EVP_DigestUpdate(hashctx,
|
||||
expanded + EDDSA_448_PRIVATE_BYTES,
|
||||
EDDSA_448_PRIVATE_BYTES)
|
||||
|| (message_len > 0
|
||||
&& !EVP_DigestUpdate(hashctx, message, message_len))) {
|
||||
|| !EVP_DigestUpdate(hashctx, message, message_len)) {
|
||||
OPENSSL_cleanse(expanded, sizeof(expanded));
|
||||
goto err;
|
||||
}
|
||||
@@ -202,8 +200,7 @@ c448_error_t c448_ed448_sign(
|
||||
if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
|
||||
|| !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
|
||||
|| !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
|
||||
|| (message_len > 0
|
||||
&& !EVP_DigestUpdate(hashctx, message, message_len))
|
||||
|| !EVP_DigestUpdate(hashctx, message, message_len)
|
||||
|| !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -75,14 +75,10 @@ int engine_free_util(ENGINE *e, int not_locked)
|
||||
|
||||
if (e == NULL)
|
||||
return 1;
|
||||
#ifdef HAVE_ATOMICS
|
||||
CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock);
|
||||
#else
|
||||
if (not_locked)
|
||||
CRYPTO_atomic_add(&e->struct_ref, -1, &i, global_engine_lock);
|
||||
CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock);
|
||||
else
|
||||
i = --e->struct_ref;
|
||||
#endif
|
||||
engine_ref_debug(e, 0, -1);
|
||||
if (i > 0)
|
||||
return 1;
|
||||
|
||||
@@ -22,3 +22,4 @@ INCLUDE[e_camellia.o]=.. ../modes
|
||||
INCLUDE[e_sm4.o]=.. ../modes
|
||||
INCLUDE[e_des.o]=..
|
||||
INCLUDE[e_des3.o]=..
|
||||
INCLUDE[m_sha3.o]=..
|
||||
@@ -217,9 +217,8 @@ int EVP_PBE_find(int type, int pbe_nid,
|
||||
pbelu.pbe_type = type;
|
||||
pbelu.pbe_nid = pbe_nid;
|
||||
|
||||
if (pbe_algs) {
|
||||
if (pbe_algs != NULL) {
|
||||
i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu);
|
||||
if (i != -1)
|
||||
pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i);
|
||||
}
|
||||
if (pbetmp == NULL) {
|
||||
|
||||
+229
-5
@@ -66,6 +66,9 @@ static int sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len)
|
||||
size_t bsz = ctx->block_size;
|
||||
size_t num, rem;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
if ((num = ctx->num) != 0) { /* process intermediate buffer? */
|
||||
rem = bsz - num;
|
||||
|
||||
@@ -134,6 +137,226 @@ static int shake_ctrl(EVP_MD_CTX *evp_ctx, int cmd, int p1, void *p2)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
|
||||
/*
|
||||
* IBM S390X support
|
||||
*/
|
||||
# include "s390x_arch.h"
|
||||
|
||||
# define S390X_SHA3_FC(ctx) ((ctx)->pad)
|
||||
|
||||
# define S390X_sha3_224_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_224)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_224)))
|
||||
# define S390X_sha3_256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_256)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_256)))
|
||||
# define S390X_sha3_384_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_384)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_384)))
|
||||
# define S390X_sha3_512_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_512)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHA3_512)))
|
||||
# define S390X_shake128_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHAKE_128)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHAKE_128)))
|
||||
# define S390X_shake256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \
|
||||
S390X_CAPBIT(S390X_SHAKE_256)) && \
|
||||
(OPENSSL_s390xcap_P.klmd[0] & \
|
||||
S390X_CAPBIT(S390X_SHAKE_256)))
|
||||
|
||||
/* Convert md-size to block-size. */
|
||||
# define S390X_KECCAK1600_BSZ(n) ((KECCAK1600_WIDTH - ((n) << 1)) >> 3)
|
||||
|
||||
static int s390x_sha3_init(EVP_MD_CTX *evp_ctx)
|
||||
{
|
||||
KECCAK1600_CTX *ctx = evp_ctx->md_data;
|
||||
const size_t bsz = evp_ctx->digest->block_size;
|
||||
|
||||
/*-
|
||||
* KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD
|
||||
* function code.
|
||||
*/
|
||||
switch (bsz) {
|
||||
case S390X_KECCAK1600_BSZ(224):
|
||||
ctx->pad = S390X_SHA3_224;
|
||||
break;
|
||||
case S390X_KECCAK1600_BSZ(256):
|
||||
ctx->pad = S390X_SHA3_256;
|
||||
break;
|
||||
case S390X_KECCAK1600_BSZ(384):
|
||||
ctx->pad = S390X_SHA3_384;
|
||||
break;
|
||||
case S390X_KECCAK1600_BSZ(512):
|
||||
ctx->pad = S390X_SHA3_512;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(ctx->A, 0, sizeof(ctx->A));
|
||||
ctx->num = 0;
|
||||
ctx->block_size = bsz;
|
||||
ctx->md_size = evp_ctx->digest->md_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_shake_init(EVP_MD_CTX *evp_ctx)
|
||||
{
|
||||
KECCAK1600_CTX *ctx = evp_ctx->md_data;
|
||||
const size_t bsz = evp_ctx->digest->block_size;
|
||||
|
||||
/*-
|
||||
* KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD
|
||||
* function code.
|
||||
*/
|
||||
switch (bsz) {
|
||||
case S390X_KECCAK1600_BSZ(128):
|
||||
ctx->pad = S390X_SHAKE_128;
|
||||
break;
|
||||
case S390X_KECCAK1600_BSZ(256):
|
||||
ctx->pad = S390X_SHAKE_256;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(ctx->A, 0, sizeof(ctx->A));
|
||||
ctx->num = 0;
|
||||
ctx->block_size = bsz;
|
||||
ctx->md_size = evp_ctx->digest->md_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len)
|
||||
{
|
||||
KECCAK1600_CTX *ctx = evp_ctx->md_data;
|
||||
const unsigned char *inp = _inp;
|
||||
const size_t bsz = ctx->block_size;
|
||||
size_t num, rem;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
if ((num = ctx->num) != 0) {
|
||||
rem = bsz - num;
|
||||
|
||||
if (len < rem) {
|
||||
memcpy(ctx->buf + num, inp, len);
|
||||
ctx->num += len;
|
||||
return 1;
|
||||
}
|
||||
memcpy(ctx->buf + num, inp, rem);
|
||||
inp += rem;
|
||||
len -= rem;
|
||||
s390x_kimd(ctx->buf, bsz, ctx->pad, ctx->A);
|
||||
ctx->num = 0;
|
||||
}
|
||||
rem = len % bsz;
|
||||
|
||||
s390x_kimd(inp, len - rem, ctx->pad, ctx->A);
|
||||
|
||||
if (rem) {
|
||||
memcpy(ctx->buf, inp + len - rem, rem);
|
||||
ctx->num = rem;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_sha3_final(EVP_MD_CTX *evp_ctx, unsigned char *md)
|
||||
{
|
||||
KECCAK1600_CTX *ctx = evp_ctx->md_data;
|
||||
|
||||
s390x_klmd(ctx->buf, ctx->num, NULL, 0, ctx->pad, ctx->A);
|
||||
memcpy(md, ctx->A, ctx->md_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_shake_final(EVP_MD_CTX *evp_ctx, unsigned char *md)
|
||||
{
|
||||
KECCAK1600_CTX *ctx = evp_ctx->md_data;
|
||||
|
||||
s390x_klmd(ctx->buf, ctx->num, md, ctx->md_size, ctx->pad, ctx->A);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define EVP_MD_SHA3(bitlen) \
|
||||
const EVP_MD *EVP_sha3_##bitlen(void) \
|
||||
{ \
|
||||
static const EVP_MD s390x_sha3_##bitlen##_md = { \
|
||||
NID_sha3_##bitlen, \
|
||||
NID_RSA_SHA3_##bitlen, \
|
||||
bitlen / 8, \
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT, \
|
||||
s390x_sha3_init, \
|
||||
s390x_sha3_update, \
|
||||
s390x_sha3_final, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(KECCAK1600_WIDTH - bitlen * 2) / 8, \
|
||||
sizeof(KECCAK1600_CTX), \
|
||||
}; \
|
||||
static const EVP_MD sha3_##bitlen##_md = { \
|
||||
NID_sha3_##bitlen, \
|
||||
NID_RSA_SHA3_##bitlen, \
|
||||
bitlen / 8, \
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT, \
|
||||
sha3_init, \
|
||||
sha3_update, \
|
||||
sha3_final, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(KECCAK1600_WIDTH - bitlen * 2) / 8, \
|
||||
sizeof(KECCAK1600_CTX), \
|
||||
}; \
|
||||
return S390X_sha3_##bitlen##_CAPABLE ? \
|
||||
&s390x_sha3_##bitlen##_md : \
|
||||
&sha3_##bitlen##_md; \
|
||||
}
|
||||
|
||||
# define EVP_MD_SHAKE(bitlen) \
|
||||
const EVP_MD *EVP_shake##bitlen(void) \
|
||||
{ \
|
||||
static const EVP_MD s390x_shake##bitlen##_md = { \
|
||||
NID_shake##bitlen, \
|
||||
0, \
|
||||
bitlen / 8, \
|
||||
EVP_MD_FLAG_XOF, \
|
||||
s390x_shake_init, \
|
||||
s390x_sha3_update, \
|
||||
s390x_shake_final, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(KECCAK1600_WIDTH - bitlen * 2) / 8, \
|
||||
sizeof(KECCAK1600_CTX), \
|
||||
shake_ctrl \
|
||||
}; \
|
||||
static const EVP_MD shake##bitlen##_md = { \
|
||||
NID_shake##bitlen, \
|
||||
0, \
|
||||
bitlen / 8, \
|
||||
EVP_MD_FLAG_XOF, \
|
||||
shake_init, \
|
||||
sha3_update, \
|
||||
sha3_final, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(KECCAK1600_WIDTH - bitlen * 2) / 8, \
|
||||
sizeof(KECCAK1600_CTX), \
|
||||
shake_ctrl \
|
||||
}; \
|
||||
return S390X_shake##bitlen##_CAPABLE ? \
|
||||
&s390x_shake##bitlen##_md : \
|
||||
&shake##bitlen##_md; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define EVP_MD_SHA3(bitlen) \
|
||||
const EVP_MD *EVP_sha3_##bitlen(void) \
|
||||
{ \
|
||||
@@ -153,11 +376,6 @@ const EVP_MD *EVP_sha3_##bitlen(void) \
|
||||
return &sha3_##bitlen##_md; \
|
||||
}
|
||||
|
||||
EVP_MD_SHA3(224)
|
||||
EVP_MD_SHA3(256)
|
||||
EVP_MD_SHA3(384)
|
||||
EVP_MD_SHA3(512)
|
||||
|
||||
# define EVP_MD_SHAKE(bitlen) \
|
||||
const EVP_MD *EVP_shake##bitlen(void) \
|
||||
{ \
|
||||
@@ -177,6 +395,12 @@ const EVP_MD *EVP_shake##bitlen(void) \
|
||||
}; \
|
||||
return &shake##bitlen##_md; \
|
||||
}
|
||||
#endif
|
||||
|
||||
EVP_MD_SHA3(224)
|
||||
EVP_MD_SHA3(256)
|
||||
EVP_MD_SHA3(384)
|
||||
EVP_MD_SHA3(512)
|
||||
|
||||
EVP_MD_SHAKE(128)
|
||||
EVP_MD_SHAKE(256)
|
||||
@@ -182,6 +182,7 @@ struct x509_st {
|
||||
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
|
||||
X509_CERT_AUX *aux;
|
||||
CRYPTO_RWLOCK *lock;
|
||||
volatile int ex_cached;
|
||||
} /* X509 */ ;
|
||||
|
||||
/*
|
||||
|
||||
@@ -157,16 +157,18 @@ void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data)
|
||||
OPENSSL_LH_NODE **rn;
|
||||
void *ret;
|
||||
|
||||
lh->error = 0;
|
||||
tsan_store((TSAN_QUALIFIER int *)&lh->error, 0);
|
||||
|
||||
rn = getrn(lh, data, &hash);
|
||||
|
||||
if (*rn == NULL) {
|
||||
lh->num_retrieve_miss++;
|
||||
tsan_counter(&lh->num_retrieve_miss);
|
||||
return NULL;
|
||||
} else {
|
||||
ret = (*rn)->data;
|
||||
lh->num_retrieve++;
|
||||
tsan_counter(&lh->num_retrieve);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -296,7 +298,7 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh,
|
||||
OPENSSL_LH_COMPFUNC cf;
|
||||
|
||||
hash = (*(lh->hash)) (data);
|
||||
lh->num_hash_calls++;
|
||||
tsan_counter(&lh->num_hash_calls);
|
||||
*rhash = hash;
|
||||
|
||||
nn = hash % lh->pmax;
|
||||
@@ -306,12 +308,12 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh,
|
||||
cf = lh->comp;
|
||||
ret = &(lh->b[(int)nn]);
|
||||
for (n1 = *ret; n1 != NULL; n1 = n1->next) {
|
||||
lh->num_hash_comps++;
|
||||
tsan_counter(&lh->num_hash_comps);
|
||||
if (n1->hash != hash) {
|
||||
ret = &(n1->next);
|
||||
continue;
|
||||
}
|
||||
lh->num_comp_calls++;
|
||||
tsan_counter(&lh->num_comp_calls);
|
||||
if (cf(n1->data, data) == 0)
|
||||
break;
|
||||
ret = &(n1->next);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "internal/tsan_assist.h"
|
||||
|
||||
struct lhash_node_st {
|
||||
void *data;
|
||||
struct lhash_node_st *next;
|
||||
@@ -29,14 +31,14 @@ struct lhash_st {
|
||||
unsigned long num_expand_reallocs;
|
||||
unsigned long num_contracts;
|
||||
unsigned long num_contract_reallocs;
|
||||
unsigned long num_hash_calls;
|
||||
unsigned long num_comp_calls;
|
||||
TSAN_QUALIFIER unsigned long num_hash_calls;
|
||||
TSAN_QUALIFIER unsigned long num_comp_calls;
|
||||
unsigned long num_insert;
|
||||
unsigned long num_replace;
|
||||
unsigned long num_delete;
|
||||
unsigned long num_no_delete;
|
||||
unsigned long num_retrieve;
|
||||
unsigned long num_retrieve_miss;
|
||||
unsigned long num_hash_comps;
|
||||
TSAN_QUALIFIER unsigned long num_retrieve;
|
||||
TSAN_QUALIFIER unsigned long num_retrieve_miss;
|
||||
TSAN_QUALIFIER unsigned long num_hash_comps;
|
||||
int error;
|
||||
};
|
||||
+9
-9
@@ -31,13 +31,13 @@ static void (*free_impl)(void *, const char *, int)
|
||||
= CRYPTO_free;
|
||||
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
static int malloc_count;
|
||||
static int realloc_count;
|
||||
static int free_count;
|
||||
static int dummy;
|
||||
# include "internal/tsan_assist.h"
|
||||
|
||||
# define INCREMENT(x) CRYPTO_atomic_add(&x, 1, &dummy, memdbg_lock)
|
||||
# define GET(ret, val) CRYPTO_atomic_read(&val, ret, memdbg_lock)
|
||||
static TSAN_QUALIFIER int malloc_count;
|
||||
static TSAN_QUALIFIER int realloc_count;
|
||||
static TSAN_QUALIFIER int free_count;
|
||||
|
||||
# define INCREMENT(x) tsan_counter(&(x))
|
||||
|
||||
static char *md_failstring;
|
||||
static long md_count;
|
||||
@@ -98,11 +98,11 @@ void CRYPTO_get_mem_functions(
|
||||
void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
|
||||
{
|
||||
if (mcount != NULL)
|
||||
GET(mcount, malloc_count);
|
||||
*mcount = tsan_load(&malloc_count);
|
||||
if (rcount != NULL)
|
||||
GET(rcount, realloc_count);
|
||||
*rcount = tsan_load(&realloc_count);
|
||||
if (fcount != NULL)
|
||||
GET(fcount, free_count);
|
||||
*fcount = tsan_load(&free_count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,9 +46,8 @@ int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid)
|
||||
const nid_triple *rv = NULL;
|
||||
tmp.sign_id = signid;
|
||||
|
||||
if (sig_app) {
|
||||
if (sig_app != NULL) {
|
||||
int idx = sk_nid_triple_find(sig_app, &tmp);
|
||||
if (idx >= 0)
|
||||
rv = sk_nid_triple_value(sig_app, idx);
|
||||
}
|
||||
#ifndef OBJ_XREF_TEST2
|
||||
|
||||
@@ -1605,7 +1605,7 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
|
||||
id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth
|
||||
id-pkinit 5 : pkInitKDC : Signing KDC Response
|
||||
|
||||
# New algorithms from draft-ietf-curdle-pkix-04
|
||||
# From RFC8410
|
||||
1 3 101 110 : X25519
|
||||
1 3 101 111 : X448
|
||||
1 3 101 112 : ED25519
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
|
||||
void s390x_kimd(const unsigned char *in, size_t len, unsigned int fc,
|
||||
void *param);
|
||||
void s390x_klmd(const unsigned char *in, size_t inlen, unsigned char *out,
|
||||
size_t outlen, unsigned int fc, void *param);
|
||||
void s390x_km(const unsigned char *in, size_t len, unsigned char *out,
|
||||
unsigned int fc, void *param);
|
||||
void s390x_kmac(const unsigned char *in, size_t len, unsigned int fc,
|
||||
|
||||
@@ -262,6 +262,48 @@ OPENSSL_vx_probe:
|
||||
.size OPENSSL_vx_probe,.-OPENSSL_vx_probe
|
||||
___
|
||||
|
||||
{
|
||||
################
|
||||
# void s390x_kimd(const unsigned char *in, size_t len, unsigned int fc,
|
||||
# void *param)
|
||||
my ($in,$len,$fc,$param) = map("%r$_",(2..5));
|
||||
$code.=<<___;
|
||||
.globl s390x_kimd
|
||||
.type s390x_kimd,\@function
|
||||
.align 16
|
||||
s390x_kimd:
|
||||
llgfr %r0,$fc
|
||||
lgr %r1,$param
|
||||
|
||||
.long 0xb93e0002 # kimd %r0,%r2
|
||||
brc 1,.-4 # pay attention to "partial completion"
|
||||
|
||||
br $ra
|
||||
.size s390x_kimd,.-s390x_kimd
|
||||
___
|
||||
}
|
||||
|
||||
{
|
||||
################
|
||||
# void s390x_klmd(const unsigned char *in, size_t inlen, unsigned char *out,
|
||||
# size_t outlen, unsigned int fc, void *param)
|
||||
my ($in,$inlen,$out,$outlen,$fc) = map("%r$_",(2..6));
|
||||
$code.=<<___;
|
||||
.globl s390x_klmd
|
||||
.type s390x_klmd,\@function
|
||||
.align 32
|
||||
s390x_klmd:
|
||||
llgfr %r0,$fc
|
||||
l${g} %r1,$stdframe($sp)
|
||||
|
||||
.long 0xb93f0042 # klmd %r4,%r2
|
||||
brc 1,.-4 # pay attention to "partial completion"
|
||||
|
||||
br $ra
|
||||
.size s390x_klmd,.-s390x_klmd
|
||||
___
|
||||
}
|
||||
|
||||
################
|
||||
# void s390x_km(const unsigned char *in, size_t len, unsigned char *out,
|
||||
# unsigned int fc, void *param)
|
||||
|
||||
@@ -329,10 +329,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
|
||||
*/
|
||||
CRYPTO_THREAD_write_lock(ctx->lock);
|
||||
j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
|
||||
if (j != -1)
|
||||
tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
|
||||
else
|
||||
tmp = NULL;
|
||||
CRYPTO_THREAD_unlock(ctx->lock);
|
||||
|
||||
/* If a CRL, update the last file suffix added for this */
|
||||
@@ -343,10 +340,9 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
|
||||
* Look for entry again in case another thread added an entry
|
||||
* first.
|
||||
*/
|
||||
if (!hent) {
|
||||
if (hent == NULL) {
|
||||
htmp.hash = h;
|
||||
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
|
||||
if (idx >= 0)
|
||||
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
|
||||
}
|
||||
if (hent == NULL) {
|
||||
|
||||
@@ -619,17 +619,18 @@ STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
|
||||
X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
|
||||
X509_OBJECT *x)
|
||||
{
|
||||
int idx, i;
|
||||
int idx, i, num;
|
||||
X509_OBJECT *obj;
|
||||
|
||||
idx = sk_X509_OBJECT_find(h, x);
|
||||
if (idx == -1)
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
|
||||
return sk_X509_OBJECT_value(h, idx);
|
||||
for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
|
||||
for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
|
||||
obj = sk_X509_OBJECT_value(h, i);
|
||||
if (x509_object_cmp
|
||||
((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
|
||||
if (x509_object_cmp((const X509_OBJECT **)&obj,
|
||||
(const X509_OBJECT **)&x))
|
||||
return NULL;
|
||||
if (x->type == X509_LU_X509) {
|
||||
if (!X509_cmp(obj->data.x509, x->data.x509))
|
||||
|
||||
@@ -98,13 +98,14 @@ int X509_TRUST_get_by_id(int id)
|
||||
{
|
||||
X509_TRUST tmp;
|
||||
int idx;
|
||||
|
||||
if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
|
||||
return id - X509_TRUST_MIN;
|
||||
tmp.trust = id;
|
||||
if (!trtable)
|
||||
if (trtable == NULL)
|
||||
return -1;
|
||||
tmp.trust = id;
|
||||
idx = sk_X509_TRUST_find(trtable, &tmp);
|
||||
if (idx == -1)
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
return idx + X509_TRUST_COUNT;
|
||||
}
|
||||
|
||||
@@ -555,10 +555,9 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
|
||||
return 0;
|
||||
} else {
|
||||
idx = sk_X509_VERIFY_PARAM_find(param_table, param);
|
||||
if (idx != -1) {
|
||||
ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
|
||||
if (idx >= 0) {
|
||||
ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx);
|
||||
X509_VERIFY_PARAM_free(ptmp);
|
||||
(void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
|
||||
}
|
||||
}
|
||||
if (!sk_X509_VERIFY_PARAM_push(param_table, param))
|
||||
@@ -588,9 +587,9 @@ const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
|
||||
X509_VERIFY_PARAM pm;
|
||||
|
||||
pm.name = (char *)name;
|
||||
if (param_table) {
|
||||
if (param_table != NULL) {
|
||||
idx = sk_X509_VERIFY_PARAM_find(param_table, &pm);
|
||||
if (idx != -1)
|
||||
if (idx >= 0)
|
||||
return sk_X509_VERIFY_PARAM_value(param_table, idx);
|
||||
}
|
||||
return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table));
|
||||
|
||||
@@ -26,8 +26,8 @@ int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
|
||||
return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
|
||||
}
|
||||
|
||||
int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf,
|
||||
int len)
|
||||
int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
|
||||
char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
const ASN1_STRING *data;
|
||||
@@ -36,9 +36,11 @@ int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf
|
||||
if (i < 0)
|
||||
return -1;
|
||||
data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
|
||||
i = (data->length > (len - 1)) ? (len - 1) : data->length;
|
||||
if (buf == NULL)
|
||||
return data->length;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
i = (data->length > (len - 1)) ? (len - 1) : data->length;
|
||||
memcpy(buf, data->data, i);
|
||||
buf[i] = '\0';
|
||||
return i;
|
||||
|
||||
+7
-3
@@ -383,8 +383,11 @@ static int def_crl_lookup(X509_CRL *crl,
|
||||
X509_NAME *issuer)
|
||||
{
|
||||
X509_REVOKED rtmp, *rev;
|
||||
int idx;
|
||||
rtmp.serialNumber = *serial;
|
||||
int idx, num;
|
||||
|
||||
if (crl->crl.revoked == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Sort revoked into serial number order if not already sorted. Do this
|
||||
* under a lock to avoid race condition.
|
||||
@@ -394,11 +397,12 @@ static int def_crl_lookup(X509_CRL *crl,
|
||||
sk_X509_REVOKED_sort(crl->crl.revoked);
|
||||
CRYPTO_THREAD_unlock(crl->lock);
|
||||
}
|
||||
rtmp.serialNumber = *serial;
|
||||
idx = sk_X509_REVOKED_find(crl->crl.revoked, &rtmp);
|
||||
if (idx < 0)
|
||||
return 0;
|
||||
/* Need to look for matching name */
|
||||
for (; idx < sk_X509_REVOKED_num(crl->crl.revoked); idx++) {
|
||||
for (num = sk_X509_REVOKED_num(crl->crl.revoked); idx < num; idx++) {
|
||||
rev = sk_X509_REVOKED_value(crl->crl.revoked, idx);
|
||||
if (ASN1_INTEGER_cmp(&rev->serialNumber, serial))
|
||||
return 0;
|
||||
|
||||
@@ -26,19 +26,19 @@ static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
|
||||
static int policy_cache_create(X509 *x,
|
||||
CERTIFICATEPOLICIES *policies, int crit)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int i, num, ret = 0;
|
||||
X509_POLICY_CACHE *cache = x->policy_cache;
|
||||
X509_POLICY_DATA *data = NULL;
|
||||
POLICYINFO *policy;
|
||||
|
||||
if (sk_POLICYINFO_num(policies) == 0)
|
||||
if ((num = sk_POLICYINFO_num(policies)) <= 0)
|
||||
goto bad_policy;
|
||||
cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
|
||||
if (cache->data == NULL) {
|
||||
X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
|
||||
goto just_cleanup;
|
||||
}
|
||||
for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
|
||||
for (i = 0; i < num; i++) {
|
||||
policy = sk_POLICYINFO_value(policies, i);
|
||||
data = policy_data_new(policy, NULL, crit);
|
||||
if (data == NULL) {
|
||||
@@ -54,7 +54,7 @@ static int policy_cache_create(X509 *x,
|
||||
goto bad_policy;
|
||||
}
|
||||
cache->anyPolicy = data;
|
||||
} else if (sk_X509_POLICY_DATA_find(cache->data, data) != -1) {
|
||||
} else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) {
|
||||
ret = -1;
|
||||
goto bad_policy;
|
||||
} else if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
|
||||
@@ -204,8 +204,6 @@ X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
|
||||
X509_POLICY_DATA tmp;
|
||||
tmp.valid_policy = (ASN1_OBJECT *)id;
|
||||
idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
|
||||
if (idx == -1)
|
||||
return NULL;
|
||||
return sk_X509_POLICY_DATA_value(cache->data, idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
|
||||
l.data = &n;
|
||||
|
||||
idx = sk_X509_POLICY_NODE_find(nodes, &l);
|
||||
if (idx == -1)
|
||||
return NULL;
|
||||
|
||||
return sk_X509_POLICY_NODE_value(nodes, idx);
|
||||
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
|
||||
if (*pnodes == NULL &&
|
||||
(*pnodes = policy_node_cmp_new()) == NULL)
|
||||
return 0;
|
||||
if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
|
||||
if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
|
||||
return 1;
|
||||
return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,6 @@ const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
|
||||
if (!ext_list)
|
||||
return NULL;
|
||||
idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
|
||||
if (idx == -1)
|
||||
return NULL;
|
||||
return sk_X509V3_EXT_METHOD_value(ext_list, idx);
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -13,6 +13,7 @@
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include "internal/x509_int.h"
|
||||
#include "internal/tsan_assist.h"
|
||||
|
||||
static void x509v3_cache_extensions(X509 *x);
|
||||
|
||||
@@ -133,13 +134,14 @@ int X509_PURPOSE_get_by_id(int purpose)
|
||||
{
|
||||
X509_PURPOSE tmp;
|
||||
int idx;
|
||||
|
||||
if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
|
||||
return purpose - X509_PURPOSE_MIN;
|
||||
tmp.purpose = purpose;
|
||||
if (!xptable)
|
||||
if (xptable == NULL)
|
||||
return -1;
|
||||
tmp.purpose = purpose;
|
||||
idx = sk_X509_PURPOSE_find(xptable, &tmp);
|
||||
if (idx == -1)
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
return idx + X509_PURPOSE_COUNT;
|
||||
}
|
||||
@@ -350,10 +352,10 @@ static void x509v3_cache_extensions(X509 *x)
|
||||
ASN1_BIT_STRING *ns;
|
||||
EXTENDED_KEY_USAGE *extusage;
|
||||
X509_EXTENSION *ex;
|
||||
|
||||
int i;
|
||||
|
||||
if (x->ex_flags & EXFLAG_SET)
|
||||
/* fast lock-free check, see end of the function for details. */
|
||||
if (tsan_load((TSAN_QUALIFIER int *)&x->ex_cached))
|
||||
return;
|
||||
|
||||
CRYPTO_THREAD_write_lock(x->lock);
|
||||
@@ -497,6 +499,12 @@ static void x509v3_cache_extensions(X509 *x)
|
||||
x509_init_sig_info(x);
|
||||
x->ex_flags |= EXFLAG_SET;
|
||||
CRYPTO_THREAD_unlock(x->lock);
|
||||
/*
|
||||
* It has to be placed after memory barrier, which is implied by unlock.
|
||||
* Worst thing that can happen is that another thread proceeds to lock
|
||||
* and checks x->ex_flags & EXFLAGS_SET. See beginning of the function.
|
||||
*/
|
||||
tsan_store((TSAN_QUALIFIER int *)&x->ex_cached, 1);
|
||||
}
|
||||
|
||||
/*-
|
||||
|
||||
@@ -18,7 +18,7 @@ lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_error - dynamic hash table
|
||||
|
||||
DECLARE_LHASH_OF(TYPE);
|
||||
|
||||
LHASH *lh_TYPE_new();
|
||||
LHASH *lh_TYPE_new(OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC compare);
|
||||
void lh_TYPE_free(LHASH_OF(TYPE) *table);
|
||||
|
||||
TYPE *lh_TYPE_insert(LHASH_OF(TYPE) *table, TYPE *data);
|
||||
@@ -27,7 +27,7 @@ lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_error - dynamic hash table
|
||||
|
||||
void lh_TYPE_doall(LHASH_OF(TYPE) *table, OPENSSL_LH_DOALL_FUNC func);
|
||||
void lh_TYPE_doall_arg(LHASH_OF(TYPE) *table, OPENSSL_LH_DOALL_FUNCARG func,
|
||||
TYPE, TYPE *arg);
|
||||
TYPE *arg);
|
||||
|
||||
int lh_TYPE_error(LHASH_OF(TYPE) *table);
|
||||
|
||||
@@ -171,25 +171,18 @@ lh_TYPE_retrieve() returns the hash table entry if it has been found,
|
||||
B<NULL> otherwise.
|
||||
|
||||
lh_TYPE_error() returns 1 if an error occurred in the last operation, 0
|
||||
otherwise.
|
||||
otherwise. It's meaningful only after non-retrieve operations.
|
||||
|
||||
lh_TYPE_free(), lh_TYPE_doall() and lh_TYPE_doall_arg() return no values.
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
The various LHASH macros and callback types exist to make it possible
|
||||
to write type-checked code without resorting to function-prototype
|
||||
casting - an evil that makes application code much harder to
|
||||
audit/verify and also opens the window of opportunity for stack
|
||||
corruption and other hard-to-find bugs. It also, apparently, violates
|
||||
ANSI-C.
|
||||
|
||||
The LHASH code is not thread safe. All updating operations must be
|
||||
performed under a write lock. All retrieve operations should be performed
|
||||
under a read lock, I<unless> accurate usage statistics are desired.
|
||||
In which case, a write lock should be used for retrieve operations
|
||||
as well. For output of the usage statistics, using the functions from
|
||||
L<OPENSSL_LH_stats(3)>, a read lock suffices.
|
||||
The LHASH code is not thread safe. All updating operations, as well as
|
||||
lh_TYPE_error call must be performed under a write lock. All retrieve
|
||||
operations should be performed under a read lock, I<unless> accurate
|
||||
usage statistics are desired. In which case, a write lock should be used
|
||||
for retrieve operations as well. For output of the usage statistics,
|
||||
using the functions from L<OPENSSL_LH_stats(3)>, a read lock suffices.
|
||||
|
||||
The LHASH code regards table entries as constant data. As such, it
|
||||
internally represents lh_insert()'d items with a "const void *"
|
||||
|
||||
+1
-1
@@ -49,9 +49,9 @@ int FuzzerInitialize(int *argc, char ***argv)
|
||||
idx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
FuzzerSetRand();
|
||||
comp_methods = SSL_COMP_get_compression_methods();
|
||||
if (comp_methods != NULL)
|
||||
sk_SSL_COMP_sort(comp_methods);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -496,9 +496,9 @@ int FuzzerInitialize(int *argc, char ***argv)
|
||||
idx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
FuzzerSetRand();
|
||||
comp_methods = SSL_COMP_get_compression_methods();
|
||||
if (comp_methods != NULL)
|
||||
sk_SSL_COMP_sort(comp_methods);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Goal here is to facilitate writing "thread-opportunistic" code that
|
||||
* withstands Thread Sanitizer's scrutiny. "Thread-opportunistic" is when
|
||||
* exact result is not required, e.g. some statistics, or execution flow
|
||||
* doesn't have to be unambiguous. Simplest example is lazy "constant"
|
||||
* initialization when one can synchronize on variable itself, e.g.
|
||||
*
|
||||
* if (var == NOT_YET_INITIALIZED)
|
||||
* var = function_returning_same_value();
|
||||
*
|
||||
* This does work provided that loads and stores are single-instuction
|
||||
* operations (and integer ones are on *all* supported platforms), but
|
||||
* it upsets Thread Sanitizer. Suggested solution is
|
||||
*
|
||||
* if (tsan_load(&var) == NOT_YET_INITIALIZED)
|
||||
* tsan_store(&var, function_returning_same_value());
|
||||
*
|
||||
* Production machine code would be the same, so one can wonder why
|
||||
* bother. Having Thread Sanitizer accept "thread-opportunistic" code
|
||||
* allows to move on trouble-shooting real bugs.
|
||||
*
|
||||
* We utilize the fact that compilers that implement Thread Sanitizer
|
||||
* implement even atomic operations. Then it's assumed that
|
||||
* ATOMIC_{LONG|INT}_LOCK_FREE are assigned same value as
|
||||
* ATOMIC_POINTER_LOCK_FREE. And check for >= 2 ensures that correspodning
|
||||
* code is inlined. It should be noted that statistics counters become
|
||||
* accurate in such case.
|
||||
*/
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
|
||||
&& !defined(__STDC_NO_ATOMICS__)
|
||||
# include <stdatomic.h>
|
||||
|
||||
# if defined(ATOMIC_POINTER_LOCK_FREE) \
|
||||
&& ATOMIC_POINTER_LOCK_FREE >= 2
|
||||
# define TSAN_QUALIFIER _Atomic
|
||||
# define tsan_load(ptr) atomic_load_explicit((ptr), memory_order_relaxed)
|
||||
# define tsan_store(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed)
|
||||
# define tsan_counter(ptr) atomic_fetch_add_explicit((ptr), 1, memory_order_relaxed)
|
||||
# endif
|
||||
|
||||
#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED)
|
||||
|
||||
# if defined(__GCC_ATOMIC_POINTER_LOCK_FREE) \
|
||||
&& __GCC_ATOMIC_POINTER_LOCK_FREE >= 2
|
||||
# define TSAN_QUALIFIER volatile
|
||||
# define tsan_load(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED)
|
||||
# define tsan_store(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED)
|
||||
# define tsan_counter(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_RELAXED)
|
||||
# endif
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER>=1200
|
||||
|
||||
# define TSAN_QUALIFIER volatile
|
||||
# define tsan_load(ptr) (*(ptr))
|
||||
# define tsan_store(ptr, val) (*(ptr) = (val))
|
||||
# pragma intrinsic(_InterlockedExchangeAdd)
|
||||
# ifdef _WIN64
|
||||
# pragma intrinsic(_InterlockedExchangeAdd64)
|
||||
# define tsan_counter(ptr) (sizeof(*ptr) == 8 ? _InterlockedExchangeAdd64((ptr), 1) \
|
||||
: _InterlockedExchangeAdd((ptr), 1))
|
||||
# else
|
||||
# define tsan_counter(ptr) _InterlockedExchangeAdd((ptr), 1)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TSAN_QUALIFIER
|
||||
|
||||
# define TSAN_QUALIFIER volatile
|
||||
# define tsan_load(ptr) (*(ptr))
|
||||
# define tsan_store(ptr, val) (*(ptr) = (val))
|
||||
# define tsan_counter(ptr) ((*(ptr))++)
|
||||
|
||||
#endif
|
||||
@@ -263,9 +263,15 @@ extern "C" {
|
||||
# define SSL3_CT_FORTEZZA_DMS 20
|
||||
/*
|
||||
* SSL3_CT_NUMBER is used to size arrays and it must be large enough to
|
||||
* contain all of the cert types defined either for SSLv3 and TLSv1.
|
||||
* contain all of the cert types defined for *either* SSLv3 and TLSv1.
|
||||
*/
|
||||
# define SSL3_CT_NUMBER 9
|
||||
# define SSL3_CT_NUMBER 10
|
||||
|
||||
# if defined(TLS_CT_NUMBER)
|
||||
# if TLS_CT_NUMBER != SSL3_CT_NUMBER
|
||||
# error "SSL/TLS CT_NUMBER values do not match"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* No longer used as of OpenSSL 1.1.1 */
|
||||
# define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
|
||||
|
||||
@@ -1151,7 +1151,13 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
||||
* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see
|
||||
* comment there)
|
||||
*/
|
||||
# define TLS_CT_NUMBER 9
|
||||
# define TLS_CT_NUMBER 10
|
||||
|
||||
# if defined(SSL3_CT_NUMBER)
|
||||
# if TLS_CT_NUMBER != SSL3_CT_NUMBER
|
||||
# error "SSL/TLS CT_NUMBER values do not match"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define TLS1_FINISH_MAC_LENGTH 12
|
||||
|
||||
|
||||
@@ -816,7 +816,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
/* Clear our SSL3_RECORD structures */
|
||||
memset(wr, 0, sizeof(wr));
|
||||
for (j = 0; j < numpipes; j++) {
|
||||
unsigned int version = SSL_TREAT_AS_TLS13(s) ? TLS1_2_VERSION
|
||||
unsigned int version = (s->version == TLS1_3_VERSION) ? TLS1_2_VERSION
|
||||
: s->version;
|
||||
unsigned char *compressdata = NULL;
|
||||
size_t maxcomplen;
|
||||
@@ -829,7 +829,10 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
* In TLSv1.3, once encrypting, we always use application data for the
|
||||
* record type
|
||||
*/
|
||||
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL)
|
||||
if (SSL_TREAT_AS_TLS13(s)
|
||||
&& s->enc_write_ctx != NULL
|
||||
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|
||||
|| type != SSL3_RT_ALERT))
|
||||
rectype = SSL3_RT_APPLICATION_DATA;
|
||||
else
|
||||
rectype = type;
|
||||
@@ -892,7 +895,10 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
SSL3_RECORD_reset_input(&wr[j]);
|
||||
}
|
||||
|
||||
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
|
||||
if (SSL_TREAT_AS_TLS13(s)
|
||||
&& s->enc_write_ctx != NULL
|
||||
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|
||||
|| type != SSL3_RT_ALERT)) {
|
||||
size_t rlen, max_send_fragment;
|
||||
|
||||
if (!WPACKET_put_bytes_u8(thispkt, type)) {
|
||||
@@ -981,8 +987,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
SSL3_RECORD_set_length(thiswr, len);
|
||||
}
|
||||
|
||||
if (s->early_data_state == SSL_EARLY_DATA_WRITING
|
||||
|| s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
|
||||
if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
|
||||
/*
|
||||
* We haven't actually negotiated the version yet, but we're trying to
|
||||
* send early data - so we need to use the tls13enc function.
|
||||
|
||||
@@ -342,7 +342,10 @@ int ssl3_get_record(SSL *s)
|
||||
if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
|
||||
if (thisrr->type != SSL3_RT_APPLICATION_DATA
|
||||
&& (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
|
||||
|| !SSL_IS_FIRST_HANDSHAKE(s))) {
|
||||
|| !SSL_IS_FIRST_HANDSHAKE(s))
|
||||
&& (thisrr->type != SSL3_RT_ALERT
|
||||
|| s->statem.enc_read_state
|
||||
!= ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
|
||||
return -1;
|
||||
@@ -692,7 +695,9 @@ int ssl3_get_record(SSL *s)
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& s->enc_read_ctx != NULL
|
||||
&& thisrr->type != SSL3_RT_ALERT) {
|
||||
size_t end;
|
||||
|
||||
if (thisrr->length == 0
|
||||
|
||||
@@ -52,7 +52,13 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
|
||||
seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
/*
|
||||
* If we're sending an alert and ctx != NULL then we must be forcing
|
||||
* plaintext alerts. If we're reading and ctx != NULL then we allow
|
||||
* plaintext alerts at certain points in the handshake. If we've got this
|
||||
* far then we have already validated that a plaintext alert is ok here.
|
||||
*/
|
||||
if (ctx == NULL || rec->type == SSL3_RT_ALERT) {
|
||||
memmove(rec->data, rec->input, rec->length);
|
||||
rec->input = rec->data;
|
||||
return 1;
|
||||
|
||||
+2
-2
@@ -155,7 +155,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
mac_secret = &(s->s3->read_mac_secret[0]);
|
||||
} else {
|
||||
s->statem.invalid_enc_write_ctx = 1;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->enc_write_ctx != NULL) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
@@ -238,7 +238,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->statem.invalid_enc_write_ctx = 0;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
OPENSSL_cleanse(exp_key, sizeof(exp_key));
|
||||
OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
|
||||
return 1;
|
||||
|
||||
@@ -507,10 +507,7 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
|
||||
ctmp.id = s->compress_meth;
|
||||
if (ssl_comp_methods != NULL) {
|
||||
i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp);
|
||||
if (i >= 0)
|
||||
*comp = sk_SSL_COMP_value(ssl_comp_methods, i);
|
||||
else
|
||||
*comp = NULL;
|
||||
}
|
||||
/* If were only interested in comp then return success */
|
||||
if ((enc == NULL) && (md == NULL))
|
||||
|
||||
+1
-1
@@ -129,8 +129,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
|
||||
"ERR_load_SSL_strings()\n");
|
||||
# endif
|
||||
ERR_load_SSL_strings();
|
||||
#endif
|
||||
ssl_strings_inited = 1;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+13
-28
@@ -2330,7 +2330,6 @@ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
|
||||
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
||||
{
|
||||
long l;
|
||||
int i;
|
||||
/* For some cases with ctx == NULL perform syntax checks */
|
||||
if (ctx == NULL) {
|
||||
switch (cmd) {
|
||||
@@ -2385,40 +2384,27 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
||||
case SSL_CTRL_SESS_NUMBER:
|
||||
return lh_SSL_SESSION_num_items(ctx->sessions);
|
||||
case SSL_CTRL_SESS_CONNECT:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_connect, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_connect);
|
||||
case SSL_CTRL_SESS_CONNECT_GOOD:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_connect_good, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_connect_good);
|
||||
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_connect_renegotiate, &i,
|
||||
ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_connect_renegotiate);
|
||||
case SSL_CTRL_SESS_ACCEPT:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_accept, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_accept);
|
||||
case SSL_CTRL_SESS_ACCEPT_GOOD:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_accept_good, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_accept_good);
|
||||
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_accept_renegotiate, &i,
|
||||
ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_accept_renegotiate);
|
||||
case SSL_CTRL_SESS_HIT:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_hit, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_hit);
|
||||
case SSL_CTRL_SESS_CB_HIT:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_cb_hit, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_cb_hit);
|
||||
case SSL_CTRL_SESS_MISSES:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_miss, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_miss);
|
||||
case SSL_CTRL_SESS_TIMEOUTS:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_timeout, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_timeout);
|
||||
case SSL_CTRL_SESS_CACHE_FULL:
|
||||
return CRYPTO_atomic_read(&ctx->stats.sess_cache_full, &i, ctx->lock)
|
||||
? i : 0;
|
||||
return tsan_load(&ctx->stats.sess_cache_full);
|
||||
case SSL_CTRL_MODE:
|
||||
return (ctx->mode |= larg);
|
||||
case SSL_CTRL_CLEAR_MODE:
|
||||
@@ -3492,13 +3478,12 @@ void ssl_update_cache(SSL *s, int mode)
|
||||
|
||||
/* auto flush every 255 connections */
|
||||
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
|
||||
int *stat, val;
|
||||
TSAN_QUALIFIER int *stat;
|
||||
if (mode & SSL_SESS_CACHE_CLIENT)
|
||||
stat = &s->session_ctx->stats.sess_connect_good;
|
||||
else
|
||||
stat = &s->session_ctx->stats.sess_accept_good;
|
||||
if (CRYPTO_atomic_read(stat, &val, s->session_ctx->lock)
|
||||
&& (val & 0xff) == 0xff)
|
||||
if ((tsan_load(stat) & 0xff) == 0xff)
|
||||
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
|
||||
}
|
||||
}
|
||||
|
||||
+17
-14
@@ -33,6 +33,7 @@
|
||||
# include "packet_locl.h"
|
||||
# include "internal/dane.h"
|
||||
# include "internal/refcount.h"
|
||||
# include "internal/tsan_assist.h"
|
||||
|
||||
# ifdef OPENSSL_BUILD_SHLIBSSL
|
||||
# undef OPENSSL_EXTERN
|
||||
@@ -816,20 +817,22 @@ struct ssl_ctx_st {
|
||||
const unsigned char *data, int len,
|
||||
int *copy);
|
||||
struct {
|
||||
int sess_connect; /* SSL new conn - started */
|
||||
int sess_connect_renegotiate; /* SSL reneg - requested */
|
||||
int sess_connect_good; /* SSL new conne/reneg - finished */
|
||||
int sess_accept; /* SSL new accept - started */
|
||||
int sess_accept_renegotiate; /* SSL reneg - requested */
|
||||
int sess_accept_good; /* SSL accept/reneg - finished */
|
||||
int sess_miss; /* session lookup misses */
|
||||
int sess_timeout; /* reuse attempt on timeouted session */
|
||||
int sess_cache_full; /* session removed due to full cache */
|
||||
int sess_hit; /* session reuse actually done */
|
||||
int sess_cb_hit; /* session-id that was not in the cache was
|
||||
* passed back via the callback. This
|
||||
* indicates that the application is supplying
|
||||
* session-id's from other processes - spooky
|
||||
TSAN_QUALIFIER int sess_connect; /* SSL new conn - started */
|
||||
TSAN_QUALIFIER int sess_connect_renegotiate; /* SSL reneg - requested */
|
||||
TSAN_QUALIFIER int sess_connect_good; /* SSL new conne/reneg - finished */
|
||||
TSAN_QUALIFIER int sess_accept; /* SSL new accept - started */
|
||||
TSAN_QUALIFIER int sess_accept_renegotiate; /* SSL reneg - requested */
|
||||
TSAN_QUALIFIER int sess_accept_good; /* SSL accept/reneg - finished */
|
||||
TSAN_QUALIFIER int sess_miss; /* session lookup misses */
|
||||
TSAN_QUALIFIER int sess_timeout; /* reuse attempt on timeouted session */
|
||||
TSAN_QUALIFIER int sess_cache_full; /* session removed due to full cache */
|
||||
TSAN_QUALIFIER int sess_hit; /* session reuse actually done */
|
||||
TSAN_QUALIFIER int sess_cb_hit; /* session-id that was not in
|
||||
* the cache was passed back via
|
||||
* the callback. This indicates
|
||||
* that the application is
|
||||
* supplying session-id's from
|
||||
* other processes - spooky
|
||||
* :-) */
|
||||
} stats;
|
||||
|
||||
|
||||
+7
-13
@@ -448,7 +448,6 @@ 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) {
|
||||
@@ -469,8 +468,7 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
|
||||
}
|
||||
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);
|
||||
tsan_counter(&s->session_ctx->stats.sess_miss);
|
||||
}
|
||||
|
||||
if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
|
||||
@@ -479,8 +477,7 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
|
||||
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);
|
||||
tsan_counter(&s->session_ctx->stats.sess_cb_hit);
|
||||
|
||||
/*
|
||||
* Increment reference count now if the session callback asks us
|
||||
@@ -533,7 +530,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
/* This is used only by servers. */
|
||||
|
||||
SSL_SESSION *ret = NULL;
|
||||
int fatal = 0, discard;
|
||||
int fatal = 0;
|
||||
int try_session_cache = 0;
|
||||
SSL_TICKET_STATUS r;
|
||||
|
||||
@@ -612,8 +609,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
}
|
||||
|
||||
if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_timeout, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_timeout);
|
||||
if (try_session_cache) {
|
||||
/* session was from the cache, so remove it */
|
||||
SSL_CTX_remove_session(s->session_ctx, ret);
|
||||
@@ -641,8 +637,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
s->session = ret;
|
||||
}
|
||||
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_hit, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_hit);
|
||||
s->verify_result = s->session->verify_result;
|
||||
return 1;
|
||||
|
||||
@@ -669,7 +664,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
|
||||
|
||||
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
|
||||
{
|
||||
int ret = 0, discard;
|
||||
int ret = 0;
|
||||
SSL_SESSION *s;
|
||||
|
||||
/*
|
||||
@@ -736,8 +731,7 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
|
||||
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
|
||||
break;
|
||||
else
|
||||
CRYPTO_atomic_add(&ctx->stats.sess_cache_full, 1, &discard,
|
||||
ctx->lock);
|
||||
tsan_counter(&ctx->stats.sess_cache_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,7 +912,7 @@ static int init_server_name(SSL *s, unsigned int context)
|
||||
|
||||
static int final_server_name(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
int ret = SSL_TLSEXT_ERR_NOACK, discard;
|
||||
int ret = SSL_TLSEXT_ERR_NOACK;
|
||||
int altmp = SSL_AD_UNRECOGNIZED_NAME;
|
||||
int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
|
||||
|
||||
@@ -960,10 +960,8 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
|
||||
* exceed sess_accept (zero) for the new context.
|
||||
*/
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) {
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &discard,
|
||||
s->ctx->lock);
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, -1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->ctx->stats.sess_accept);
|
||||
tsan_counter(&s->session_ctx->stats.sess_accept);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-1
@@ -123,7 +123,8 @@ void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
|
||||
s->statem.in_init = 1;
|
||||
s->statem.state = MSG_FLOW_ERROR;
|
||||
ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
|
||||
if (al != SSL_AD_NO_ALERT && !s->statem.invalid_enc_write_ctx)
|
||||
if (al != SSL_AD_NO_ALERT
|
||||
&& s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
}
|
||||
|
||||
|
||||
+18
-1
@@ -71,6 +71,22 @@ typedef enum {
|
||||
WRITE_STATE_POST_WORK
|
||||
} WRITE_STATE;
|
||||
|
||||
typedef enum {
|
||||
/* The enc_write_ctx can be used normally */
|
||||
ENC_WRITE_STATE_VALID,
|
||||
/* The enc_write_ctx cannot be used */
|
||||
ENC_WRITE_STATE_INVALID,
|
||||
/* Write alerts in plaintext, but otherwise use the enc_write_ctx */
|
||||
ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|
||||
} ENC_WRITE_STATES;
|
||||
|
||||
typedef enum {
|
||||
/* The enc_read_ctx can be used normally */
|
||||
ENC_READ_STATE_VALID,
|
||||
/* We may receive encrypted or plaintext alerts */
|
||||
ENC_READ_STATE_ALLOW_PLAIN_ALERTS
|
||||
} ENC_READ_STATES;
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* This structure should be considered "opaque" to anything outside of the *
|
||||
@@ -100,7 +116,8 @@ struct ossl_statem_st {
|
||||
/* Should we skip the CertificateVerify message? */
|
||||
unsigned int no_cert_verify;
|
||||
int use_timer;
|
||||
int invalid_enc_write_ctx;
|
||||
ENC_WRITE_STATES enc_write_state;
|
||||
ENC_READ_STATES enc_read_state;
|
||||
};
|
||||
typedef struct ossl_statem_st OSSL_STATEM;
|
||||
|
||||
|
||||
@@ -1409,7 +1409,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
unsigned int compression;
|
||||
unsigned int sversion;
|
||||
unsigned int context;
|
||||
int discard;
|
||||
RAW_EXTENSION *extensions = NULL;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
SSL_COMP *comp;
|
||||
@@ -1616,8 +1615,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& s->session->ext.tick_identity
|
||||
!= TLSEXT_PSK_BAD_IDENTITY)) {
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_miss);
|
||||
if (!ssl_get_new_session(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
@@ -2647,10 +2645,16 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
|
||||
PACKET extpkt;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|
||||
|| PACKET_remaining(pkt) != 0
|
||||
|| !tls_collect_extensions(s, &extpkt,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
&exts, NULL, 1)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!tls_collect_extensions(s, &extpkt,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET, &exts,
|
||||
NULL, 1)
|
||||
|| !tls_parse_all_extensions(s,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
exts, NULL, 0, 1)) {
|
||||
|
||||
+16
-16
@@ -132,23 +132,18 @@ int tls_setup_handshake(SSL *s)
|
||||
}
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
/* N.B. s->session_ctx == s->ctx here */
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, 1, &i,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_accept);
|
||||
} else {
|
||||
/* N.B. s->ctx may not equal s->session_ctx */
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept_renegotiate, 1, &i,
|
||||
s->ctx->lock);
|
||||
tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
|
||||
|
||||
s->s3->tmp.cert_request = 0;
|
||||
}
|
||||
} else {
|
||||
int discard;
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s))
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_connect);
|
||||
else
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_renegotiate,
|
||||
1, &discard, s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
|
||||
|
||||
/* mark client_random uninitialized */
|
||||
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
|
||||
@@ -752,6 +747,12 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
|
||||
|
||||
/* This is a real handshake so make sure we clean it up at the end */
|
||||
if (s->server) {
|
||||
/*
|
||||
* To get this far we must have read encrypted data from the client. We
|
||||
* no longer tolerate unencrypted alerts. This value is ignored if less
|
||||
* than TLSv1.3
|
||||
*/
|
||||
s->statem.enc_read_state = ENC_READ_STATE_VALID;
|
||||
if (s->post_handshake_auth != SSL_PHA_REQUESTED)
|
||||
s->statem.cleanuphand = 1;
|
||||
if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) {
|
||||
@@ -1009,7 +1010,6 @@ unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
|
||||
*/
|
||||
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
|
||||
{
|
||||
int discard;
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
|
||||
if (clearbufs) {
|
||||
@@ -1055,8 +1055,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
|
||||
|
||||
/* N.B. s->ctx may not equal s->session_ctx */
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept_good, 1, &discard,
|
||||
s->ctx->lock);
|
||||
tsan_counter(&s->ctx->stats.sess_accept_good);
|
||||
s->handshake_func = ossl_statem_accept;
|
||||
|
||||
if (SSL_IS_DTLS(s) && !s->hit) {
|
||||
@@ -1084,12 +1083,10 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
|
||||
}
|
||||
if (s->hit)
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_hit, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_hit);
|
||||
|
||||
s->handshake_func = ossl_statem_connect;
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_good, 1,
|
||||
&discard, s->session_ctx->lock);
|
||||
tsan_counter(&s->session_ctx->stats.sess_connect_good);
|
||||
|
||||
if (SSL_IS_DTLS(s) && s->hit) {
|
||||
/*
|
||||
@@ -1917,6 +1914,9 @@ int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
|
||||
if (highver != 0 && s->version != vent->version)
|
||||
continue;
|
||||
|
||||
if (highver == 0 && (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) != 0)
|
||||
highver = vent->version;
|
||||
|
||||
method = vent->cmeth();
|
||||
err = ssl_method_error(s, method);
|
||||
if (err != 0) {
|
||||
|
||||
+22
-10
@@ -848,12 +848,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
return WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* TODO(TLS1.3): This actually causes a problem. We don't yet know
|
||||
* whether the next record we are going to receive is an unencrypted
|
||||
* alert, or an encrypted handshake message. We're going to need
|
||||
* something clever in the record layer for this.
|
||||
*/
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!s->method->ssl3_enc->setup_key_block(s)
|
||||
|| !s->method->ssl3_enc->change_cipher_state(s,
|
||||
@@ -868,6 +863,12 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
/*
|
||||
* We don't yet know whether the next record we are going to receive
|
||||
* is an unencrypted alert, an encrypted alert, or an encrypted
|
||||
* handshake message. We temporarily tolerate unencrypted alerts.
|
||||
*/
|
||||
s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2371,10 +2372,14 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
|
||||
|
||||
if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
|
||||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|
||||
|| !WPACKET_put_bytes_u8(pkt, compm)
|
||||
|| !tls_construct_extensions(s, pkt,
|
||||
s->hello_retry_request
|
||||
== SSL_HRR_PENDING
|
||||
|| !WPACKET_put_bytes_u8(pkt, compm)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tls_construct_extensions(s, pkt,
|
||||
s->hello_retry_request == SSL_HRR_PENDING
|
||||
? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
|
||||
: (SSL_IS_TLS13(s)
|
||||
? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
@@ -3520,6 +3525,13 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|
||||
size_t chainidx;
|
||||
SSL_SESSION *new_sess = NULL;
|
||||
|
||||
/*
|
||||
* To get this far we must have read encrypted data from the client. We no
|
||||
* longer tolerate unencrypted alerts. This value is ignored if less than
|
||||
* TLSv1.3
|
||||
*/
|
||||
s->statem.enc_read_state = ENC_READ_STATE_VALID;
|
||||
|
||||
if ((sk = sk_X509_new_null()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
|
||||
+2
-2
@@ -154,7 +154,7 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
mac_secret = &(s->s3->read_mac_secret[0]);
|
||||
mac_secret_size = &(s->s3->read_mac_secret_size);
|
||||
} else {
|
||||
s->statem.invalid_enc_write_ctx = 1;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->ext.use_etm)
|
||||
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
|
||||
else
|
||||
@@ -316,7 +316,7 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
s->statem.invalid_enc_write_ctx = 0;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
|
||||
#ifdef SSL_DEBUG
|
||||
printf("which = %04X\nkey=", which);
|
||||
|
||||
+7
-4
@@ -425,7 +425,7 @@ int tls13_change_cipher_state(SSL *s, int which)
|
||||
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
} else {
|
||||
s->statem.invalid_enc_write_ctx = 1;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->enc_write_ctx != NULL) {
|
||||
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
|
||||
} else {
|
||||
@@ -648,7 +648,10 @@ int tls13_change_cipher_state(SSL *s, int which)
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->statem.invalid_enc_write_ctx = 0;
|
||||
if (!s->server && label == client_early_traffic)
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
|
||||
else
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_cleanse(secret, sizeof(secret));
|
||||
@@ -671,7 +674,7 @@ int tls13_update_key(SSL *s, int sending)
|
||||
insecret = s->client_app_traffic_secret;
|
||||
|
||||
if (sending) {
|
||||
s->statem.invalid_enc_write_ctx = 1;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
iv = s->write_iv;
|
||||
ciph_ctx = s->enc_write_ctx;
|
||||
RECORD_LAYER_reset_write_sequence(&s->rlayer);
|
||||
@@ -692,7 +695,7 @@ int tls13_update_key(SSL *s, int sending)
|
||||
|
||||
memcpy(insecret, secret, hashlen);
|
||||
|
||||
s->statem.invalid_enc_write_ctx = 0;
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_cleanse(secret, sizeof(secret));
|
||||
|
||||
@@ -67,6 +67,7 @@ static int test_standard_methods(void)
|
||||
const EVP_PKEY_ASN1_METHOD **tmp;
|
||||
int last_pkey_id = -1;
|
||||
size_t i;
|
||||
int ok = 1;
|
||||
|
||||
for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods);
|
||||
i++, tmp++) {
|
||||
@@ -75,11 +76,26 @@ static int test_standard_methods(void)
|
||||
break;
|
||||
}
|
||||
last_pkey_id = (*tmp)->pkey_id;
|
||||
|
||||
/*
|
||||
* One of the following must be true:
|
||||
*
|
||||
* pem_str == NULL AND ASN1_PKEY_ALIAS is set
|
||||
* pem_str != NULL AND ASN1_PKEY_ALIAS is clear
|
||||
*
|
||||
* Anything else is an error and may lead to a corrupt ASN1 method table
|
||||
*/
|
||||
if (!TEST_true(((*tmp)->pem_str == NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) != 0)
|
||||
|| ((*tmp)->pem_str != NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
|
||||
TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s",
|
||||
i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id));
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (TEST_int_ne(last_pkey_id, 0)) {
|
||||
TEST_info("asn1 standard methods: Table order OK");
|
||||
return 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
TEST_note("asn1 standard methods: out of order");
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
use strict;
|
||||
use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
|
||||
use OpenSSL::Test::Utils;
|
||||
use TLSProxy::Proxy;
|
||||
|
||||
my $test_name = "test_tls13alerts";
|
||||
setup($test_name);
|
||||
|
||||
plan skip_all => "TLSProxy isn't usable on $^O"
|
||||
if $^O =~ /^(VMS)$/;
|
||||
|
||||
plan skip_all => "$test_name needs the dynamic engine feature enabled"
|
||||
if disabled("engine") || disabled("dynamic-engine");
|
||||
|
||||
plan skip_all => "$test_name needs the sock feature enabled"
|
||||
if disabled("sock");
|
||||
|
||||
plan skip_all => "$test_name needs TLS1.3 enabled"
|
||||
if disabled("tls1_3");
|
||||
|
||||
$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
|
||||
|
||||
my $proxy = TLSProxy::Proxy->new(
|
||||
undef,
|
||||
cmdstr(app(["openssl"]), display => 1),
|
||||
srctop_file("apps", "server.pem"),
|
||||
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
||||
);
|
||||
|
||||
#Test 1: We test that a server can handle an unencrypted alert when normally the
|
||||
# next message is encrypted
|
||||
$proxy->filter(\&alert_filter);
|
||||
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
||||
plan tests => 1;
|
||||
my $alert = TLSProxy::Message->alert();
|
||||
ok(TLSProxy::Message->fail() && !$alert->server() && !$alert->encrypted(), "Client sends an unecrypted alert");
|
||||
|
||||
sub alert_filter
|
||||
{
|
||||
my $proxy = shift;
|
||||
|
||||
if ($proxy->flight != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
${$proxy->message_list}[1]->session_id_len(1);
|
||||
${$proxy->message_list}[1]->repack();
|
||||
}
|
||||
@@ -41,14 +41,15 @@ my $proxy = TLSProxy::Proxy->new(
|
||||
|
||||
use constant {
|
||||
DOWNGRADE_TO_TLS_1_2 => 0,
|
||||
DOWNGRADE_TO_TLS_1_1 => 1
|
||||
DOWNGRADE_TO_TLS_1_1 => 1,
|
||||
FALLBACK_FROM_TLS_1_3 => 2,
|
||||
};
|
||||
|
||||
#Test 1: Downgrade from TLSv1.3 to TLSv1.2
|
||||
$proxy->filter(\&downgrade_filter);
|
||||
my $testtype = DOWNGRADE_TO_TLS_1_2;
|
||||
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
||||
plan tests => 3;
|
||||
plan tests => 4;
|
||||
ok(TLSProxy::Message->fail(), "Downgrade TLSv1.3 to TLSv1.2");
|
||||
|
||||
#Test 2: Downgrade from TLSv1.3 to TLSv1.1
|
||||
@@ -64,6 +65,18 @@ $proxy->serverflags("-no_tls1_3");
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->fail(), "Downgrade TLSv1.2 to TLSv1.1");
|
||||
|
||||
#Test 4: Client falls back from TLSv1.3 (server does not support the fallback
|
||||
# SCSV)
|
||||
$proxy->clear();
|
||||
$testtype = FALLBACK_FROM_TLS_1_3;
|
||||
$proxy->clientflags("-fallback_scsv -no_tls1_3");
|
||||
$proxy->start();
|
||||
my $alert = TLSProxy::Message->alert();
|
||||
ok(TLSProxy::Message->fail()
|
||||
&& !$alert->server()
|
||||
&& $alert->description() == TLSProxy::Message::AL_DESC_ILLEGAL_PARAMETER,
|
||||
"Fallback from TLSv1.3");
|
||||
|
||||
sub downgrade_filter
|
||||
{
|
||||
my $proxy = shift;
|
||||
@@ -76,6 +89,12 @@ sub downgrade_filter
|
||||
my $message = ${$proxy->message_list}[0];
|
||||
|
||||
my $ext;
|
||||
if ($testtype == FALLBACK_FROM_TLS_1_3) {
|
||||
#The default ciphersuite we use for TLSv1.2 without any SCSV
|
||||
my @ciphersuites = (TLSProxy::Message::CIPHER_RSA_WITH_AES_128_CBC_SHA);
|
||||
$message->ciphersuite_len(2 * scalar @ciphersuites);
|
||||
$message->ciphersuites(\@ciphersuites);
|
||||
} else {
|
||||
if ($testtype == DOWNGRADE_TO_TLS_1_2) {
|
||||
$ext = pack "C3",
|
||||
0x02, # Length
|
||||
@@ -87,6 +106,7 @@ sub downgrade_filter
|
||||
}
|
||||
|
||||
$message->set_extension(TLSProxy::Message::EXT_SUPPORTED_VERSIONS, $ext);
|
||||
}
|
||||
|
||||
$message->repack();
|
||||
}
|
||||
|
||||
@@ -84,6 +84,11 @@ static int test_sanity_range(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_sanity_memcmp(void)
|
||||
{
|
||||
return CRYPTO_memcmp("ab","cd",2);
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_sanity_null_zero);
|
||||
@@ -92,6 +97,7 @@ int setup_tests(void)
|
||||
ADD_TEST(test_sanity_sign);
|
||||
ADD_TEST(test_sanity_unsigned_conversion);
|
||||
ADD_TEST(test_sanity_range);
|
||||
ADD_TEST(test_sanity_memcmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -531,11 +531,6 @@ static int test_bn_output(int n)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_memcmp(void)
|
||||
{
|
||||
return CRYPTO_memcmp("ab","cd",2);
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_int);
|
||||
@@ -557,7 +552,6 @@ int setup_tests(void)
|
||||
ADD_TEST(test_messages);
|
||||
ADD_TEST(test_single_eval);
|
||||
ADD_TEST(test_output);
|
||||
ADD_TEST(test_memcmp);
|
||||
ADD_ALL_TESTS(test_bn_output, OSSL_NELEM(bn_output_tests));
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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
|
||||
|
||||
use strict;
|
||||
|
||||
package TLSProxy::Alert;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my ($server,
|
||||
$encrypted,
|
||||
$level,
|
||||
$description) = @_;
|
||||
|
||||
my $self = {
|
||||
server => $server,
|
||||
encrypted => $encrypted,
|
||||
level => $level,
|
||||
description => $description
|
||||
};
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
#Read only accessors
|
||||
sub server
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{server};
|
||||
}
|
||||
sub encrypted
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{encrypted};
|
||||
}
|
||||
sub level
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{level};
|
||||
}
|
||||
sub description
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{description};
|
||||
}
|
||||
1;
|
||||
@@ -9,6 +9,8 @@ use strict;
|
||||
|
||||
package TLSProxy::Message;
|
||||
|
||||
use TLSProxy::Alert;
|
||||
|
||||
use constant TLS_MESSAGE_HEADER_LENGTH => 4;
|
||||
|
||||
#Message types
|
||||
@@ -39,6 +41,7 @@ use constant {
|
||||
use constant {
|
||||
AL_DESC_CLOSE_NOTIFY => 0,
|
||||
AL_DESC_UNEXPECTED_MESSAGE => 10,
|
||||
AL_DESC_ILLEGAL_PARAMETER => 47,
|
||||
AL_DESC_NO_RENEGOTIATION => 100
|
||||
};
|
||||
|
||||
@@ -123,6 +126,7 @@ use constant {
|
||||
};
|
||||
|
||||
use constant {
|
||||
CIPHER_RSA_WITH_AES_128_CBC_SHA => 0x002f,
|
||||
CIPHER_DHE_RSA_AES_128_SHA => 0x0033,
|
||||
CIPHER_ADH_AES_128_SHA => 0x0034,
|
||||
CIPHER_TLS13_AES_128_GCM_SHA256 => 0x1301,
|
||||
@@ -140,6 +144,7 @@ my @message_rec_list = ();
|
||||
my @message_frag_lens = ();
|
||||
my $ciphersuite = 0;
|
||||
my $successondata = 0;
|
||||
my $alert;
|
||||
|
||||
sub clear
|
||||
{
|
||||
@@ -152,6 +157,7 @@ sub clear
|
||||
$successondata = 0;
|
||||
@message_rec_list = ();
|
||||
@message_frag_lens = ();
|
||||
$alert = undef;
|
||||
}
|
||||
|
||||
#Class method to extract messages from a record
|
||||
@@ -281,6 +287,11 @@ sub get_messages
|
||||
if ($alertlev == AL_LEVEL_FATAL || $alertdesc == AL_DESC_CLOSE_NOTIFY) {
|
||||
$end = 1;
|
||||
}
|
||||
$alert = TLSProxy::Alert->new(
|
||||
$server,
|
||||
$record->encrypted,
|
||||
$alertlev,
|
||||
$alertdesc);
|
||||
}
|
||||
|
||||
return @messages;
|
||||
@@ -388,6 +399,12 @@ sub fail
|
||||
my $class = shift;
|
||||
return !$success && $end;
|
||||
}
|
||||
|
||||
sub alert
|
||||
{
|
||||
return $alert;
|
||||
}
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
|
||||
@@ -97,7 +97,9 @@ sub get_records
|
||||
$data # decrypt_data
|
||||
);
|
||||
|
||||
if ($content_type != RT_CCS) {
|
||||
if ($content_type != RT_CCS
|
||||
&& (!TLSProxy::Proxy->is_tls13()
|
||||
|| $content_type != RT_ALERT)) {
|
||||
if (($server && $server_encrypting)
|
||||
|| (!$server && $client_encrypting)) {
|
||||
if (!TLSProxy::Proxy->is_tls13() && $etm) {
|
||||
|
||||
Reference in New Issue
Block a user