Blame SOURCES/0001-Encrypt-unwrap-symmetric-key-in-FIPS-mode-678.patch

23f496
From 3cc2f62eaca0e616dadc3053919180615b48bf54 Mon Sep 17 00:00:00 2001
23f496
From: Alexander Scheel <alexander.m.scheel@gmail.com>
23f496
Date: Fri, 12 Mar 2021 20:41:51 -0500
23f496
Subject: [PATCH] Encrypt & unwrap symmetric key in FIPS mode (#678)
23f496
23f496
NSS doesn't generally allow keys to be imported in FIPS mode. However,
23f496
for portability with other JCA providers, we sometimes need to import
23f496
keys from byte arrays. Do this in the JNI layer by executing a PKCS#11
23f496
encrypt and then unwrap using the same key. This lets us effectively
23f496
"import" a key into a token, if the token supports using the given
23f496
mechanism for both encryption and unwrapping operations. Some HSMs are
23f496
getting stricter about this and forbid using the same key for encrypt
23f496
and unwrap operations.
23f496
23f496
Resolves: #334
23f496
23f496
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
23f496
Signed-off-by: Alexander Scheel <alexander.m.scheel@gmail.com>
23f496
---
23f496
 org/mozilla/jss/pkcs11/PK11KeyWrapper.c | 62 ++++++++++++++++++++++++-
23f496
 1 file changed, 60 insertions(+), 2 deletions(-)
23f496
23f496
diff --git a/org/mozilla/jss/pkcs11/PK11KeyWrapper.c b/org/mozilla/jss/pkcs11/PK11KeyWrapper.c
23f496
index f39a3796..e8e9da16 100644
23f496
--- a/org/mozilla/jss/pkcs11/PK11KeyWrapper.c
23f496
+++ b/org/mozilla/jss/pkcs11/PK11KeyWrapper.c
23f496
@@ -712,6 +712,61 @@ finish:
23f496
     return keyObj;
23f496
 }
23f496
 
23f496
+PK11SymKey *JSS_PK11_ImportSymKeyWithFlagsFIPS(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
23f496
+        CK_ATTRIBUTE_TYPE operation, SECItem *key, CK_FLAGS flags,
23f496
+        PRBool isPerm, void *wincx)
23f496
+{
23f496
+    PK11SymKey *result = NULL;
23f496
+    PK11SymKey *wrapper = NULL;
23f496
+    SECStatus ret = SECFailure;
23f496
+    unsigned int wrapped_len = 0;
23f496
+    unsigned int wrapped_max = key->len + 64;
23f496
+    unsigned char *wrapped_key = calloc(wrapped_max, sizeof(unsigned char));
23f496
+    SECItem wrapped_item = { siBuffer, wrapped_key, 0 };
23f496
+    SECItem *param = NULL;
23f496
+
23f496
+    /* Steps:
23f496
+     * 1. Generate a temporary key to encrypt and unwrap with,
23f496
+     * 2. Encrypt our key to import using the wrapping key,
23f496
+     * 3. Unwrap into the token using the wrapping key.
23f496
+     */
23f496
+
23f496
+#define FIPS_KEYGEN_ALGO CKM_AES_KEY_GEN
23f496
+#define FIPS_ENCRYPT_UNWRAP_ALGO CKM_AES_KEY_WRAP_PAD
23f496
+
23f496
+    wrapper = PK11_KeyGen(slot, FIPS_KEYGEN_ALGO, NULL, 32, wincx);
23f496
+    if (wrapper == NULL) {
23f496
+        goto done;
23f496
+    }
23f496
+
23f496
+    param = PK11_GenerateNewParam(FIPS_ENCRYPT_UNWRAP_ALGO, wrapper);
23f496
+    if (param == NULL) {
23f496
+        goto done;
23f496
+    }
23f496
+
23f496
+    ret = PK11_Encrypt(wrapper, FIPS_ENCRYPT_UNWRAP_ALGO, param,
23f496
+            wrapped_key, &wrapped_len, wrapped_max,
23f496
+            key->data, key->len);
23f496
+    if (ret != SECSuccess) {
23f496
+        goto done;
23f496
+    }
23f496
+
23f496
+    wrapped_item.len = wrapped_len;
23f496
+
23f496
+    result = PK11_UnwrapSymKeyWithFlagsPerm(wrapper, FIPS_ENCRYPT_UNWRAP_ALGO,
23f496
+            param, &wrapped_item, type, operation, key->len, flags,
23f496
+            isPerm);
23f496
+
23f496
+done:
23f496
+    free(wrapped_key);
23f496
+    SECITEM_FreeItem(param, PR_TRUE);
23f496
+    if (wrapper != NULL) {
23f496
+        PK11_DeleteTokenSymKey(wrapper);
23f496
+        PK11_FreeSymKey(wrapper);
23f496
+    }
23f496
+    return result;
23f496
+}
23f496
+
23f496
 /***********************************************************************
23f496
  *
23f496
  * PK11KeyWrapper.nativeUnwrapSymPlaintext
23f496
@@ -765,8 +820,11 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymPlaintext
23f496
     }
23f496
 
23f496
     /* pull in the key */
23f496
-    symKey = PK11_ImportSymKeyWithFlags(slot, keyTypeMech, PK11_OriginUnwrap,
23f496
-        operation, wrappedKey, flags, isPerm, NULL);
23f496
+    if (PK11_IsFIPS()) {
23f496
+        symKey = JSS_PK11_ImportSymKeyWithFlagsFIPS(slot, keyTypeMech, operation, wrappedKey, flags, isPerm, NULL);
23f496
+    } else {
23f496
+        symKey = PK11_ImportSymKeyWithFlags(slot, keyTypeMech, PK11_OriginUnwrap, operation, wrappedKey, flags, isPerm, NULL);
23f496
+    }
23f496
     if( symKey == NULL ) {
23f496
         JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to unwrap key");
23f496
         goto finish;
23f496
-- 
23f496
2.26.2
23f496