Update pre9

This commit is contained in:
2018-07-08 16:02:48 +09:00
parent 89af373a04
commit 1914ae9055
15 changed files with 416 additions and 49 deletions
+77 -3
View File
@@ -11,6 +11,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include "apps.h" #include "apps.h"
#include "progs.h" #include "progs.h"
#include <openssl/bio.h> #include <openssl/bio.h>
@@ -23,6 +24,8 @@
#include <openssl/objects.h> #include <openssl/objects.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/bn.h>
#include <openssl/lhash.h>
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h> # include <openssl/rsa.h>
#endif #endif
@@ -147,6 +150,68 @@ const OPTIONS req_options[] = {
{NULL} {NULL}
}; };
/*
* An LHASH of strings, where each string is an extension name.
*/
static unsigned long ext_name_hash(const OPENSSL_STRING *a)
{
return OPENSSL_LH_strhash((const char *)a);
}
static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
{
return strcmp((const char *)a, (const char *)b);
}
static void exts_cleanup(OPENSSL_STRING *x)
{
OPENSSL_free((char *)x);
}
/*
* Is the |kv| key already duplicated? This is remarkably tricky to get
* right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax
* error.
*/
static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
{
char *p;
/* Check syntax. */
if (strchr(kv, '=') == NULL)
return 1;
/* Skip leading whitespace, make a copy. */
while (*kv && isspace(*kv))
if (*++kv == '\0')
return 1;
if ((kv = OPENSSL_strdup(kv)) == NULL)
return -1;
/* Skip trailing space before the equal sign. */
for (p = strchr(kv, '='); p > kv; --p)
if (p[-1] != ' ' && p[-1] != '\t')
break;
if (p == kv) {
OPENSSL_free(kv);
return 1;
}
*p = '\0';
/* Finally have a clean "key"; see if it's there. */
if (lh_OPENSSL_STRING_retrieve(addexts, (OPENSSL_STRING*)kv) != NULL) {
BIO_printf(bio_err, "Extension \"%s\" repeated\n", kv);
OPENSSL_free(kv);
return 1;
}
/* Not found; add it. */
if (lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv) == NULL)
return -1;
return 0;
}
int req_main(int argc, char **argv) int req_main(int argc, char **argv)
{ {
ASN1_INTEGER *serial = NULL; ASN1_INTEGER *serial = NULL;
@@ -155,6 +220,7 @@ int req_main(int argc, char **argv)
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *genctx = NULL; EVP_PKEY_CTX *genctx = NULL;
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
LHASH_OF(OPENSSL_STRING) *addexts = NULL;
X509 *x509ss = NULL; X509 *x509ss = NULL;
X509_REQ *req = NULL; X509_REQ *req = NULL;
const EVP_CIPHER *cipher = NULL; const EVP_CIPHER *cipher = NULL;
@@ -324,11 +390,17 @@ int req_main(int argc, char **argv)
multirdn = 1; multirdn = 1;
break; break;
case OPT_ADDEXT: case OPT_ADDEXT:
if (addext_bio == NULL) { p = opt_arg();
if (addexts == NULL) {
addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp);
addext_bio = BIO_new(BIO_s_mem()); addext_bio = BIO_new(BIO_s_mem());
if (addexts == NULL || addext_bio == NULL)
goto end;
} }
if (addext_bio == NULL i = duplicated(addexts, p);
|| BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) if (i == 1)
goto opthelp;
if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
goto end; goto end;
break; break;
case OPT_EXTENSIONS: case OPT_EXTENSIONS:
@@ -885,6 +957,8 @@ int req_main(int argc, char **argv)
EVP_PKEY_CTX_free(genctx); EVP_PKEY_CTX_free(genctx);
sk_OPENSSL_STRING_free(pkeyopts); sk_OPENSSL_STRING_free(pkeyopts);
sk_OPENSSL_STRING_free(sigopts); sk_OPENSSL_STRING_free(sigopts);
lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
lh_OPENSSL_STRING_free(addexts);
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
ENGINE_free(gen_eng); ENGINE_free(gen_eng);
#endif #endif
+20 -6
View File
@@ -192,8 +192,11 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
const SSL_CIPHER *cipher = NULL; const SSL_CIPHER *cipher = NULL;
if (strlen(psk_identity) != identity_len if (strlen(psk_identity) != identity_len
|| memcmp(psk_identity, identity, identity_len) != 0) || memcmp(psk_identity, identity, identity_len) != 0) {
return 0; BIO_printf(bio_s_out,
"PSK warning: client identity not what we expected"
" (got '%s' expected '%s')\n", identity, psk_identity);
}
if (psksess != NULL) { if (psksess != NULL) {
SSL_SESSION_up_ref(psksess); SSL_SESSION_up_ref(psksess);
@@ -748,8 +751,8 @@ typedef enum OPTION_choice {
OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA, OPT_S_NUM_TICKETS, OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY,
OPT_R_ENUM, OPT_R_ENUM,
OPT_S_ENUM, OPT_S_ENUM,
OPT_V_ENUM, OPT_V_ENUM,
@@ -955,7 +958,9 @@ const OPTIONS s_server_options[] = {
#endif #endif
{"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"max_early_data", OPT_MAX_EARLY, 'n', {"max_early_data", OPT_MAX_EARLY, 'n',
"The maximum number of bytes of early data"}, "The maximum number of bytes of early data as advertised in tickets"},
{"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
"The maximum number of bytes of early data (hard limit)"},
{"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
{"num_tickets", OPT_S_NUM_TICKETS, 'n', {"num_tickets", OPT_S_NUM_TICKETS, 'n',
"The number of TLSv1.3 session tickets that a server will automatically issue" }, "The number of TLSv1.3 session tickets that a server will automatically issue" },
@@ -1041,7 +1046,7 @@ int s_server_main(int argc, char *argv[])
unsigned int split_send_fragment = 0, max_pipelines = 0; unsigned int split_send_fragment = 0, max_pipelines = 0;
const char *s_serverinfo_file = NULL; const char *s_serverinfo_file = NULL;
const char *keylog_file = NULL; const char *keylog_file = NULL;
int max_early_data = -1; int max_early_data = -1, recv_max_early_data = -1;
char *psksessf = NULL; char *psksessf = NULL;
/* Init of few remaining global variables */ /* Init of few remaining global variables */
@@ -1570,6 +1575,13 @@ int s_server_main(int argc, char *argv[])
goto end; goto end;
} }
break; break;
case OPT_RECV_MAX_EARLY:
recv_max_early_data = atoi(opt_arg());
if (recv_max_early_data < 0) {
BIO_printf(bio_err, "Invalid value for recv_max_early_data\n");
goto end;
}
break;
case OPT_EARLY_DATA: case OPT_EARLY_DATA:
early_data = 1; early_data = 1;
if (max_early_data == -1) if (max_early_data == -1)
@@ -2110,6 +2122,8 @@ int s_server_main(int argc, char *argv[])
if (max_early_data >= 0) if (max_early_data >= 0)
SSL_CTX_set_max_early_data(ctx, max_early_data); SSL_CTX_set_max_early_data(ctx, max_early_data);
if (recv_max_early_data >= 0)
SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data);
if (rev) if (rev)
server_cb = rev_body; server_cb = rev_body;
+46 -8
View File
@@ -196,14 +196,23 @@ static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
} }
# if !defined(OPENSSL_SMALL_FOOTPRINT) # if !defined(OPENSSL_SMALL_FOOTPRINT)
# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64))
# define XOR128_HELPERS
void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
# else
static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 }; static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
# endif
static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len) const unsigned char *in, size_t len)
{ {
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
size_t i, tail, tohash_len, plen = actx->tls_payload_length; size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length;
unsigned char *buf, *tohash, *ctr, storage[2 * CHACHA_BLK_SIZE + 32]; unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
if (len != plen + POLY1305_BLOCK_SIZE) if (len != plen + POLY1305_BLOCK_SIZE)
return -1; return -1;
@@ -212,9 +221,11 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
ctr = buf + CHACHA_BLK_SIZE; ctr = buf + CHACHA_BLK_SIZE;
tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE; tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
if (plen <= CHACHA_BLK_SIZE) { # ifdef XOR128_HELPERS
if (plen <= 3 * CHACHA_BLK_SIZE) {
actx->key.counter[0] = 0; actx->key.counter[0] = 0;
ChaCha20_ctr32(buf, zero, 2 * CHACHA_BLK_SIZE, actx->key.key.d, buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d,
actx->key.counter); actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf); Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.partial_len = 0; actx->key.partial_len = 0;
@@ -223,6 +234,31 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->len.text = plen; actx->len.text = plen;
if (plen) {
if (ctx->encrypt)
ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
else
ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
in += plen;
out += plen;
tohash_len = (size_t)(ctr - tohash);
}
}
# else
if (plen <= CHACHA_BLK_SIZE) {
size_t i;
actx->key.counter[0] = 0;
ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
actx->key.key.d, actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.partial_len = 0;
memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
tohash_len = POLY1305_BLOCK_SIZE;
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->len.text = plen;
if (ctx->encrypt) { if (ctx->encrypt) {
for (i = 0; i < plen; i++) { for (i = 0; i < plen; i++) {
out[i] = ctr[i] ^= in[i]; out[i] = ctr[i] ^= in[i];
@@ -242,10 +278,12 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
memset(ctr + i, 0, tail); memset(ctr + i, 0, tail);
ctr += i + tail; ctr += i + tail;
tohash_len += i + tail; tohash_len += i + tail;
} else { }
# endif
else {
actx->key.counter[0] = 0; actx->key.counter[0] = 0;
ChaCha20_ctr32(buf, zero, CHACHA_BLK_SIZE, actx->key.key.d, ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
actx->key.counter); actx->key.key.d, actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf); Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.counter[0] = 1; actx->key.counter[0] = 1;
actx->key.partial_len = 0; actx->key.partial_len = 0;
@@ -300,7 +338,7 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
} }
Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len); Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len);
OPENSSL_cleanse(buf, 2 * CHACHA_BLK_SIZE); OPENSSL_cleanse(buf, buf_len);
Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
: tohash); : tohash);
+104
View File
@@ -3753,6 +3753,110 @@ poly1305_emit_base2_44:
.size poly1305_emit_base2_44,.-poly1305_emit_base2_44 .size poly1305_emit_base2_44,.-poly1305_emit_base2_44
___ ___
} } } } } }
{ # chacha20-poly1305 helpers
my ($out,$inp,$otp,$len)=$win64 ? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
("%rdi","%rsi","%rdx","%rcx"); # Unix order
$code.=<<___;
.globl xor128_encrypt_n_pad
.type xor128_encrypt_n_pad,\@abi-omnipotent
.align 16
xor128_encrypt_n_pad:
sub $otp,$inp
sub $otp,$out
mov $len,%r10 # put len aside
shr \$4,$len # len / 16
jz .Ltail_enc
nop
.Loop_enc_xmm:
movdqu ($inp,$otp),%xmm0
pxor ($otp),%xmm0
movdqu %xmm0,($out,$otp)
movdqa %xmm0,($otp)
lea 16($otp),$otp
dec $len
jnz .Loop_enc_xmm
and \$15,%r10 # len % 16
jz .Ldone_enc
.Ltail_enc:
mov \$16,$len
sub %r10,$len
xor %eax,%eax
.Loop_enc_byte:
mov ($inp,$otp),%al
xor ($otp),%al
mov %al,($out,$otp)
mov %al,($otp)
lea 1($otp),$otp
dec %r10
jnz .Loop_enc_byte
xor %eax,%eax
.Loop_enc_pad:
mov %al,($otp)
lea 1($otp),$otp
dec $len
jnz .Loop_enc_pad
.Ldone_enc:
mov $otp,%rax
ret
.size xor128_encrypt_n_pad,.-xor128_encrypt_n_pad
.globl xor128_decrypt_n_pad
.type xor128_decrypt_n_pad,\@abi-omnipotent
.align 16
xor128_decrypt_n_pad:
sub $otp,$inp
sub $otp,$out
mov $len,%r10 # put len aside
shr \$4,$len # len / 16
jz .Ltail_dec
nop
.Loop_dec_xmm:
movdqu ($inp,$otp),%xmm0
movdqa ($otp),%xmm1
pxor %xmm0,%xmm1
movdqu %xmm1,($out,$otp)
movdqa %xmm0,($otp)
lea 16($otp),$otp
dec $len
jnz .Loop_dec_xmm
pxor %xmm1,%xmm1
and \$15,%r10 # len % 16
jz .Ldone_dec
.Ltail_dec:
mov \$16,$len
sub %r10,$len
xor %eax,%eax
xor %r11,%r11
.Loop_dec_byte:
mov ($inp,$otp),%r11b
mov ($otp),%al
xor %r11b,%al
mov %al,($out,$otp)
mov %r11b,($otp)
lea 1($otp),$otp
dec %r10
jnz .Loop_dec_byte
xor %eax,%eax
.Loop_dec_pad:
mov %al,($otp)
lea 1($otp),$otp
dec $len
jnz .Loop_dec_pad
.Ldone_dec:
mov $otp,%rax
ret
.size xor128_decrypt_n_pad,.-xor128_decrypt_n_pad
___
}
$code.=<<___; $code.=<<___;
.align 64 .align 64
.Lconst: .Lconst:
+12 -10
View File
@@ -48,7 +48,8 @@ static size_t ec_field_size(const EC_GROUP *group)
if (p == NULL || a == NULL || b == NULL) if (p == NULL || a == NULL || b == NULL)
goto done; goto done;
EC_GROUP_get_curve_GFp(group, p, a, b, NULL); if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL))
goto done;
field_size = (BN_num_bits(p) + 7) / 8; field_size = (BN_num_bits(p) + 7) / 8;
done: done:
@@ -121,19 +122,20 @@ int sm2_encrypt(const EC_KEY *key,
uint8_t *msg_mask = NULL; uint8_t *msg_mask = NULL;
uint8_t *x2y2 = NULL; uint8_t *x2y2 = NULL;
uint8_t *C3 = NULL; uint8_t *C3 = NULL;
const size_t field_size = ec_field_size(group); size_t field_size;
const size_t C3_size = EVP_MD_size(digest); const int C3_size = EVP_MD_size(digest);
/* NULL these before any "goto done" */ /* NULL these before any "goto done" */
ctext_struct.C2 = NULL; ctext_struct.C2 = NULL;
ctext_struct.C3 = NULL; ctext_struct.C3 = NULL;
if (hash == NULL if (hash == NULL || C3_size <= 0) {
|| group == NULL SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
|| order == NULL goto done;
|| P == NULL }
|| field_size == 0
|| C3_size == 0) { field_size = ec_field_size(group);
if (field_size == 0) {
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto done; goto done;
} }
@@ -273,7 +275,7 @@ int sm2_decrypt(const EC_KEY *key,
int msg_len = 0; int msg_len = 0;
EVP_MD_CTX *hash = NULL; EVP_MD_CTX *hash = NULL;
if (field_size == 0 || hash_size == 0) if (field_size == 0 || hash_size <= 0)
goto done; goto done;
memset(ptext_buf, 0xFF, *ptext_len); memset(ptext_buf, 0xFF, *ptext_len);
+7 -6
View File
@@ -25,19 +25,20 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
{ {
EVP_MD_CTX *hash = EVP_MD_CTX_new(); EVP_MD_CTX *hash = EVP_MD_CTX_new();
const int md_size = EVP_MD_size(digest); const int md_size = EVP_MD_size(digest);
uint8_t *za = OPENSSL_zalloc(md_size); uint8_t *za = NULL;
BIGNUM *e = NULL; BIGNUM *e = NULL;
if (hash == NULL || za == NULL) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
goto done;
}
if (md_size < 0) { if (md_size < 0) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST); SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST);
goto done; goto done;
} }
za = OPENSSL_zalloc(md_size);
if (hash == NULL || za == NULL) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!sm2_compute_userid_digest(za, digest, user_id, key)) { if (!sm2_compute_userid_digest(za, digest, user_id, key)) {
/* SM2err already called */ /* SM2err already called */
goto done; goto done;
-2
View File
@@ -59,8 +59,6 @@ int sm2_compute_userid_digest(uint8_t *out,
goto done; goto done;
} }
memset(out, 0, EVP_MD_size(digest));
if (!EVP_DigestInit(hash, digest)) { if (!EVP_DigestInit(hash, digest)) {
SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB); SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
goto done; goto done;
+30 -3
View File
@@ -6,6 +6,10 @@ SSL_set_max_early_data,
SSL_CTX_set_max_early_data, SSL_CTX_set_max_early_data,
SSL_get_max_early_data, SSL_get_max_early_data,
SSL_CTX_get_max_early_data, SSL_CTX_get_max_early_data,
SSL_set_recv_max_early_data,
SSL_CTX_set_recv_max_early_data,
SSL_get_recv_max_early_data,
SSL_CTX_get_recv_max_early_data,
SSL_SESSION_get_max_early_data, SSL_SESSION_get_max_early_data,
SSL_SESSION_set_max_early_data, SSL_SESSION_set_max_early_data,
SSL_write_early_data, SSL_write_early_data,
@@ -24,6 +28,12 @@ SSL_set_allow_early_data_cb
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s); uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);
uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s); uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data); int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data);
@@ -195,9 +205,26 @@ since there is no practical benefit from using only one of them. If the maximum
early data setting for a server is non-zero then replay protection is early data setting for a server is non-zero then replay protection is
automatically enabled (see L</REPLAY PROTECTION> below). automatically enabled (see L</REPLAY PROTECTION> below).
In the event that the current maximum early data setting for the server is If the server rejects the early data sent by a client then it will skip over
different to that originally specified in a session that a client is resuming the data that is sent. The maximum amount of received early data that is skipped
with then the lower of the two values will apply. is controlled by the recv_max_early_data setting. If a client sends more than
this then the connection will abort. This value can be set by calling
SSL_CTX_set_recv_max_early_data() or SSL_set_recv_max_early_data(). The current
value for this setting can be obtained by calling
SSL_CTX_get_recv_max_early_data() or SSL_get_recv_max_early_data(). The default
value for this setting is 16,384 bytes.
The recv_max_early_data value also has an impact on early data that is accepted.
The amount of data that is accepted will always be the lower of the
max_early_data for the session and the recv_max_early_data setting for the
server. If a client sends more data than this then the connection will abort.
The configured value for max_early_data on a server may change over time as
required. However clients may have tickets containing the previously configured
max_early_data value. The recv_max_early_data should always be equal to or
higher than any recently configured max_early_data value in order to avoid
aborted connections. The recv_max_early_data should never be set to less than
the current configured max_early_data value.
Some server applications may wish to have more control over whether early data Some server applications may wish to have more control over whether early data
is accepted or not, for example to mitigate replay risks (see L</REPLAY PROTECTION> is accepted or not, for example to mitigate replay risks (see L</REPLAY PROTECTION>
+4
View File
@@ -919,6 +919,10 @@ int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s); uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);
#ifdef __cplusplus #ifdef __cplusplus
} }
+8 -3
View File
@@ -103,7 +103,7 @@ static int ssl3_record_app_data_waiting(SSL *s)
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send) int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
{ {
uint32_t max_early_data = s->max_early_data; uint32_t max_early_data;
SSL_SESSION *sess = s->session; SSL_SESSION *sess = s->session;
/* /*
@@ -120,9 +120,14 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
} }
sess = s->psksession; sess = s->psksession;
} }
if (!s->server
|| (s->hit && sess->ext.max_early_data < s->max_early_data)) if (!s->server)
max_early_data = sess->ext.max_early_data; max_early_data = sess->ext.max_early_data;
else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
max_early_data = s->recv_max_early_data;
else
max_early_data = s->recv_max_early_data < sess->ext.max_early_data
? s->recv_max_early_data : sess->ext.max_early_data;
if (max_early_data == 0) { if (max_early_data == 0) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
+35
View File
@@ -700,6 +700,7 @@ SSL *SSL_new(SSL_CTX *ctx)
s->mode = ctx->mode; s->mode = ctx->mode;
s->max_cert_list = ctx->max_cert_list; s->max_cert_list = ctx->max_cert_list;
s->max_early_data = ctx->max_early_data; s->max_early_data = ctx->max_early_data;
s->recv_max_early_data = ctx->recv_max_early_data;
s->num_tickets = ctx->num_tickets; s->num_tickets = ctx->num_tickets;
/* Shallow copy of the ciphersuites stack */ /* Shallow copy of the ciphersuites stack */
@@ -3105,6 +3106,16 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
*/ */
ret->max_early_data = 0; ret->max_early_data = 0;
/*
* Default recv_max_early_data is a fully loaded single record. Could be
* split across multiple records in practice. We set this differently to
* max_early_data so that, in the default case, we do not advertise any
* support for early_data, but if a client were to send us some (e.g.
* because of an old, stale ticket) then we will tolerate it and skip over
* it.
*/
ret->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
/* By default we send two session tickets automatically in TLSv1.3 */ /* By default we send two session tickets automatically in TLSv1.3 */
ret->num_tickets = 2; ret->num_tickets = 2;
@@ -5444,6 +5455,30 @@ uint32_t SSL_get_max_early_data(const SSL *s)
return s->max_early_data; return s->max_early_data;
} }
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data)
{
ctx->recv_max_early_data = recv_max_early_data;
return 1;
}
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx)
{
return ctx->recv_max_early_data;
}
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data)
{
s->recv_max_early_data = recv_max_early_data;
return 1;
}
uint32_t SSL_get_recv_max_early_data(const SSL *s)
{
return s->recv_max_early_data;
}
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl) __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl)
{ {
/* Return any active Max Fragment Len extension */ /* Return any active Max Fragment Len extension */
+20 -2
View File
@@ -1069,9 +1069,18 @@ struct ssl_ctx_st {
*/ */
SSL_CTX_keylog_cb_func keylog_callback; SSL_CTX_keylog_cb_func keylog_callback;
/* The maximum number of bytes that can be sent as early data */ /*
* The maximum number of bytes advertised in session tickets that can be
* sent as early data.
*/
uint32_t max_early_data; uint32_t max_early_data;
/*
* The maximum number of bytes of early data that a server will tolerate
* (which should be at least as much as max_early_data).
*/
uint32_t recv_max_early_data;
/* TLS1.3 padding callback */ /* TLS1.3 padding callback */
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg); size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
void *record_padding_arg; void *record_padding_arg;
@@ -1443,8 +1452,17 @@ struct ssl_st {
ASYNC_WAIT_CTX *waitctx; ASYNC_WAIT_CTX *waitctx;
size_t asyncrw; size_t asyncrw;
/* The maximum number of plaintext bytes that can be sent as early data */ /*
* The maximum number of bytes advertised in session tickets that can be
* sent as early data.
*/
uint32_t max_early_data; uint32_t max_early_data;
/*
* The maximum number of bytes of early data that a server will tolerate
* (which should be at least as much as max_early_data).
*/
uint32_t recv_max_early_data;
/* /*
* The number of bytes of early data received so far. If we accepted early * The number of bytes of early data received so far. If we accepted early
* data then this is a count of the plaintext bytes. If we rejected it then * data then this is a count of the plaintext bytes. If we rejected it then
+12 -1
View File
@@ -15,13 +15,24 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_req"); setup("test_req");
plan tests => 4; plan tests => 8;
require_ok(srctop_file('test','recipes','tconversion.pl')); require_ok(srctop_file('test','recipes','tconversion.pl'));
open RND, ">>", ".rnd"; open RND, ">>", ".rnd";
print RND "string to make the random number generator think it has randomness"; print RND "string to make the random number generator think it has randomness";
close RND; close RND;
# Check for duplicate -addext parameters
my $val = "subjectAltName=DNS:example.com";
my $val2 = " " . $val;
my $val3 = $val;
$val3 =~ s/=/ =/;
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val])));
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val2])));
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val3])));
ok(!run(app(["openssl", "req", "-new", "-addext", $val2, "-addext", $val3])));
subtest "generating certificate requests" => sub { subtest "generating certificate requests" => sub {
my @req_new; my @req_new;
if (disabled("rsa")) { if (disabled("rsa")) {
+37 -5
View File
@@ -2314,8 +2314,11 @@ static int test_early_data_replay(int idx)
/* /*
* Helper function to test that a server attempting to read early data can * Helper function to test that a server attempting to read early data can
* handle a connection from a client where the early data should be skipped. * handle a connection from a client where the early data should be skipped.
* testtype: 0 == No HRR
* testtype: 1 == HRR
* testtype: 2 == recv_max_early_data set to 0
*/ */
static int early_data_skip_helper(int hrr, int idx) static int early_data_skip_helper(int testtype, int idx)
{ {
SSL_CTX *cctx = NULL, *sctx = NULL; SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL; SSL *clientssl = NULL, *serverssl = NULL;
@@ -2328,7 +2331,7 @@ static int early_data_skip_helper(int hrr, int idx)
&serverssl, &sess, idx))) &serverssl, &sess, idx)))
goto end; goto end;
if (hrr) { if (testtype == 1) {
/* Force an HRR to occur */ /* Force an HRR to occur */
if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256"))) if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256")))
goto end; goto end;
@@ -2348,13 +2351,17 @@ static int early_data_skip_helper(int hrr, int idx)
goto end; goto end;
} }
if (testtype == 2
&& !TEST_true(SSL_set_recv_max_early_data(serverssl, 0)))
goto end;
/* Write some early data */ /* Write some early data */
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)) &written))
|| !TEST_size_t_eq(written, strlen(MSG1))) || !TEST_size_t_eq(written, strlen(MSG1)))
goto end; goto end;
/* Server should reject the early data and skip over it */ /* Server should reject the early data */
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes), &readbytes),
SSL_READ_EARLY_DATA_FINISH) SSL_READ_EARLY_DATA_FINISH)
@@ -2363,7 +2370,7 @@ static int early_data_skip_helper(int hrr, int idx)
SSL_EARLY_DATA_REJECTED)) SSL_EARLY_DATA_REJECTED))
goto end; goto end;
if (hrr) { if (testtype == 1) {
/* /*
* Finish off the handshake. We perform the same writes and reads as * Finish off the handshake. We perform the same writes and reads as
* further down but we expect them to fail due to the incomplete * further down but we expect them to fail due to the incomplete
@@ -2373,9 +2380,24 @@ static int early_data_skip_helper(int hrr, int idx)
|| !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), || !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
&readbytes))) &readbytes)))
goto end; goto end;
} else if (testtype == 2) {
/*
* This client has sent more early_data than we are willing to skip so
* the connection should abort.
*/
if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|| !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL))
goto end;
/* Connection has failed - nothing more to do */
testresult = 1;
goto end;
} }
/* Should be able to send normal data despite rejection of early data */ /*
* Should be able to send normal data despite rejection of early data. The
* early_data should be skipped.
*/
if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written)) if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
|| !TEST_size_t_eq(written, strlen(MSG2)) || !TEST_size_t_eq(written, strlen(MSG2))
|| !TEST_int_eq(SSL_get_early_data_status(clientssl), || !TEST_int_eq(SSL_get_early_data_status(clientssl),
@@ -2416,6 +2438,15 @@ static int test_early_data_skip_hrr(int idx)
return early_data_skip_helper(1, idx); return early_data_skip_helper(1, idx);
} }
/*
* Test that a server attempting to read early data will abort if it tries to
* skip over too much.
*/
static int test_early_data_skip_abort(int idx)
{
return early_data_skip_helper(2, idx);
}
/* /*
* Test that a server attempting to read early data can handle a connection * Test that a server attempting to read early data can handle a connection
* from a client that doesn't send any. * from a client that doesn't send any.
@@ -5267,6 +5298,7 @@ int setup_tests(void)
ADD_ALL_TESTS(test_early_data_replay, 2); ADD_ALL_TESTS(test_early_data_replay, 2);
ADD_ALL_TESTS(test_early_data_skip, 3); ADD_ALL_TESTS(test_early_data_skip, 3);
ADD_ALL_TESTS(test_early_data_skip_hrr, 3); ADD_ALL_TESTS(test_early_data_skip_hrr, 3);
ADD_ALL_TESTS(test_early_data_skip_abort, 3);
ADD_ALL_TESTS(test_early_data_not_sent, 3); ADD_ALL_TESTS(test_early_data_not_sent, 3);
ADD_ALL_TESTS(test_early_data_psk, 8); ADD_ALL_TESTS(test_early_data_psk, 8);
ADD_ALL_TESTS(test_early_data_not_expected, 3); ADD_ALL_TESTS(test_early_data_not_expected, 3);
+4
View File
@@ -492,3 +492,7 @@ SSL_get_num_tickets 492 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_num_tickets 493 1_1_1 EXIST::FUNCTION: SSL_CTX_set_num_tickets 493 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_allow_early_data_cb 494 1_1_1 EXIST::FUNCTION: SSL_CTX_set_allow_early_data_cb 494 1_1_1 EXIST::FUNCTION:
SSL_set_allow_early_data_cb 495 1_1_1 EXIST::FUNCTION: SSL_set_allow_early_data_cb 495 1_1_1 EXIST::FUNCTION:
SSL_set_recv_max_early_data 496 1_1_1 EXIST::FUNCTION:
SSL_get_recv_max_early_data 497 1_1_1 EXIST::FUNCTION:
SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION: