diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-08-10 10:12:23 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-08-10 12:36:55 +0200 |
commit | 53eda574a61396b6765cd1cb0ac9804c754ac4c1 (patch) | |
tree | 661570a87a0581d83df01976e42220b4a1de4117 | |
parent | bc634e9d2c1fe79228c94a1a92fc6cb5be57b659 (diff) |
Resolves: rhbz#1614419 FIPS mode PK11_ImportSymKey failure
use rhbz#1461450 style workaround
Change-Id: I9e3b17deb9bac6af76ac253634c91d5e8ccd4963
Reviewed-on: https://gerrit.libreoffice.org/58816
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | oox/source/crypto/CryptTools.cxx | 99 |
1 files changed, 86 insertions, 13 deletions
diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx index 99fb01fe88d2..9ffc6eabfe47 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/oox/source/crypto/CryptTools.cxx @@ -123,18 +123,24 @@ struct CryptoImpl #elif USE_TLS_NSS +#define MAX_WRAPPED_KEY_LEN 128 + struct CryptoImpl { + PK11SlotInfo* mSlot; PK11Context* mContext; SECItem* mSecParam; PK11SymKey* mSymKey; - PK11SlotInfo* mpSlot; + PK11Context* mWrapKeyContext; + PK11SymKey* mWrapKey; CryptoImpl() - : mContext(nullptr) + : mSlot(nullptr) + , mContext(nullptr) , mSecParam(nullptr) , mSymKey(nullptr) - , mpSlot(nullptr) + , mWrapKeyContext(nullptr) + , mWrapKey(nullptr) { // Initialize NSS, database functions are not needed NSS_NoDB_Init(nullptr); @@ -144,12 +150,79 @@ struct CryptoImpl { if (mContext) PK11_DestroyContext(mContext, PR_TRUE); - if (mSymKey) - PK11_FreeSymKey(mSymKey); if (mSecParam) SECITEM_FreeItem(mSecParam, PR_TRUE); - if (mpSlot) - PK11_FreeSlot(mpSlot); + if (mSymKey) + PK11_FreeSymKey(mSymKey); + if (mWrapKeyContext) + PK11_DestroyContext(mWrapKeyContext, PR_TRUE); + if (mWrapKey) + PK11_FreeSymKey(mWrapKey); + if (mSlot) + PK11_FreeSlot(mSlot); + } + + PK11SymKey* ImportSymKey(CK_MECHANISM_TYPE mechanism, CK_ATTRIBUTE_TYPE operation, SECItem* key) + { + mSymKey = PK11_ImportSymKey(mSlot, mechanism, PK11_OriginUnwrap, operation, key, 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<css::uno::XInterface>()); + + /* + * 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<css::uno::XInterface>()); + + 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), key->data, key->len) != SECSuccess) + { + throw css::uno::RuntimeException("PK11_CipherOp failure", css::uno::Reference<css::uno::XInterface>()); + } + + if (PK11_Finalize(mWrapKeyContext) != SECSuccess) + throw css::uno::RuntimeException("PK11_Finalize failure", css::uno::Reference<css::uno::XInterface>()); + + /* + * 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, operation, key->len); + } + return mSymKey; } void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type, CK_ATTRIBUTE_TYPE operation) @@ -183,9 +256,9 @@ struct CryptoImpl break; } - mpSlot = PK11_GetBestSlot(mechanism, nullptr); + mSlot = PK11_GetBestSlot(mechanism, nullptr); - if (!mpSlot) + if (!mSlot) throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>()); SECItem keyItem; @@ -193,7 +266,7 @@ struct CryptoImpl keyItem.data = key.data(); keyItem.len = key.size(); - mSymKey = PK11_ImportSymKey(mpSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr); + mSymKey = ImportSymKey(mechanism, CKA_ENCRYPT, &keyItem); if (!mSymKey) throw css::uno::RuntimeException("NSS SymKey failure", css::uno::Reference<css::uno::XInterface>()); @@ -218,16 +291,16 @@ struct CryptoImpl break; } - mpSlot = PK11_GetBestSlot(aMechanism, nullptr); + mSlot = PK11_GetBestSlot(aMechanism, nullptr); - if (!mpSlot) + if (!mSlot) throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>()); SECItem aKeyItem; aKeyItem.data = rKey.data(); aKeyItem.len = rKey.size(); - mSymKey = PK11_ImportSymKey(mpSlot, aMechanism, PK11_OriginUnwrap, CKA_SIGN, &aKeyItem, nullptr); + mSymKey = ImportSymKey(aMechanism, CKA_SIGN, &aKeyItem); if (!mSymKey) throw css::uno::RuntimeException("NSS SymKey failure", css::uno::Reference<css::uno::XInterface>()); |