mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-30 03:34:39 +00:00
Enable the ability to use an external PSK for sending early_data
Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/3926)
This commit is contained in:
parent
177503752b
commit
add8d0e9e0
@ -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)
|
|||||||
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)
|
|||||||
|
|
||||||
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) {
|
||||||
|
if (s->session != NULL && s->session->ext.max_early_data > 0)
|
||||||
alg_enc = s->session->cipher->algorithm_enc;
|
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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,
|
|||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
#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,
|
|||||||
* 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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|| !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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user