Add TLSv1.3 client side external PSK support
Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3670)
This commit is contained in:
parent
3a7c56b2c0
commit
9368f86526
8 changed files with 172 additions and 60 deletions
|
@ -2137,6 +2137,7 @@ SSL_R_BAD_KEY_UPDATE:122:bad key update
|
||||||
SSL_R_BAD_LENGTH:271:bad length
|
SSL_R_BAD_LENGTH:271:bad length
|
||||||
SSL_R_BAD_PACKET_LENGTH:115:bad packet length
|
SSL_R_BAD_PACKET_LENGTH:115:bad packet length
|
||||||
SSL_R_BAD_PROTOCOL_VERSION_NUMBER:116:bad protocol version number
|
SSL_R_BAD_PROTOCOL_VERSION_NUMBER:116:bad protocol version number
|
||||||
|
SSL_R_BAD_PSK:219:bad psk
|
||||||
SSL_R_BAD_PSK_IDENTITY:114:bad psk identity
|
SSL_R_BAD_PSK_IDENTITY:114:bad psk identity
|
||||||
SSL_R_BAD_RECORD_TYPE:443:bad record type
|
SSL_R_BAD_RECORD_TYPE:443:bad record type
|
||||||
SSL_R_BAD_RSA_ENCRYPT:119:bad rsa encrypt
|
SSL_R_BAD_RSA_ENCRYPT:119:bad rsa encrypt
|
||||||
|
|
|
@ -767,6 +767,10 @@ typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
|
||||||
const unsigned char *identity,
|
const unsigned char *identity,
|
||||||
size_t identity_len,
|
size_t identity_len,
|
||||||
SSL_SESSION **sess);
|
SSL_SESSION **sess);
|
||||||
|
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
|
||||||
|
const unsigned char **id,
|
||||||
|
size_t *idlen,
|
||||||
|
SSL_SESSION **sess);
|
||||||
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
|
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
|
||||||
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);
|
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);
|
||||||
|
|
||||||
|
|
|
@ -381,6 +381,7 @@ int ERR_load_SSL_strings(void);
|
||||||
# define SSL_R_BAD_LENGTH 271
|
# define SSL_R_BAD_LENGTH 271
|
||||||
# define SSL_R_BAD_PACKET_LENGTH 115
|
# define SSL_R_BAD_PACKET_LENGTH 115
|
||||||
# define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116
|
# define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116
|
||||||
|
# define SSL_R_BAD_PSK 219
|
||||||
# define SSL_R_BAD_PSK_IDENTITY 114
|
# define SSL_R_BAD_PSK_IDENTITY 114
|
||||||
# define SSL_R_BAD_RECORD_TYPE 443
|
# define SSL_R_BAD_RECORD_TYPE 443
|
||||||
# define SSL_R_BAD_RSA_ENCRYPT 119
|
# define SSL_R_BAD_RSA_ENCRYPT 119
|
||||||
|
|
|
@ -594,6 +594,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET_LENGTH), "bad packet length"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET_LENGTH), "bad packet length"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PROTOCOL_VERSION_NUMBER),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PROTOCOL_VERSION_NUMBER),
|
||||||
"bad protocol version number"},
|
"bad protocol version number"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK), "bad psk"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK_IDENTITY), "bad psk identity"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK_IDENTITY), "bad psk identity"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RECORD_TYPE), "bad record type"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RECORD_TYPE), "bad record type"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_ENCRYPT), "bad rsa encrypt"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_ENCRYPT), "bad rsa encrypt"},
|
||||||
|
|
|
@ -419,6 +419,8 @@ int SSL_clear(SSL *s)
|
||||||
SSL_SESSION_free(s->session);
|
SSL_SESSION_free(s->session);
|
||||||
s->session = NULL;
|
s->session = NULL;
|
||||||
}
|
}
|
||||||
|
SSL_SESSION_free(s->psksession);
|
||||||
|
s->psksession = NULL;
|
||||||
|
|
||||||
s->error = 0;
|
s->error = 0;
|
||||||
s->hit = 0;
|
s->hit = 0;
|
||||||
|
@ -969,6 +971,7 @@ void SSL_free(SSL *s)
|
||||||
ssl_clear_bad_session(s);
|
ssl_clear_bad_session(s);
|
||||||
SSL_SESSION_free(s->session);
|
SSL_SESSION_free(s->session);
|
||||||
}
|
}
|
||||||
|
SSL_SESSION_free(s->psksession);
|
||||||
|
|
||||||
clear_ciphers(s);
|
clear_ciphers(s);
|
||||||
|
|
||||||
|
|
|
@ -485,6 +485,8 @@ struct ssl_session_st {
|
||||||
* in here? */
|
* in here? */
|
||||||
size_t master_key_length;
|
size_t master_key_length;
|
||||||
|
|
||||||
|
/* TLSv1.3 early_secret used for external PSKs */
|
||||||
|
unsigned char early_secret[EVP_MAX_MD_SIZE];
|
||||||
/*
|
/*
|
||||||
* For <=TLS1.2 this is the master_key. For TLS1.3 this is the resumption
|
* For <=TLS1.2 this is the master_key. For TLS1.3 this is the resumption
|
||||||
* master secret
|
* master secret
|
||||||
|
@ -953,6 +955,7 @@ struct ssl_ctx_st {
|
||||||
SSL_psk_server_cb_func psk_server_callback;
|
SSL_psk_server_cb_func psk_server_callback;
|
||||||
# endif
|
# endif
|
||||||
SSL_psk_find_session_cb_func psk_find_session_cb;
|
SSL_psk_find_session_cb_func psk_find_session_cb;
|
||||||
|
SSL_psk_use_session_cb_func psk_use_session_cb;
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_SRP
|
# ifndef OPENSSL_NO_SRP
|
||||||
SRP_CTX srp_ctx; /* ctx for SRP authentication */
|
SRP_CTX srp_ctx; /* ctx for SRP authentication */
|
||||||
|
@ -1103,6 +1106,8 @@ struct ssl_st {
|
||||||
unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
|
unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
|
||||||
/* This can also be in the session once a session is established */
|
/* This can also be in the session once a session is established */
|
||||||
SSL_SESSION *session;
|
SSL_SESSION *session;
|
||||||
|
/* TLSv1.3 PSK session */
|
||||||
|
SSL_SESSION *psksession;
|
||||||
/* 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 */
|
||||||
|
@ -1124,6 +1129,7 @@ struct ssl_st {
|
||||||
SSL_psk_server_cb_func psk_server_callback;
|
SSL_psk_server_cb_func psk_server_callback;
|
||||||
# endif
|
# endif
|
||||||
SSL_psk_find_session_cb_func psk_find_session_cb;
|
SSL_psk_find_session_cb_func psk_find_session_cb;
|
||||||
|
SSL_psk_use_session_cb_func psk_use_session_cb;
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
/* Verified chain of peer */
|
/* Verified chain of peer */
|
||||||
STACK_OF(X509) *verified_chain;
|
STACK_OF(X509) *verified_chain;
|
||||||
|
|
|
@ -1234,6 +1234,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
|
||||||
EVP_MD_CTX *mctx = NULL;
|
EVP_MD_CTX *mctx = NULL;
|
||||||
unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
|
unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
|
||||||
unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
|
unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned char *early_secret;
|
||||||
const char resumption_label[] = "res binder";
|
const char resumption_label[] = "res binder";
|
||||||
const char external_label[] = "ext binder";
|
const char external_label[] = "ext binder";
|
||||||
const char *label;
|
const char *label;
|
||||||
|
@ -1248,10 +1249,19 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
|
||||||
labelsize = sizeof(resumption_label) - 1;
|
labelsize = sizeof(resumption_label) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the early_secret */
|
/*
|
||||||
|
* 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
|
||||||
|
* side we do this for a non-external (i.e. resumption) PSK so that it
|
||||||
|
* is in place for sending early data. For client side external PSK we
|
||||||
|
* generate it but store it away for later use.
|
||||||
|
*/
|
||||||
|
if (s->server || !external)
|
||||||
|
early_secret = (unsigned char *)s->early_secret;
|
||||||
|
else
|
||||||
|
early_secret = (unsigned char *)sess->early_secret;
|
||||||
if (!tls13_generate_secret(s, md, NULL, sess->master_key,
|
if (!tls13_generate_secret(s, md, NULL, sess->master_key,
|
||||||
sess->master_key_length,
|
sess->master_key_length, early_secret)) {
|
||||||
(unsigned char *)&s->early_secret)) {
|
|
||||||
SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
|
SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1279,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the binder key */
|
/* Generate the binder key */
|
||||||
if (!tls13_hkdf_expand(s, md, s->early_secret, (unsigned char *)label,
|
if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label,
|
||||||
labelsize, hash, binderkey, hashsize)) {
|
labelsize, hash, binderkey, hashsize)) {
|
||||||
SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
|
SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -791,10 +791,13 @@ 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;
|
uint32_t now, agesec, agems;
|
||||||
size_t hashsize, binderoffset, msglen;
|
size_t reshashsize, pskhashsize, binderoffset, msglen, idlen;
|
||||||
unsigned char *binder = NULL, *msgstart = NULL;
|
unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
|
||||||
const EVP_MD *md;
|
const unsigned char *id;
|
||||||
|
const EVP_MD *handmd = NULL, *mdres, *mdpsk;
|
||||||
EXT_RETURN ret = EXT_RETURN_FAIL;
|
EXT_RETURN ret = EXT_RETURN_FAIL;
|
||||||
|
SSL_SESSION *psksess = NULL;
|
||||||
|
int dores = 0;
|
||||||
|
|
||||||
s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
|
s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
|
||||||
|
|
||||||
|
@ -809,76 +812,136 @@ 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->session->ext.ticklen == 0 && s->psk_use_session_cb == NULL))
|
||||||
return EXT_RETURN_NOT_SENT;
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
|
||||||
if (s->session->cipher == NULL) {
|
if (s->hello_retry_request)
|
||||||
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
md = ssl_md(s->session->cipher->algorithm2);
|
if (s->session->ext.ticklen != 0) {
|
||||||
if (md == NULL) {
|
if (s->session->cipher == NULL) {
|
||||||
/* Don't recognize this cipher so we can't use the session. Ignore it */
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||||
return EXT_RETURN_NOT_SENT;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mdres = ssl_md(s->session->cipher->algorithm2);
|
||||||
|
if (mdres == NULL) {
|
||||||
|
/* Don't recognize this cipher so we can't use the session. Ignore it */
|
||||||
|
goto dopsksess;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->hello_retry_request && mdres != handmd) {
|
||||||
|
/*
|
||||||
|
* Selected ciphersuite hash does not match the hash for the session so
|
||||||
|
* we can't use it.
|
||||||
|
*/
|
||||||
|
goto dopsksess;
|
||||||
|
}
|
||||||
|
|
||||||
if (s->hello_retry_request && md != ssl_handshake_md(s)) {
|
|
||||||
/*
|
/*
|
||||||
* Selected ciphersuite hash does not match the hash for the session so
|
* Technically the C standard just says time() returns a time_t and says
|
||||||
* we can't use it.
|
* nothing about the encoding of that type. In practice most implementations
|
||||||
|
* follow POSIX which holds it as an integral type in seconds since epoch.
|
||||||
|
* We've already made the assumption that we can do this in multiple places
|
||||||
|
* in the code, so portability shouldn't be an issue.
|
||||||
*/
|
*/
|
||||||
return EXT_RETURN_NOT_SENT;
|
now = (uint32_t)time(NULL);
|
||||||
}
|
agesec = now - (uint32_t)s->session->time;
|
||||||
|
|
||||||
/*
|
if (s->session->ext.tick_lifetime_hint < agesec) {
|
||||||
* Technically the C standard just says time() returns a time_t and says
|
/* Ticket is too old. Ignore it. */
|
||||||
* nothing about the encoding of that type. In practice most implementations
|
goto dopsksess;
|
||||||
* follow POSIX which holds it as an integral type in seconds since epoch.
|
}
|
||||||
* We've already made the assumption that we can do this in multiple places
|
|
||||||
* in the code, so portability shouldn't be an issue.
|
|
||||||
*/
|
|
||||||
now = (uint32_t)time(NULL);
|
|
||||||
agesec = now - (uint32_t)s->session->time;
|
|
||||||
|
|
||||||
if (s->session->ext.tick_lifetime_hint < agesec) {
|
|
||||||
/* Ticket is too old. Ignore it. */
|
|
||||||
return EXT_RETURN_NOT_SENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate age in ms. We're just doing it to nearest second. Should be
|
|
||||||
* good enough.
|
|
||||||
*/
|
|
||||||
agems = agesec * (uint32_t)1000;
|
|
||||||
|
|
||||||
if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
|
|
||||||
/*
|
/*
|
||||||
* Overflow. Shouldn't happen unless this is a *really* old session. If
|
* Calculate age in ms. We're just doing it to nearest second. Should be
|
||||||
* so we just ignore it.
|
* good enough.
|
||||||
*/
|
*/
|
||||||
return EXT_RETURN_NOT_SENT;
|
agems = agesec * (uint32_t)1000;
|
||||||
|
|
||||||
|
if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
|
||||||
|
/*
|
||||||
|
* Overflow. Shouldn't happen unless this is a *really* old session. If
|
||||||
|
* so we just ignore it.
|
||||||
|
*/
|
||||||
|
goto dopsksess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obfuscate the age. Overflow here is fine, this addition is supposed to
|
||||||
|
* be mod 2^32.
|
||||||
|
*/
|
||||||
|
agems += s->session->ext.tick_age_add;
|
||||||
|
|
||||||
|
reshashsize = EVP_MD_size(mdres);
|
||||||
|
dores = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
dopsksess:
|
||||||
* Obfuscate the age. Overflow here is fine, this addition is supposed to
|
if (!dores && psksess == NULL)
|
||||||
* be mod 2^32.
|
return EXT_RETURN_NOT_SENT;
|
||||||
*/
|
|
||||||
agems += s->session->ext.tick_age_add;
|
|
||||||
|
|
||||||
hashsize = EVP_MD_size(md);
|
if (psksess != NULL) {
|
||||||
|
mdpsk = ssl_md(psksess->cipher->algorithm2);
|
||||||
|
if (mdpsk == NULL) {
|
||||||
|
/*
|
||||||
|
* Don't recognize this cipher so we can't use the session.
|
||||||
|
* If this happens it's an application bug.
|
||||||
|
*/
|
||||||
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->hello_retry_request && mdres != handmd) {
|
||||||
|
/*
|
||||||
|
* Selected ciphersuite hash does not match the hash for the PSK
|
||||||
|
* session. This is an application bug.
|
||||||
|
*/
|
||||||
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pskhashsize = EVP_MD_size(mdpsk);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the extension, but skip over the binder for now */
|
/* Create the extension, but skip over the binder for now */
|
||||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|
||||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||||
|| !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||||
s->session->ext.ticklen)
|
goto err;
|
||||||
|| !WPACKET_put_bytes_u32(pkt, agems)
|
}
|
||||||
|| !WPACKET_close(pkt)
|
|
||||||
|
if (dores) {
|
||||||
|
if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
|
||||||
|
s->session->ext.ticklen)
|
||||||
|
|| !WPACKET_put_bytes_u32(pkt, agems)) {
|
||||||
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psksess != NULL) {
|
||||||
|
if (!WPACKET_sub_memcpy_u16(pkt, id, idlen)
|
||||||
|
|| !WPACKET_put_bytes_u32(pkt, 0)) {
|
||||||
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WPACKET_close(pkt)
|
||||||
|| !WPACKET_get_total_written(pkt, &binderoffset)
|
|| !WPACKET_get_total_written(pkt, &binderoffset)
|
||||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|| !WPACKET_sub_allocate_bytes_u8(pkt, hashsize, &binder)
|
|| (dores
|
||||||
|
&& !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
|
||||||
|
|| (psksess != NULL
|
||||||
|
&& !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
|
||||||
|| !WPACKET_close(pkt)
|
|| !WPACKET_close(pkt)
|
||||||
|| !WPACKET_close(pkt)
|
|| !WPACKET_close(pkt)
|
||||||
|| !WPACKET_get_total_written(pkt, &msglen)
|
|| !WPACKET_get_total_written(pkt, &msglen)
|
||||||
|
@ -893,13 +956,24 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||||
|
|
||||||
msgstart = WPACKET_get_curr(pkt) - msglen;
|
msgstart = WPACKET_get_curr(pkt) - msglen;
|
||||||
|
|
||||||
if (tls_psk_do_binder(s, md, msgstart, binderoffset, NULL, binder,
|
if (dores && tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
|
||||||
s->session, 1, 0) != 1) {
|
resbinder, s->session, 1, 0) != 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->session->ext.tick_identity = 0;
|
if (psksess != NULL && tls_psk_do_binder(s, mdpsk, msgstart,
|
||||||
|
binderoffset, NULL, pskbinder,
|
||||||
|
psksess, 1, 1) != 1) {
|
||||||
|
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dores)
|
||||||
|
s->session->ext.tick_identity = 0;
|
||||||
|
s->psksession = psksess;
|
||||||
|
if (psksess != NULL)
|
||||||
|
s->psksession->ext.tick_identity = (dores ? 1 : 0);
|
||||||
|
|
||||||
ret = EXT_RETURN_SENT;
|
ret = EXT_RETURN_SENT;
|
||||||
err:
|
err:
|
||||||
|
@ -1508,12 +1582,24 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->session->ext.tick_identity != (int)identity) {
|
if (s->session->ext.tick_identity == (int)identity) {
|
||||||
|
s->hit = 1;
|
||||||
|
SSL_SESSION_free(s->psksession);
|
||||||
|
s->psksession = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->psksession == NULL
|
||||||
|
|| s->psksession->ext.tick_identity != (int)identity) {
|
||||||
*al = SSL_AD_ILLEGAL_PARAMETER;
|
*al = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
SSLerr(SSL_F_TLS_PARSE_STOC_PSK, SSL_R_BAD_PSK_IDENTITY);
|
SSLerr(SSL_F_TLS_PARSE_STOC_PSK, SSL_R_BAD_PSK_IDENTITY);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSL_SESSION_free(s->session);
|
||||||
|
s->session = s->psksession;
|
||||||
|
s->psksession = NULL;
|
||||||
|
memcpy(s->early_secret, s->session->early_secret, EVP_MAX_MD_SIZE);
|
||||||
s->hit = 1;
|
s->hit = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue