From df0fed9aab239e2e9a269d06637a6442051dee3b Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 15 Mar 2017 13:25:55 -0400 Subject: [PATCH] Session Ticket app data Adds application data into the encrypted session ticket Reviewed-by: Paul Dale Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/3802) --- doc/man3/SSL_CTX_set_session_ticket_cb.pod | 149 +++++++++++++++++++++ include/openssl/ssl.h | 32 +++++ ssl/ssl_asn1.c | 20 ++- ssl/ssl_lib.c | 11 ++ ssl/ssl_locl.h | 37 ++--- ssl/ssl_sess.c | 48 +++++-- ssl/statem/extensions_srvr.c | 6 +- ssl/statem/statem_srvr.c | 4 + ssl/t1_lib.c | 84 +++++++----- test/handshake_helper.c | 44 ++++++ test/handshake_helper.h | 2 + test/recipes/80-test_ssl_new.t | 2 +- test/ssl-tests/27-ticket-appdata.conf | 146 ++++++++++++++++++++ test/ssl-tests/27-ticket-appdata.conf.in | 99 ++++++++++++++ test/ssl_test.c | 22 +++ test/ssl_test_ctx.c | 10 ++ test/ssl_test_ctx.h | 3 + test/ssl_test_ctx_test.c | 4 + util/libssl.num | 3 + util/private.num | 2 + 20 files changed, 661 insertions(+), 67 deletions(-) create mode 100644 doc/man3/SSL_CTX_set_session_ticket_cb.pod create mode 100644 test/ssl-tests/27-ticket-appdata.conf create mode 100644 test/ssl-tests/27-ticket-appdata.conf.in diff --git a/doc/man3/SSL_CTX_set_session_ticket_cb.pod b/doc/man3/SSL_CTX_set_session_ticket_cb.pod new file mode 100644 index 0000000000..e9aeb909f0 --- /dev/null +++ b/doc/man3/SSL_CTX_set_session_ticket_cb.pod @@ -0,0 +1,149 @@ +=pod + +=head1 NAME + +SSL_CTX_set_session_ticket_cb, +SSL_SESSION_get0_ticket_appdata, +SSL_SESSION_set1_ticket_appdata, +SSL_CTX_generate_session_ticket_fn, +SSL_CTX_decrypt_session_ticket_fn - manage session ticket application data + +=head1 SYNOPSIS + + #include + + typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg); + typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_len, + SSL_TICKET_RETURN retv, + void *arg); + int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg); + int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len); + int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len); + +=head1 DESCRIPTION + +SSL_CTX_set_set_session_ticket_cb() sets the application callbacks B +and B that are used by a server to set and get application data stored +with a session, and placed into a session ticket. Either callback function may +be set to NULL. The value of B is passed to the callbacks. + +B is the application defined callback invoked when a session ticket is +about to be created. The application can call SSL_SESSION_set1_ticket_appdata() +at this time to add application data to the session ticket. The value of B +is the same as that given to SSL_CTX_set_session_ticket_cb(). The B +callback is defined as type B. + +B is the application defined callback invoked after session ticket +decryption has been attempted and any session ticket application data is available. +The application can call SSL_SESSION_get_ticket_appdata() at this time to retrieve +the application data. The value of B is the same as that given to +SSL_CTX_set_session_ticket_cb(). The B arguement is the result of the ticket +decryption. The B and B identify the key used to decrypt the +session ticket. The B callback is defined as type +B. + +SSL_SESSION_set1_ticket_appdata() sets the application data specified by +B and B into B which is then placed into any generated session +tickets. It can be called at any time before a session ticket is created to +update the data placed into the session ticket. However, given that sessions +and tickets are created by the handshake, the B is provided to notify +the application that a session ticket is about to be generated. + +SSL_SESSION_get0_ticket_appdata() assigns B to the session ticket +application data and assigns B to the length of the session ticket +application data from B. The application data can be set via +SSL_SESSION_set1_ticket_appdata() or by a session ticket. NULL will be assigned +to B and 0 will be assigned to B if there is no session ticket +application data. SSL_SESSION_get0_ticket_appdata() can be called any time +after a session has been created. The B is provided to notify the +application that a session ticket has just been decrypted. + +=head1 NOTES + +When the B callback is invoked, the SSL_SESSION B has not yet been +assigned to the SSL B. The B indicates the result of the ticket +decryption which can be modified by the callback before being returned. The +callback must check the B value before performing any action, as it's +called even if ticket decryption fails. + +The B and B arguments to B may be used to identify +the key that was used to encrypt the session ticket. + +When the B callback is invoked, the SSL_get_session() function can be +used to retrieve the SSL_SESSION for SSL_SESSION_set1_ticket_appdata(). + +=head1 RETURN VALUES + +The SSL_CTX_set_session_ticket_cb(), SSL_SESSION_set1_ticket_appdata() and +SSL_SESSION_get0_ticket_appdata() functions return 1 on success and 0 on +failure. + +The B callback must return 1 to continue the connection. A return of 0 +will terminate the connection with an INTERNAL_ERROR alert. + +The B callback must return one of the following B +values. Under normal circumstances the B value is returned unmodified, +but the callback can change the behavior of the post-ticket decryption code +by returning something different. The B callback must check the B +value before performing any action. + + typedef int SSL_TICKET_RETURN; + +=over 4 + +=item SSL_TICKET_FATAL_ERR_MALLOC + +Fatal error, malloc failure. + +=item SSL_TICKET_FATAL_ERR_OTHER + +Fatal error, either from parsing or decrypting the ticket. + +=item SSL_TICKET_NONE + +No ticket present. + +=item SSL_TICKET_EMPTY + +Empty ticket present. + +=item SSL_TICKET_NO_DECRYPT + +The ticket couldn't be decrypted. + +=item SSL_TICKET_SUCCESS + +A ticket was successfully decrypted, any session ticket application data should +be available. + +=item TICKET_SUCCESS_RENEW + +Same as B, but the ticket needs to be renewed. + +=back + +=head1 SEE ALSO + +L, +L + +=head1 HISTORY + +SSL_CTX_set_session_ticket_cb(), SSSL_SESSION_set1_ticket_appdata() and +SSL_SESSION_get_ticket_appdata() were added to OpenSSL 1.1.1. + +=head1 COPYRIGHT + +Copyright 2017 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 +L. + +=cut diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 3561dee33b..a47975d355 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2294,6 +2294,38 @@ __owur const struct openssl_ssl_test_functions *SSL_test_functions(void); __owur int SSL_free_buffers(SSL *ssl); __owur int SSL_alloc_buffers(SSL *ssl); +/* Return codes for tls_get_ticket_from_client() and tls_decrypt_ticket() */ +typedef int SSL_TICKET_RETURN; + +/* Support for ticket appdata */ +/* fatal error, malloc failure */ +# define SSL_TICKET_FATAL_ERR_MALLOC 0 +/* fatal error, either from parsing or decrypting the ticket */ +# define SSL_TICKET_FATAL_ERR_OTHER 1 +/* No ticket present */ +# define SSL_TICKET_NONE 2 +/* Empty ticket present */ +# define SSL_TICKET_EMPTY 3 +/* the ticket couldn't be decrypted */ +# define SSL_TICKET_NO_DECRYPT 4 +/* a ticket was successfully decrypted */ +# define SSL_TICKET_SUCCESS 5 +/* same as above but the ticket needs to be renewed */ +# define SSL_TICKET_SUCCESS_RENEW 6 + +typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg); +typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_length, + SSL_TICKET_RETURN retv, + void *arg); +int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg); +int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len); +int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len); + extern const char SSL_version_str[]; diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index 9327b339ca..7d39ba15c0 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -43,6 +43,7 @@ typedef struct { ASN1_OCTET_STRING *alpn_selected; ASN1_OCTET_STRING *tick_nonce; uint32_t tlsext_max_fragment_len_mode; + ASN1_OCTET_STRING *ticket_appdata; } SSL_SESSION_ASN1; ASN1_SEQUENCE(SSL_SESSION_ASN1) = { @@ -73,7 +74,8 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = { ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15), ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16), ASN1_EXP_OPT(SSL_SESSION_ASN1, tick_nonce, ASN1_OCTET_STRING, 17), - ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 18) + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 18), + ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 19) } static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1) IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1) @@ -123,6 +125,7 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) #endif ASN1_OCTET_STRING alpn_selected; ASN1_OCTET_STRING tick_nonce; + ASN1_OCTET_STRING ticket_appdata; long l; @@ -200,6 +203,12 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) as.tlsext_max_fragment_len_mode = in->ext.max_fragment_len_mode; + if (in->ticket_appdata == NULL) + as.ticket_appdata = NULL; + else + ssl_session_oinit(&as.ticket_appdata, &ticket_appdata, + in->ticket_appdata, in->ticket_appdata_len); + return i2d_SSL_SESSION_ASN1(&as, pp); } @@ -376,6 +385,15 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, ret->ext.max_fragment_len_mode = as->tlsext_max_fragment_len_mode; + if (as->ticket_appdata != NULL) { + ret->ticket_appdata = as->ticket_appdata->data; + ret->ticket_appdata_len = as->ticket_appdata->length; + as->ticket_appdata->data = NULL; + } else { + ret->ticket_appdata = NULL; + ret->ticket_appdata_len = 0; + } + M_ASN1_free_of(as, SSL_SESSION_ASN1); if ((a != NULL) && (*a == NULL)) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index f5219c22d1..0814fb362b 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -5409,3 +5409,14 @@ int SSL_verify_client_post_handshake(SSL *ssl) ossl_statem_set_in_init(ssl, 1); return 1; } + +int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg) +{ + ctx->generate_ticket_cb = gen_cb; + ctx->decrypt_ticket_cb = dec_cb; + ctx->ticket_cb_data = arg; + return 1; +} diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index f179efa231..9eb58342a8 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -591,6 +591,8 @@ struct ssl_session_st { # ifndef OPENSSL_NO_SRP char *srp_username; # endif + unsigned char *ticket_appdata; + size_t ticket_appdata_len; uint32_t flags; CRYPTO_RWLOCK *lock; }; @@ -1025,6 +1027,11 @@ struct ssl_ctx_st { size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg); void *record_padding_arg; size_t block_padding; + + /* Session ticket appdata */ + SSL_CTX_generate_session_ticket_fn generate_ticket_cb; + SSL_CTX_decrypt_session_ticket_fn decrypt_ticket_cb; + void *ticket_cb_data; }; struct ssl_st { @@ -2446,30 +2453,12 @@ void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups, __owur int tls1_set_server_sigalgs(SSL *s); -/* Return codes for tls_get_ticket_from_client() and tls_decrypt_ticket() */ -typedef enum ticket_en { - /* fatal error, malloc failure */ - TICKET_FATAL_ERR_MALLOC, - /* fatal error, either from parsing or decrypting the ticket */ - TICKET_FATAL_ERR_OTHER, - /* No ticket present */ - TICKET_NONE, - /* Empty ticket present */ - TICKET_EMPTY, - /* the ticket couldn't be decrypted */ - TICKET_NO_DECRYPT, - /* a ticket was successfully decrypted */ - TICKET_SUCCESS, - /* same as above but the ticket needs to be renewed */ - TICKET_SUCCESS_RENEW -} TICKET_RETURN; - -__owur TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, - SSL_SESSION **ret); -__owur TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, - size_t eticklen, - const unsigned char *sess_id, - size_t sesslen, SSL_SESSION **psess); +__owur SSL_TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, + SSL_SESSION **ret); +__owur SSL_TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, + size_t eticklen, + const unsigned char *sess_id, + size_t sesslen, SSL_SESSION **psess); __owur int tls_use_ticket(SSL *s); diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 5d2e1719be..f78c9cde5f 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -134,6 +134,7 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) dest->peer_chain = NULL; dest->peer = NULL; dest->ext.tick_nonce = NULL; + dest->ticket_appdata = NULL; memset(&dest->ex_data, 0, sizeof(dest->ex_data)); /* We deliberately don't copy the prev and next pointers */ @@ -244,6 +245,13 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) } #endif + if (src->ticket_appdata != NULL) { + dest->ticket_appdata = + OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); + if (dest->ticket_appdata == NULL) + goto err; + } + return dest; err: SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); @@ -471,7 +479,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) SSL_SESSION *ret = NULL; int fatal = 0, discard; int try_session_cache = 0; - TICKET_RETURN r; + SSL_TICKET_RETURN r; if (SSL_IS_TLS13(s)) { if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, @@ -486,20 +494,20 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) /* sets s->ext.ticket_expected */ r = tls_get_ticket_from_client(s, hello, &ret); switch (r) { - case TICKET_FATAL_ERR_MALLOC: - case TICKET_FATAL_ERR_OTHER: + case SSL_TICKET_FATAL_ERR_MALLOC: + case SSL_TICKET_FATAL_ERR_OTHER: fatal = 1; SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, ERR_R_INTERNAL_ERROR); goto err; - case TICKET_NONE: - case TICKET_EMPTY: + case SSL_TICKET_NONE: + case SSL_TICKET_EMPTY: if (hello->session_id_len > 0) try_session_cache = 1; break; - case TICKET_NO_DECRYPT: - case TICKET_SUCCESS: - case TICKET_SUCCESS_RENEW: + case SSL_TICKET_NO_DECRYPT: + case SSL_TICKET_SUCCESS: + case SSL_TICKET_SUCCESS_RENEW: break; } } @@ -806,6 +814,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) #endif OPENSSL_free(ss->ext.alpn_selected); OPENSSL_free(ss->ext.tick_nonce); + OPENSSL_free(ss->ticket_appdata); CRYPTO_THREAD_lock_free(ss->lock); OPENSSL_clear_free(ss, sizeof(*ss)); } @@ -1269,4 +1278,27 @@ void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, ctx->app_verify_cookie_cb = cb; } +int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) +{ + OPENSSL_free(ss->ticket_appdata); + ss->ticket_appdata_len = 0; + if (data == NULL || len == 0) { + ss->ticket_appdata = NULL; + return 1; + } + ss->ticket_appdata = OPENSSL_memdup(data, len); + if (ss->ticket_appdata != NULL) { + ss->ticket_appdata_len = len; + return 1; + } + return 0; +} + +int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) +{ + *data = ss->ticket_appdata; + *len = ss->ticket_appdata_len; + return 1; +} + IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index b9692f46e4..74acdb2d21 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -1124,13 +1124,13 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, PACKET_remaining(&identity), NULL, 0, &sess); - if (ret == TICKET_FATAL_ERR_MALLOC - || ret == TICKET_FATAL_ERR_OTHER) { + if (ret == SSL_TICKET_FATAL_ERR_MALLOC + || ret == SSL_TICKET_FATAL_ERR_OTHER) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR); return 0; } - if (ret == TICKET_NO_DECRYPT) + if (ret == SSL_TICKET_NO_DECRYPT) continue; ticket_age = (uint32_t)ticket_agel; diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 8092684af7..041089cf96 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -3728,6 +3728,10 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) s->session->ext.max_early_data = s->max_early_data; } + if (tctx->generate_ticket_cb != NULL && + tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) + goto err; + /* get session encoding length */ slen_full = i2d_SSL_SESSION(s->session, NULL); /* diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 8b0d9aa309..596fdd4c34 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1205,8 +1205,8 @@ int tls1_set_server_sigalgs(SSL *s) * s->ctx->ext.ticket_key_cb asked to renew the client's ticket. * Otherwise, s->ext.ticket_expected is set to 0. */ -TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, - SSL_SESSION **ret) +SSL_TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, + SSL_SESSION **ret) { int retv; size_t size; @@ -1221,11 +1221,11 @@ TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, * resumption. */ if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) - return TICKET_NONE; + return SSL_TICKET_NONE; ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket]; if (!ticketext->present) - return TICKET_NONE; + return SSL_TICKET_NONE; size = PACKET_remaining(&ticketext->data); if (size == 0) { @@ -1234,7 +1234,7 @@ TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, * one. */ s->ext.ticket_expected = 1; - return TICKET_EMPTY; + return SSL_TICKET_EMPTY; } if (s->ext.session_secret_cb) { /* @@ -1243,25 +1243,49 @@ TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, * abbreviated handshake based on external mechanism to * calculate the master secret later. */ - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; } retv = tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size, hello->session_id, hello->session_id_len, ret); + + /* + * If set, the decrypt_ticket_cb() is always called regardless of the + * return from tls_decrypt_ticket(). The callback is responsible for + * checking |retv| before it performs any action + */ + if (s->session_ctx->decrypt_ticket_cb != NULL) { + size_t keyname_len = size; + + if (keyname_len > TLSEXT_KEYNAME_LENGTH) + keyname_len = TLSEXT_KEYNAME_LENGTH; + retv = s->session_ctx->decrypt_ticket_cb(s, *ret, + PACKET_data(&ticketext->data), + keyname_len, + retv, s->session_ctx->ticket_cb_data); + } + switch (retv) { - case TICKET_NO_DECRYPT: + case SSL_TICKET_NO_DECRYPT: s->ext.ticket_expected = 1; - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; + + case SSL_TICKET_SUCCESS: + return SSL_TICKET_SUCCESS; - case TICKET_SUCCESS: - return TICKET_SUCCESS; + case SSL_TICKET_SUCCESS_RENEW: + s->ext.ticket_expected = 1; + return SSL_TICKET_SUCCESS; - case TICKET_SUCCESS_RENEW: + case SSL_TICKET_EMPTY: s->ext.ticket_expected = 1; - return TICKET_SUCCESS; + return SSL_TICKET_EMPTY; + + case SSL_TICKET_NONE: + return SSL_TICKET_NONE; default: - return TICKET_FATAL_ERR_OTHER; + return SSL_TICKET_FATAL_ERR_OTHER; } } @@ -1275,15 +1299,15 @@ TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, * psess: (output) on return, if a ticket was decrypted, then this is set to * point to the resulting session. */ -TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, - size_t eticklen, const unsigned char *sess_id, - size_t sesslen, SSL_SESSION **psess) +SSL_TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, + size_t eticklen, const unsigned char *sess_id, + size_t sesslen, SSL_SESSION **psess) { SSL_SESSION *sess; unsigned char *sdec; const unsigned char *p; int slen, renew_ticket = 0, declen; - TICKET_RETURN ret = TICKET_FATAL_ERR_OTHER; + SSL_TICKET_RETURN ret = SSL_TICKET_FATAL_ERR_OTHER; size_t mlen; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; HMAC_CTX *hctx = NULL; @@ -1292,17 +1316,17 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, /* Need at least keyname + iv */ if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) { - ret = TICKET_NO_DECRYPT; + ret = SSL_TICKET_NO_DECRYPT; goto err; } /* Initialize session ticket encryption and HMAC contexts */ hctx = HMAC_CTX_new(); if (hctx == NULL) - return TICKET_FATAL_ERR_MALLOC; + return SSL_TICKET_FATAL_ERR_MALLOC; ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { - ret = TICKET_FATAL_ERR_MALLOC; + ret = SSL_TICKET_FATAL_ERR_MALLOC; goto err; } if (tctx->ext.ticket_key_cb) { @@ -1313,7 +1337,7 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, if (rv < 0) goto err; if (rv == 0) { - ret = TICKET_NO_DECRYPT; + ret = SSL_TICKET_NO_DECRYPT; goto err; } if (rv == 2) @@ -1322,7 +1346,7 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, /* Check key name matches */ if (memcmp(etick, tctx->ext.tick_key_name, TLSEXT_KEYNAME_LENGTH) != 0) { - ret = TICKET_NO_DECRYPT; + ret = SSL_TICKET_NO_DECRYPT; goto err; } if (HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key, @@ -1345,7 +1369,7 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, /* Sanity check ticket length: must exceed keyname + IV + HMAC */ if (eticklen <= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) { - ret = TICKET_NO_DECRYPT; + ret = SSL_TICKET_NO_DECRYPT; goto err; } eticklen -= mlen; @@ -1357,7 +1381,7 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, HMAC_CTX_free(hctx); if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) { EVP_CIPHER_CTX_free(ctx); - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; } /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ @@ -1368,12 +1392,12 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, (int)eticklen) <= 0) { EVP_CIPHER_CTX_free(ctx); OPENSSL_free(sdec); - return TICKET_FATAL_ERR_OTHER; + return SSL_TICKET_FATAL_ERR_OTHER; } if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) { EVP_CIPHER_CTX_free(ctx); OPENSSL_free(sdec); - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; } slen += declen; EVP_CIPHER_CTX_free(ctx); @@ -1387,7 +1411,7 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, /* Some additional consistency checks */ if (slen != 0 || sess->session_id_length != 0) { SSL_SESSION_free(sess); - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; } /* * The session ID, if non-empty, is used by some clients to detect @@ -1400,15 +1424,15 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, sess->session_id_length = sesslen; *psess = sess; if (renew_ticket) - return TICKET_SUCCESS_RENEW; + return SSL_TICKET_SUCCESS_RENEW; else - return TICKET_SUCCESS; + return SSL_TICKET_SUCCESS; } ERR_clear_error(); /* * For session parse failure, indicate that we need to send a new ticket. */ - return TICKET_NO_DECRYPT; + return SSL_TICKET_NO_DECRYPT; err: EVP_CIPHER_CTX_free(ctx); HMAC_CTX_free(hctx); diff --git a/test/handshake_helper.c b/test/handshake_helper.c index c0265ab3c0..9b781b03c9 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -38,6 +38,7 @@ void HANDSHAKE_RESULT_free(HANDSHAKE_RESULT *result) OPENSSL_free(result->server_npn_negotiated); OPENSSL_free(result->client_alpn_negotiated); OPENSSL_free(result->server_alpn_negotiated); + OPENSSL_free(result->result_session_ticket_app_data); sk_X509_NAME_pop_free(result->server_ca_names, X509_NAME_free); sk_X509_NAME_pop_free(result->client_ca_names, X509_NAME_free); OPENSSL_free(result->cipher); @@ -64,6 +65,7 @@ typedef struct ctx_data_st { size_t alpn_protocols_len; char *srp_user; char *srp_password; + char *session_ticket_app_data; } CTX_DATA; /* |ctx_data| itself is stack-allocated. */ @@ -77,6 +79,8 @@ static void ctx_data_free_data(CTX_DATA *ctx_data) ctx_data->srp_user = NULL; OPENSSL_free(ctx_data->srp_password); ctx_data->srp_password = NULL; + OPENSSL_free(ctx_data->session_ticket_app_data); + ctx_data->session_ticket_app_data = NULL; } static int ex_data_idx; @@ -453,6 +457,26 @@ static int server_srp_cb(SSL *s, int *ad, void *arg) } #endif /* !OPENSSL_NO_SRP */ +static int generate_session_ticket_cb(SSL *s, void *arg) +{ + CTX_DATA *server_ctx_data = arg; + SSL_SESSION *ss = SSL_get_session(s); + char *app_data = server_ctx_data->session_ticket_app_data; + + if (ss == NULL || app_data == NULL) + return 0; + + return SSL_SESSION_set1_ticket_appdata(ss, app_data, strlen(app_data)); +} + +static SSL_TICKET_RETURN decrypt_session_ticket_cb(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_len, + SSL_TICKET_RETURN retv, void *arg) +{ + return retv; +} + /* * Configure callbacks and other properties that can't be set directly * in the server/client CONF. @@ -607,6 +631,21 @@ static int configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, OPENSSL_free(alpn_protos); } + if (extra->server.session_ticket_app_data != NULL) { + server_ctx_data->session_ticket_app_data = + OPENSSL_strdup(extra->server.session_ticket_app_data); + SSL_CTX_set_session_ticket_cb(server_ctx, generate_session_ticket_cb, + decrypt_session_ticket_cb, server_ctx_data); + } + if (extra->server2.session_ticket_app_data != NULL) { + if (!TEST_ptr(server2_ctx)) + goto err; + server2_ctx_data->session_ticket_app_data = + OPENSSL_strdup(extra->server2.session_ticket_app_data); + SSL_CTX_set_session_ticket_cb(server2_ctx, NULL, + decrypt_session_ticket_cb, server2_ctx_data); + } + /* * Use fixed session ticket keys so that we can decrypt a ticket created with * one CTX in another CTX. Don't address server2 for the moment. @@ -1583,6 +1622,11 @@ static HANDSHAKE_RESULT *do_handshake_internal( SSL_get0_alpn_selected(server.ssl, &proto, &proto_len); ret->server_alpn_negotiated = dup_str(proto, proto_len); + if ((sess = SSL_get0_session(server.ssl)) != NULL) { + SSL_SESSION_get0_ticket_appdata(sess, (void**)&tick, &tick_len); + ret->result_session_ticket_app_data = OPENSSL_strndup((const char*)tick, tick_len); + } + ret->client_resumed = SSL_session_reused(client.ssl); ret->server_resumed = SSL_session_reused(server.ssl); diff --git a/test/handshake_helper.h b/test/handshake_helper.h index 9dcbeb78f7..8b11230707 100644 --- a/test/handshake_helper.h +++ b/test/handshake_helper.h @@ -65,6 +65,8 @@ typedef struct handshake_result { /* Session id status */ ssl_session_id_t session_id; char *cipher; + /* session ticket application data */ + char *result_session_ticket_app_data; } HANDSHAKE_RESULT; HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void); diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index d5a130f75b..8d52d1b354 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -28,7 +28,7 @@ map { s/\^// } @conf_files if $^O eq "VMS"; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 26; # = scalar @conf_srcs +plan tests => 27; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. diff --git a/test/ssl-tests/27-ticket-appdata.conf b/test/ssl-tests/27-ticket-appdata.conf new file mode 100644 index 0000000000..863ca7a901 --- /dev/null +++ b/test/ssl-tests/27-ticket-appdata.conf @@ -0,0 +1,146 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 4 + +test-0 = 0-session-ticket-app-data12 +test-1 = 1-session-ticket-app-data12 +test-2 = 2-session-ticket-app-data13 +test-3 = 3-session-ticket-app-data13 +# =========================================================== + +[0-session-ticket-app-data12] +ssl_conf = 0-session-ticket-app-data12-ssl + +[0-session-ticket-app-data12-ssl] +server = 0-session-ticket-app-data12-server +client = 0-session-ticket-app-data12-client +resume-server = 0-session-ticket-app-data12-server +resume-client = 0-session-ticket-app-data12-client + +[0-session-ticket-app-data12-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = SessionTicket +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[0-session-ticket-app-data12-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +Options = SessionTicket +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-0] +ExpectedResult = Success +ExpectedSessionTicketAppData = HelloWorld +HandshakeMode = Resume +ResumptionExpected = Yes +SessionTicketExpected = Yes +server = 0-session-ticket-app-data12-server-extra +resume-server = 0-session-ticket-app-data12-server-extra + +[0-session-ticket-app-data12-server-extra] +SessionTicketAppData = HelloWorld + + +# =========================================================== + +[1-session-ticket-app-data12] +ssl_conf = 1-session-ticket-app-data12-ssl + +[1-session-ticket-app-data12-ssl] +server = 1-session-ticket-app-data12-server +client = 1-session-ticket-app-data12-client +resume-server = 1-session-ticket-app-data12-server +resume-client = 1-session-ticket-app-data12-client + +[1-session-ticket-app-data12-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = SessionTicket +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[1-session-ticket-app-data12-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +Options = SessionTicket +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-1] +ExpectedResult = Success +ExpectedSessionTicketAppData = +HandshakeMode = Resume +ResumptionExpected = Yes +SessionTicketExpected = Yes + + +# =========================================================== + +[2-session-ticket-app-data13] +ssl_conf = 2-session-ticket-app-data13-ssl + +[2-session-ticket-app-data13-ssl] +server = 2-session-ticket-app-data13-server +client = 2-session-ticket-app-data13-client +resume-server = 2-session-ticket-app-data13-server +resume-client = 2-session-ticket-app-data13-client + +[2-session-ticket-app-data13-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = SessionTicket +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[2-session-ticket-app-data13-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +Options = SessionTicket +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-2] +ExpectedResult = Success +ExpectedSessionTicketAppData = HelloWorld +HandshakeMode = Resume +ResumptionExpected = Yes +SessionTicketExpected = Yes +server = 2-session-ticket-app-data13-server-extra +resume-server = 2-session-ticket-app-data13-server-extra + +[2-session-ticket-app-data13-server-extra] +SessionTicketAppData = HelloWorld + + +# =========================================================== + +[3-session-ticket-app-data13] +ssl_conf = 3-session-ticket-app-data13-ssl + +[3-session-ticket-app-data13-ssl] +server = 3-session-ticket-app-data13-server +client = 3-session-ticket-app-data13-client +resume-server = 3-session-ticket-app-data13-server +resume-client = 3-session-ticket-app-data13-client + +[3-session-ticket-app-data13-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = SessionTicket +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[3-session-ticket-app-data13-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +Options = SessionTicket +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-3] +ExpectedResult = Success +ExpectedSessionTicketAppData = +HandshakeMode = Resume +ResumptionExpected = Yes +SessionTicketExpected = Yes + + diff --git a/test/ssl-tests/27-ticket-appdata.conf.in b/test/ssl-tests/27-ticket-appdata.conf.in new file mode 100644 index 0000000000..ed919d9bae --- /dev/null +++ b/test/ssl-tests/27-ticket-appdata.conf.in @@ -0,0 +1,99 @@ +# -*- mode: perl; -*- +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +## Test session ticket app data + +use strict; +use warnings; + +package ssltests; +use OpenSSL::Test::Utils; + +our @tests12 = ( + { + "name" => "session-ticket-app-data12", + "client" => { + "MaxProtocol" => "TLSv1.2", + "Options" => "SessionTicket", + }, + "server" => { + "Options" => "SessionTicket", + "extra" => { + "SessionTicketAppData" => "HelloWorld", + }, + }, + "test" => { + "HandshakeMode" => "Resume", + "ExpectedResult" => "Success", + "SessionTicketExpected" => "Yes", + "ResumptionExpected" => "Yes", + "ExpectedSessionTicketAppData" => "HelloWorld", + } + }, + { + "name" => "session-ticket-app-data12", + "client" => { + "MaxProtocol" => "TLSv1.2", + "Options" => "SessionTicket", + }, + "server" => { + "Options" => "SessionTicket", + }, + "test" => { + "HandshakeMode" => "Resume", + "ExpectedResult" => "Success", + "SessionTicketExpected" => "Yes", + "ResumptionExpected" => "Yes", + "ExpectedSessionTicketAppData" => "", + } + } +); +our @tests13 = ( + { + "name" => "session-ticket-app-data13", + "client" => { + "MaxProtocol" => "TLSv1.3", + "Options" => "SessionTicket", + }, + "server" => { + "Options" => "SessionTicket", + "extra" => { + "SessionTicketAppData" => "HelloWorld", + }, + }, + "test" => { + "HandshakeMode" => "Resume", + "ExpectedResult" => "Success", + "SessionTicketExpected" => "Yes", + "ResumptionExpected" => "Yes", + "ExpectedSessionTicketAppData" => "HelloWorld", + } + }, + { + "name" => "session-ticket-app-data13", + "client" => { + "MaxProtocol" => "TLSv1.3", + "Options" => "SessionTicket", + }, + "server" => { + "Options" => "SessionTicket", + }, + "test" => { + "HandshakeMode" => "Resume", + "ExpectedResult" => "Success", + "SessionTicketExpected" => "Yes", + "ResumptionExpected" => "Yes", + "ExpectedSessionTicketAppData" => "", + } + } +); + +our @tests = (); +push @tests, @tests12 unless disabled("tls1_2"); +push @tests, @tests13 unless disabled("tls1_3"); diff --git a/test/ssl_test.c b/test/ssl_test.c index a21a0f773b..778c330313 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -188,6 +188,27 @@ static int check_alpn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) return ret; } +static int check_session_ticket_app_data(HANDSHAKE_RESULT *result, + SSL_TEST_CTX *test_ctx) +{ + size_t result_len = 0; + size_t expected_len = 0; + + /* consider empty and NULL strings to be the same */ + if (result->result_session_ticket_app_data != NULL) + result_len = strlen(result->result_session_ticket_app_data); + if (test_ctx->expected_session_ticket_app_data != NULL) + expected_len = strlen(test_ctx->expected_session_ticket_app_data); + if (result_len == 0 && expected_len == 0) + return 1; + + if (!TEST_str_eq(result->result_session_ticket_app_data, + test_ctx->expected_session_ticket_app_data)) + return 0; + + return 1; +} + static int check_resumption(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) { if (!TEST_int_eq(result->client_resumed, result->server_resumed)) @@ -352,6 +373,7 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) #endif ret &= check_cipher(result, test_ctx); ret &= check_alpn(result, test_ctx); + ret &= check_session_ticket_app_data(result, test_ctx); ret &= check_resumption(result, test_ctx); ret &= check_tmp_key(result, test_ctx); ret &= check_server_cert_type(result, test_ctx); diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index c55b272863..7676966938 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -99,6 +99,7 @@ static const test_enum ssl_test_results[] = { {"ServerFail", SSL_TEST_SERVER_FAIL}, {"ClientFail", SSL_TEST_CLIENT_FAIL}, {"InternalError", SSL_TEST_INTERNAL_ERROR}, + {"FirstHandshakeFailed", SSL_TEST_FIRST_HANDSHAKE_FAILED}, }; __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value) @@ -360,6 +361,10 @@ IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, srp_user) IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, srp_password) IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, srp_password) +/* Session Ticket App Data options */ +IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_session_ticket_app_data) +IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, session_ticket_app_data) + /* Handshake mode */ static const test_enum ssl_handshake_modes[] = { @@ -664,6 +669,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = { { "ExpectedClientCANames", &parse_expected_client_ca_names }, { "UseSCTP", &parse_test_use_sctp }, { "ExpectedCipher", &parse_test_expected_cipher }, + { "ExpectedSessionTicketAppData", &parse_test_expected_session_ticket_app_data }, }; /* Nested client options. */ @@ -700,6 +706,7 @@ static const ssl_test_server_option ssl_test_server_options[] = { { "SRPUser", &parse_server_srp_user }, { "SRPPassword", &parse_server_srp_password }, { "ForcePHA", &parse_server_force_pha }, + { "SessionTicketAppData", &parse_server_session_ticket_app_data }, }; SSL_TEST_CTX *SSL_TEST_CTX_new() @@ -729,6 +736,8 @@ static void ssl_test_extra_conf_free_data(SSL_TEST_EXTRA_CONF *conf) OPENSSL_free(conf->server2.srp_password); OPENSSL_free(conf->client.srp_user); OPENSSL_free(conf->client.srp_password); + OPENSSL_free(conf->server.session_ticket_app_data); + OPENSSL_free(conf->server2.session_ticket_app_data); } static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx) @@ -742,6 +751,7 @@ void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx) ssl_test_ctx_free_extra_data(ctx); OPENSSL_free(ctx->expected_npn_protocol); OPENSSL_free(ctx->expected_alpn_protocol); + OPENSSL_free(ctx->expected_session_ticket_app_data); sk_X509_NAME_pop_free(ctx->expected_server_ca_names, X509_NAME_free); sk_X509_NAME_pop_free(ctx->expected_client_ca_names, X509_NAME_free); OPENSSL_free(ctx->expected_cipher); diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index f9b9217b31..e26c207657 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -127,6 +127,7 @@ typedef struct { char *srp_password; /* Forced PHA */ int force_pha; + char *session_ticket_app_data; } SSL_TEST_SERVER_CONF; typedef struct { @@ -216,6 +217,8 @@ typedef struct { /* Whether to expect a session id from the server */ ssl_session_id_t session_id_expected; char *expected_cipher; + /* Expected Session Ticket Application Data */ + char *expected_session_ticket_app_data; } SSL_TEST_CTX; const char *ssl_test_result_name(ssl_test_result_t result); diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c index 70ebb2a0bd..e0458a177e 100644 --- a/test/ssl_test_ctx_test.c +++ b/test/ssl_test_ctx_test.c @@ -55,6 +55,8 @@ static int serverconf_eq(SSL_TEST_SERVER_CONF *serv, || !TEST_str_eq(serv->alpn_protocols, serv2->alpn_protocols) || !TEST_int_eq(serv->broken_session_ticket, serv2->broken_session_ticket) + || !TEST_str_eq(serv->session_ticket_app_data, + serv2->session_ticket_app_data) || !TEST_int_eq(serv->cert_status, serv2->cert_status)) return 0; return 1; @@ -95,6 +97,8 @@ static int testctx_eq(SSL_TEST_CTX *ctx, SSL_TEST_CTX *ctx2) ctx2->expected_alpn_protocol) || !TEST_str_eq(ctx->expected_cipher, ctx2->expected_cipher) + || !TEST_str_eq(ctx->expected_session_ticket_app_data, + ctx2->expected_session_ticket_app_data) || !TEST_int_eq(ctx->resumption_expected, ctx2->resumption_expected) || !TEST_int_eq(ctx->session_id_expected, diff --git a/util/libssl.num b/util/libssl.num index b299035042..6c02a9b154 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -479,3 +479,6 @@ SSL_force_post_handshake_auth 479 1_1_1 EXIST::FUNCTION: SSL_export_keying_material_early 480 1_1_1 EXIST::FUNCTION: SSL_CTX_use_cert_and_key 481 1_1_1 EXIST::FUNCTION: SSL_use_cert_and_key 482 1_1_1 EXIST::FUNCTION: +SSL_SESSION_get0_ticket_appdata 483 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set1_ticket_appdata 484 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_session_ticket_cb 485 1_1_1 EXIST::FUNCTION: diff --git a/util/private.num b/util/private.num index c106e60899..6c1a0ef32f 100644 --- a/util/private.num +++ b/util/private.num @@ -248,7 +248,9 @@ SSL_CTX_build_cert_chain define SSL_CTX_clear_chain_certs define SSL_CTX_clear_extra_chain_certs define SSL_CTX_clear_mode define +SSL_CTX_decrypt_session_ticket_fn define SSL_CTX_disable_ct define +SSL_CTX_generate_session_ticket_fn define SSL_CTX_get0_chain_certs define SSL_CTX_get_default_read_ahead define SSL_CTX_get_max_cert_list define -- 2.39.2