86 changes: 54 additions & 32 deletions ssl/s3_enc.c
Expand Up @@ -177,39 +177,47 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
EVP_MD_CTX_init(&s1);
for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) {
k++;
if (k > sizeof buf) {
if (k > sizeof(buf))
/* bug: 'buf' is too small for this ciphersuite */
SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
return 0;
}
goto err;

for (j = 0; j < k; j++)
buf[j] = c;
c++;
EVP_DigestInit_ex(&s1, EVP_sha1(), NULL);
EVP_DigestUpdate(&s1, buf, k);
EVP_DigestUpdate(&s1, s->session->master_key,
s->session->master_key_length);
EVP_DigestUpdate(&s1, s->s3->server_random, SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&s1, s->s3->client_random, SSL3_RANDOM_SIZE);
EVP_DigestFinal_ex(&s1, smd, NULL);

EVP_DigestInit_ex(&m5, EVP_md5(), NULL);
EVP_DigestUpdate(&m5, s->session->master_key,
s->session->master_key_length);
EVP_DigestUpdate(&m5, smd, SHA_DIGEST_LENGTH);
if (!EVP_DigestInit_ex(&s1, EVP_sha1(), NULL) ||
!EVP_DigestUpdate(&s1, buf, k) ||
!EVP_DigestUpdate(&s1, s->session->master_key,
s->session->master_key_length) ||
!EVP_DigestUpdate(&s1, s->s3->server_random, SSL3_RANDOM_SIZE) ||
!EVP_DigestUpdate(&s1, s->s3->client_random, SSL3_RANDOM_SIZE) ||
!EVP_DigestFinal_ex(&s1, smd, NULL))
goto err2;

if (!EVP_DigestInit_ex(&m5, EVP_md5(), NULL) ||
!EVP_DigestUpdate(&m5, s->session->master_key,
s->session->master_key_length) ||
!EVP_DigestUpdate(&m5, smd, SHA_DIGEST_LENGTH))
goto err2;
if ((int)(i + MD5_DIGEST_LENGTH) > num) {
EVP_DigestFinal_ex(&m5, smd, NULL);
if (!EVP_DigestFinal_ex(&m5, smd, NULL))
goto err2;
memcpy(km, smd, (num - i));
} else
EVP_DigestFinal_ex(&m5, km, NULL);
if (!EVP_DigestFinal_ex(&m5, km, NULL))
goto err2;

km += MD5_DIGEST_LENGTH;
}
OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
EVP_MD_CTX_cleanup(&m5);
EVP_MD_CTX_cleanup(&s1);
return 1;
err:
SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
err2:
EVP_MD_CTX_cleanup(&m5);
EVP_MD_CTX_cleanup(&s1);
return 0;
}

int ssl3_change_cipher_state(SSL *s, int which)
Expand Down Expand Up @@ -360,25 +368,33 @@ int ssl3_change_cipher_state(SSL *s, int which)
* In here I set both the read and write key/iv to the same value
* since only the correct one will be used :-).
*/
EVP_DigestInit_ex(&md, EVP_md5(), NULL);
EVP_DigestUpdate(&md, key, j);
EVP_DigestUpdate(&md, er1, SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&md, er2, SSL3_RANDOM_SIZE);
EVP_DigestFinal_ex(&md, &(exp_key[0]), NULL);
if (!EVP_DigestInit_ex(&md, EVP_md5(), NULL) ||
!EVP_DigestUpdate(&md, key, j) ||
!EVP_DigestUpdate(&md, er1, SSL3_RANDOM_SIZE) ||
!EVP_DigestUpdate(&md, er2, SSL3_RANDOM_SIZE) ||
!EVP_DigestFinal_ex(&md, &(exp_key[0]), NULL)) {
EVP_MD_CTX_cleanup(&md);
goto err2;
}
key = &(exp_key[0]);

if (k > 0) {
EVP_DigestInit_ex(&md, EVP_md5(), NULL);
EVP_DigestUpdate(&md, er1, SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&md, er2, SSL3_RANDOM_SIZE);
EVP_DigestFinal_ex(&md, &(exp_iv[0]), NULL);
if (!EVP_DigestInit_ex(&md, EVP_md5(), NULL) ||
!EVP_DigestUpdate(&md, er1, SSL3_RANDOM_SIZE) ||
!EVP_DigestUpdate(&md, er2, SSL3_RANDOM_SIZE) ||
!EVP_DigestFinal_ex(&md, &(exp_iv[0]), NULL)) {
EVP_MD_CTX_cleanup(&md);
goto err2;
}
iv = &(exp_iv[0]);
}
}
EVP_MD_CTX_cleanup(&md);

s->session->key_arg_length = 0;

EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE));
if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE)))
goto err2;

#ifdef OPENSSL_SSL_TRACE_CRYPTO
if (s->msg_callback) {
Expand All @@ -399,7 +415,6 @@ int ssl3_change_cipher_state(SSL *s, int which)

OPENSSL_cleanse(&(exp_key[0]), sizeof(exp_key));
OPENSSL_cleanse(&(exp_iv[0]), sizeof(exp_iv));
EVP_MD_CTX_cleanup(&md);
return (1);
err:
SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
Expand Down Expand Up @@ -555,17 +570,20 @@ int ssl3_enc(SSL *s, int send)
if ((bs != 1) && !send)
return ssl3_cbc_remove_padding(s, rec, bs, mac_size);
}
return (1);
return 1;
}

void ssl3_init_finished_mac(SSL *s)
int ssl3_init_finished_mac(SSL *s)
{
if (s->s3->handshake_buffer)
BIO_free(s->s3->handshake_buffer);
if (s->s3->handshake_dgst)
ssl3_free_digest_list(s);
s->s3->handshake_buffer = BIO_new(BIO_s_mem());
if (s->s3->handshake_buffer == NULL)
return 0;
(void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
return 1;
}

void ssl3_free_digest_list(SSL *s)
Expand Down Expand Up @@ -622,6 +640,10 @@ int ssl3_digest_cached_records(SSL *s)
for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
if ((mask & ssl_get_algorithm2(s)) && md) {
s->s3->handshake_dgst[i] = EVP_MD_CTX_create();
if (s->s3->handshake_dgst[i] == NULL) {
SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE);
return 0;
}
#ifdef OPENSSL_FIPS
if (EVP_MD_nid(md) == NID_md5) {
EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i],
Expand Down Expand Up @@ -903,7 +925,7 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
s, s->msg_callback_arg);
}
#endif
OPENSSL_cleanse(buf, sizeof buf);
OPENSSL_cleanse(buf, sizeof(buf));
return (ret);
}

Expand Down
2 changes: 1 addition & 1 deletion ssl/s3_lib.c
Expand Up @@ -4237,7 +4237,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
return (int)s->cert->ctype_num;
}
/* get configured sigalgs */
siglen = tls12_get_psigalgs(s, &sig);
siglen = tls12_get_psigalgs(s, 1, &sig);
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
nostrict = 0;
for (i = 0; i < siglen; i += 2, sig += 2) {
Expand Down
3 changes: 2 additions & 1 deletion ssl/s3_pkt.c
Expand Up @@ -670,7 +670,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
* promptly send beyond the end of the users buffer ... so we trap and
* report the error in a way the user will notice
*/
if (len < tot) {
if ((len < tot) || ((wb->left != 0) && (len < (tot + s->s3->wpend_tot)))) {
SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_BAD_LENGTH);
return (-1);
}
Expand Down Expand Up @@ -699,6 +699,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
len >= 4 * (int)(max_send_fragment = s->max_send_fragment) &&
s->compress == NULL && s->msg_callback == NULL &&
SSL_USE_EXPLICIT_IV(s) &&
s->enc_write_ctx != NULL &&
EVP_CIPHER_flags(s->enc_write_ctx->cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
unsigned char aad[13];
Expand Down
56 changes: 41 additions & 15 deletions ssl/s3_srvr.c
Expand Up @@ -311,7 +311,12 @@ int ssl3_accept(SSL *s)
goto end;
}

ssl3_init_finished_mac(s);
if (!ssl3_init_finished_mac(s)) {
ret = -1;
s->state = SSL_ST_ERR;
goto end;
}

s->state = SSL3_ST_SR_CLNT_HELLO_A;
s->ctx->stats.sess_accept++;
} else if (!s->s3->send_connection_binding &&
Expand Down Expand Up @@ -348,7 +353,11 @@ int ssl3_accept(SSL *s)
s->state = SSL3_ST_SW_FLUSH;
s->init_num = 0;

ssl3_init_finished_mac(s);
if (!ssl3_init_finished_mac(s)) {
ret = -1;
s->state = SSL_ST_ERR;
goto end;
}
break;

case SSL3_ST_SW_HELLO_REQ_C:
Expand Down Expand Up @@ -1704,6 +1713,12 @@ int ssl3_send_server_key_exchange(SSL *s)
if (type & SSL_kEECDH) {
const EC_GROUP *group;

if (s->s3->tmp.ecdh != NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}

ecdhp = cert->ecdh_tmp;
if (s->cert->ecdh_tmp_auto) {
/* Get NID of appropriate shared curve */
Expand All @@ -1724,17 +1739,7 @@ int ssl3_send_server_key_exchange(SSL *s)
goto f_err;
}

if (s->s3->tmp.ecdh != NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}

/* Duplicate the ECDH structure. */
if (ecdhp == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB);
goto err;
}
if (s->cert->ecdh_tmp_auto)
ecdh = ecdhp;
else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) {
Expand Down Expand Up @@ -2084,7 +2089,7 @@ int ssl3_send_certificate_request(SSL *s)

if (SSL_USE_SIGALGS(s)) {
const unsigned char *psigs;
nl = tls12_get_psigalgs(s, &psigs);
nl = tls12_get_psigalgs(s, 1, &psigs);
s2n(nl, p);
memcpy(p, psigs, nl);
p += nl;
Expand Down Expand Up @@ -3018,6 +3023,11 @@ int ssl3_get_cert_verify(SSL *s)

peer = s->session->peer;
pkey = X509_get_pubkey(peer);
if (pkey == NULL) {
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}

type = X509_certificate_type(peer, pkey);

if (!(type & EVP_PKT_SIGN)) {
Expand Down Expand Up @@ -3154,7 +3164,9 @@ int ssl3_get_cert_verify(SSL *s)
goto f_err;
}
if (i != 64) {
#ifdef SSL_DEBUG
fprintf(stderr, "GOST signature length is %d", i);
#endif
}
for (idx = 0; idx < 64; idx++) {
signature[63 - idx] = p[idx];
Expand Down Expand Up @@ -3463,8 +3475,22 @@ int ssl3_send_newsession_ticket(SSL *s)
* all the work otherwise use generated values from parent ctx.
*/
if (tctx->tlsext_ticket_key_cb) {
if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
&hctx, 1) < 0)
/* if 0 is returned, write en empty ticket */
int ret = tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
&hctx, 1);

if (ret == 0) {
l2n(0, p); /* timeout */
s2n(0, p); /* length */
ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET,
p - ssl_handshake_start(s));
s->state = SSL3_ST_SW_SESSION_TICKET_B;
OPENSSL_free(senc);
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_cleanup(&hctx);
return ssl_do_write(s);
}
if (ret < 0)
goto err;
} else {
if (RAND_bytes(iv, 16) <= 0)
Expand Down
1 change: 1 addition & 0 deletions ssl/ssl_cert.c
Expand Up @@ -412,6 +412,7 @@ CERT *ssl_cert_dup(CERT *cert)
#endif

ssl_cert_clear_certs(ret);
OPENSSL_free(ret);

return NULL;
}
Expand Down
3 changes: 2 additions & 1 deletion ssl/ssl_ciph.c
Expand Up @@ -2001,7 +2001,7 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
if (id < 193 || id > 255) {
SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
return 0;
return 1;
}

MemCheck_off();
Expand All @@ -2013,6 +2013,7 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
}
comp->id = id;
comp->method = cm;
comp->name = cm->name;
load_builtin_compressions();
if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
OPENSSL_free(comp);
Expand Down
19 changes: 15 additions & 4 deletions ssl/ssl_lib.c
Expand Up @@ -1838,13 +1838,21 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,

static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
const unsigned char *session_id = a->session_id;
unsigned long l;
unsigned char tmp_storage[4];

if (a->session_id_length < sizeof(tmp_storage)) {
memset(tmp_storage, 0, sizeof(tmp_storage));
memcpy(tmp_storage, a->session_id, a->session_id_length);
session_id = tmp_storage;
}

l = (unsigned long)
((unsigned int)a->session_id[0]) |
((unsigned int)a->session_id[1] << 8L) |
((unsigned long)a->session_id[2] << 16L) |
((unsigned long)a->session_id[3] << 24L);
((unsigned long)session_id[0]) |
((unsigned long)session_id[1] << 8L) |
((unsigned long)session_id[2] << 16L) |
((unsigned long)session_id[3] << 24L);
return (l);
}

Expand Down Expand Up @@ -3186,6 +3194,9 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
ssl->cert->alpn_proposed_len = ocert->alpn_proposed_len;
ocert->alpn_proposed = NULL;
ssl->cert->alpn_sent = ocert->alpn_sent;

if (!custom_exts_copy_flags(&ssl->cert->srv_ext, &ocert->srv_ext))
return NULL;
#endif
ssl_cert_free(ocert);
}
Expand Down
6 changes: 4 additions & 2 deletions ssl/ssl_locl.h
Expand Up @@ -1158,7 +1158,7 @@ long ssl2_default_timeout(void);

const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
void ssl3_init_finished_mac(SSL *s);
int ssl3_init_finished_mac(SSL *s);
int ssl3_send_server_certificate(SSL *s);
int ssl3_send_newsession_ticket(SSL *s);
int ssl3_send_cert_status(SSL *s);
Expand Down Expand Up @@ -1430,7 +1430,7 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
long ssl_get_algorithm2(SSL *s);
int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize);
int tls1_process_sigalgs(SSL *s);
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
size_t tls12_get_psigalgs(SSL *s, int sent, const unsigned char **psigs);
int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
const unsigned char *sig, EVP_PKEY *pkey);
void ssl_set_client_disabled(SSL *s);
Expand Down Expand Up @@ -1482,6 +1482,8 @@ int custom_ext_add(SSL *s, int server,
unsigned char **pret, unsigned char *limit, int *al);

int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src);
int custom_exts_copy_flags(custom_ext_methods *dst,
const custom_ext_methods *src);
void custom_exts_free(custom_ext_methods *exts);

# else
Expand Down
6 changes: 4 additions & 2 deletions ssl/ssl_rsa.c
Expand Up @@ -964,6 +964,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
int ret = 0;
BIO *bin = NULL;
size_t num_extensions = 0;
unsigned char *new_serverinfo;

if (ctx == NULL || file == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
Expand Down Expand Up @@ -1014,12 +1015,13 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
goto end;
}
/* Append the decoded extension to the serverinfo buffer */
serverinfo =
new_serverinfo =
OPENSSL_realloc(serverinfo, serverinfo_length + extension_length);
if (serverinfo == NULL) {
if (new_serverinfo == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE);
goto end;
}
serverinfo = new_serverinfo;
memcpy(serverinfo + serverinfo_length, extension, extension_length);
serverinfo_length += extension_length;

Expand Down
3 changes: 2 additions & 1 deletion ssl/ssl_sess.c
Expand Up @@ -1006,7 +1006,8 @@ int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
return 0;
}
s->sid_ctx_length = sid_ctx_len;
memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
if (s->sid_ctx != sid_ctx)
memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);

return 1;
}
Expand Down
126 changes: 124 additions & 2 deletions ssl/ssltest.c
Expand Up @@ -311,6 +311,10 @@ static const char *sn_client;
static const char *sn_server1;
static const char *sn_server2;
static int sn_expect = 0;
static int s_ticket1 = 0;
static int s_ticket2 = 0;
static int c_ticket = 0;
static int ticket_expect = -1;

static int servername_cb(SSL *s, int *ad, void *arg)
{
Expand All @@ -325,6 +329,9 @@ static int servername_cb(SSL *s, int *ad, void *arg)
!strcasecmp(servername, sn_server2)) {
BIO_printf(bio_stdout, "Switching server context.\n");
SSL_set_SSL_CTX(s, s_ctx2);
/* Copy over all the SSL_CTX options */
SSL_clear_options(s, 0xFFFFFFFFL);
SSL_set_options(s, SSL_CTX_get_options(s_ctx2));
}
}
return SSL_TLSEXT_ERR_OK;
Expand All @@ -349,6 +356,21 @@ static int verify_servername(SSL *client, SSL *server)
return -1;
}

static int verify_ticket(SSL* ssl)
{
if (ticket_expect == -1)
return 0;
if (ticket_expect == 0 &&
(ssl->session->tlsext_tick == NULL ||
ssl->session->tlsext_ticklen == 0))
return 1;
if (ticket_expect == 1 &&
(ssl->session->tlsext_tick != NULL &&
ssl->session->tlsext_ticklen != 0))
return 1;
return -1;
}

/*-
* next_protos_parse parses a comma separated list of strings into a string
* in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
Expand Down Expand Up @@ -477,6 +499,42 @@ static int verify_alpn(SSL *client, SSL *server)
return -1;
}

#ifndef OPENSSL_NO_TLSEXT

static int cb_ticket0(SSL* s, unsigned char* key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
{
return 0;
}

static int cb_ticket1(SSL* s, unsigned char* key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
{
static unsigned char key[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
static char name[] = "ticket11ticket11";
if (SSL_get_options(s) & SSL_OP_NO_TICKET)
return 0;
if (enc) {
RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH);
EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
HMAC_Init_ex(hctx, key, sizeof(key), EVP_sha1(), NULL);
memcpy(key_name, name, 16);
return 1;
} else {
if (memcmp(key_name, name, 16) == 0) {
EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
HMAC_Init_ex(hctx, key, sizeof(key), EVP_sha1(), NULL);
return 1;
}
}
return 0;
}

static int cb_ticket2(SSL* s, unsigned char* key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
{
fprintf(stderr, "ticket callback for SNI context should never be called\n");
EXIT(1);
}
#endif

#define SCT_EXT_TYPE 18

/*
Expand Down Expand Up @@ -820,6 +878,12 @@ static void sv_usage(void)
fprintf(stderr, " -sn_server2 <string> - have server context 2 respond to this servername\n");
fprintf(stderr, " -sn_expect1 - expected server 1\n");
fprintf(stderr, " -sn_expect2 - expected server 2\n");
#ifndef OPENSSL_NO_TLSEXT
fprintf(stderr, " -s_ticket1 <yes|no|broken> - enable/disable session tickets on context 1\n");
fprintf(stderr, " -s_ticket2 <yes|no> - enable/disable session tickets on context 2\n");
fprintf(stderr, " -c_ticket <yes|no> - enable/disable session tickets on the client\n");
fprintf(stderr, " -ticket_expect <yes|no> - indicate that the client should (or should not) have a ticket\n");
#endif
}

static void print_details(SSL *c_ssl, const char *prefix)
Expand Down Expand Up @@ -1175,13 +1239,21 @@ int main(int argc, char *argv[])
} else if (strcmp(*argv, "-time") == 0) {
print_time = 1;
}
#ifndef OPENSSL_NO_COMP
else if (strcmp(*argv, "-zlib") == 0) {
#ifndef OPENSSL_NO_COMP
comp = COMP_ZLIB;
#else
fprintf(stderr,
"ignoring -zlib, since I'm compiled without COMP\n");
#endif
} else if (strcmp(*argv, "-rle") == 0) {
#ifndef OPENSSL_NO_COMP
comp = COMP_RLE;
}
#else
fprintf(stderr,
"ignoring -rle, since I'm compiled without COMP\n");
#endif
}
else if (strcmp(*argv, "-named_curve") == 0) {
if (--argc < 1)
goto bad;
Expand Down Expand Up @@ -1241,6 +1313,36 @@ int main(int argc, char *argv[])
sn_expect = 1;
} else if (strcmp(*argv, "-sn_expect2") == 0) {
sn_expect = 2;
#ifndef OPENSSL_NO_TLSEXT
} else if (strcmp(*argv, "-s_ticket1") == 0) {
if (--argc < 1)
goto bad;
argv++;
if (strcmp(*argv, "yes") == 0)
s_ticket1 = 1;
if (strcmp(*argv, "broken") == 0)
s_ticket1 = 2;
} else if (strcmp(*argv, "-s_ticket2") == 0) {
if (--argc < 1)
goto bad;
argv++;
if (strcmp(*argv, "yes") == 0)
s_ticket2 = 1;
} else if (strcmp(*argv, "-c_ticket") == 0) {
if (--argc < 1)
goto bad;
argv++;
if (strcmp(*argv, "yes") == 0)
c_ticket = 1;
} else if (strcmp(*argv, "-ticket_expect") == 0) {
if (--argc < 1)
goto bad;
argv++;
if (strcmp(*argv, "yes") == 0)
ticket_expect = 1;
else if (strcmp(*argv, "no") == 0)
ticket_expect = 0;
#endif
} else {
fprintf(stderr, "unknown option %s\n", *argv);
badop = 1;
Expand Down Expand Up @@ -1679,6 +1781,24 @@ int main(int argc, char *argv[])
if (sn_server1 || sn_server2)
SSL_CTX_set_tlsext_servername_callback(s_ctx, servername_cb);

#ifndef OPENSSL_NO_TLSEXT
if (s_ticket1 == 0)
SSL_CTX_set_options(s_ctx, SSL_OP_NO_TICKET);
/* always set the callback */
if (s_ticket1 == 2)
SSL_CTX_set_tlsext_ticket_key_cb(s_ctx, cb_ticket0);
else
SSL_CTX_set_tlsext_ticket_key_cb(s_ctx, cb_ticket1);

if (!s_ticket2)
SSL_CTX_set_options(s_ctx2, SSL_OP_NO_TICKET);
/* always set the callback - this should never be called */
SSL_CTX_set_tlsext_ticket_key_cb(s_ctx2, cb_ticket2);

if (!c_ticket)
SSL_CTX_set_options(c_ctx, SSL_OP_NO_TICKET);
#endif

c_ssl = SSL_new(c_ctx);
s_ssl = SSL_new(s_ctx);

Expand Down Expand Up @@ -1742,6 +1862,8 @@ int main(int argc, char *argv[])
ret = 1;
if (verify_servername(c_ssl, s_ssl) < 0)
ret = 1;
if (verify_ticket(c_ssl) < 0)
ret = 1;

SSL_free(s_ssl);
SSL_free(c_ssl);
Expand Down
33 changes: 25 additions & 8 deletions ssl/t1_ext.c
Expand Up @@ -179,6 +179,25 @@ int custom_ext_add(SSL *s, int server,
return 1;
}

/* Copy the flags from src to dst for any extensions that exist in both */
int custom_exts_copy_flags(custom_ext_methods *dst,
const custom_ext_methods *src)
{
size_t i;
custom_ext_method *methsrc = src->meths;

for (i = 0; i < src->meths_count; i++, methsrc++) {
custom_ext_method *methdst = custom_ext_find(dst, methsrc->ext_type);

if (methdst == NULL)
continue;

methdst->ext_flags = methsrc->ext_flags;
}

return 1;
}

/* Copy table of custom extensions */
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
{
Expand Down Expand Up @@ -223,16 +242,14 @@ static int custom_ext_meth_add(custom_ext_methods *exts,
/* Search for duplicate */
if (custom_ext_find(exts, ext_type))
return 0;
exts->meths = OPENSSL_realloc(exts->meths,
(exts->meths_count +
1) * sizeof(custom_ext_method));

if (!exts->meths) {
exts->meths_count = 0;
meth = OPENSSL_realloc(exts->meths,
(exts->meths_count + 1)
* sizeof(custom_ext_method));
if (meth == NULL)
return 0;
}

meth = exts->meths + exts->meths_count;
exts->meths = meth;
meth += exts->meths_count;
memset(meth, 0, sizeof(custom_ext_method));
meth->parse_cb = parse_cb;
meth->add_cb = add_cb;
Expand Down
21 changes: 15 additions & 6 deletions ssl/t1_lib.c
Expand Up @@ -1035,7 +1035,7 @@ static unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
# endif
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
size_t tls12_get_psigalgs(SSL *s, int sent, const unsigned char **psigs)
{
/*
* If Suite B mode use Suite B sigalgs only, ignore any other
Expand All @@ -1057,7 +1057,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
}
# endif
/* If server use client authentication sigalgs if not NULL */
if (s->server && s->cert->client_sigalgs) {
if (s->server == sent && s->cert->client_sigalgs) {
*psigs = s->cert->client_sigalgs;
return s->cert->client_sigalgslen;
} else if (s->cert->conf_sigalgs) {
Expand Down Expand Up @@ -1121,7 +1121,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
# endif

/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
break;
Expand Down Expand Up @@ -1169,7 +1169,7 @@ void ssl_set_client_disabled(SSL *s)
* Now go through all signature algorithms seeing if we support any for
* RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2.
*/
sigalgslen = tls12_get_psigalgs(s, &sigalgs);
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
switch (sigalgs[1]) {
# ifndef OPENSSL_NO_RSA
Expand Down Expand Up @@ -1440,7 +1440,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
if (SSL_CLIENT_USE_SIGALGS(s)) {
size_t salglen;
const unsigned char *salg;
salglen = tls12_get_psigalgs(s, &salg);
salglen = tls12_get_psigalgs(s, 1, &salg);

/*-
* check for enough space.
Expand Down Expand Up @@ -1769,6 +1769,9 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
return NULL;
s2n(TLSEXT_TYPE_session_ticket, ret);
s2n(0, ret);
} else {
/* if we don't add the above TLSEXT, we can't add a session ticket later */
s->tlsext_ticket_expected = 0;
}

if (s->tlsext_status_expected) {
Expand Down Expand Up @@ -3574,8 +3577,14 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
p = sdec;

sess = d2i_SSL_SESSION(NULL, &p, slen);
slen -= p - sdec;
OPENSSL_free(sdec);
if (sess) {
/* Some additional consistency checks */
if (slen != 0 || sess->session_id_length != 0) {
SSL_SESSION_free(sess);
return 2;
}
/*
* The session ID, if non-empty, is used by some clients to detect
* that the ticket has been accepted. So we copy it to the session
Expand Down Expand Up @@ -3803,7 +3812,7 @@ static int tls1_set_shared_sigalgs(SSL *s)
conf = c->conf_sigalgs;
conflen = c->conf_sigalgslen;
} else
conflen = tls12_get_psigalgs(s, &conf);
conflen = tls12_get_psigalgs(s, 0, &conf);
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
Expand Down
1 change: 1 addition & 0 deletions test/Makefile
Expand Up @@ -307,6 +307,7 @@ test_ssl: keyU.ss certU.ss certCA.ss certP1.ss keyP1.ss certP2.ss keyP2.ss \
fi
../util/shlib_wrap.sh ./$(SSLTEST) -test_cipherlist
@sh ./testssl keyU.ss certU.ss certCA.ss
@sh ./testssl keyU.ss certU.ss certCA.ss -rle
@sh ./testsslproxy keyP1.ss certP1.ss intP1.ss
@sh ./testsslproxy keyP2.ss certP2.ss intP2.ss

Expand Down
Binary file added test/ssltest_old
Binary file not shown.
21 changes: 21 additions & 0 deletions test/testssl
Expand Up @@ -292,4 +292,25 @@ if [ -z "$extra" -a `uname -m` = "x86_64" ]; then
$ssltest -cipher AES128-SHA256 -bytes 8m || exit 1
fi


$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 no -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 no -c_ticket yes -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 yes -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 yes -c_ticket yes -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 no -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 no -c_ticket yes -ticket_expect yes || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 yes -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client alice -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 yes -c_ticket yes -ticket_expect yes || exit 1

$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 no -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 no -c_ticket yes -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 yes -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 no -s_ticket2 yes -c_ticket yes -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 no -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 no -c_ticket yes -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 yes -c_ticket no -ticket_expect no || exit 1
$ssltest -bio_pair -sn_client bob -sn_server1 alice -sn_server2 bob -s_ticket1 yes -s_ticket2 yes -c_ticket yes -ticket_expect yes || exit 1

$ssltest -bio_pair -s_ticket1 broken -c_ticket yes -ticket_expect no || exit 1

exit 0
2 changes: 1 addition & 1 deletion test/testutil.h
Expand Up @@ -103,7 +103,7 @@
* TEST_CASE_NAME is defined as the name of the test case function where
* possible; otherwise we get by with the file name and line number.
*/
# if __STDC_VERSION__ < 199901L
# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
# if defined(_MSC_VER)
# define TEST_CASE_NAME __FUNCTION__
# else
Expand Down
Binary file added test/v3ext
Binary file not shown.
Binary file added test/x509aux
Binary file not shown.
6 changes: 3 additions & 3 deletions util/domd
Expand Up @@ -34,11 +34,11 @@ else
${PERL} $TOP/util/clean-depend.pl < Makefile > Makefile.new
RC=$?
fi
if ! cmp -s Makefile.save Makefile.new; then
mv Makefile.new Makefile
else
if cmp -s Makefile.save Makefile.new; then
mv Makefile.save Makefile
rm -f Makefile.new
else
mv Makefile.new Makefile
fi
# unfake the presence of Kerberos
rm $TOP/krb5.h
Expand Down
1 change: 1 addition & 0 deletions util/mk1mf.pl
Expand Up @@ -1207,6 +1207,7 @@ sub read_options
"no-ssl3-method" => 0,
"no-tlsext" => \$no_tlsext,
"no-tls1" => \$no_tls1,
"no-dtls1" => 0,
"no-srp" => \$no_srp,
"no-cms" => \$no_cms,
"no-jpake" => \$no_jpake,
Expand Down