Blame SOURCES/0001-rhbz-1614419-use-workaround-for-PK11_ImportSymKey-fa.patch

27aea6
From 3fe2dd8094fcec76a1310d3ab33c1cc27c85c356 Mon Sep 17 00:00:00 2001
27aea6
From: rpmbuild <rpmbuild@fedoraproject.org>
27aea6
Date: Fri, 10 Aug 2018 09:45:56 +0100
27aea6
Subject: [PATCH] rhbz#1614419 use workaround for PK11_ImportSymKey failure
27aea6
 under FIPS
27aea6
27aea6
---
27aea6
 include/oox/crypto/CryptTools.hxx |  3 ++
27aea6
 oox/source/crypto/CryptTools.cxx  | 83 +++++++++++++++++++++++++++++++++++----
27aea6
 2 files changed, 79 insertions(+), 7 deletions(-)
27aea6
27aea6
diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx
27aea6
index 84e4c48..07605da 100644
27aea6
--- a/include/oox/crypto/CryptTools.hxx
27aea6
+++ b/include/oox/crypto/CryptTools.hxx
27aea6
@@ -56,9 +56,12 @@ protected:
27aea6
     EVP_CIPHER_CTX mContext;
27aea6
 #endif
27aea6
 #if USE_TLS_NSS
27aea6
+    PK11SlotInfo* mSlot;
27aea6
     PK11Context* mContext;
27aea6
     SECItem*     mSecParam;
27aea6
     PK11SymKey*  mSymKey;
27aea6
+    PK11Context* mWrapKeyContext;
27aea6
+    PK11SymKey*  mWrapKey;
27aea6
 #endif
27aea6
 
27aea6
 #if USE_TLS_OPENSSL
27aea6
diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx
27aea6
index 5ecf7b3..ee91925 100644
27aea6
--- a/oox/source/crypto/CryptTools.cxx
27aea6
+++ b/oox/source/crypto/CryptTools.cxx
27aea6
@@ -19,9 +19,12 @@ using namespace std;
27aea6
 
27aea6
 Crypto::Crypto()
27aea6
 #if USE_TLS_NSS
27aea6
-    : mContext(nullptr)
27aea6
+    : mSlot(nullptr)
27aea6
+    , mContext(nullptr)
27aea6
     , mSecParam(nullptr)
27aea6
     , mSymKey(nullptr)
27aea6
+    , mWrapKeyContext(nullptr)
27aea6
+    , mWrapKey(nullptr)
27aea6
 #endif
27aea6
 {
27aea6
 #if USE_TLS_NSS
27aea6
@@ -38,10 +41,16 @@ Crypto::~Crypto()
27aea6
 #if USE_TLS_NSS
27aea6
     if (mContext)
27aea6
         PK11_DestroyContext(mContext, PR_TRUE);
27aea6
-    if (mSymKey)
27aea6
-        PK11_FreeSymKey(mSymKey);
27aea6
     if (mSecParam)
27aea6
         SECITEM_FreeItem(mSecParam, PR_TRUE);
27aea6
+    if (mSymKey)
27aea6
+        PK11_FreeSymKey(mSymKey);
27aea6
+    if (mWrapKeyContext)
27aea6
+        PK11_DestroyContext(mWrapKeyContext, PR_TRUE);
27aea6
+    if (mWrapKey)
27aea6
+        PK11_FreeSymKey(mWrapKey);
27aea6
+    if (mSlot)
27aea6
+        PK11_FreeSlot(mSlot);
27aea6
 #endif
27aea6
 }
27aea6
 
27aea6
@@ -59,11 +68,14 @@ const EVP_CIPHER* Crypto::getCipher(CryptoType type)
27aea6
         default:
27aea6
             break;
27aea6
     }
27aea6
-    return NULL;
27aea6
+    return nullptr;
27aea6
 }
27aea6
 #endif
27aea6
 
27aea6
 #if USE_TLS_NSS
27aea6
+
27aea6
+#define MAX_WRAPPED_KEY_LEN 128
27aea6
+
27aea6
 void Crypto::setupContext(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type, CK_ATTRIBUTE_TYPE operation)
27aea6
 {
27aea6
     CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
27aea6
@@ -95,9 +107,9 @@ void Crypto::setupContext(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoT
27aea6
             break;
27aea6
     }
27aea6
 
27aea6
-    PK11SlotInfo* pSlot( PK11_GetBestSlot( mechanism, nullptr ) );
27aea6
+    mSlot = PK11_GetBestSlot(mechanism, nullptr);
27aea6
 
27aea6
-    if (!pSlot)
27aea6
+    if (!mSlot)
27aea6
         throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
27aea6
 
27aea6
     SECItem keyItem;
27aea6
@@ -105,7 +117,64 @@ void Crypto::setupContext(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoT
27aea6
     keyItem.data = &key[0];
27aea6
     keyItem.len  = key.size();
27aea6
 
27aea6
-    mSymKey = PK11_ImportSymKey( pSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr );
27aea6
+    mSymKey = PK11_ImportSymKey( mSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr );
27aea6
+    if (!mSymKey) //rhbz#1614419 maybe failed due to FIPS, use rhbz#1461450 style workaround
27aea6
+    {
27aea6
+        /*
27aea6
+         * Without FIPS it would be possible to just use
27aea6
+         *  mSymKey = PK11_ImportSymKey( mSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr );
27aea6
+         * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using
27aea6
+         * following method:
27aea6
+         * 1. Generate wrap key
27aea6
+         * 2. Encrypt authkey with wrap key
27aea6
+         * 3. Unwrap encrypted authkey using wrap key
27aea6
+         */
27aea6
+
27aea6
+        /*
27aea6
+         * Generate wrapping key
27aea6
+         */
27aea6
+        CK_MECHANISM_TYPE wrap_mechanism = PK11_GetBestWrapMechanism(mSlot);
27aea6
+        int wrap_key_len = PK11_GetBestKeyLength(mSlot, wrap_mechanism);
27aea6
+        mWrapKey = PK11_KeyGen(mSlot, wrap_mechanism, nullptr, wrap_key_len, nullptr);
27aea6
+        if (!mWrapKey)
27aea6
+            throw css::uno::RuntimeException("PK11_KeyGen SymKey failure", css::uno::Reference<css::uno::XInterface>());
27aea6
+
27aea6
+        /*
27aea6
+         * Encrypt authkey with wrapping key
27aea6
+         */
27aea6
+
27aea6
+        /*
27aea6
+         * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode
27aea6
+         */
27aea6
+        SECItem tmp_sec_item;
27aea6
+        memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
27aea6
+        mWrapKeyContext = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, mWrapKey, &tmp_sec_item);
27aea6
+        if (!mWrapKeyContext)
27aea6
+            throw css::uno::RuntimeException("PK11_CreateContextBySymKey failure", css::uno::Reference<css::uno::XInterface>());
27aea6
+
27aea6
+        unsigned char wrapped_key_data[MAX_WRAPPED_KEY_LEN];
27aea6
+        int wrapped_key_len = sizeof(wrapped_key_data);
27aea6
+
27aea6
+        if (PK11_CipherOp(mWrapKeyContext, wrapped_key_data, &wrapped_key_len,
27aea6
+            sizeof(wrapped_key_data), keyItem.data, keyItem.len) != SECSuccess)
27aea6
+        {
27aea6
+            throw css::uno::RuntimeException("PK11_CipherOp failure", css::uno::Reference<css::uno::XInterface>());
27aea6
+        }
27aea6
+
27aea6
+        if (PK11_Finalize(mWrapKeyContext) != SECSuccess)
27aea6
+            throw css::uno::RuntimeException("PK11_Finalize failure", css::uno::Reference<css::uno::XInterface>());
27aea6
+
27aea6
+        /*
27aea6
+         * Finally unwrap sym key
27aea6
+         */
27aea6
+        SECItem wrapped_key;
27aea6
+        memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
27aea6
+        wrapped_key.data = wrapped_key_data;
27aea6
+        wrapped_key.len = wrapped_key_len;
27aea6
+
27aea6
+        mSymKey = PK11_UnwrapSymKey(mWrapKey, wrap_mechanism, &tmp_sec_item, &wrapped_key,
27aea6
+            mechanism, CKA_ENCRYPT, keyItem.len);
27aea6
+    }
27aea6
     if (!mSymKey)
27aea6
         throw css::uno::RuntimeException("NSS SymKey failure", css::uno::Reference<css::uno::XInterface>());
27aea6
     mSecParam = PK11_ParamFromIV( mechanism, pIvItem );
27aea6
-- 
27aea6
1.8.3.1
27aea6