提交 add8d0e9 编写于 作者: M Matt Caswell

Enable the ability to use an external PSK for sending early_data

Reviewed-by: NBen Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3926)
上级 17750375
...@@ -2600,8 +2600,10 @@ int s_client_main(int argc, char **argv) ...@@ -2600,8 +2600,10 @@ int s_client_main(int argc, char **argv)
} }
if (early_data_file != NULL if (early_data_file != NULL
&& SSL_get0_session(con) != NULL && ((SSL_get0_session(con) != NULL
&& SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0) { && SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0)
|| (psksess != NULL
&& SSL_SESSION_get_max_early_data(psksess) > 0))) {
BIO *edfile = BIO_new_file(early_data_file, "r"); BIO *edfile = BIO_new_file(early_data_file, "r");
size_t readbytes, writtenbytes; size_t readbytes, writtenbytes;
int finish = 0; int finish = 0;
......
...@@ -104,15 +104,24 @@ static int ssl3_record_app_data_waiting(SSL *s) ...@@ -104,15 +104,24 @@ static int ssl3_record_app_data_waiting(SSL *s)
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al) int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al)
{ {
uint32_t max_early_data = s->max_early_data; uint32_t max_early_data = s->max_early_data;
SSL_SESSION *sess = s->session;
/* /*
* If we are a client then we always use the max_early_data from the * If we are a client then we always use the max_early_data from the
* session. Otherwise we go with the lowest out of the max early data set in * session/psksession. Otherwise we go with the lowest out of the max early
* the session and the configured max_early_data. * data set in the session and the configured max_early_data.
*/ */
if (!s->server || (s->hit if (!s->server && sess->ext.max_early_data == 0) {
&& s->session->ext.max_early_data < s->max_early_data)) if (!ossl_assert(s->psksession != NULL
max_early_data = s->session->ext.max_early_data; && s->psksession->ext.max_early_data > 0)) {
SSLerr(SSL_F_EARLY_DATA_COUNT_OK, ERR_R_INTERNAL_ERROR);
return 0;
}
sess = s->psksession;
}
if (!s->server
|| (s->hit && sess->ext.max_early_data < s->max_early_data))
max_early_data = sess->ext.max_early_data;
if (max_early_data == 0) { if (max_early_data == 0) {
if (al != NULL) if (al != NULL)
......
...@@ -58,7 +58,10 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) ...@@ -58,7 +58,10 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
if (s->early_data_state == SSL_EARLY_DATA_WRITING if (s->early_data_state == SSL_EARLY_DATA_WRITING
|| s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
alg_enc = s->session->cipher->algorithm_enc; if (s->session != NULL && s->session->ext.max_early_data > 0)
alg_enc = s->session->cipher->algorithm_enc;
else
alg_enc = s->psksession->cipher->algorithm_enc;
} else { } else {
/* /*
* To get here we must have selected a ciphersuite - otherwise ctx would * To get here we must have selected a ciphersuite - otherwise ctx would
......
...@@ -534,6 +534,9 @@ int SSL_clear(SSL *s) ...@@ -534,6 +534,9 @@ int SSL_clear(SSL *s)
} }
SSL_SESSION_free(s->psksession); SSL_SESSION_free(s->psksession);
s->psksession = NULL; s->psksession = NULL;
OPENSSL_free(s->psksession_id);
s->psksession_id = NULL;
s->psksession_id_len = 0;
s->error = 0; s->error = 0;
s->hit = 0; s->hit = 0;
...@@ -1097,6 +1100,7 @@ void SSL_free(SSL *s) ...@@ -1097,6 +1100,7 @@ void SSL_free(SSL *s)
SSL_SESSION_free(s->session); SSL_SESSION_free(s->session);
} }
SSL_SESSION_free(s->psksession); SSL_SESSION_free(s->psksession);
OPENSSL_free(s->psksession_id);
clear_ciphers(s); clear_ciphers(s);
...@@ -1910,8 +1914,8 @@ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written) ...@@ -1910,8 +1914,8 @@ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
case SSL_EARLY_DATA_NONE: case SSL_EARLY_DATA_NONE:
if (s->server if (s->server
|| !SSL_in_before(s) || !SSL_in_before(s)
|| s->session == NULL || ((s->session == NULL || s->session->ext.max_early_data == 0)
|| s->session->ext.max_early_data == 0) { && (s->psk_use_session_cb == NULL))) {
SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, SSLerr(SSL_F_SSL_WRITE_EARLY_DATA,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0; return 0;
......
...@@ -1119,6 +1119,8 @@ struct ssl_st { ...@@ -1119,6 +1119,8 @@ struct ssl_st {
SSL_SESSION *session; SSL_SESSION *session;
/* TLSv1.3 PSK session */ /* TLSv1.3 PSK session */
SSL_SESSION *psksession; SSL_SESSION *psksession;
unsigned char *psksession_id;
size_t psksession_id_len;
/* Default generate session ID callback. */ /* Default generate session ID callback. */
GEN_SESSION_CB generate_session_id; GEN_SESSION_CB generate_session_id;
/* Used in SSL3 */ /* Used in SSL3 */
......
...@@ -1206,6 +1206,13 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, ...@@ -1206,6 +1206,13 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
const char *label; const char *label;
size_t bindersize, labelsize, hashsize = EVP_MD_size(md); size_t bindersize, labelsize, hashsize = EVP_MD_size(md);
int ret = -1; int ret = -1;
int usepskfored = 0;
if (external
&& s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->session->ext.max_early_data == 0
&& sess->ext.max_early_data > 0)
usepskfored = 1;
if (external) { if (external) {
label = external_label; label = external_label;
...@@ -1236,11 +1243,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, ...@@ -1236,11 +1243,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
/* /*
* Generate the early_secret. On the server side we've selected a PSK to * Generate the early_secret. On the server side we've selected a PSK to
* resume with (internal or external) so we always do this. On the client * resume with (internal or external) so we always do this. On the client
* side we do this for a non-external (i.e. resumption) PSK so that it * side we do this for a non-external (i.e. resumption) PSK or external PSK
* is in place for sending early data. For client side external PSK we * that will be used for early_data so that it is in place for sending early
* data. For client side external PSK not being used for early_data we
* generate it but store it away for later use. * generate it but store it away for later use.
*/ */
if (s->server || !external) if (s->server || !external || usepskfored)
early_secret = (unsigned char *)s->early_secret; early_secret = (unsigned char *)s->early_secret;
else else
early_secret = (unsigned char *)sess->early_secret; early_secret = (unsigned char *)sess->early_secret;
......
...@@ -679,12 +679,41 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, ...@@ -679,12 +679,41 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x, unsigned int context, X509 *x,
size_t chainidx, int *al) size_t chainidx, int *al)
{ {
const unsigned char *id;
size_t idlen;
SSL_SESSION *psksess = NULL;
const EVP_MD *handmd = NULL;
if (s->hello_retry_request)
handmd = ssl_handshake_md(s);
if (s->psk_use_session_cb != NULL
&& !s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
SSL_SESSION_free(s->psksession);
s->psksession = psksess;
if (psksess != NULL) {
OPENSSL_free(s->psksession_id);
s->psksession_id = OPENSSL_memdup(id, idlen);
if (s->psksession_id == NULL) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->psksession_id_len = idlen;
}
if (s->early_data_state != SSL_EARLY_DATA_CONNECTING if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
|| s->session->ext.max_early_data == 0) { || (s->session->ext.max_early_data == 0
&& (psksess == NULL || psksess->ext.max_early_data == 0))) {
s->max_early_data = 0; s->max_early_data = 0;
return EXT_RETURN_NOT_SENT; return EXT_RETURN_NOT_SENT;
} }
s->max_early_data = s->session->ext.max_early_data; s->max_early_data = s->session->ext.max_early_data != 0 ?
s->session->ext.max_early_data
: psksess->ext.max_early_data;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)
...@@ -793,12 +822,10 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -793,12 +822,10 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
{ {
#ifndef OPENSSL_NO_TLS1_3 #ifndef OPENSSL_NO_TLS1_3
uint32_t now, agesec, agems = 0; uint32_t now, agesec, agems = 0;
size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen, idlen = 0; size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
const unsigned char *id = 0;
const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
EXT_RETURN ret = EXT_RETURN_FAIL; EXT_RETURN ret = EXT_RETURN_FAIL;
SSL_SESSION *psksess = NULL;
int dores = 0; int dores = 0;
s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY; s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
...@@ -814,18 +841,12 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -814,18 +841,12 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
* so don't add this extension. * so don't add this extension.
*/ */
if (s->session->ssl_version != TLS1_3_VERSION if (s->session->ssl_version != TLS1_3_VERSION
|| (s->session->ext.ticklen == 0 && s->psk_use_session_cb == NULL)) || (s->session->ext.ticklen == 0 && s->psksession == NULL))
return EXT_RETURN_NOT_SENT; return EXT_RETURN_NOT_SENT;
if (s->hello_retry_request) if (s->hello_retry_request)
handmd = ssl_handshake_md(s); handmd = ssl_handshake_md(s);
if (s->psk_use_session_cb != NULL
&& !s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK);
goto err;
}
if (s->session->ext.ticklen != 0) { if (s->session->ext.ticklen != 0) {
/* Get the digest associated with the ciphersuite in the session */ /* Get the digest associated with the ciphersuite in the session */
if (s->session->cipher == NULL) { if (s->session->cipher == NULL) {
...@@ -890,11 +911,11 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -890,11 +911,11 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
} }
dopsksess: dopsksess:
if (!dores && psksess == NULL) if (!dores && s->psksession == NULL)
return EXT_RETURN_NOT_SENT; return EXT_RETURN_NOT_SENT;
if (psksess != NULL) { if (s->psksession != NULL) {
mdpsk = ssl_md(psksess->cipher->algorithm2); mdpsk = ssl_md(s->psksession->cipher->algorithm2);
if (mdpsk == NULL) { if (mdpsk == NULL) {
/* /*
* Don't recognize this cipher so we can't use the session. * Don't recognize this cipher so we can't use the session.
...@@ -933,8 +954,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -933,8 +954,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
} }
} }
if (psksess != NULL) { if (s->psksession != NULL) {
if (!WPACKET_sub_memcpy_u16(pkt, id, idlen) if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
s->psksession_id_len)
|| !WPACKET_put_bytes_u32(pkt, 0)) { || !WPACKET_put_bytes_u32(pkt, 0)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
goto err; goto err;
...@@ -946,7 +968,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -946,7 +968,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|| !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)
|| (dores || (dores
&& !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder)) && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
|| (psksess != NULL || (s->psksession != NULL
&& !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder)) && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
|| !WPACKET_close(pkt) || !WPACKET_close(pkt)
|| !WPACKET_close(pkt) || !WPACKET_close(pkt)
...@@ -969,24 +991,20 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ...@@ -969,24 +991,20 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
goto err; goto err;
} }
if (psksess != NULL if (s->psksession != NULL
&& tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL, && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
pskbinder, psksess, 1, 1) != 1) { pskbinder, s->psksession, 1, 1) != 1) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
goto err; goto err;
} }
if (dores) if (dores)
s->session->ext.tick_identity = 0; s->session->ext.tick_identity = 0;
SSL_SESSION_free(s->psksession); if (s->psksession != NULL)
s->psksession = psksess;
if (psksess != NULL)
s->psksession->ext.tick_identity = (dores ? 1 : 0); s->psksession->ext.tick_identity = (dores ? 1 : 0);
psksess = NULL;
ret = EXT_RETURN_SENT; ret = EXT_RETURN_SENT;
err: err:
SSL_SESSION_free(psksess);
return ret; return ret;
#else #else
return 1; return 1;
...@@ -1606,10 +1624,20 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, ...@@ -1606,10 +1624,20 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0; return 0;
} }
/*
* If we used the external PSK for sending early_data then s->early_secret
* is already set up, so don't overwrite it. Otherwise we copy the
* early_secret across that we generated earlier.
*/
if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
|| s->session->ext.max_early_data > 0
|| s->psksession->ext.max_early_data == 0)
memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE);
SSL_SESSION_free(s->session); SSL_SESSION_free(s->session);
s->session = s->psksession; s->session = s->psksession;
s->psksession = NULL; s->psksession = NULL;
memcpy(s->early_secret, s->session->early_secret, EVP_MAX_MD_SIZE);
s->hit = 1; s->hit = 1;
#endif #endif
......
...@@ -745,6 +745,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, ...@@ -745,6 +745,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length); memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length; sess->sid_ctx_length = s->sid_ctx_length;
ext = 1; ext = 1;
s->ext.early_data_ok = 1;
} else { } else {
uint32_t ticket_age = 0, now, agesec, agems; uint32_t ticket_age = 0, now, agesec, agems;
int ret = tls_decrypt_ticket(s, PACKET_data(&identity), int ret = tls_decrypt_ticket(s, PACKET_data(&identity),
......
...@@ -404,6 +404,9 @@ int tls13_change_cipher_state(SSL *s, int which) ...@@ -404,6 +404,9 @@ int tls13_change_cipher_state(SSL *s, int which)
SSL_R_BAD_HANDSHAKE_LENGTH); SSL_R_BAD_HANDSHAKE_LENGTH);
goto err; goto err;
} }
if (sslcipher == NULL && s->psksession != NULL)
sslcipher = SSL_SESSION_get0_cipher(s->psksession);
if (sslcipher == NULL) { if (sslcipher == NULL) {
SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
goto err; goto err;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册