[openssl-commits] [openssl] master update
Matt Caswell
matt at openssl.org
Mon Mar 12 10:32:03 UTC 2018
The branch master has been updated
via df0fed9aab239e2e9a269d06637a6442051dee3b (commit)
from f1c00b93e2138e5a45e8b500dec6bb3b2e035771 (commit)
- Log -----------------------------------------------------------------
commit df0fed9aab239e2e9a269d06637a6442051dee3b
Author: Todd Short <tshort at akamai.com>
Date: Wed Mar 15 13:25:55 2017 -0400
Session Ticket app data
Adds application data into the encrypted session ticket
Reviewed-by: Paul Dale <paul.dale at oracle.com>
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3802)
-----------------------------------------------------------------------
Summary of changes:
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 0000000..e9aeb90
--- /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 <openssl/ssl.h>
+
+ 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<gen_cb>
+and B<dec_cb> 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<arg> is passed to the callbacks.
+
+B<gen_cb> 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<arg>
+is the same as that given to SSL_CTX_set_session_ticket_cb(). The B<gen_cb>
+callback is defined as type B<SSL_CTX_generate_session_ticket_fn>.
+
+B<dec_cb> 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<arg> is the same as that given to
+SSL_CTX_set_session_ticket_cb(). The B<retv> arguement is the result of the ticket
+decryption. The B<keyname> and B<keyname_len> identify the key used to decrypt the
+session ticket. The B<dec_cb> callback is defined as type
+B<SSL_CTX_decrypt_session_ticket_fn>.
+
+SSL_SESSION_set1_ticket_appdata() sets the application data specified by
+B<data> and B<len> into B<ss> 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<gen_cb> is provided to notify
+the application that a session ticket is about to be generated.
+
+SSL_SESSION_get0_ticket_appdata() assigns B<data> to the session ticket
+application data and assigns B<len> to the length of the session ticket
+application data from B<ss>. The application data can be set via
+SSL_SESSION_set1_ticket_appdata() or by a session ticket. NULL will be assigned
+to B<data> and 0 will be assigned to B<len> 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<dec_cb> is provided to notify the
+application that a session ticket has just been decrypted.
+
+=head1 NOTES
+
+When the B<dec_cb> callback is invoked, the SSL_SESSION B<ss> has not yet been
+assigned to the SSL B<s>. The B<retv> indicates the result of the ticket
+decryption which can be modified by the callback before being returned. The
+callback must check the B<retv> value before performing any action, as it's
+called even if ticket decryption fails.
+
+The B<keyname> and B<keyname_len> arguments to B<dec_cb> may be used to identify
+the key that was used to encrypt the session ticket.
+
+When the B<gen_cb> 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<gen_cb> callback must return 1 to continue the connection. A return of 0
+will terminate the connection with an INTERNAL_ERROR alert.
+
+The B<dec_cb> callback must return one of the following B<SSL_TICKET_RETURN>
+values. Under normal circumstances the B<retv> value is returned unmodified,
+but the callback can change the behavior of the post-ticket decryption code
+by returning something different. The B<dec_cb> callback must check the B<retv>
+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<TICKET_SUCCESS>, but the ticket needs to be renewed.
+
+=back
+
+=head1 SEE ALSO
+
+L<ssl(7)>,
+L<SSL_get_session(3)>
+
+=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<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 3561dee..a47975d 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 9327b33..7d39ba1 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 f5219c2..0814fb3 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 f179efa..9eb5834 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 5d2e171..f78c9cd 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 b9692f4..74acdb2 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 8092684..041089c 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 8b0d9aa..596fdd4 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 c0265ab..9b781b0 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 9dcbeb7..8b11230 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 d5a130f..8d52d1b 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 0000000..863ca7a
--- /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 0000000..ed919d9
--- /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 a21a0f7..778c330 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 c55b272..7676966 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 f9b9217..e26c207 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 70ebb2a..e0458a1 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 b299035..6c02a9b 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 c106e60..6c1a0ef 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
More information about the openssl-commits
mailing list