Skip to content

Commit

Permalink
QUIC: removed key field from ngx_quic_secret_t.
Browse files Browse the repository at this point in the history
It is made local as it is only needed now when creating crypto context.

BoringSSL lacks EVP interface for ChaCha20, providing instead
a function for one-shot encryption, thus hp is still preserved.

Based on a patch by Roman Arutyunyan.
  • Loading branch information
pluknet committed Oct 20, 2023
1 parent 01bd8ca commit b94f1fb
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 29 deletions.
10 changes: 7 additions & 3 deletions src/event/quic/ngx_event_quic_openssl_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ ngx_quic_compat_set_encryption_secret(ngx_connection_t *c,
ngx_int_t key_len;
ngx_str_t secret_str;
ngx_uint_t i;
ngx_quic_md_t key;
ngx_quic_hkdf_t seq[2];
ngx_quic_secret_t *peer_secret;
ngx_quic_ciphers_t ciphers;
Expand All @@ -254,13 +255,14 @@ ngx_quic_compat_set_encryption_secret(ngx_connection_t *c,
peer_secret->secret.len = secret_len;
ngx_memcpy(peer_secret->secret.data, secret, secret_len);

peer_secret->key.len = key_len;
key.len = key_len;

peer_secret->iv.len = NGX_QUIC_IV_LEN;

secret_str.len = secret_len;
secret_str.data = (u_char *) secret;

ngx_quic_hkdf_set(&seq[0], "tls13 key", &peer_secret->key, &secret_str);
ngx_quic_hkdf_set(&seq[0], "tls13 key", &key, &secret_str);
ngx_quic_hkdf_set(&seq[1], "tls13 iv", &peer_secret->iv, &secret_str);

for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
Expand All @@ -284,7 +286,9 @@ ngx_quic_compat_set_encryption_secret(ngx_connection_t *c,
cln->data = peer_secret;
}

if (ngx_quic_crypto_init(ciphers.c, peer_secret, 1, c->log) == NGX_ERROR) {
if (ngx_quic_crypto_init(ciphers.c, peer_secret, &key, 1, c->log)
== NGX_ERROR)
{
return NGX_ERROR;
}

Expand Down
63 changes: 39 additions & 24 deletions src/event/quic/ngx_event_quic_protection.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
ngx_str_t iss;
ngx_uint_t i;
const EVP_MD *digest;
ngx_quic_md_t client_key, server_key;
ngx_quic_hkdf_t seq[8];
ngx_quic_secret_t *client, *server;
ngx_quic_ciphers_t ciphers;
Expand Down Expand Up @@ -160,8 +161,8 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
client->secret.len = SHA256_DIGEST_LENGTH;
server->secret.len = SHA256_DIGEST_LENGTH;

client->key.len = NGX_QUIC_AES_128_KEY_LEN;
server->key.len = NGX_QUIC_AES_128_KEY_LEN;
client_key.len = NGX_QUIC_AES_128_KEY_LEN;
server_key.len = NGX_QUIC_AES_128_KEY_LEN;

client->hp.len = NGX_QUIC_AES_128_KEY_LEN;
server->hp.len = NGX_QUIC_AES_128_KEY_LEN;
Expand All @@ -171,11 +172,11 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,

/* labels per RFC 9001, 5.1. Packet Protection Keys */
ngx_quic_hkdf_set(&seq[0], "tls13 client in", &client->secret, &iss);
ngx_quic_hkdf_set(&seq[1], "tls13 quic key", &client->key, &client->secret);
ngx_quic_hkdf_set(&seq[1], "tls13 quic key", &client_key, &client->secret);
ngx_quic_hkdf_set(&seq[2], "tls13 quic iv", &client->iv, &client->secret);
ngx_quic_hkdf_set(&seq[3], "tls13 quic hp", &client->hp, &client->secret);
ngx_quic_hkdf_set(&seq[4], "tls13 server in", &server->secret, &iss);
ngx_quic_hkdf_set(&seq[5], "tls13 quic key", &server->key, &server->secret);
ngx_quic_hkdf_set(&seq[5], "tls13 quic key", &server_key, &server->secret);
ngx_quic_hkdf_set(&seq[6], "tls13 quic iv", &server->iv, &server->secret);
ngx_quic_hkdf_set(&seq[7], "tls13 quic hp", &server->hp, &server->secret);

Expand All @@ -189,11 +190,15 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
return NGX_ERROR;
}

if (ngx_quic_crypto_init(ciphers.c, client, 0, log) == NGX_ERROR) {
if (ngx_quic_crypto_init(ciphers.c, client, &client_key, 0, log)
== NGX_ERROR)
{
return NGX_ERROR;
}

if (ngx_quic_crypto_init(ciphers.c, server, 1, log) == NGX_ERROR) {
if (ngx_quic_crypto_init(ciphers.c, server, &server_key, 1, log)
== NGX_ERROR)
{
goto failed;
}

Expand Down Expand Up @@ -376,13 +381,13 @@ ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest,

ngx_int_t
ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
ngx_int_t enc, ngx_log_t *log)
ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log)
{

#ifdef OPENSSL_IS_BORINGSSL
EVP_AEAD_CTX *ctx;

ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len,
ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len,
EVP_AEAD_DEFAULT_TAG_LENGTH);
if (ctx == NULL) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_new() failed");
Expand Down Expand Up @@ -423,7 +428,7 @@ ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
return NGX_ERROR;
}

if (EVP_CipherInit_ex(ctx, NULL, NULL, s->key.data, NULL, enc) != 1) {
if (EVP_CipherInit_ex(ctx, NULL, NULL, key->data, NULL, enc) != 1) {
EVP_CIPHER_CTX_free(ctx);
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed");
return NGX_ERROR;
Expand Down Expand Up @@ -652,6 +657,7 @@ ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
ngx_int_t key_len;
ngx_str_t secret_str;
ngx_uint_t i;
ngx_quic_md_t key;
ngx_quic_hkdf_t seq[3];
ngx_quic_secret_t *peer_secret;
ngx_quic_ciphers_t ciphers;
Expand All @@ -677,15 +683,14 @@ ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
peer_secret->secret.len = secret_len;
ngx_memcpy(peer_secret->secret.data, secret, secret_len);

peer_secret->key.len = key_len;
key.len = key_len;
peer_secret->iv.len = NGX_QUIC_IV_LEN;
peer_secret->hp.len = key_len;

secret_str.len = secret_len;
secret_str.data = (u_char *) secret;

ngx_quic_hkdf_set(&seq[0], "tls13 quic key",
&peer_secret->key, &secret_str);
ngx_quic_hkdf_set(&seq[0], "tls13 quic key", &key, &secret_str);
ngx_quic_hkdf_set(&seq[1], "tls13 quic iv", &peer_secret->iv, &secret_str);
ngx_quic_hkdf_set(&seq[2], "tls13 quic hp", &peer_secret->hp, &secret_str);

Expand All @@ -695,7 +700,7 @@ ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
}
}

if (ngx_quic_crypto_init(ciphers.c, peer_secret, is_write, log)
if (ngx_quic_crypto_init(ciphers.c, peer_secret, &key, is_write, log)
== NGX_ERROR)
{
return NGX_ERROR;
Expand Down Expand Up @@ -758,7 +763,9 @@ ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys)
void
ngx_quic_keys_update(ngx_event_t *ev)
{
ngx_int_t key_len;
ngx_uint_t i;
ngx_quic_md_t client_key, server_key;
ngx_quic_hkdf_t seq[6];
ngx_quic_keys_t *keys;
ngx_connection_t *c;
Expand All @@ -777,32 +784,35 @@ ngx_quic_keys_update(ngx_event_t *ev)

c->log->action = "updating keys";

if (ngx_quic_ciphers(keys->cipher, &ciphers) == NGX_ERROR) {
key_len = ngx_quic_ciphers(keys->cipher, &ciphers);

if (key_len == NGX_ERROR) {
goto failed;
}

client_key.len = key_len;
server_key.len = key_len;

next->client.secret.len = current->client.secret.len;
next->client.key.len = current->client.key.len;
next->client.iv.len = NGX_QUIC_IV_LEN;
next->client.hp = current->client.hp;
next->client.hp_ctx = current->client.hp_ctx;

next->server.secret.len = current->server.secret.len;
next->server.key.len = current->server.key.len;
next->server.iv.len = NGX_QUIC_IV_LEN;
next->server.hp = current->server.hp;
next->server.hp_ctx = current->server.hp_ctx;

ngx_quic_hkdf_set(&seq[0], "tls13 quic ku",
&next->client.secret, &current->client.secret);
ngx_quic_hkdf_set(&seq[1], "tls13 quic key",
&next->client.key, &next->client.secret);
&client_key, &next->client.secret);
ngx_quic_hkdf_set(&seq[2], "tls13 quic iv",
&next->client.iv, &next->client.secret);
ngx_quic_hkdf_set(&seq[3], "tls13 quic ku",
&next->server.secret, &current->server.secret);
ngx_quic_hkdf_set(&seq[4], "tls13 quic key",
&next->server.key, &next->server.secret);
&server_key, &next->server.secret);
ngx_quic_hkdf_set(&seq[5], "tls13 quic iv",
&next->server.iv, &next->server.secret);

Expand All @@ -812,12 +822,14 @@ ngx_quic_keys_update(ngx_event_t *ev)
}
}

if (ngx_quic_crypto_init(ciphers.c, &next->client, 0, c->log) == NGX_ERROR)
if (ngx_quic_crypto_init(ciphers.c, &next->client, &client_key, 0, c->log)
== NGX_ERROR)
{
goto failed;
}

if (ngx_quic_crypto_init(ciphers.c, &next->server, 1, c->log) == NGX_ERROR)
if (ngx_quic_crypto_init(ciphers.c, &next->server, &server_key, 1, c->log)
== NGX_ERROR)
{
goto failed;
}
Expand Down Expand Up @@ -901,11 +913,12 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res)
{
u_char *start;
ngx_str_t ad, itag;
ngx_quic_md_t key;
ngx_quic_secret_t secret;
ngx_quic_ciphers_t ciphers;

/* 5.8. Retry Packet Integrity */
static u_char key[16] =
static u_char key_data[16] =
"\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e";
static u_char nonce[NGX_QUIC_IV_LEN] =
"\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb";
Expand All @@ -926,11 +939,13 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res)
return NGX_ERROR;
}

secret.key.len = sizeof(key);
ngx_memcpy(secret.key.data, key, sizeof(key));
key.len = sizeof(key_data);
ngx_memcpy(key.data, key_data, sizeof(key_data));
secret.iv.len = NGX_QUIC_IV_LEN;

if (ngx_quic_crypto_init(ciphers.c, &secret, 1, pkt->log) == NGX_ERROR) {
if (ngx_quic_crypto_init(ciphers.c, &secret, &key, 1, pkt->log)
== NGX_ERROR)
{
return NGX_ERROR;
}

Expand Down
3 changes: 1 addition & 2 deletions src/event/quic/ngx_event_quic_protection.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ typedef struct {

typedef struct {
ngx_quic_md_t secret;
ngx_quic_md_t key;
ngx_quic_iv_t iv;
ngx_quic_md_t hp;
ngx_quic_crypto_ctx_t *ctx;
Expand Down Expand Up @@ -110,7 +109,7 @@ ngx_int_t ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn);
void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn);
ngx_int_t ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers);
ngx_int_t ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher,
ngx_quic_secret_t *s, ngx_int_t enc, ngx_log_t *log);
ngx_quic_secret_t *s, ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log);
ngx_int_t ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out,
u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
void ngx_quic_crypto_cleanup(ngx_quic_secret_t *s);
Expand Down

0 comments on commit b94f1fb

Please sign in to comment.