mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-21 21:26:58 +00:00
MEDIUM: quic: implement CHACHA20_POLY1305 for AWS-LC
With AWS-LC, the aead part is covered by the EVP_AEAD API which provides the correct EVP_aead_chacha20_poly1305(), however for header protection it does not provides an EVP_CIPHER for chacha20. This patch implements exceptions in the header protection code and use EVP_CIPHER_CHACHA20 and EVP_CIPHER_CTX_CHACHA20 placeholders so we can use the CRYPTO_chacha_20() primitive manually instead of the EVP_CIPHER API. This requires to check if we are using EVP_CIPHER_CTX_CHACHA20 when doing EVP_CIPHER_CTX_free().
This commit is contained in:
parent
177c84808c
commit
28cb01f8e8
@ -17,6 +17,9 @@
|
||||
#error "Must define USE_OPENSSL"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENSSL_AWSLC)
|
||||
#include <openssl/chacha.h>
|
||||
#endif
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <import/ebtree.h>
|
||||
@ -38,6 +41,9 @@
|
||||
# define QUIC_AEAD_key_length EVP_AEAD_key_length
|
||||
# define QUIC_AEAD_iv_length EVP_AEAD_nonce_length
|
||||
|
||||
# define EVP_CIPHER_CTX_CHACHA20 ((EVP_CIPHER_CTX *)EVP_aead_chacha20_poly1305())
|
||||
# define EVP_CIPHER_CHACHA20 ((EVP_CIPHER*)EVP_aead_chacha20_poly1305())
|
||||
|
||||
#else
|
||||
|
||||
# define QUIC_AEAD EVP_CIPHER
|
||||
|
@ -150,7 +150,7 @@ static inline const QUIC_AEAD *tls_aead(const SSL_CIPHER *cipher)
|
||||
return EVP_aes_256_gcm();
|
||||
#endif
|
||||
|
||||
#if !defined(OPENSSL_IS_AWSLC) && (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x4000000fL)
|
||||
#if (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x4000000fL)
|
||||
/* WT: LibreSSL has an issue with CHACHA20 running in-place till 3.9.2
|
||||
* included, but the fix is already identified and will be merged
|
||||
* into next major version. Given that on machines without AES-NI
|
||||
@ -160,7 +160,11 @@ static inline const QUIC_AEAD *tls_aead(const SSL_CIPHER *cipher)
|
||||
* Thanks to Theo Buehler for his help!
|
||||
*/
|
||||
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
|
||||
# ifdef QUIC_AEAD_API
|
||||
return EVP_aead_chacha20_poly1305();
|
||||
# else
|
||||
return EVP_chacha20_poly1305();
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(USE_OPENSSL_WOLFSSL) && !defined(OPENSSL_IS_AWSLC)
|
||||
case TLS1_3_CK_AES_128_CCM_SHA256:
|
||||
@ -188,8 +192,10 @@ static inline const EVP_MD *tls_md(const SSL_CIPHER *cipher)
|
||||
static inline const EVP_CIPHER *tls_hp(const SSL_CIPHER *cipher)
|
||||
{
|
||||
switch (SSL_CIPHER_get_id(cipher)) {
|
||||
#if !defined(OPENSSL_IS_AWSLC)
|
||||
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
|
||||
#ifdef QUIC_AEAD_API
|
||||
return EVP_CIPHER_CHACHA20;
|
||||
#else
|
||||
return EVP_chacha20();
|
||||
#endif
|
||||
case TLS1_3_CK_AES_128_CCM_SHA256:
|
||||
@ -754,14 +760,24 @@ static inline void quic_tls_ctx_secs_free(struct quic_tls_ctx *ctx)
|
||||
}
|
||||
|
||||
/* RX HP protection */
|
||||
#ifdef QUIC_AEAD_API
|
||||
if (ctx->rx.hp_ctx != EVP_CIPHER_CTX_CHACHA20)
|
||||
EVP_CIPHER_CTX_free(ctx->rx.hp_ctx);
|
||||
#else
|
||||
EVP_CIPHER_CTX_free(ctx->rx.hp_ctx);
|
||||
#endif
|
||||
/* RX AEAD decryption */
|
||||
QUIC_AEAD_CTX_free(ctx->rx.ctx);
|
||||
pool_free(pool_head_quic_tls_iv, ctx->rx.iv);
|
||||
pool_free(pool_head_quic_tls_key, ctx->rx.key);
|
||||
|
||||
/* TX HP protection */
|
||||
#ifdef QUIC_AEAD_API
|
||||
if (ctx->tx.hp_ctx != EVP_CIPHER_CTX_CHACHA20)
|
||||
EVP_CIPHER_CTX_free(ctx->tx.hp_ctx);
|
||||
#else
|
||||
EVP_CIPHER_CTX_free(ctx->tx.hp_ctx);
|
||||
#endif
|
||||
/* TX AEAD encryption */
|
||||
QUIC_AEAD_CTX_free(ctx->tx.ctx);
|
||||
pool_free(pool_head_quic_tls_iv, ctx->tx.iv);
|
||||
|
@ -454,7 +454,16 @@ int quic_tls_derive_keys(const QUIC_AEAD *aead, const EVP_CIPHER *hp,
|
||||
{
|
||||
size_t aead_keylen = (size_t)QUIC_AEAD_key_length(aead);
|
||||
size_t aead_ivlen = (size_t)QUIC_AEAD_iv_length(aead);
|
||||
#ifdef QUIC_AEAD_API
|
||||
size_t hp_len = 0;
|
||||
|
||||
if (hp == EVP_CIPHER_CHACHA20)
|
||||
hp_len = 32;
|
||||
else if (hp)
|
||||
hp_len = (size_t)EVP_CIPHER_key_length(hp);
|
||||
#else
|
||||
size_t hp_len = hp ? (size_t)EVP_CIPHER_key_length(hp) : 0;
|
||||
#endif
|
||||
|
||||
if (aead_keylen > keylen || aead_ivlen > ivlen || hp_len > hp_keylen)
|
||||
return 0;
|
||||
@ -599,6 +608,14 @@ int quic_tls_enc_hp_ctx_init(EVP_CIPHER_CTX **hp_ctx,
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
#ifdef QUIC_AEAD_API
|
||||
|
||||
if (hp == EVP_CIPHER_CHACHA20) {
|
||||
*hp_ctx = EVP_CIPHER_CTX_CHACHA20;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx)
|
||||
return 0;
|
||||
@ -625,6 +642,25 @@ int quic_tls_hp_encrypt(unsigned char *out,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef QUIC_AEAD_API
|
||||
|
||||
if (ctx == EVP_CIPHER_CTX_CHACHA20) {
|
||||
uint32_t counter;
|
||||
/* According to RFC 9001, 5.4.4. ChaCha20-Based Header Protection:
|
||||
* The first 4 bytes of the sampled ciphertext are the block counter.
|
||||
* The remaining 12 bytes are used as the nonce.
|
||||
*/
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
counter = (uint32_t)in[0] + (uint32_t)(in[1] << 8) + (uint32_t)(in[2] << 16) + (uint32_t)(in[3] << 24);
|
||||
#else
|
||||
memcpy(&counter, in, sizeof(counter));
|
||||
#endif
|
||||
CRYPTO_chacha_20(out, out, inlen, key, in + sizeof(counter), counter);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, in) ||
|
||||
!EVP_EncryptUpdate(ctx, out, &ret, out, inlen) ||
|
||||
!EVP_EncryptFinal_ex(ctx, out, &ret))
|
||||
@ -639,6 +675,14 @@ int quic_tls_dec_hp_ctx_init(EVP_CIPHER_CTX **hp_ctx,
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
#ifdef QUIC_AEAD_API
|
||||
|
||||
if (hp == EVP_CIPHER_CHACHA20) {
|
||||
*hp_ctx = EVP_CIPHER_CTX_CHACHA20;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx)
|
||||
return 0;
|
||||
@ -665,6 +709,25 @@ int quic_tls_hp_decrypt(unsigned char *out,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef QUIC_AEAD_API
|
||||
if (ctx == EVP_CIPHER_CTX_CHACHA20) {
|
||||
uint32_t counter;
|
||||
|
||||
/* According to RFC 9001, 5.4.4. ChaCha20-Based Header Protection:
|
||||
* The first 4 bytes of the sampled ciphertext are the block counter.
|
||||
* The remaining 12 bytes are used as the nonce.
|
||||
*/
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
counter = (uint32_t)in[0] + (uint32_t)(in[1] << 8) + (uint32_t)(in[2] << 16) + (uint32_t)(in[3] << 24);
|
||||
#else
|
||||
memcpy(&counter, in, sizeof(counter));
|
||||
#endif
|
||||
CRYPTO_chacha_20(out, out, inlen, key, in + sizeof(counter), counter);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, in) ||
|
||||
!EVP_DecryptUpdate(ctx, out, &ret, out, inlen) ||
|
||||
!EVP_DecryptFinal_ex(ctx, out, &ret))
|
||||
|
Loading…
Reference in New Issue
Block a user