public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/yubihsm-shell] epel10: Use low-level AES operations to prevent session leak (#2487009)
@ 2026-06-23 13:26 Jakub Jelen
  0 siblings, 0 replies; only message in thread
From: Jakub Jelen @ 2026-06-23 13:26 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/yubihsm-shell
Branch : epel10
Commit : c5bcf991845084d774d391c717423ee7857acbcf
Author : Jakub Jelen <jjelen@redhat.com>
Date   : 2026-06-23T15:25:54+02:00
Stats  : +231/-2 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/yubihsm-shell/c/c5bcf991845084d774d391c717423ee7857acbcf?branch=epel10

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 9bf2362..f88c681 100644
--- a/yubihsm-shell.spec
+++ b/yubihsm-shell.spec
@@ -13,6 +13,8 @@ Source1:	https://developers.yubico.com/%{name}/Releases/%{name}-%{version}.tar.g
 Source2:	gpgkey-9588EA0F.gpg
 # https://github.com/Yubico/yubihsm-shell/pull/411
 Patch2:	yubihsm-shell-2.5.0-pcsc-lite.patch
+# https://github.com/Yubico/yubihsm-shell/pull/528
+Patch3:	yubihsm-shell-2.7.0-session-leak.patch
 
 BuildRequires:	cmake
 BuildRequires:	cppcheck
@@ -45,8 +47,7 @@ Development libraries for working with yubihsm 2.
 
 %prep
 gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0}
-%setup -q
-%patch 2 -p1
+%autosetup -p1
 
 
 %build

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-06-23 13:26 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:26 [rpms/yubihsm-shell] epel10: 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