From 0f4313def9df0b6c7a567c071d46787c86af3f35 Mon Sep 17 00:00:00 2001 From: Jiri Kucera Date: Mon, 31 Jul 2023 16:33:03 +0200 Subject: [PATCH] Make volume_key FIPS compliant Resolves: #2143223 --- volume_key-0.3.11-FIPS.patch | 146 ++++++++++++++++++ ...e_key-0.3.11-show_get_password_error.patch | 49 ++++++ volume_key.spec | 13 +- 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 volume_key-0.3.11-FIPS.patch create mode 100644 volume_key-0.3.11-show_get_password_error.patch diff --git a/volume_key-0.3.11-FIPS.patch b/volume_key-0.3.11-FIPS.patch new file mode 100644 index 0000000..ffe3ec8 --- /dev/null +++ b/volume_key-0.3.11-FIPS.patch @@ -0,0 +1,146 @@ +diff --git a/lib/crypto.c b/lib/crypto.c +index 4b9006a..5b562d1 100644 +--- a/lib/crypto.c ++++ b/lib/crypto.c +@@ -69,6 +69,115 @@ error_from_pr (GError **error) + g_free (err); + } + ++/* ++ * FIPS compliant implementation of PK11_ImportSymKey(). ++ * Source: https://github.com/ceph/ceph/pull/27104/files ++ */ ++static PK11SymKey * ++import_sym_key (PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin, ++ CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx) ++{ ++ CK_MECHANISM_TYPE wrap_mechanism = 0UL; ++ PK11SymKey *wrapping_key = NULL, *sym_key = NULL; ++ SECItem tmp_sec_item, wrapped_key_item, *raw_key_aligned = NULL; ++ PK11Context *wrap_key_crypt_context = NULL; ++ int block_size = 0; ++ size_t wrapped_key_size = 0; ++ unsigned char *wrapped_key = NULL; ++ int out_len = 0; ++ SECStatus ret = 0; ++ ++ /* Fall back to PK11_ImportSymKey() if FIPS mode is disabled. */ ++ if (PK11_IsFIPS () == PR_FALSE) ++ return PK11_ImportSymKey (slot, type, origin, operation, key, wincx); ++ ++ /* Get the best mechanism for the wrapping operation. */ ++ wrap_mechanism = PK11_GetBestWrapMechanism (slot); ++ ++ /* Based on that mechanism, generate a symetric key . */ ++ wrapping_key = PK11_KeyGen (slot, wrap_mechanism, NULL, ++ PK11_GetBestKeyLength (slot, wrap_mechanism), ++ NULL); ++ if (wrapping_key == NULL) ++ return NULL; ++ ++ /* Create the context for the wrapping operation. The context contains: ++ * - ++ * - operation to perform (CKA_ENCRYPT) ++ */ ++ memset (&tmp_sec_item, 0, sizeof (tmp_sec_item)); ++ wrap_key_crypt_context = PK11_CreateContextBySymKey (wrap_mechanism, ++ CKA_ENCRYPT, ++ wrapping_key, ++ &tmp_sec_item); ++ if (wrap_key_crypt_context == NULL) { ++ PK11_FreeSymKey (wrapping_key); ++ return NULL; ++ } ++ ++ /* Align to the block size specified by the wrapping mechanism. */ ++ block_size = PK11_GetBlockSize (wrap_mechanism, NULL); ++ raw_key_aligned = PK11_BlockData (key, block_size); ++ if (raw_key_aligned == NULL) { ++ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE); ++ PK11_FreeSymKey (wrapping_key); ++ return NULL; ++ } ++ ++ /* Prepare for wrap. First, allocate enough space for ++ * the wrapped . Add the padding of the size of one block behind the ++ * aligned to make sure the wrapping operation will not hit the wall. ++ */ ++ wrapped_key_size = raw_key_aligned->len + block_size; ++ wrapped_key = g_try_malloc0 (wrapped_key_size); ++ if (wrapped_key == NULL) { ++ SECITEM_FreeItem (raw_key_aligned, PR_TRUE); ++ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE); ++ PK11_FreeSymKey (wrapping_key); ++ return NULL; ++ } ++ ++ /* Do the wrap operation. is now a pair (, ) ++ * expressing that raw key is now encrypted with the . ++ */ ++ ret = PK11_CipherOp (wrap_key_crypt_context, wrapped_key, &out_len, ++ wrapped_key_size, raw_key_aligned->data, ++ raw_key_aligned->len); ++ if (ret != SECSuccess) { ++ g_free (wrapped_key); ++ SECITEM_FreeItem (raw_key_aligned, PR_TRUE); ++ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE); ++ PK11_FreeSymKey (wrapping_key); ++ return NULL; ++ } ++ ++ /* Finish the wrapping operation and release no more needed resources. */ ++ ret = PK11_Finalize (wrap_key_crypt_context); ++ SECITEM_FreeItem (raw_key_aligned, PR_TRUE); ++ PK11_DestroyContext (wrap_key_crypt_context, PR_TRUE); ++ if (ret != SECSuccess) { ++ g_free (wrapped_key); ++ PK11_FreeSymKey (wrapping_key); ++ return NULL; ++ } ++ ++ /* Prepare for unwrapping the . */ ++ 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; ++ ++ /* Unwrap the . First, decrypt the with the to get ++ * its raw form. Then make a symmetric key (, , ). This ++ * makes a symmetric key from the raw in a FIPS compliant manner. ++ */ ++ sym_key = PK11_UnwrapSymKey (wrapping_key, wrap_mechanism, &tmp_sec_item, ++ &wrapped_key_item, type, operation, key->len); ++ g_free (wrapped_key); ++ PK11_FreeSymKey (wrapping_key); ++ return sym_key; ++} ++ + /* LIBVK_PACKET_FORMAT_ASYMMETRIC */ + + /* Encrypt DATA of SIZE for CERT. +@@ -291,9 +400,9 @@ wrap_asymmetric (void **wrapped_secret, size_t *wrapped_secret_size, + CKM_GENERIC_SECRET_KEY_GEN. */ + clear_secret_item.data = (void *)clear_secret_data; + clear_secret_item.len = clear_secret_size; +- secret_key = PK11_ImportSymKey (slot, CKM_GENERIC_SECRET_KEY_GEN, +- PK11_OriginUnwrap, CKA_WRAP, +- &clear_secret_item, pwfn_arg); ++ secret_key = import_sym_key (slot, CKM_GENERIC_SECRET_KEY_GEN, ++ PK11_OriginUnwrap, CKA_WRAP, ++ &clear_secret_item, pwfn_arg); + PK11_FreeSlot (slot); + if (secret_key == NULL) + { +@@ -471,9 +580,9 @@ wrap_symmetric (void **wrapped_secret, size_t *wrapped_secret_size, void **iv, + /* The disk encryption mechanism might not have a PKCS11 name, and we don't + really need to tell NSS specifics anyway, so just use + CKM_GENERIC_SECRET_KEY_GEN. */ +- secret_key = PK11_ImportSymKey (slot, CKM_GENERIC_SECRET_KEY_GEN, +- PK11_OriginUnwrap, CKA_WRAP, +- &clear_secret_item, pwfn_arg); ++ secret_key = import_sym_key (slot, CKM_GENERIC_SECRET_KEY_GEN, ++ PK11_OriginUnwrap, CKA_WRAP, ++ &clear_secret_item, pwfn_arg); + PK11_FreeSlot (slot); + if (secret_key == NULL) + { diff --git a/volume_key-0.3.11-show_get_password_error.patch b/volume_key-0.3.11-show_get_password_error.patch new file mode 100644 index 0000000..6923917 --- /dev/null +++ b/volume_key-0.3.11-show_get_password_error.patch @@ -0,0 +1,49 @@ +diff --git a/src/volume_key.c b/src/volume_key.c +index 24b70d6..9642072 100644 +--- a/src/volume_key.c ++++ b/src/volume_key.c +@@ -17,6 +17,7 @@ Author: Miloslav Trmač */ + #include + + #include ++#include + #include + #include + #include +@@ -403,6 +404,7 @@ get_password (const char *prompt) + char buf[LINE_MAX], *p; + struct termios otermios; + gboolean echo_disabled; ++ int saved_errno = 0; + + tty = fopen ("/dev/tty", "r+"); + if (tty != NULL) +@@ -430,7 +432,8 @@ get_password (const char *prompt) + echo_disabled = tcsetattr (fileno (in_file), TCSAFLUSH, &ntermios) == 0; + } + +- p = fgets(buf, sizeof(buf), in_file); ++ p = fgets (buf, sizeof (buf), in_file); ++ saved_errno = errno; + + if (echo_disabled) + { +@@ -441,13 +444,15 @@ get_password (const char *prompt) + if (tty != NULL) + fclose (tty); + +- if (p == NULL) ++ if (p == NULL) { ++ fprintf (stderr, "fgets: %s\n", strerror (saved_errno)); + return NULL; ++ } + +- p = strchr(buf, '\r'); ++ p = strchr (buf, '\r'); + if (p != NULL) + *p = '\0'; +- p = strchr(buf, '\n'); ++ p = strchr (buf, '\n'); + if (p != NULL) + *p = '\0'; + diff --git a/volume_key.spec b/volume_key.spec index 15f06fe..6a50e32 100644 --- a/volume_key.spec +++ b/volume_key.spec @@ -1,7 +1,7 @@ Summary: An utility for manipulating storage encryption keys and passphrases Name: volume_key Version: 0.3.11 -Release: 5%{?dist} +Release: 6%{?dist} # lib/{SECerrs,SSLerrs}.h are both licensed under MPLv1.1, GPLv2 and LGPLv2 License: GPLv2 and (MPLv1.1 or GPLv2 or LGPLv2) Group: Applications/System @@ -12,6 +12,11 @@ Source0: https://releases.pagure.org/volume_key/volume_key-%{version}.tar.xz # Add support for opening all types of LUKS devices (not just LUKS1) # Resolves: rhbz#1626974 Patch0: volume_key-0.3.11-support_LUKS_all.patch +# Make volume_key working in FIPS mode +# Resolves: rhbz#2143223 +Patch1: volume_key-0.3.11-FIPS.patch +# Diagnose patch to get more insight on whats wrong +Patch2: volume_key-0.3.11-show_get_password_error.patch BuildRequires: cryptsetup-luks-devel, gettext-devel, glib2-devel, /usr/bin/gpg2 BuildRequires: gpgme-devel, libblkid-devel, nss-devel, python3-devel # Needed by %%check: @@ -80,6 +85,8 @@ for other formats is possible, some formats are planned for future releases. %prep %setup -q %patch0 -p1 +%patch1 -p1 +%patch2 -p1 %build %configure @@ -128,6 +135,10 @@ rm -rf $RPM_BUILD_ROOT %{python3_sitearch}/__pycache__/volume_key.* %changelog +* Fri Jul 21 2023 Jiri Kucera - 0.3.11-6 +- Make volume_key working in FIPS mode + Resolves: #2143223 + * Wed Aug 14 2019 Jiri Kucera - 0.3.11-5 - Place %%find_lang to proper place Resolves: #1665135