comphelper: put each Crypto impl. in own file - minimize ifdefs
This puts NSS and OpenSSL implementations into own classes and adds an interface to make this possible. The implementation is now determined in Library_comphelper. Change-Id: I4918f19bca0adfd2f9180fb418d1bd57bb83982d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177383 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
This commit is contained in:
parent
4908455dc5
commit
dee760e92c
6 changed files with 604 additions and 480 deletions
|
@ -70,12 +70,15 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
|
|||
comphelper/source/container/NamedPropertyValuesContainer \
|
||||
comphelper/source/container/container \
|
||||
comphelper/source/container/containermultiplexer \
|
||||
comphelper/source/container/interfacecontainer2 \
|
||||
comphelper/source/container/interfacecontainer2 \
|
||||
comphelper/source/container/embeddedobjectcontainer \
|
||||
comphelper/source/container/enumerablemap \
|
||||
comphelper/source/container/enumhelper \
|
||||
comphelper/source/container/namecontainer \
|
||||
comphelper/source/crypto/Crypto \
|
||||
$(if $(filter NSS,$(TLS)), comphelper/source/crypto/Crypto_NSS) \
|
||||
$(if $(filter OPENSSL,$(TLS)), comphelper/source/crypto/Crypto_OpenSSL) \
|
||||
$(if $(filter NSS OPENSSL,$(TLS)),,comphelper/source/crypto/Crypto_None) \
|
||||
comphelper/source/eventattachermgr/eventattachermgr \
|
||||
comphelper/source/misc/accessiblecomponenthelper \
|
||||
comphelper/source/misc/accessibleeventnotifier \
|
||||
|
|
|
@ -5,447 +5,34 @@
|
|||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <comphelper/crypto/Crypto.hxx>
|
||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||
#include <sal/types.h>
|
||||
|
||||
#include <config_oox.h>
|
||||
|
||||
#if USE_TLS_OPENSSL
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/hmac.h>
|
||||
#endif // USE_TLS_OPENSSL
|
||||
|
||||
#if USE_TLS_NSS
|
||||
#include <nss.h>
|
||||
#include <nspr.h>
|
||||
#include <pk11pub.h>
|
||||
#endif // USE_TLS_NSS
|
||||
|
||||
namespace comphelper
|
||||
{
|
||||
#if USE_TLS_OPENSSL
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
|
||||
static HMAC_CTX* HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX* pContext = new HMAC_CTX;
|
||||
HMAC_CTX_init(pContext);
|
||||
return pContext;
|
||||
}
|
||||
|
||||
static void HMAC_CTX_free(HMAC_CTX* pContext)
|
||||
{
|
||||
HMAC_CTX_cleanup(pContext);
|
||||
delete pContext;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
struct cipher_delete
|
||||
{
|
||||
void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); }
|
||||
};
|
||||
|
||||
struct hmac_delete
|
||||
{
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated
|
||||
void
|
||||
operator()(HMAC_CTX* p)
|
||||
{
|
||||
HMAC_CTX_free(p);
|
||||
}
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
};
|
||||
}
|
||||
|
||||
struct CryptoImpl
|
||||
{
|
||||
std::unique_ptr<EVP_CIPHER_CTX, cipher_delete> mpContext;
|
||||
std::unique_ptr<HMAC_CTX, hmac_delete> mpHmacContext;
|
||||
|
||||
CryptoImpl() = default;
|
||||
|
||||
void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType eType)
|
||||
{
|
||||
mpContext.reset(EVP_CIPHER_CTX_new());
|
||||
EVP_CIPHER_CTX_init(mpContext.get());
|
||||
|
||||
const EVP_CIPHER* cipher = getCipher(eType);
|
||||
if (cipher == nullptr)
|
||||
return;
|
||||
|
||||
if (iv.empty())
|
||||
EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), nullptr);
|
||||
else
|
||||
EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), iv.data());
|
||||
EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
|
||||
}
|
||||
|
||||
void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType eType)
|
||||
{
|
||||
mpContext.reset(EVP_CIPHER_CTX_new());
|
||||
EVP_CIPHER_CTX_init(mpContext.get());
|
||||
|
||||
const EVP_CIPHER* pCipher = getCipher(eType);
|
||||
if (pCipher == nullptr)
|
||||
return;
|
||||
|
||||
const size_t nMinKeySize = EVP_CIPHER_key_length(pCipher);
|
||||
if (key.size() < nMinKeySize)
|
||||
key.resize(nMinKeySize, 0);
|
||||
|
||||
if (iv.empty())
|
||||
EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), nullptr);
|
||||
else
|
||||
{
|
||||
const size_t nMinIVSize = EVP_CIPHER_iv_length(pCipher);
|
||||
if (iv.size() < nMinIVSize)
|
||||
iv.resize(nMinIVSize, 0);
|
||||
|
||||
EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), iv.data());
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
|
||||
}
|
||||
|
||||
void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType)
|
||||
{
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_new' is deprecated
|
||||
mpHmacContext.reset(HMAC_CTX_new());
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
const EVP_MD* aEvpMd = nullptr;
|
||||
switch (eType)
|
||||
{
|
||||
case CryptoHashType::SHA1:
|
||||
aEvpMd = EVP_sha1();
|
||||
break;
|
||||
case CryptoHashType::SHA256:
|
||||
aEvpMd = EVP_sha256();
|
||||
break;
|
||||
case CryptoHashType::SHA384:
|
||||
aEvpMd = EVP_sha384();
|
||||
break;
|
||||
case CryptoHashType::SHA512:
|
||||
aEvpMd = EVP_sha512();
|
||||
break;
|
||||
}
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Init_ex' is deprecated
|
||||
HMAC_Init_ex(mpHmacContext.get(), rKey.data(), rKey.size(), aEvpMd, nullptr);
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
}
|
||||
|
||||
~CryptoImpl()
|
||||
{
|
||||
if (mpContext)
|
||||
EVP_CIPHER_CTX_cleanup(mpContext.get());
|
||||
}
|
||||
|
||||
static const EVP_CIPHER* getCipher(CryptoType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
return EVP_aes_128_ecb();
|
||||
case CryptoType::AES_256_ECB:
|
||||
return EVP_aes_256_ecb();
|
||||
case CryptoType::AES_128_CBC:
|
||||
return EVP_aes_128_cbc();
|
||||
case CryptoType::AES_256_CBC:
|
||||
return EVP_aes_256_cbc();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#elif USE_TLS_NSS
|
||||
|
||||
#define MAX_WRAPPED_KEY_LEN 128
|
||||
|
||||
struct CryptoImpl
|
||||
{
|
||||
PK11SlotInfo* mSlot;
|
||||
PK11Context* mContext;
|
||||
SECItem* mSecParam;
|
||||
PK11SymKey* mSymKey;
|
||||
PK11Context* mWrapKeyContext;
|
||||
PK11SymKey* mWrapKey;
|
||||
|
||||
CryptoImpl()
|
||||
: mSlot(nullptr)
|
||||
, mContext(nullptr)
|
||||
, mSecParam(nullptr)
|
||||
, mSymKey(nullptr)
|
||||
, mWrapKeyContext(nullptr)
|
||||
, mWrapKey(nullptr)
|
||||
{
|
||||
// Initialize NSS, database functions are not needed
|
||||
if (!NSS_IsInitialized())
|
||||
{
|
||||
auto const e = NSS_NoDB_Init(nullptr);
|
||||
if (e != SECSuccess)
|
||||
{
|
||||
PRErrorCode error = PR_GetError();
|
||||
const char* errorText = PR_ErrorToName(error);
|
||||
throw css::uno::RuntimeException(
|
||||
"NSS_NoDB_Init failed with "
|
||||
+ OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) + " ("
|
||||
+ OUString::number(static_cast<int>(error)) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CryptoImpl()
|
||||
{
|
||||
if (mContext)
|
||||
PK11_DestroyContext(mContext, PR_TRUE);
|
||||
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);
|
||||
}
|
||||
|
||||
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(u"PK11_KeyGen SymKey failure"_ustr,
|
||||
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 = {};
|
||||
mWrapKeyContext
|
||||
= PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, mWrapKey, &tmp_sec_item);
|
||||
if (!mWrapKeyContext)
|
||||
throw css::uno::RuntimeException(u"PK11_CreateContextBySymKey failure"_ustr,
|
||||
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(u"PK11_CipherOp failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
}
|
||||
|
||||
if (PK11_Finalize(mWrapKeyContext) != SECSuccess)
|
||||
throw css::uno::RuntimeException(u"PK11_Finalize failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
/*
|
||||
* Finally unwrap sym key
|
||||
*/
|
||||
SECItem wrapped_key = {};
|
||||
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 setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type)
|
||||
{
|
||||
setupCryptoContext(key, iv, type, CKA_ENCRYPT);
|
||||
}
|
||||
|
||||
void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type)
|
||||
{
|
||||
setupCryptoContext(key, iv, type, CKA_DECRYPT);
|
||||
}
|
||||
|
||||
void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type, CK_ATTRIBUTE_TYPE operation)
|
||||
{
|
||||
CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
|
||||
|
||||
SECItem ivItem;
|
||||
ivItem.type = siBuffer;
|
||||
if (iv.empty())
|
||||
ivItem.data = nullptr;
|
||||
else
|
||||
ivItem.data = iv.data();
|
||||
ivItem.len = iv.size();
|
||||
|
||||
SECItem* pIvItem = nullptr;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
case CryptoType::AES_256_ECB:
|
||||
mechanism = CKM_AES_ECB;
|
||||
break;
|
||||
case CryptoType::AES_128_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
break;
|
||||
case CryptoType::AES_256_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mSlot = PK11_GetBestSlot(mechanism, nullptr);
|
||||
|
||||
if (!mSlot)
|
||||
throw css::uno::RuntimeException(u"NSS Slot failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem keyItem;
|
||||
keyItem.type = siBuffer;
|
||||
keyItem.data = key.data();
|
||||
keyItem.len = key.size();
|
||||
|
||||
mSymKey = ImportSymKey(mechanism, CKA_ENCRYPT, &keyItem);
|
||||
if (!mSymKey)
|
||||
throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
mSecParam = PK11_ParamFromIV(mechanism, pIvItem);
|
||||
mContext = PK11_CreateContextBySymKey(mechanism, operation, mSymKey, mSecParam);
|
||||
}
|
||||
|
||||
void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType)
|
||||
{
|
||||
CK_MECHANISM_TYPE aMechanism = static_cast<CK_ULONG>(-1);
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case CryptoHashType::SHA1:
|
||||
aMechanism = CKM_SHA_1_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA256:
|
||||
aMechanism = CKM_SHA256_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA384:
|
||||
aMechanism = CKM_SHA384_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA512:
|
||||
aMechanism = CKM_SHA512_HMAC;
|
||||
break;
|
||||
}
|
||||
|
||||
mSlot = PK11_GetBestSlot(aMechanism, nullptr);
|
||||
|
||||
if (!mSlot)
|
||||
throw css::uno::RuntimeException(u"NSS Slot failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem aKeyItem;
|
||||
aKeyItem.data = rKey.data();
|
||||
aKeyItem.len = rKey.size();
|
||||
|
||||
mSymKey = ImportSymKey(aMechanism, CKA_SIGN, &aKeyItem);
|
||||
if (!mSymKey)
|
||||
throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem param;
|
||||
param.data = nullptr;
|
||||
param.len = 0;
|
||||
mContext = PK11_CreateContextBySymKey(aMechanism, CKA_SIGN, mSymKey, ¶m);
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct CryptoImpl
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
Crypto::Crypto()
|
||||
: mpImpl(std::make_unique<CryptoImpl>())
|
||||
: mpImpl(ICryptoImplementation::createInstance())
|
||||
{
|
||||
}
|
||||
|
||||
Crypto::~Crypto() {}
|
||||
Crypto::~Crypto() = default;
|
||||
|
||||
// DECRYPT
|
||||
|
||||
Decrypt::Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type)
|
||||
{
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS == 0
|
||||
(void)key;
|
||||
(void)iv;
|
||||
(void)type;
|
||||
#else
|
||||
mpImpl->setupDecryptContext(key, iv, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
sal_uInt32 Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength)
|
||||
{
|
||||
int outputLength = 0;
|
||||
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
|
||||
sal_uInt32 actualInputLength
|
||||
= inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
|
||||
#else
|
||||
(void)output;
|
||||
(void)input;
|
||||
(void)inputLength;
|
||||
#endif
|
||||
|
||||
#if USE_TLS_OPENSSL
|
||||
(void)EVP_DecryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(),
|
||||
actualInputLength);
|
||||
#endif // USE_TLS_OPENSSL
|
||||
|
||||
#if USE_TLS_NSS
|
||||
if (!mpImpl->mContext)
|
||||
return 0;
|
||||
(void)PK11_CipherOp(mpImpl->mContext, output.data(), &outputLength, actualInputLength,
|
||||
input.data(), actualInputLength);
|
||||
#endif // USE_TLS_NSS
|
||||
|
||||
return static_cast<sal_uInt32>(outputLength);
|
||||
return mpImpl->decryptUpdate(output, input, actualInputLength);
|
||||
}
|
||||
|
||||
sal_uInt32 Decrypt::aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
|
@ -462,40 +49,15 @@ sal_uInt32 Decrypt::aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uI
|
|||
|
||||
Encrypt::Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type)
|
||||
{
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS == 0
|
||||
(void)key;
|
||||
(void)iv;
|
||||
(void)type;
|
||||
#else
|
||||
mpImpl->setupEncryptContext(key, iv, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength)
|
||||
{
|
||||
int outputLength = 0;
|
||||
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
|
||||
sal_uInt32 actualInputLength
|
||||
= inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
|
||||
#else
|
||||
(void)output;
|
||||
(void)input;
|
||||
(void)inputLength;
|
||||
#endif
|
||||
|
||||
#if USE_TLS_OPENSSL
|
||||
(void)EVP_EncryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(),
|
||||
actualInputLength);
|
||||
#endif // USE_TLS_OPENSSL
|
||||
|
||||
#if USE_TLS_NSS
|
||||
(void)PK11_CipherOp(mpImpl->mContext, output.data(), &outputLength, actualInputLength,
|
||||
input.data(), actualInputLength);
|
||||
#endif // USE_TLS_NSS
|
||||
|
||||
return static_cast<sal_uInt32>(outputLength);
|
||||
return mpImpl->encryptUpdate(output, input, actualInputLength);
|
||||
}
|
||||
|
||||
// CryptoHash - HMAC
|
||||
|
@ -523,52 +85,20 @@ sal_Int32 getSizeForHashType(CryptoHashType eType)
|
|||
CryptoHash::CryptoHash(std::vector<sal_uInt8>& rKey, CryptoHashType eType)
|
||||
: mnHashSize(getSizeForHashType(eType))
|
||||
{
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
|
||||
mpImpl->setupCryptoHashContext(rKey, eType);
|
||||
|
||||
#if USE_TLS_NSS
|
||||
PK11_DigestBegin(mpImpl->mContext);
|
||||
#endif
|
||||
|
||||
#else
|
||||
(void)rKey;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CryptoHash::update(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength)
|
||||
{
|
||||
#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
|
||||
sal_uInt32 nActualInputLength
|
||||
= (nInputLength == 0 || nInputLength > rInput.size()) ? rInput.size() : nInputLength;
|
||||
#else
|
||||
(void)rInput;
|
||||
(void)nInputLength;
|
||||
#endif
|
||||
|
||||
#if USE_TLS_OPENSSL
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Update' is deprecated
|
||||
return HMAC_Update(mpImpl->mpHmacContext.get(), rInput.data(), nActualInputLength)
|
||||
!= 0;
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
#elif USE_TLS_NSS
|
||||
return PK11_DigestOp(mpImpl->mContext, rInput.data(), nActualInputLength) == SECSuccess;
|
||||
#else
|
||||
return false; // ???
|
||||
#endif
|
||||
return mpImpl->cryptoHashUpdate(rInput, nActualInputLength);
|
||||
}
|
||||
|
||||
std::vector<sal_uInt8> CryptoHash::finalize()
|
||||
{
|
||||
std::vector<sal_uInt8> aHash(mnHashSize, 0);
|
||||
#if USE_TLS_OPENSSL
|
||||
unsigned int nSizeWritten = 0;
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Final' is deprecated
|
||||
(void) HMAC_Final(mpImpl->mpHmacContext.get(), aHash.data(), &nSizeWritten);
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
#elif USE_TLS_NSS
|
||||
unsigned int nSizeWritten = 0;
|
||||
PK11_DigestFinal(mpImpl->mContext, aHash.data(), &nSizeWritten, aHash.size());
|
||||
#endif
|
||||
mpImpl->cryptoHashFinalize(aHash);
|
||||
return aHash;
|
||||
}
|
||||
|
||||
|
|
295
comphelper/source/crypto/Crypto_NSS.cxx
Normal file
295
comphelper/source/crypto/Crypto_NSS.cxx
Normal file
|
@ -0,0 +1,295 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <comphelper/crypto/Crypto.hxx>
|
||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||
#include <sal/types.h>
|
||||
#include <config_oox.h>
|
||||
|
||||
#include <nss.h>
|
||||
#include <nspr.h>
|
||||
#include <pk11pub.h>
|
||||
|
||||
namespace comphelper
|
||||
{
|
||||
namespace
|
||||
{
|
||||
#define MAX_WRAPPED_KEY_LEN 128
|
||||
|
||||
class CryptoImplementationNSS : public ICryptoImplementation
|
||||
{
|
||||
PK11SlotInfo* mSlot;
|
||||
PK11Context* mContext;
|
||||
SECItem* mSecParam;
|
||||
PK11SymKey* mSymKey;
|
||||
PK11Context* mWrapKeyContext;
|
||||
PK11SymKey* mWrapKey;
|
||||
|
||||
public:
|
||||
CryptoImplementationNSS()
|
||||
: mSlot(nullptr)
|
||||
, mContext(nullptr)
|
||||
, mSecParam(nullptr)
|
||||
, mSymKey(nullptr)
|
||||
, mWrapKeyContext(nullptr)
|
||||
, mWrapKey(nullptr)
|
||||
{
|
||||
// Initialize NSS, database functions are not needed
|
||||
if (!NSS_IsInitialized())
|
||||
{
|
||||
auto const e = NSS_NoDB_Init(nullptr);
|
||||
if (e != SECSuccess)
|
||||
{
|
||||
PRErrorCode error = PR_GetError();
|
||||
const char* errorText = PR_ErrorToName(error);
|
||||
throw css::uno::RuntimeException(
|
||||
"NSS_NoDB_Init failed with "
|
||||
+ OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) + " ("
|
||||
+ OUString::number(static_cast<int>(error)) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~CryptoImplementationNSS()
|
||||
{
|
||||
if (mContext)
|
||||
PK11_DestroyContext(mContext, PR_TRUE);
|
||||
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);
|
||||
}
|
||||
|
||||
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(u"PK11_KeyGen SymKey failure"_ustr,
|
||||
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 = {};
|
||||
mWrapKeyContext
|
||||
= PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, mWrapKey, &tmp_sec_item);
|
||||
if (!mWrapKeyContext)
|
||||
throw css::uno::RuntimeException(u"PK11_CreateContextBySymKey failure"_ustr,
|
||||
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(u"PK11_CipherOp failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
}
|
||||
|
||||
if (PK11_Finalize(mWrapKeyContext) != SECSuccess)
|
||||
throw css::uno::RuntimeException(u"PK11_Finalize failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
/*
|
||||
* Finally unwrap sym key
|
||||
*/
|
||||
SECItem wrapped_key = {};
|
||||
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 setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type) override
|
||||
{
|
||||
setupCryptoContext(key, iv, type, CKA_ENCRYPT);
|
||||
}
|
||||
|
||||
void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type) override
|
||||
{
|
||||
setupCryptoContext(key, iv, type, CKA_DECRYPT);
|
||||
}
|
||||
|
||||
void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type, CK_ATTRIBUTE_TYPE operation)
|
||||
{
|
||||
CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
|
||||
|
||||
SECItem ivItem;
|
||||
ivItem.type = siBuffer;
|
||||
if (iv.empty())
|
||||
ivItem.data = nullptr;
|
||||
else
|
||||
ivItem.data = iv.data();
|
||||
ivItem.len = iv.size();
|
||||
|
||||
SECItem* pIvItem = nullptr;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
case CryptoType::AES_256_ECB:
|
||||
mechanism = CKM_AES_ECB;
|
||||
break;
|
||||
case CryptoType::AES_128_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
break;
|
||||
case CryptoType::AES_256_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mSlot = PK11_GetBestSlot(mechanism, nullptr);
|
||||
|
||||
if (!mSlot)
|
||||
throw css::uno::RuntimeException(u"NSS Slot failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem keyItem;
|
||||
keyItem.type = siBuffer;
|
||||
keyItem.data = key.data();
|
||||
keyItem.len = key.size();
|
||||
|
||||
mSymKey = ImportSymKey(mechanism, CKA_ENCRYPT, &keyItem);
|
||||
if (!mSymKey)
|
||||
throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
mSecParam = PK11_ParamFromIV(mechanism, pIvItem);
|
||||
mContext = PK11_CreateContextBySymKey(mechanism, operation, mSymKey, mSecParam);
|
||||
}
|
||||
|
||||
void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) override
|
||||
{
|
||||
CK_MECHANISM_TYPE aMechanism = static_cast<CK_ULONG>(-1);
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case CryptoHashType::SHA1:
|
||||
aMechanism = CKM_SHA_1_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA256:
|
||||
aMechanism = CKM_SHA256_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA384:
|
||||
aMechanism = CKM_SHA384_HMAC;
|
||||
break;
|
||||
case CryptoHashType::SHA512:
|
||||
aMechanism = CKM_SHA512_HMAC;
|
||||
break;
|
||||
}
|
||||
|
||||
mSlot = PK11_GetBestSlot(aMechanism, nullptr);
|
||||
|
||||
if (!mSlot)
|
||||
throw css::uno::RuntimeException(u"NSS Slot failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem aKeyItem;
|
||||
aKeyItem.data = rKey.data();
|
||||
aKeyItem.len = rKey.size();
|
||||
|
||||
mSymKey = ImportSymKey(aMechanism, CKA_SIGN, &aKeyItem);
|
||||
if (!mSymKey)
|
||||
throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr,
|
||||
css::uno::Reference<css::uno::XInterface>());
|
||||
|
||||
SECItem param;
|
||||
param.data = nullptr;
|
||||
param.len = 0;
|
||||
mContext = PK11_CreateContextBySymKey(aMechanism, CKA_SIGN, mSymKey, ¶m);
|
||||
|
||||
// Also call digest to begin
|
||||
PK11_DigestBegin(mContext);
|
||||
}
|
||||
|
||||
sal_uInt32 decryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength) override
|
||||
{
|
||||
if (!mContext)
|
||||
return 0;
|
||||
int outputLength = 0;
|
||||
(void)PK11_CipherOp(mContext, output.data(), &outputLength, inputLength, input.data(),
|
||||
inputLength);
|
||||
return outputLength;
|
||||
}
|
||||
|
||||
sal_uInt32 encryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength) override
|
||||
{
|
||||
if (!mContext)
|
||||
return 0;
|
||||
int outputLength = 0;
|
||||
(void)PK11_CipherOp(mContext, output.data(), &outputLength, inputLength, input.data(),
|
||||
inputLength);
|
||||
return outputLength;
|
||||
}
|
||||
|
||||
bool cryptoHashUpdate(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength) override
|
||||
{
|
||||
return PK11_DigestOp(mContext, rInput.data(), nInputLength) == SECSuccess;
|
||||
}
|
||||
|
||||
bool cryptoHashFinalize(std::vector<sal_uInt8>& rHash) override
|
||||
{
|
||||
unsigned int nSizeWritten = 0;
|
||||
PK11_DigestFinal(mContext, rHash.data(), &nSizeWritten, rHash.size());
|
||||
return nSizeWritten == rHash.size();
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::shared_ptr<ICryptoImplementation> ICryptoImplementation::createInstance()
|
||||
{
|
||||
return std::shared_ptr<ICryptoImplementation>(new CryptoImplementationNSS);
|
||||
}
|
||||
|
||||
} // namespace comphelper
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
67
comphelper/source/crypto/Crypto_None.cxx
Normal file
67
comphelper/source/crypto/Crypto_None.cxx
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <comphelper/crypto/Crypto.hxx>
|
||||
#include <sal/types.h>
|
||||
#include <config_oox.h>
|
||||
|
||||
namespace comphelper
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class CryptoImplementationNone : public ICryptoImplementation
|
||||
{
|
||||
public:
|
||||
CryptoImplementationNone() = default;
|
||||
|
||||
virtual ~CryptoImplementationNone() {}
|
||||
|
||||
void setupEncryptContext(std::vector<sal_uInt8>& /*key*/, std::vector<sal_uInt8>& /*iv*/,
|
||||
CryptoType /*eType*/) override
|
||||
{
|
||||
}
|
||||
|
||||
void setupDecryptContext(std::vector<sal_uInt8>& /*key*/, std::vector<sal_uInt8>& /*iv*/,
|
||||
CryptoType /*eType*/) override
|
||||
{
|
||||
}
|
||||
|
||||
void setupCryptoHashContext(std::vector<sal_uInt8>& /*rKey*/, CryptoHashType /*eType*/) override
|
||||
{
|
||||
}
|
||||
|
||||
sal_uInt32 decryptUpdate(std::vector<sal_uInt8>& /*output*/, std::vector<sal_uInt8>& /*input*/,
|
||||
sal_uInt32 /*inputLength*/) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sal_uInt32 encryptUpdate(std::vector<sal_uInt8>& /*output*/, std::vector<sal_uInt8>& /*input*/,
|
||||
sal_uInt32 /*inputLength*/) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cryptoHashUpdate(std::vector<sal_uInt8>& /*rInput*/, sal_uInt32 /*nInputLength*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cryptoHashFinalize(std::vector<sal_uInt8>& /*rHash*/) override { return false; }
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
std::shared_ptr<ICryptoImplementation> ICryptoImplementation::createInstance()
|
||||
{
|
||||
return std::shared_ptr<ICryptoImplementation>(new CryptoImplementationNone);
|
||||
}
|
||||
|
||||
} // namespace comphelper
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
208
comphelper/source/crypto/Crypto_OpenSSL.cxx
Normal file
208
comphelper/source/crypto/Crypto_OpenSSL.cxx
Normal file
|
@ -0,0 +1,208 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <comphelper/crypto/Crypto.hxx>
|
||||
#include <sal/types.h>
|
||||
#include <config_oox.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
namespace comphelper
|
||||
{
|
||||
namespace
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
|
||||
static HMAC_CTX* HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX* pContext = new HMAC_CTX;
|
||||
HMAC_CTX_init(pContext);
|
||||
return pContext;
|
||||
}
|
||||
|
||||
static void HMAC_CTX_free(HMAC_CTX* pContext)
|
||||
{
|
||||
HMAC_CTX_cleanup(pContext);
|
||||
delete pContext;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
struct cipher_delete
|
||||
{
|
||||
void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); }
|
||||
};
|
||||
|
||||
struct hmac_delete
|
||||
{
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated
|
||||
void
|
||||
operator()(HMAC_CTX* p)
|
||||
{
|
||||
HMAC_CTX_free(p);
|
||||
}
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
};
|
||||
}
|
||||
|
||||
class CryptoImplementationOpenSSL : public ICryptoImplementation
|
||||
{
|
||||
std::unique_ptr<EVP_CIPHER_CTX, cipher_delete> mpContext;
|
||||
std::unique_ptr<HMAC_CTX, hmac_delete> mpHmacContext;
|
||||
|
||||
public:
|
||||
CryptoImplementationOpenSSL() = default;
|
||||
|
||||
virtual ~CryptoImplementationOpenSSL()
|
||||
{
|
||||
if (mpContext)
|
||||
EVP_CIPHER_CTX_cleanup(mpContext.get());
|
||||
}
|
||||
|
||||
void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType eType) override
|
||||
{
|
||||
mpContext.reset(EVP_CIPHER_CTX_new());
|
||||
EVP_CIPHER_CTX_init(mpContext.get());
|
||||
|
||||
const EVP_CIPHER* cipher = getCipher(eType);
|
||||
if (cipher == nullptr)
|
||||
return;
|
||||
|
||||
if (iv.empty())
|
||||
EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), nullptr);
|
||||
else
|
||||
EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), iv.data());
|
||||
EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
|
||||
}
|
||||
|
||||
void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType eType) override
|
||||
{
|
||||
mpContext.reset(EVP_CIPHER_CTX_new());
|
||||
EVP_CIPHER_CTX_init(mpContext.get());
|
||||
|
||||
const EVP_CIPHER* pCipher = getCipher(eType);
|
||||
if (pCipher == nullptr)
|
||||
return;
|
||||
|
||||
const size_t nMinKeySize = EVP_CIPHER_key_length(pCipher);
|
||||
if (key.size() < nMinKeySize)
|
||||
key.resize(nMinKeySize, 0);
|
||||
|
||||
if (iv.empty())
|
||||
EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), nullptr);
|
||||
else
|
||||
{
|
||||
const size_t nMinIVSize = EVP_CIPHER_iv_length(pCipher);
|
||||
if (iv.size() < nMinIVSize)
|
||||
iv.resize(nMinIVSize, 0);
|
||||
|
||||
EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), iv.data());
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
|
||||
}
|
||||
|
||||
void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) override
|
||||
{
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_new' is deprecated
|
||||
mpHmacContext.reset(HMAC_CTX_new());
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
const EVP_MD* aEvpMd = nullptr;
|
||||
switch (eType)
|
||||
{
|
||||
case CryptoHashType::SHA1:
|
||||
aEvpMd = EVP_sha1();
|
||||
break;
|
||||
case CryptoHashType::SHA256:
|
||||
aEvpMd = EVP_sha256();
|
||||
break;
|
||||
case CryptoHashType::SHA384:
|
||||
aEvpMd = EVP_sha384();
|
||||
break;
|
||||
case CryptoHashType::SHA512:
|
||||
aEvpMd = EVP_sha512();
|
||||
break;
|
||||
}
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Init_ex' is deprecated
|
||||
HMAC_Init_ex(mpHmacContext.get(), rKey.data(), rKey.size(), aEvpMd, nullptr);
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
}
|
||||
|
||||
static const EVP_CIPHER* getCipher(CryptoType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
return EVP_aes_128_ecb();
|
||||
case CryptoType::AES_256_ECB:
|
||||
return EVP_aes_256_ecb();
|
||||
case CryptoType::AES_128_CBC:
|
||||
return EVP_aes_128_cbc();
|
||||
case CryptoType::AES_256_CBC:
|
||||
return EVP_aes_256_cbc();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sal_uInt32 decryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength) override
|
||||
{
|
||||
if (!mpContext)
|
||||
return 0;
|
||||
int outputLength = 0;
|
||||
(void)EVP_DecryptUpdate(mpContext.get(), output.data(), &outputLength, input.data(),
|
||||
inputLength);
|
||||
return outputLength;
|
||||
}
|
||||
|
||||
sal_uInt32 encryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength) override
|
||||
{
|
||||
if (!mpContext)
|
||||
return 0;
|
||||
int outputLength = 0;
|
||||
(void)EVP_EncryptUpdate(mpContext.get(), output.data(), &outputLength, input.data(),
|
||||
inputLength);
|
||||
return sal_uInt32(outputLength);
|
||||
}
|
||||
|
||||
bool cryptoHashUpdate(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength) override
|
||||
{
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Update' is deprecated
|
||||
return HMAC_Update(mpHmacContext.get(), rInput.data(), nInputLength)
|
||||
!= 0;
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
}
|
||||
|
||||
bool cryptoHashFinalize(std::vector<sal_uInt8>& rHash) override
|
||||
{
|
||||
unsigned int nSizeWritten = 0;
|
||||
SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Final' is deprecated
|
||||
(void) HMAC_Final(mpHmacContext.get(), rHash.data(), &nSizeWritten);
|
||||
SAL_WNODEPRECATED_DECLARATIONS_POP
|
||||
return nSizeWritten == rHash.size();
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::shared_ptr<ICryptoImplementation> ICryptoImplementation::createInstance()
|
||||
{
|
||||
return std::shared_ptr<ICryptoImplementation>(new CryptoImplementationOpenSSL);
|
||||
}
|
||||
|
||||
} // namespace comphelper
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -50,20 +50,41 @@ enum class CryptoType
|
|||
AES_256_CBC,
|
||||
};
|
||||
|
||||
struct CryptoImpl;
|
||||
class ICryptoImplementation
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<ICryptoImplementation> createInstance();
|
||||
|
||||
virtual void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType eType)
|
||||
= 0;
|
||||
virtual void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
|
||||
CryptoType type)
|
||||
= 0;
|
||||
virtual void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) = 0;
|
||||
|
||||
virtual sal_uInt32 decryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength)
|
||||
= 0;
|
||||
virtual sal_uInt32 encryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
|
||||
sal_uInt32 inputLength)
|
||||
= 0;
|
||||
virtual bool cryptoHashUpdate(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength) = 0;
|
||||
virtual bool cryptoHashFinalize(std::vector<sal_uInt8>& rHash) = 0;
|
||||
};
|
||||
|
||||
class COMPHELPER_DLLPUBLIC Crypto
|
||||
{
|
||||
protected:
|
||||
std::unique_ptr<CryptoImpl> mpImpl;
|
||||
std::shared_ptr<ICryptoImplementation> mpImpl;
|
||||
|
||||
protected:
|
||||
Crypto();
|
||||
|
||||
public:
|
||||
virtual ~Crypto();
|
||||
};
|
||||
|
||||
/** Decrypt vector of bytes with AES encryption */
|
||||
class COMPHELPER_DLLPUBLIC Decrypt final : public Crypto
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue