crypto: Add support for Poly1305 from LibreSSL

Signed-off-by: Shreyas Mahajan <shreyasmahajan05@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
Shreyas Mahajan
2026-01-21 17:45:08 +05:30
committed by Jakub Jelen
parent 6c5459e7fc
commit a1e49728ba

View File

@@ -40,7 +40,9 @@
#endif #endif
#ifdef HAVE_LIBCRYPTO #ifdef HAVE_LIBCRYPTO
#ifdef LIBRESSL_VERSION_NUMBER
#include <openssl/poly1305.h>
#endif
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/md5.h> #include <openssl/md5.h>
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
@@ -738,7 +740,10 @@ struct chacha20_poly1305_keysched {
EVP_CIPHER_CTX *main_evp; EVP_CIPHER_CTX *main_evp;
/* cipher handle used for encrypting the length field */ /* cipher handle used for encrypting the length field */
EVP_CIPHER_CTX *header_evp; EVP_CIPHER_CTX *header_evp;
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if defined(LIBRESSL_VERSION_NUMBER)
/* LibreSSL Poly1305 context */
poly1305_context poly_ctx;
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
/* mac handle used for authenticating the packets */ /* mac handle used for authenticating the packets */
EVP_PKEY_CTX *pctx; EVP_PKEY_CTX *pctx;
/* Poly1305 key */ /* Poly1305 key */
@@ -765,7 +770,9 @@ static void chacha20_poly1305_cleanup(struct ssh_cipher_struct *cipher)
ctx->main_evp = NULL; ctx->main_evp = NULL;
EVP_CIPHER_CTX_free(ctx->header_evp); EVP_CIPHER_CTX_free(ctx->header_evp);
ctx->header_evp = NULL; ctx->header_evp = NULL;
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if defined(LIBRESSL_VERSION_NUMBER)
/* nothing to free */
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
/* ctx->pctx is freed as part of MD context */ /* ctx->pctx is freed as part of MD context */
EVP_PKEY_free(ctx->key); EVP_PKEY_free(ctx->key);
ctx->key = NULL; ctx->key = NULL;
@@ -828,7 +835,9 @@ static int chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
/* The Poly1305 key initialization is delayed to the time we know /* The Poly1305 key initialization is delayed to the time we know
* the actual key for packet so we do not need to create a bogus keys * the actual key for packet so we do not need to create a bogus keys
*/ */
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if defined(LIBRESSL_VERSION_NUMBER)
/* nothing, poly1305_context is stack based */
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
ctx->mctx = EVP_MD_CTX_new(); ctx->mctx = EVP_MD_CTX_new();
if (ctx->mctx == NULL) { if (ctx->mctx == NULL) {
SSH_LOG(SSH_LOG_TRACE, "EVP_MD_CTX_new failed"); SSH_LOG(SSH_LOG_TRACE, "EVP_MD_CTX_new failed");
@@ -920,8 +929,11 @@ static int chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
ssh_log_hexdump("poly_key", poly_key, POLY1305_KEYLEN); ssh_log_hexdump("poly_key", poly_key, POLY1305_KEYLEN);
#endif /* DEBUG_CRYPTO */ #endif /* DEBUG_CRYPTO */
/* LibreSSL path: use direct Poly1305 implementation */
#if defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_poly1305_init(&ctx->poly_ctx, poly_key);
/* Set the Poly1305 key */ /* Set the Poly1305 key */
#if OPENSSL_VERSION_NUMBER < 0x30000000L #elif OPENSSL_VERSION_NUMBER < 0x30000000L
if (ctx->key == NULL) { if (ctx->key == NULL) {
/* Poly1305 Initialization needs to know the actual key */ /* Poly1305 Initialization needs to know the actual key */
ctx->key = EVP_PKEY_new_mac_key(EVP_PKEY_POLY1305, ctx->key = EVP_PKEY_new_mac_key(EVP_PKEY_POLY1305,
@@ -1019,7 +1031,9 @@ static int chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
uint8_t tag[POLY1305_TAGLEN] = {0}; uint8_t tag[POLY1305_TAGLEN] = {0};
int ret = SSH_ERROR; int ret = SSH_ERROR;
int rv, cmp, len = 0; int rv, cmp, len = 0;
#if !defined(LIBRESSL_VERSION_NUMBER)
size_t taglen = POLY1305_TAGLEN; size_t taglen = POLY1305_TAGLEN;
#endif
/* Prepare the Poly1305 key */ /* Prepare the Poly1305 key */
rv = chacha20_poly1305_packet_setup(cipher, seq, 0); rv = chacha20_poly1305_packet_setup(cipher, seq, 0);
@@ -1033,7 +1047,13 @@ static int chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
#endif /* DEBUG_CRYPTO */ #endif /* DEBUG_CRYPTO */
/* Calculate MAC of received data */ /* Calculate MAC of received data */
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_poly1305_update(&ctx->poly_ctx,
complete_packet,
encrypted_size + sizeof(uint32_t));
CRYPTO_poly1305_finish(&ctx->poly_ctx, tag);
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
rv = EVP_DigestSignUpdate(ctx->mctx, complete_packet, rv = EVP_DigestSignUpdate(ctx->mctx, complete_packet,
encrypted_size + sizeof(uint32_t)); encrypted_size + sizeof(uint32_t));
if (rv != 1) { if (rv != 1) {
@@ -1105,7 +1125,9 @@ static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
{ {
struct ssh_packet_header *in_packet = in, *out_packet = out; struct ssh_packet_header *in_packet = in, *out_packet = out;
struct chacha20_poly1305_keysched *ctx = cipher->chacha20_schedule; struct chacha20_poly1305_keysched *ctx = cipher->chacha20_schedule;
#if !defined(LIBRESSL_VERSION_NUMBER)
size_t taglen = POLY1305_TAGLEN; size_t taglen = POLY1305_TAGLEN;
#endif
int ret, outlen = 0; int ret, outlen = 0;
/* Prepare the Poly1305 key */ /* Prepare the Poly1305 key */
@@ -1154,7 +1176,13 @@ static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
} }
/* step 4, compute the MAC */ /* step 4, compute the MAC */
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_poly1305_update(&ctx->poly_ctx,
(const unsigned char *)out_packet,
len);
CRYPTO_poly1305_finish(&ctx->poly_ctx, tag);
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
ret = EVP_DigestSignUpdate(ctx->mctx, out_packet, len); ret = EVP_DigestSignUpdate(ctx->mctx, out_packet, len);
if (ret <= 0) { if (ret <= 0) {
SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignUpdate failed"); SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignUpdate failed");