aboutsummaryrefslogtreecommitdiffstats
path: root/ssl/statem
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/statem')
-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
4 files changed, 202 insertions, 79 deletions
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);