summaryrefslogtreecommitdiffstats
path: root/ssl/statem/extensions_srvr.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2018-03-06 16:41:51 +0000
committerMatt Caswell <matt@openssl.org>2018-03-09 11:22:23 +0000
commitf3d40db1b947f546541b815a0363de3120c16506 (patch)
treedcc421ae5ca2151cada49bacdf143f12ed775455 /ssl/statem/extensions_srvr.c
parente73c6eaeff82615d20845692c5c72ba9dfa895f5 (diff)
Fallback on old style PSK callbacks if the new style ones aren't present
Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5554)
Diffstat (limited to 'ssl/statem/extensions_srvr.c')
-rw-r--r--ssl/statem/extensions_srvr.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index d1be32c2bc..bcabb858be 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -1028,6 +1028,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
for (id = 0; PACKET_remaining(&identities) != 0; id++) {
PACKET identity;
unsigned long ticket_agel;
+ size_t idlen;
if (!PACKET_get_length_prefixed_2(&identities, &identity)
|| !PACKET_get_net_4(&identities, &ticket_agel)) {
@@ -1036,15 +1037,66 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0;
}
+ idlen = PACKET_remaining(&identity);
if (s->psk_find_session_cb != NULL
- && !s->psk_find_session_cb(s, PACKET_data(&identity),
- PACKET_remaining(&identity),
+ && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
&sess)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
return 0;
}
+ if(sess == NULL
+ && s->psk_server_callback != NULL
+ && idlen <= PSK_MAX_IDENTITY_LEN) {
+ char *pskid = NULL;
+ unsigned char pskdata[PSK_MAX_PSK_LEN];
+ unsigned int pskdatalen;
+
+ if (!PACKET_strndup(&identity, &pskid)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ pskdatalen = s->psk_server_callback(s, pskid, pskdata,
+ sizeof(pskdata));
+ OPENSSL_free(pskid);
+ if (pskdatalen > PSK_MAX_PSK_LEN) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (pskdatalen > 0) {
+ const SSL_CIPHER *cipher;
+ const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
+
+ /*
+ * We found a PSK using an old style callback. We don't know
+ * the digest so we default to SHA256 as per the TLSv1.3 spec
+ */
+ cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
+ if (cipher == NULL) {
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ sess = SSL_SESSION_new();
+ if (sess == NULL
+ || !SSL_SESSION_set1_master_key(sess, pskdata,
+ pskdatalen)
+ || !SSL_SESSION_set_cipher(sess, cipher)
+ || !SSL_SESSION_set_protocol_version(sess,
+ TLS1_3_VERSION)) {
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ }
+ }
+
if (sess != NULL) {
/* We found a PSK */
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);