Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
[WIP] deps: update openssl QUIC apis
Browse files Browse the repository at this point in the history
This is a partial fix that replaces the Key Callback with the
Set Encryption Secrets callback modeled after the BoringSSL
APIs that are being worked on for OpenSSL3.
  • Loading branch information
jasnell committed Oct 3, 2019
1 parent dece94e commit 0cf6f83
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 92 deletions.
37 changes: 24 additions & 13 deletions deps/openssl/openssl/include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,19 +639,30 @@ void SSL_set_msg_callback(SSL *ssl,
# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))

typedef enum {
SSL_KEY_CLIENT_EARLY_TRAFFIC,
SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC,
SSL_KEY_CLIENT_APPLICATION_TRAFFIC,
SSL_KEY_SERVER_HANDSHAKE_TRAFFIC,
SSL_KEY_SERVER_APPLICATION_TRAFFIC
} OSSL_KEY_TYPE;

void SSL_set_key_callback(SSL *ssl,
int (*cb)(SSL *ssl, int name,
const unsigned char *secret,
size_t secretlen, void *arg),
void *arg);
/*
* ssl_encryption_level_t represents a specific QUIC encryption level used to
* transmit handshake messages.
*/
typedef enum ssl_encryption_level_t {
ssl_encryption_initial = 0,
ssl_encryption_early_data,
ssl_encryption_handshake,
ssl_encryption_application
} OSSL_ENCRYPTION_LEVEL;

/*
* Adaptation of the set_encryption_secrets approach defined in
* https://github.com/openssl/openssl/pull/8797
*/
void SSL_set_encryption_secrets_callback(SSL *ssl,
int (*cb)(SSL* ssl,
/* OSSL_ENCRYPTION_LEVEL */
int level,
const uint8_t *read_secret,
const uint8_t *write_secret,
size_t secret_len,
void* arg),
void *arg);

# define SSL_get_extms_support(s) \
SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)
Expand Down
2 changes: 2 additions & 0 deletions deps/openssl/openssl/include/openssl/sslerr.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ int ERR_load_SSL_strings(void);
# define SSL_F_PITEM_NEW 624
# define SSL_F_PQUEUE_NEW 625
# define SSL_F_PROCESS_KEY_SHARE_EXT 439
# define SSL_F_QUIC_CHANGE_CIPHER_STATE 0
# define SSL_F_QUIC_SET_ENCRYPTION_SECRETS 0
# define SSL_F_READ_STATE_MACHINE 352
# define SSL_F_SET_CLIENT_CIPHERSUITE 540
# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 595
Expand Down
20 changes: 12 additions & 8 deletions deps/openssl/openssl/ssl/ssl_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -4333,14 +4333,18 @@ void SSL_set_msg_callback(SSL *ssl,
SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
}

void SSL_set_key_callback(SSL *ssl,
int (*cb)(SSL *ssl, int name,
const unsigned char *secret,
size_t secretlen, void *arg),
void *arg)
{
ssl->key_callback = cb;
ssl->key_callback_arg = arg;
void SSL_set_encryption_secrets_callback(SSL *ssl,
int (*cb)(SSL* ssl,
/* OSSL_ENCRYPTION_LEVEL */
int level,
const uint8_t *read_secret,
const uint8_t *write_secret,
size_t secret_len,
void *arg),
void *arg)
{
ssl->encryption_secrets_callback = cb;
ssl->encryption_secrets_callback_arg = arg;
}

void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
Expand Down
12 changes: 9 additions & 3 deletions deps/openssl/openssl/ssl/ssl_locl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1125,9 +1125,12 @@ struct ssl_st {
void (*msg_callback) (int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
void *msg_callback_arg;
int (*key_callback)(SSL *ssl, int name, const unsigned char *secret,
size_t secretlen, void *arg);
void *key_callback_arg;
int (*encryption_secrets_callback)(SSL* ssl, int level,
const uint8_t *read_secret,
const uint8_t *write_secret,
size_t secret_len,
void *arg);
void *encryption_secrets_callback_arg;
int hit; /* reusing a previous session */
X509_VERIFY_PARAM *param;
/* Per connection DANE state */
Expand Down Expand Up @@ -1156,6 +1159,9 @@ struct ssl_st {
unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE];
unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char client_hand_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char server_hand_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char client_early_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char exporter_master_secret[EVP_MAX_MD_SIZE];
unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
Expand Down
269 changes: 202 additions & 67 deletions deps/openssl/openssl/ssl/tls13_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,27 +427,207 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
return 0;
}

int tls13_change_cipher_state(SSL *s, int which)
static int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level)
{
uint8_t *c2s_secret = NULL;
uint8_t *s2c_secret = NULL;
size_t len;
const EVP_MD *md;

if (!(ssl->mode & SSL_MODE_QUIC_HACK))
return 1;

/* secrets from the POV of the client */
switch (level) {
case ssl_encryption_early_data:
c2s_secret = ssl->client_early_traffic_secret;
break;
case ssl_encryption_handshake:
c2s_secret = ssl->client_hand_traffic_secret;
s2c_secret = ssl->server_hand_traffic_secret;
break;
case ssl_encryption_application:
c2s_secret = ssl->client_app_traffic_secret;
s2c_secret = ssl->server_app_traffic_secret;
break;
default:
return 1;
}

md = ssl_handshake_md(ssl);
if (md == NULL) {
/* May not have selected cipher, yet */
const SSL_CIPHER *c = NULL;

if (ssl->session != NULL)
c = SSL_SESSION_get0_cipher(ssl->session);
else if (ssl->psksession != NULL)
c = SSL_SESSION_get0_cipher(ssl->psksession);

if (c != NULL)
md = SSL_CIPHER_get_handshake_digest(c);
}

if ((len = EVP_MD_size(md)) <= 0) {
SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
ERR_R_INTERNAL_ERROR);
return 0;
}

void *arg = ssl->encryption_secrets_callback_arg;
if (ssl->server) {
if (!ssl->encryption_secrets_callback(ssl, level, c2s_secret,
s2c_secret, len, arg)) {
SSLfatal(ssl, SSL_AD_INTERNAL_ERROR,
SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
if (!ssl->encryption_secrets_callback(ssl, level, s2c_secret,
c2s_secret, len, arg)) {
SSLfatal(ssl, SSL_AD_INTERNAL_ERROR,
SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
ERR_R_INTERNAL_ERROR);
return 0;
}
}

return 1;
}

#ifdef CHARSET_EBCDIC
static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
#else
static const unsigned char client_early_traffic[] = "c e traffic";
static const unsigned char client_handshake_traffic[] = "c hs traffic";
static const unsigned char client_application_traffic[] = "c ap traffic";
static const unsigned char server_handshake_traffic[] = "s hs traffic";
static const unsigned char server_application_traffic[] = "s ap traffic";
static const unsigned char exporter_master_secret[] = "exp master";
static const unsigned char resumption_master_secret[] = "res master";
static const unsigned char early_exporter_master_secret[] = "e exp master";
static const unsigned char client_early_traffic[] = "c e traffic";
static const unsigned char client_handshake_traffic[] = "c hs traffic";
static const unsigned char client_application_traffic[] = "c ap traffic";
static const unsigned char server_handshake_traffic[] = "s hs traffic";
static const unsigned char server_application_traffic[] = "s ap traffic";
static const unsigned char exporter_master_secret[] = "exp master";
static const unsigned char resumption_master_secret[] = "res master";
static const unsigned char early_exporter_master_secret[] = "e exp master";
#endif

static int quic_change_cipher_state(SSL *s, int which)
{
unsigned char hash[EVP_MAX_MD_SIZE];
size_t hashlen = 0;
int hashleni;
int ret = 0;
const EVP_MD *md = NULL;
OSSL_ENCRYPTION_LEVEL level = ssl_encryption_initial;
int is_handshake = ((which & SSL3_CC_HANDSHAKE) == SSL3_CC_HANDSHAKE);
int is_client_read = ((which & SSL3_CHANGE_CIPHER_CLIENT_READ) == SSL3_CHANGE_CIPHER_CLIENT_READ);
int is_server_write = ((which & SSL3_CHANGE_CIPHER_SERVER_WRITE) == SSL3_CHANGE_CIPHER_SERVER_WRITE);
int is_early = (which & SSL3_CC_EARLY);

md = ssl_handshake_md(s);
if (!ssl3_digest_cached_records(s, 1)
|| !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
/* SSLfatal() already called */;
goto err;
}

/* Ensure cast to size_t is safe */
hashleni = EVP_MD_size(md);
if (!ossl_assert(hashleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_CHANGE_CIPHER_STATE,
ERR_R_EVP_LIB);
goto err;
}
hashlen = (size_t)hashleni;

if (is_client_read || is_server_write) {
if (is_handshake) {
level = ssl_encryption_handshake;

if (!tls13_hkdf_expand(s, md, s->handshake_secret,
client_handshake_traffic,
sizeof(client_handshake_traffic)-1,
hash, hashlen,
s->client_hand_traffic_secret, hashlen, 1)
|| !ssl_log_secret(s, CLIENT_HANDSHAKE_LABEL,
s->client_hand_traffic_secret, hashlen)
|| !tls13_derive_finishedkey(s, md,
s->client_hand_traffic_secret,
s->client_finished_secret, hashlen)
|| !tls13_hkdf_expand(s, md, s->handshake_secret,
server_handshake_traffic,
sizeof(server_handshake_traffic)-1, hash,
hashlen,
s->server_hand_traffic_secret, hashlen, 1)
|| !ssl_log_secret(s, SERVER_HANDSHAKE_LABEL,
s->server_hand_traffic_secret, hashlen)
|| !tls13_derive_finishedkey(s, md,
s->server_hand_traffic_secret,
s->server_finished_secret,
hashlen)) {
/* SSLfatal() already called */
goto err;
}
} else {
level = ssl_encryption_application;

if (!tls13_hkdf_expand(s, md, s->master_secret,
client_application_traffic,
sizeof(client_application_traffic)-1,
hash, hashlen,
s->client_app_traffic_secret, hashlen, 1)
|| !ssl_log_secret(s, CLIENT_APPLICATION_LABEL,
s->client_app_traffic_secret, hashlen)
|| !tls13_hkdf_expand(s, md, s->master_secret,
server_application_traffic,
sizeof(server_application_traffic)-1,
hash, hashlen,
s->server_app_traffic_secret, hashlen, 1)
|| !ssl_log_secret(s, SERVER_APPLICATION_LABEL,
s->server_app_traffic_secret, hashlen)
|| !tls13_hkdf_expand(s, md, s->master_secret,
resumption_master_secret,
sizeof(resumption_master_secret)-1,
hash, hashlen,
s->resumption_master_secret,
hashlen, 1)) {
/* SSLfatal() already called */
goto err;
}
}
if (!quic_set_encryption_secrets(s, level)) {
/* SSLfatal() already called */
goto err;
}
} else {
if (is_early) {
level = ssl_encryption_early_data;

if (!tls13_hkdf_expand(s, md, s->early_secret, client_early_traffic,
sizeof(client_early_traffic)-1, hash,
hashlen,
s->client_early_traffic_secret, hashlen, 1)
|| !ssl_log_secret(s, CLIENT_EARLY_LABEL,
s->client_early_traffic_secret, hashlen)
|| !quic_set_encryption_secrets(s, level)) {
/* SSLfatal() already called */
goto err;
}
}
}

ret = 1;
err:
return ret;
}

int tls13_change_cipher_state(SSL *s, int which)
{
unsigned char *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
Expand All @@ -463,6 +643,11 @@ int tls13_change_cipher_state(SSL *s, int which)
const EVP_MD *md = NULL;
const EVP_CIPHER *cipher = NULL;

// If QUIC, defer to quic_change_cipher_state
if (s->mode & SSL_MODE_QUIC_HACK) {
return quic_change_cipher_state(s, which);
}

if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
Expand Down Expand Up @@ -671,56 +856,6 @@ int tls13_change_cipher_state(SSL *s, int which)
goto err;
}

if (s->key_callback) {
int type;
if (label == client_early_traffic) {
type = SSL_KEY_CLIENT_EARLY_TRAFFIC;
} else if (label == client_handshake_traffic) {
type = SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC;
} else if (label == client_application_traffic) {
type = SSL_KEY_CLIENT_APPLICATION_TRAFFIC;
} else if (label == server_handshake_traffic) {
type = SSL_KEY_SERVER_HANDSHAKE_TRAFFIC;
} else if (label == server_application_traffic) {
type = SSL_KEY_SERVER_APPLICATION_TRAFFIC;
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!s->key_callback(s, type, secret, hashlen, s->key_callback_arg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}

if (s->server) {
switch (type) {
case SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC:
case SSL_KEY_CLIENT_APPLICATION_TRAFFIC:
if (s->rlayer.rbuf.left) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
break;
}
} else {
switch (type) {
case SSL_KEY_SERVER_HANDSHAKE_TRAFFIC:
case SSL_KEY_SERVER_APPLICATION_TRAFFIC:
if (s->rlayer.rbuf.left) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS13_CHANGE_CIPHER_STATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
break;
}
}
}

if (label == server_application_traffic) {
memcpy(s->server_app_traffic_secret, secret, hashlen);
/* Now we create the exporter master secret */
Expand Down
Loading

0 comments on commit 0cf6f83

Please sign in to comment.