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