summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-01-18 16:28:23 +0000
committerMatt Caswell <matt@openssl.org>2017-01-30 10:18:21 +0000
commit1053a6e2281d81cd5d04d2d90da2c4905c9c3561 (patch)
tree8e49f4bb9e6cf5b1ea1e7a9a24f72f88278b9c89
parent71c94d3c6115ab853bbdc2e0e1e26da2c8aba76a (diff)
Implement Server side of PSK extension parsing
Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2259)
-rw-r--r--include/openssl/ssl.h2
-rw-r--r--ssl/ssl_ciph.c11
-rw-r--r--ssl/ssl_err.c2
-rw-r--r--ssl/ssl_locl.h12
-rw-r--r--ssl/ssl_sess.c59
-rw-r--r--ssl/statem/extensions.c97
-rw-r--r--ssl/statem/extensions_clnt.c80
-rw-r--r--ssl/statem/extensions_srvr.c97
-rw-r--r--ssl/statem/statem_locl.h7
-rw-r--r--ssl/t1_lib.c61
10 files changed, 297 insertions, 131 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index cee7549d9b..af8878c6bd 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2324,6 +2324,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_GET_MESSAGE_HEADER 387
# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT 449
# define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 463
+# define SSL_F_TLS_PARSE_CTOS_PSK 505
# define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464
# define SSL_F_TLS_PARSE_CTOS_USE_SRTP 465
# define SSL_F_TLS_PARSE_STOC_KEY_SHARE 445
@@ -2361,6 +2362,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_PROCESS_SKE_ECDHE 420
# define SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE 421
# define SSL_F_TLS_PROCESS_SKE_SRP 422
+# define SSL_F_TLS_PSK_DO_BINDER 506
# define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT 450
# define SSL_F_TLS_SETUP_HANDSHAKE 508
# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 220
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 88b99cca14..d4145ba5da 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -2018,3 +2018,14 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
return 1;
}
+
+const EVP_MD *ssl_cipher_get_handshake_md(int cipher_id)
+{
+ const SSL_CIPHER *cipher = ssl3_get_cipher_by_id(cipher_id);
+ if (cipher == NULL) {
+ /* Don't recognise this cipher */
+ return NULL;
+ }
+
+ return ssl_md(cipher->algorithm2);
+}
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 9edee93727..4047d0e27d 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -370,6 +370,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT),
"tls_parse_clienthello_tlsext"},
{ERR_FUNC(SSL_F_TLS_PARSE_CTOS_KEY_SHARE), "tls_parse_ctos_key_share"},
+ {ERR_FUNC(SSL_F_TLS_PARSE_CTOS_PSK), "tls_parse_ctos_psk"},
{ERR_FUNC(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE),
"tls_parse_ctos_renegotiate"},
{ERR_FUNC(SSL_F_TLS_PARSE_CTOS_USE_SRTP), "tls_parse_ctos_use_srtp"},
@@ -423,6 +424,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE),
"tls_process_ske_psk_preamble"},
{ERR_FUNC(SSL_F_TLS_PROCESS_SKE_SRP), "tls_process_ske_srp"},
+ {ERR_FUNC(SSL_F_TLS_PSK_DO_BINDER), "tls_psk_do_binder"},
{ERR_FUNC(SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT),
"tls_scan_clienthello_tlsext"},
{ERR_FUNC(SSL_F_TLS_SETUP_HANDSHAKE), "tls_setup_handshake"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index e9bb4455f1..3aeac0cdd3 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1956,6 +1956,7 @@ __owur int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
__owur int ssl_cipher_get_cert_index(const SSL_CIPHER *c);
__owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl,
const unsigned char *ptr);
+__owur const EVP_MD *ssl_cipher_get_handshake_md(int cipher_id);
__owur int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
__owur int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
__owur int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x);
@@ -2193,6 +2194,17 @@ void ssl_set_default_md(SSL *s);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
SSL_SESSION **ret);
+
+/* Return codes for tls_decrypt_ticket */
+#define TICKET_FATAL_ERR_MALLOC -2
+#define TICKET_FATAL_ERR_OTHER -1
+#define TICKET_NO_DECRYPT 2
+#define TICKET_SUCCESS 3
+#define TICKET_SUCCESS_RENEW 4
+__owur int 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);
__owur int tls12_get_sigandhash(SSL *s, WPACKET *pkt, const EVP_PKEY *pk,
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 0d9bd7a528..c42ef1e135 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -39,6 +39,7 @@
#include <openssl/rand.h>
#include <openssl/engine.h>
#include "ssl_locl.h"
+#include "statem/statem_locl.h"
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
@@ -444,8 +445,9 @@ int ssl_get_new_session(SSL *s, int session)
* hello: The parsed ClientHello data
*
* Returns:
- * -1: error
- * 0: a session may have been found.
+ * -1: fatal error
+ * 0: no session found
+ * 1: a session may have been found.
*
* Side effects:
* - If a session is found then s->session is pointed at it (after freeing an
@@ -459,27 +461,34 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
SSL_SESSION *ret = NULL;
int fatal = 0;
- int try_session_cache = 1;
+ int try_session_cache = 0;
int r;
- if (hello->session_id_len == 0)
- try_session_cache = 0;
+ if (SSL_IS_TLS13(s)) {
+ int al;
- /* sets s->ext.ticket_expected */
- r = tls_get_ticket_from_client(s, hello, &ret);
- switch (r) {
- case -1: /* Error during processing */
- fatal = 1;
- goto err;
- case 0: /* No ticket found */
- case 1: /* Zero length ticket found */
- break; /* Ok to carry on processing session id. */
- case 2: /* Ticket found but not decrypted. */
- case 3: /* Ticket decrypted, *ret has been set. */
- try_session_cache = 0;
- break;
- default:
- abort();
+ if (!tls_parse_extension(s, TLSEXT_IDX_psk, EXT_CLIENT_HELLO,
+ hello->pre_proc_exts, NULL, 0, &al))
+ return -1;
+
+ ret = s->session;
+ } else {
+ /* sets s->ext.ticket_expected */
+ r = tls_get_ticket_from_client(s, hello, &ret);
+ switch (r) {
+ case -1: /* Error during processing */
+ fatal = 1;
+ goto err;
+ case 0: /* No ticket found */
+ case 1: /* Zero length ticket found */
+ try_session_cache = 1;
+ break; /* Ok to carry on processing session id. */
+ case 2: /* Ticket found but not decrypted. */
+ case 3: /* Ticket decrypted, *ret has been set. */
+ break;
+ default:
+ abort();
+ }
}
if (try_session_cache &&
@@ -628,11 +637,15 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
goto err;
}
- s->session_ctx->stats.sess_hit++;
+ if (!SSL_IS_TLS13(s)) {
+ /* We already did this for TLS1.3 */
+ SSL_SESSION_free(s->session);
+ s->session = ret;
+ }
- SSL_SESSION_free(s->session);
- s->session = ret;
+ s->session_ctx->stats.sess_hit++;
s->verify_result = s->session->verify_result;
+
return 1;
err:
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index f1a1675d66..95bfe75393 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -279,7 +279,8 @@ static const EXTENSION_DEFINITION ext_defs[] = {
TLSEXT_TYPE_psk,
EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO | EXT_TLS_IMPLEMENTATION_ONLY
| EXT_TLS1_3_ONLY,
- NULL, NULL, tls_parse_stoc_psk, NULL, tls_construct_ctos_psk, NULL
+ NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, NULL,
+ tls_construct_ctos_psk, NULL
}
};
@@ -1002,3 +1003,97 @@ static int init_psk_kex_modes(SSL *s, unsigned int context)
return 1;
}
+
+int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
+ size_t binderoffset, const unsigned char *binderin,
+ unsigned char *binderout,
+ SSL_SESSION *sess, int sign)
+{
+ EVP_PKEY *mackey = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
+ unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
+ const char resumption_label[] = "resumption psk binder key";
+ size_t hashsize = EVP_MD_size(md), bindersize;
+ int ret = -1;
+
+ /* Generate the early_secret */
+ if (!tls13_generate_secret(s, md, NULL, sess->master_key,
+ sess->master_key_length,
+ (unsigned char *)&s->early_secret)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Create the handshake hash for the binder key...the messages so far are
+ * empty!
+ */
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL
+ || EVP_DigestInit_ex(mctx, md, NULL) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Generate the binder key */
+ if (!tls13_hkdf_expand(s, md, s->early_secret,
+ (unsigned char *)resumption_label,
+ sizeof(resumption_label) - 1, hash, binderkey,
+ hashsize)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Generate the finished key */
+ if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Get a hash of the ClientHello up to the start of the binders.
+ * TODO(TLS1.3): This will need to be tweaked when we implement
+ * HelloRetryRequest to include the digest of the previous messages here.
+ */
+ if (EVP_DigestInit_ex(mctx, md, NULL) <= 0
+ || EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ mackey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, finishedkey, hashsize);
+ if (mackey == NULL) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!sign)
+ binderout = tmpbinder;
+
+ bindersize = hashsize;
+ if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
+ || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
+ || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
+ || bindersize != hashsize) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (sign) {
+ ret = 1;
+ } else {
+ /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
+ ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
+ }
+
+ err:
+ OPENSSL_cleanse(binderkey, sizeof(binderkey));
+ OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
+ EVP_PKEY_free(mackey);
+ EVP_MD_CTX_free(mctx);
+
+ return ret;
+}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index eb8cfa3b3d..8c663320e1 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -663,16 +663,10 @@ int tls_construct_ctos_psk(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
int *al)
{
#ifndef OPENSSL_NO_TLS1_3
- const SSL_CIPHER *cipher;
uint32_t now, ages, agems;
- size_t hashsize, bindersize, binderoffset, msglen;
+ size_t hashsize, binderoffset, msglen;
unsigned char *binder = NULL, *msgstart = NULL;
- EVP_PKEY *mackey = NULL;
const EVP_MD *md;
- EVP_MD_CTX *mctx = NULL;
- unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
- unsigned char finishedkey[EVP_MAX_MD_SIZE];
- const char resumption_label[] = "resumption psk binder key";
int ret = 0;
s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
@@ -719,17 +713,12 @@ int tls_construct_ctos_psk(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
*/
agems += s->session->ext.tick_age_add;
- cipher = ssl3_get_cipher_by_id(s->session->cipher_id);
- if (cipher == NULL) {
+ md = ssl_cipher_get_handshake_md(s->session->cipher_id);
+ if (md == NULL) {
/* Don't recognise this cipher so we can't use the session. Ignore it */
return 1;
}
- md = ssl_md(cipher->algorithm2);
- if (md == NULL) {
- /* Shouldn't happen!! */
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- return 0;
- }
+
hashsize = EVP_MD_size(md);
/* Create the extension, but skip over the binder for now */
@@ -757,60 +746,8 @@ int tls_construct_ctos_psk(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
msgstart = WPACKET_get_curr(pkt) - msglen;
- /* Generate the early_secret */
- if (!tls13_generate_secret(s, md, NULL, s->session->master_key,
- s->session->master_key_length,
- (unsigned char *)&s->early_secret)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Create the handshake hash for the binder key...the messages so far are
- * empty!
- */
- mctx = EVP_MD_CTX_new();
- if (mctx == NULL
- || EVP_DigestInit_ex(mctx, md, NULL) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Generate the binder key */
- if (!tls13_hkdf_expand(s, md, s->early_secret,
- (unsigned char *)resumption_label,
- sizeof(resumption_label) - 1, hash, binderkey,
- hashsize)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Generate the finished key */
- if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Get a hash of the ClientHello up to the start of the binders.
- * TODO(TLS1.3): This will need to be tweaked when we implement
- * HelloRetryRequest to include the digest of the previous messages here.
- */
- if (EVP_DigestInit_ex(mctx, md, NULL) <= 0
- || EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- mackey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, finishedkey, hashsize);
- bindersize = hashsize;
- if (binderkey == NULL
- || EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
- || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
- || EVP_DigestSignFinal(mctx, binder, &bindersize) <= 0
- || bindersize != hashsize) {
+ if (tls_psk_do_binder(s, md, msgstart, binderoffset, NULL, binder,
+ s->session, 1) != 1) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -819,11 +756,6 @@ int tls_construct_ctos_psk(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
ret = 1;
err:
- OPENSSL_cleanse(binderkey, sizeof(binderkey));
- OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
- EVP_PKEY_free(mackey);
- EVP_MD_CTX_free(mctx);
-
return ret;
#else
return 1;
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 1e10a10c47..314cd5ad88 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -655,10 +655,9 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, X509 *x,
return 0;
}
- if (!s->hit
- && !PACKET_memdup(&supported_groups_list,
- &s->session->ext.supportedgroups,
- &s->session->ext.supportedgroups_len)) {
+ if (!PACKET_memdup(&supported_groups_list,
+ &s->session->ext.supportedgroups,
+ &s->session->ext.supportedgroups_len)) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -680,6 +679,96 @@ int tls_parse_ctos_ems(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, int *al)
return 1;
}
+int tls_parse_ctos_psk(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, int *al)
+{
+ PACKET identities, binders, binder;
+ size_t binderoffset, hashsize;
+ SSL_SESSION *sess = NULL;
+ unsigned int id, i;
+ const EVP_MD *md = NULL;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ for (id = 0; PACKET_remaining(&identities) != 0; id++) {
+ PACKET identity;
+ unsigned long ticket_age;
+ int ret;
+
+ if (!PACKET_get_length_prefixed_2(&identities, &identity)
+ || !PACKET_get_net_4(&identities, &ticket_age)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ ret = tls_decrypt_ticket(s, PACKET_data(&identity),
+ PACKET_remaining(&identity), NULL, 0, &sess);
+ if (ret == TICKET_FATAL_ERR_MALLOC || ret == TICKET_FATAL_ERR_OTHER) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ if (ret == TICKET_NO_DECRYPT)
+ continue;
+
+ md = ssl_cipher_get_handshake_md(sess->cipher_id);
+ if (md == NULL) {
+ /*
+ * Don't recognise this cipher so we can't use the session.
+ * Ignore it
+ */
+ SSL_SESSION_free(sess);
+ sess = NULL;
+ continue;
+ }
+
+ /*
+ * TODO(TLS1.3): Somehow we need to handle the case of a ticket renewal.
+ * Ignored for now
+ */
+
+ break;
+ }
+
+ if (sess == NULL)
+ return 1;
+
+ binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
+
+ hashsize = EVP_MD_size(md);
+
+ if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
+ *al = SSL_AD_DECODE_ERROR;
+ goto err;
+ }
+
+ for (i = 0; i <= id; i++) {
+ if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
+ *al = SSL_AD_DECODE_ERROR;
+ goto err;
+ }
+ }
+
+ if (PACKET_remaining(&binder) != hashsize
+ || tls_psk_do_binder(s, md,
+ (const unsigned char *)s->init_buf->data,
+ binderoffset, PACKET_data(&binder), NULL,
+ sess, 0) != 1) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ sess->ext.tick_identity = id;
+ SSL_SESSION_free(s->session);
+ s->session = sess;
+
+ return 1;
+err:
+ return 0;
+}
+
/*
* Add the server's renegotiation binding
*/
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 99f67e51ad..8079f30a93 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -166,6 +166,12 @@ __owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
__owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al);
+__owur int tls_psk_do_binder(SSL *s, const EVP_MD *md,
+ const unsigned char *msgstart,
+ size_t binderoffset, const unsigned char *binderin,
+ unsigned char *binderout,
+ SSL_SESSION *sess, int sign);
+
/* Server Extension processing */
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
int *al);
@@ -202,6 +208,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, int *al);
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
int *al);
+int tls_parse_ctos_psk(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, int *al);
int tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, X509 *x,
size_t chainidx, int *al);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index b05d148beb..046b665c07 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -20,10 +20,6 @@
#include "ssl_locl.h"
#include <openssl/ct.h>
-static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, size_t ticklen,
- const unsigned char *sess_id, size_t sesslen,
- SSL_SESSION **psess);
-
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
tls1_mac,
@@ -1097,14 +1093,14 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
retv = tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size,
hello->session_id, hello->session_id_len, ret);
switch (retv) {
- case 2: /* ticket couldn't be decrypted */
+ case TICKET_NO_DECRYPT: /* ticket couldn't be decrypted */
s->ext.ticket_expected = 1;
return 2;
- case 3: /* ticket was decrypted */
+ case TICKET_SUCCESS: /* ticket was decrypted */
return 3;
- case 4: /* ticket decrypted but need to renew */
+ case TICKET_SUCCESS_RENEW: /* ticket decrypted but need to renew */
s->ext.ticket_expected = 1;
return 3;
@@ -1124,20 +1120,27 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
* point to the resulting session.
*
* Returns:
- * -2: fatal error, malloc failure.
- * -1: fatal error, either from parsing or decrypting the ticket.
- * 2: the ticket couldn't be decrypted.
- * 3: a ticket was successfully decrypted and *psess was set.
- * 4: same as 3, but the ticket needs to be renewed.
+ * TICKET_FATAL_ERR_MALLOC: fatal error, malloc failure.
+ * TICKET_FATAL_ERR_OTHER: fatal error, either from parsing or decrypting the
+ * ticket.
+ * TICKET_NO_DECRYPT: the ticket couldn't be decrypted.
+ * TICKET_SUCCESS: a ticket was successfully decrypted and *psess was
+ * set.
+ * TICKET_SUCCESS_RENEW: same as 3, but the ticket needs to be renewed
*/
-static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
- size_t eticklen, const unsigned char *sess_id,
- size_t sesslen, SSL_SESSION **psess)
+#define TICKET_FATAL_ERR_MALLOC -2
+#define TICKET_FATAL_ERR_OTHER -1
+#define TICKET_NO_DECRYPT 2
+#define TICKET_SUCCESS 3
+#define TICKET_SUCCESS_RENEW 4
+int 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, ret = -1, declen;
+ int slen, renew_ticket = 0, ret = TICKET_FATAL_ERR_OTHER, declen;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
HMAC_CTX *hctx = NULL;
@@ -1147,10 +1150,10 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
/* Initialize session ticket encryption and HMAC contexts */
hctx = HMAC_CTX_new();
if (hctx == NULL)
- return -2;
+ return TICKET_FATAL_ERR_MALLOC;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
- ret = -2;
+ ret = TICKET_FATAL_ERR_MALLOC;
goto err;
}
if (tctx->ext.ticket_key_cb) {
@@ -1160,7 +1163,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
if (rv < 0)
goto err;
if (rv == 0) {
- ret = 2;
+ ret = TICKET_NO_DECRYPT;
goto err;
}
if (rv == 2)
@@ -1169,7 +1172,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
/* Check key name matches */
if (memcmp(etick, tctx->ext.tick_key_name,
sizeof(tctx->ext.tick_key_name)) != 0) {
- ret = 2;
+ ret = TICKET_NO_DECRYPT;
goto err;
}
if (HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key,
@@ -1177,8 +1180,8 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
EVP_sha256(), NULL) <= 0
|| EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
tctx->ext.tick_aes_key,
- etick + sizeof(tctx->ext.tick_key_name)) <=
- 0) {
+ etick
+ + sizeof(tctx->ext.tick_key_name)) <= 0) {
goto err;
}
}
@@ -1193,7 +1196,7 @@ static int 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 = 2;
+ ret = TICKET_NO_DECRYPT;
goto err;
}
eticklen -= mlen;
@@ -1205,7 +1208,7 @@ static int 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 2;
+ return TICKET_NO_DECRYPT;
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
@@ -1216,12 +1219,12 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
(int)eticklen) <= 0) {
EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(sdec);
- return -1;
+ return TICKET_FATAL_ERR_OTHER;
}
if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) {
EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(sdec);
- return 2;
+ return TICKET_NO_DECRYPT;
}
slen += declen;
EVP_CIPHER_CTX_free(ctx);
@@ -1242,15 +1245,15 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
sess->session_id_length = sesslen;
*psess = sess;
if (renew_ticket)
- return 4;
+ return TICKET_SUCCESS_RENEW;
else
- return 3;
+ return TICKET_SUCCESS;
}
ERR_clear_error();
/*
* For session parse failure, indicate that we need to send a new ticket.
*/
- return 2;
+ return TICKET_NO_DECRYPT;
err:
EVP_CIPHER_CTX_free(ctx);
HMAC_CTX_free(hctx);