public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/yubihsm-shell] epel9: Use low-level AES operations to prevent session leak (#2487009)
@ 2026-06-23 13:41 Jakub Jelen
0 siblings, 0 replies; only message in thread
From: Jakub Jelen @ 2026-06-23 13:41 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/yubihsm-shell
Branch : epel9
Commit : a54c3d03735aa8c9bd92067b3a3bef03f77c91f9
Author : Jakub Jelen <jjelen@redhat.com>
Date : 2026-06-23T15:38:34+02:00
Stats : +231/-1 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/yubihsm-shell/c/a54c3d03735aa8c9bd92067b3a3bef03f77c91f9?branch=epel9
Log:
Use low-level AES operations to prevent session leak (#2487009)
---
diff --git a/yubihsm-shell-2.7.0-session-leak.patch b/yubihsm-shell-2.7.0-session-leak.patch
new file mode 100644
index 0000000..77b8355
--- /dev/null
+++ b/yubihsm-shell-2.7.0-session-leak.patch
@@ -0,0 +1,228 @@
+diff --git a/aes_cmac/aes.c b/aes_cmac/aes.c
+index 5b5f45f..696a289 100644
+--- a/aes_cmac/aes.c
++++ b/aes_cmac/aes.c
+@@ -170,77 +170,15 @@ cleanup:
+
+ #else
+
+-static const EVP_CIPHER *aes_ecb(uint16_t key_len) {
+- switch (key_len) {
+- case 16:
+- return EVP_aes_128_ecb();
+- case 24:
+- return EVP_aes_192_ecb();
+- case 32:
+- return EVP_aes_256_ecb();
+- default:
+- return NULL;
+- }
+-}
+-
+-static const EVP_CIPHER *aes_cbc(uint16_t key_len) {
+- switch (key_len) {
+- case 16:
+- return EVP_aes_128_cbc();
+- case 24:
+- return EVP_aes_192_cbc();
+- case 32:
+- return EVP_aes_256_cbc();
+- default:
+- return NULL;
+- }
+-}
+-
+-static int aes_encrypt_ex(const EVP_CIPHER *cipher, const uint8_t *in,
+- uint8_t *out, uint16_t len, const uint8_t *iv,
+- aes_context *ctx) {
+- if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, ctx->key, iv) != 1) {
+- return -1;
+- }
+- if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) {
+- return -2;
+- }
+- int update_len = len;
+- if (EVP_EncryptUpdate(ctx->ctx, out, &update_len, in, len) != 1) {
+- return -3;
+- }
+- int final_len = len - update_len;
+- if (EVP_EncryptFinal_ex(ctx->ctx, out + update_len, &final_len) != 1) {
+- return -4;
+- }
+- if (update_len + final_len != len) {
+- return -5;
+- }
+- return 0;
+-}
+-
+-static int aes_decrypt_ex(const EVP_CIPHER *cipher, const uint8_t *in,
+- uint8_t *out, uint16_t len, const uint8_t *iv,
+- aes_context *ctx) {
+- if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, ctx->key, iv) != 1) {
+- return -1;
+- }
+- if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) {
+- return -2;
+- }
+- int update_len = len;
+- if (EVP_DecryptUpdate(ctx->ctx, out, &update_len, in, len) != 1) {
+- return -3;
+- }
+- int final_len = len - update_len;
+- if (EVP_DecryptFinal_ex(ctx->ctx, out + update_len, &final_len) != 1) {
+- return -4;
+- }
+- if (update_len + final_len != len) {
+- return -5;
+- }
+- return 0;
+-}
++/*
++ * Use the low-level AES API (AES_set_encrypt_key / AES_ecb_encrypt /
++ * AES_cbc_encrypt) instead of the EVP API. The low-level functions
++ * operate directly on an AES_KEY struct with pre-computed round keys
++ * and do not depend on OpenSSL's global library context. This means
++ * they continue to work after OPENSSL_cleanup() has been called,
++ * which is critical for SCP03 session close during application
++ * teardown.
++ */
+
+ #endif
+
+@@ -266,17 +204,15 @@ int aes_set_key(const uint8_t *key, uint16_t key_len, aes_context *ctx) {
+
+ #else
+
+- if (key == NULL || aes_ecb(key_len) == NULL) {
++ if (key == NULL || (key_len != 16 && key_len != 24 && key_len != 32)) {
+ return -1;
+ }
+- if (!ctx->ctx) {
+- ctx->ctx = EVP_CIPHER_CTX_new();
+- if (!ctx->ctx) {
+- return -2;
+- }
++ if (AES_set_encrypt_key(key, key_len * 8, &ctx->enc_key) != 0) {
++ return -2;
++ }
++ if (AES_set_decrypt_key(key, key_len * 8, &ctx->dec_key) != 0) {
++ return -3;
+ }
+- ctx->key_len = key_len;
+- memcpy(ctx->key, key, key_len);
+
+ #endif
+
+@@ -295,23 +231,18 @@ int aes_load_key(const char *key, aes_context *ctx) {
+ const uint8_t default_mac[] = {0x59, 0x2f, 0xd4, 0x83, 0xf7, 0x59,
+ 0xe2, 0x99, 0x09, 0xa0, 0x4c, 0x45,
+ 0x05, 0xd2, 0xce, 0x0a};
+- ctx->key_len = sizeof(default_enc);
+- if (key == NULL || aes_ecb(ctx->key_len) == NULL) {
++ const uint8_t *k;
++
++ if (key == NULL)
+ return -1;
+- }
+- if (!ctx->ctx) {
+- ctx->ctx = EVP_CIPHER_CTX_new();
+- if (!ctx->ctx) {
+- return -2;
+- }
+- }
+ if (!strcmp(key, "default_enc"))
+- memcpy(ctx->key, default_enc, ctx->key_len);
++ k = default_enc;
+ else if (!strcmp(key, "default_mac"))
+- memcpy(ctx->key, default_mac, ctx->key_len);
++ k = default_mac;
+ else
+- memset(ctx->key, 0, ctx->key_len);
+- return 0;
++ return -1;
++
++ return aes_set_key(k, sizeof(default_enc), ctx);
+ #endif
+ }
+
+@@ -334,8 +265,8 @@ int aes_encrypt(const uint8_t *in, uint8_t *out, aes_context *ctx) {
+
+ #else
+
+- return aes_encrypt_ex(aes_ecb(ctx->key_len), in, out, AES_BLOCK_SIZE, NULL,
+- ctx);
++ AES_ecb_encrypt(in, out, &ctx->enc_key, AES_ENCRYPT);
++ return 0;
+
+ #endif
+ }
+@@ -359,8 +290,8 @@ int aes_decrypt(const uint8_t *in, uint8_t *out, aes_context *ctx) {
+
+ #else
+
+- return aes_decrypt_ex(aes_ecb(ctx->key_len), in, out, AES_BLOCK_SIZE, NULL,
+- ctx);
++ AES_ecb_encrypt(in, out, &ctx->dec_key, AES_DECRYPT);
++ return 0;
+
+ #endif
+ }
+@@ -388,7 +319,10 @@ int aes_cbc_encrypt(const uint8_t *in, uint8_t *out, uint16_t len,
+
+ #else
+
+- return aes_encrypt_ex(aes_cbc(ctx->key_len), in, out, len, iv, ctx);
++ uint8_t _iv[AES_BLOCK_SIZE];
++ memcpy(_iv, iv, AES_BLOCK_SIZE);
++ AES_cbc_encrypt(in, out, len, &ctx->enc_key, _iv, AES_ENCRYPT);
++ return 0;
+
+ #endif
+ }
+@@ -416,7 +350,10 @@ int aes_cbc_decrypt(const uint8_t *in, uint8_t *out, uint16_t len,
+
+ #else
+
+- return aes_decrypt_ex(aes_cbc(ctx->key_len), in, out, len, iv, ctx);
++ uint8_t _iv[AES_BLOCK_SIZE];
++ memcpy(_iv, iv, AES_BLOCK_SIZE);
++ AES_cbc_encrypt(in, out, len, &ctx->dec_key, _iv, AES_DECRYPT);
++ return 0;
+
+ #endif
+ }
+@@ -484,7 +421,7 @@ void aes_destroy(aes_context *ctx) {
+
+ #else
+
+- EVP_CIPHER_CTX_free(ctx->ctx);
++ /* AES_KEY has no resources to free, just zero the key material */
+
+ #endif
+
+diff --git a/aes_cmac/aes.h b/aes_cmac/aes.h
+index 798cb15..ba0ef97 100644
+--- a/aes_cmac/aes.h
++++ b/aes_cmac/aes.h
+@@ -30,7 +30,7 @@
+ #include <bcrypt.h>
+ #include <ntstatus.h>
+ #else
+-#include <openssl/evp.h>
++#include <openssl/aes.h>
+ #endif
+
+ #ifndef AES_BLOCK_SIZE // Defined in openssl/aes.h
+@@ -51,9 +51,8 @@ typedef struct {
+ PBYTE pbKeyECBObj;
+ size_t cbKeyObj;
+ #else
+- EVP_CIPHER_CTX *ctx;
+- uint16_t key_len;
+- uint8_t key[32];
++ AES_KEY enc_key;
++ AES_KEY dec_key;
+ #endif
+ } aes_context;
+
+
diff --git a/yubihsm-shell.spec b/yubihsm-shell.spec
index fffc5f9..df96ace 100644
--- a/yubihsm-shell.spec
+++ b/yubihsm-shell.spec
@@ -10,6 +10,8 @@ URL: https://github.com/Yubico/%{name}/
Source0: https://developers.yubico.com/%{name}/Releases/%{name}-%{version}.tar.gz
Source1: https://developers.yubico.com/%{name}/Releases/%{name}-%{version}.tar.gz.sig
Source2: gpgkey-9588EA0F.gpg
+# https://github.com/Yubico/yubihsm-shell/pull/528
+Patch3: yubihsm-shell-2.7.0-session-leak.patch
BuildRequires: cmake
BuildRequires: cppcheck
@@ -46,7 +48,7 @@ Development libraries for working with yubihsm 2.
%prep
gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0}
-%setup -q
+%autosetup -p1
%build
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-23 13:41 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-23 13:41 [rpms/yubihsm-shell] epel9: Use low-level AES operations to prevent session leak (#2487009) Jakub Jelen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox