import CS volume_key-0.3.12-17.el9

This commit is contained in:
AlmaLinux RelEng Bot 2026-03-30 11:12:46 -04:00
parent f5ffc97f19
commit 1249ee7723
2 changed files with 214 additions and 1 deletions

View File

@ -0,0 +1,207 @@
diff --git a/lib/crypto.c b/lib/crypto.c
index 7554f19..7b8dc39 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -179,6 +179,150 @@ import_sym_key (PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin,
}
/* LIBVK_PACKET_FORMAT_ASYMMETRIC */
+/*
+ * FIPS compliant implementation of PK11_ExtractKeyValue() + PK11_GetKeyData().
+ * Instead of directly extracting the key value (which is not allowed in FIPS mode),
+ * we wrap the symmetric key with a temporary wrapping key, then decrypt the
+ * wrapped data to get the raw key bytes.
+ * Returns a newly allocated SECItem with the key data on success, NULL on failure.
+ * The caller must free the result with SECITEM_FreeItem(result, PR_TRUE).
+ */
+static SECItem *
+extract_sym_key (PK11SymKey *sym_key)
+{
+ CK_MECHANISM_TYPE wrap_mechanism = 0UL;
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *wrapping_key = NULL;
+ SECItem tmp_sec_item, wrapped_key_item;
+ PK11Context *wrap_key_crypt_context = NULL;
+ int block_size = 0;
+ size_t wrapped_key_size = 0;
+ unsigned char *wrapped_key = NULL;
+ SECItem *clear_key = NULL;
+ int out_len = 0;
+ unsigned int final_len = 0;
+ SECStatus ret = 0;
+ int key_len = 0;
+
+ /* Fall back to PK11_ExtractKeyValue() + PK11_GetKeyData() if FIPS mode is disabled. */
+ if (PK11_IsFIPS () == PR_FALSE)
+ {
+ SECItem *key_data;
+
+ if (PK11_ExtractKeyValue (sym_key) != SECSuccess)
+ return NULL;
+ key_data = PK11_GetKeyData (sym_key);
+ if (key_data == NULL)
+ return NULL;
+ return SECITEM_DupItem (key_data);
+ }
+
+ slot = PK11_GetSlotFromKey (sym_key);
+ if (slot == NULL)
+ return NULL;
+
+ /* Get the best mechanism for the wrapping operation. */
+ wrap_mechanism = PK11_GetBestWrapMechanism (slot);
+
+ /* Generate a symmetric wrapping key. */
+ wrapping_key = PK11_KeyGen (slot, wrap_mechanism, NULL,
+ PK11_GetBestKeyLength (slot, wrap_mechanism),
+ NULL);
+ PK11_FreeSlot (slot);
+ if (wrapping_key == NULL)
+ return NULL;
+
+ /* Get block size and key length. */
+ block_size = PK11_GetBlockSize (wrap_mechanism, NULL);
+ if (block_size == 0)
+ block_size = 1;
+ key_len = PK11_GetKeyLength (sym_key);
+ if (key_len <= 0)
+ {
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ /* Allocate space for the wrapped key.
+ * Add extra space for padding (up to one block size).
+ */
+ wrapped_key_size = key_len + block_size;
+ wrapped_key = g_try_malloc0 (wrapped_key_size);
+ if (wrapped_key == NULL)
+ {
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ memset (&tmp_sec_item, 0, sizeof (tmp_sec_item));
+ memset (&wrapped_key_item, 0, sizeof (wrapped_key_item));
+ wrapped_key_item.data = wrapped_key;
+ wrapped_key_item.len = wrapped_key_size;
+
+ /* Wrap the symmetric key using the wrapping key. */
+ ret = PK11_WrapSymKey (wrap_mechanism, &tmp_sec_item, wrapping_key, sym_key,
+ &wrapped_key_item);
+ if (ret != SECSuccess)
+ {
+ g_free (wrapped_key);
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ /* Now decrypt the wrapped key to get the raw bytes.
+ * Create a decryption context with the wrapping key.
+ */
+ wrap_key_crypt_context = PK11_CreateContextBySymKey (wrap_mechanism,
+ CKA_DECRYPT,
+ wrapping_key,
+ &tmp_sec_item);
+ if (wrap_key_crypt_context == NULL)
+ {
+ g_free (wrapped_key);
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ /* Allocate space for the decrypted (clear) key. */
+ clear_key = SECITEM_AllocItem (NULL, NULL, wrapped_key_item.len);
+ if (clear_key == NULL)
+ {
+ g_free (wrapped_key);
+ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE);
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ /* Decrypt to get the raw key bytes. */
+ ret = PK11_CipherOp (wrap_key_crypt_context, clear_key->data, &out_len,
+ clear_key->len, wrapped_key_item.data,
+ wrapped_key_item.len);
+ if (ret != SECSuccess)
+ {
+ SECITEM_FreeItem (clear_key, PR_TRUE);
+ g_free (wrapped_key);
+ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE);
+ PK11_FreeSymKey (wrapping_key);
+ return NULL;
+ }
+
+ ret = PK11_DigestFinal (wrap_key_crypt_context, clear_key->data + out_len,
+ &final_len, clear_key->len - out_len);
+ g_free (wrapped_key);
+ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE);
+ PK11_FreeSymKey (wrapping_key);
+ if (ret != SECSuccess)
+ {
+ SECITEM_FreeItem (clear_key, PR_TRUE);
+ return NULL;
+ }
+
+ /* Adjust the length to the actual key length (remove padding). */
+ clear_key->len = key_len;
+
+ return clear_key;
+}
+
/* Encrypt DATA of SIZE for CERT.
Return encrypted data (for g_free()), setting RES_SIZE to the size of the
@@ -532,20 +676,19 @@ unwrap_asymmetric (size_t *clear_secret_size, const void *wrapped_secret_data,
error_from_pr (error);
goto err;
}
- if (PK11_ExtractKeyValue (secret_key) != SECSuccess)
+ clear_secret_item = extract_sym_key (secret_key);
+ PK11_FreeSymKey (secret_key);
+ if (clear_secret_item == NULL)
{
error_from_pr (error);
- goto err_secret_key;
+ goto err;
}
- clear_secret_item = PK11_GetKeyData (secret_key);
ret = g_memdup (clear_secret_item->data, clear_secret_item->len);
*clear_secret_size = clear_secret_item->len;
- PK11_FreeSymKey (secret_key);
+ SECITEM_FreeItem (clear_secret_item, PR_TRUE);
return ret;
- err_secret_key:
- PK11_FreeSymKey (secret_key);
err:
return NULL;
}
@@ -665,20 +808,19 @@ unwrap_symmetric (size_t *clear_secret_size, PK11SymKey *wrapping_key,
error_from_pr (error);
goto err;
}
- if (PK11_ExtractKeyValue (secret_key) != SECSuccess)
+ clear_secret_item = extract_sym_key (secret_key);
+ PK11_FreeSymKey (secret_key);
+ if (clear_secret_item == NULL)
{
error_from_pr (error);
- goto err_secret_key;
+ goto err;
}
- clear_secret_item = PK11_GetKeyData (secret_key);
ret = g_memdup (clear_secret_item->data, clear_secret_item->len);
*clear_secret_size = clear_secret_item->len;
- PK11_FreeSymKey (secret_key);
+ SECITEM_FreeItem (clear_secret_item, PR_TRUE);
return ret;
- err_secret_key:
- PK11_FreeSymKey (secret_key);
err:
return NULL;
}

View File

@ -32,7 +32,7 @@
Summary: An utility for manipulating storage encryption keys and passphrases
Name: volume_key
Version: 0.3.12
Release: 16%{?dist}
Release: 17%{?dist}
License: GPLv2
URL: https://pagure.io/%{name}/
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
@ -45,6 +45,8 @@ Patch0: volume_key-0.3.12-support_LUKS2_and_more.patch
# - backport of bf6618ec0b09b4e51fc97fa021e687fbd87599ba
Patch1: volume_key-0.3.12-fix_resource_leaks.patch
Patch2: volume_key-0.3.12-FIPS.patch
# fix getting backup password from secret the FIPS way, RHEL-113757
Patch3: volume_key-0.3.12-fips2.patch
BuildRequires: make
BuildRequires: gcc
BuildRequires: cryptsetup-devel, gettext-devel, glib2-devel, /usr/bin/gpg2
@ -122,6 +124,7 @@ Requires: %{name}-libs%{?_isa} = %{version}-%{release}
%patch -P 0 -p1
%patch -P 1 -p1
%patch -P 2 -p1 -b .FIPS
%patch -P 3 -p1 -b .fips2
%build
%configure %{?with_pythons}
@ -172,6 +175,9 @@ exit 1; \
%endif
%changelog
* Thu Feb 12 2026 Michal Hlavinka <mhlavink@redhat.com> - 0.3.12-17
- ake getting password from backed up secret FIPS compatible (RHEL-113757)
* Thu Feb 06 2025 Michal Hlavinka <mhlavink@redhat.com> - 0.3.12-16
- make volume_key FIPS compliant (RHEL-78044)