12#include <com/sun/star/uno/RuntimeException.hpp>
14#include <config_oox.h>
17#include <openssl/evp.h>
18#include <openssl/sha.h>
19#include <openssl/hmac.h>
32#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
34static HMAC_CTX *HMAC_CTX_new(
void)
36 HMAC_CTX *pContext =
new HMAC_CTX;
37 HMAC_CTX_init(pContext);
41static void HMAC_CTX_free(HMAC_CTX *pContext)
43 HMAC_CTX_cleanup(pContext);
52 void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); }
57 void operator()(HMAC_CTX* p) { HMAC_CTX_free(p); }
63 std::unique_ptr<EVP_CIPHER_CTX, cipher_delete>
mpContext;
64 std::unique_ptr<HMAC_CTX, hmac_delete> mpHmacContext;
66 CryptoImpl() =
default;
68 void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
Crypto::CryptoType eType)
73 const EVP_CIPHER* cipher = getCipher(eType);
74 if (cipher ==
nullptr)
78 EVP_EncryptInit_ex(
mpContext.get(), cipher,
nullptr, key.data(),
nullptr);
80 EVP_EncryptInit_ex(
mpContext.get(), cipher,
nullptr, key.data(), iv.data());
81 EVP_CIPHER_CTX_set_padding(
mpContext.get(), 0);
84 void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
Crypto::CryptoType eType)
89 const EVP_CIPHER* pCipher = getCipher(eType);
90 if (pCipher ==
nullptr)
93 const size_t nMinKeySize = EVP_CIPHER_key_length(pCipher);
94 if (key.size() < nMinKeySize)
95 key.resize(nMinKeySize, 0);
98 EVP_DecryptInit_ex(
mpContext.get(), pCipher,
nullptr, key.data(),
nullptr);
101 const size_t nMinIVSize = EVP_CIPHER_iv_length(pCipher);
102 if (iv.size() < nMinIVSize)
103 iv.resize(nMinIVSize, 0);
105 EVP_DecryptInit_ex(
mpContext.get(), pCipher,
nullptr, key.data(), iv.data());
107 EVP_CIPHER_CTX_set_padding(
mpContext.get(), 0);
110 void setupCryptoHashContext(std::vector<sal_uInt8>& rKey,
CryptoHashType eType)
112 mpHmacContext.reset(HMAC_CTX_new());
113 const EVP_MD* aEvpMd =
nullptr;
117 aEvpMd = EVP_sha1();
break;
119 aEvpMd = EVP_sha256();
break;
121 aEvpMd = EVP_sha512();
break;
123 HMAC_Init_ex(mpHmacContext.get(), rKey.data(), rKey.size(), aEvpMd,
nullptr);
136 case Crypto::CryptoType::AES_128_ECB:
137 return EVP_aes_128_ecb();
138 case Crypto::CryptoType::AES_128_CBC:
139 return EVP_aes_128_cbc();
140 case Crypto::CryptoType::AES_256_CBC:
141 return EVP_aes_256_cbc();
151#define MAX_WRAPPED_KEY_LEN 128
156 PK11Context* mContext;
159 PK11Context* mWrapKeyContext;
160 PK11SymKey* mWrapKey;
167 , mWrapKeyContext(nullptr)
171 if (!NSS_IsInitialized())
173 auto const e = NSS_NoDB_Init(
nullptr);
176 PRErrorCode error = PR_GetError();
177 const char* errorText = PR_ErrorToName(error);
178 throw css::uno::RuntimeException(
"NSS_NoDB_Init failed with " + OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) +
" (" + OUString::number(
static_cast<int>(error)) +
")");
186 PK11_DestroyContext(mContext, PR_TRUE);
188 SECITEM_FreeItem(mSecParam, PR_TRUE);
190 PK11_FreeSymKey(mSymKey);
192 PK11_DestroyContext(mWrapKeyContext, PR_TRUE);
194 PK11_FreeSymKey(mWrapKey);
196 PK11_FreeSlot(mSlot);
199 PK11SymKey* ImportSymKey(CK_MECHANISM_TYPE mechanism, CK_ATTRIBUTE_TYPE operation, SECItem* key)
201 mSymKey = PK11_ImportSymKey(mSlot, mechanism, PK11_OriginUnwrap, operation, key,
nullptr);
217 CK_MECHANISM_TYPE wrap_mechanism = PK11_GetBestWrapMechanism(mSlot);
218 int wrap_key_len = PK11_GetBestKeyLength(mSlot, wrap_mechanism);
219 mWrapKey = PK11_KeyGen(mSlot, wrap_mechanism,
nullptr, wrap_key_len,
nullptr);
221 throw css::uno::RuntimeException(
"PK11_KeyGen SymKey failure", css::uno::Reference<css::uno::XInterface>());
230 SECItem tmp_sec_item = {};
231 mWrapKeyContext = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, mWrapKey, &tmp_sec_item);
232 if (!mWrapKeyContext)
233 throw css::uno::RuntimeException(
"PK11_CreateContextBySymKey failure", css::uno::Reference<css::uno::XInterface>());
235 unsigned char wrapped_key_data[MAX_WRAPPED_KEY_LEN];
236 int wrapped_key_len =
sizeof(wrapped_key_data);
238 if (PK11_CipherOp(mWrapKeyContext, wrapped_key_data, &wrapped_key_len,
239 sizeof(wrapped_key_data), key->data, key->len) != SECSuccess)
241 throw css::uno::RuntimeException(
"PK11_CipherOp failure", css::uno::Reference<css::uno::XInterface>());
244 if (PK11_Finalize(mWrapKeyContext) != SECSuccess)
245 throw css::uno::RuntimeException(
"PK11_Finalize failure", css::uno::Reference<css::uno::XInterface>());
250 SECItem wrapped_key = {};
251 wrapped_key.data = wrapped_key_data;
252 wrapped_key.len = wrapped_key_len;
254 mSymKey = PK11_UnwrapSymKey(mWrapKey, wrap_mechanism, &tmp_sec_item, &wrapped_key,
255 mechanism, operation, key->len);
260 void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
Crypto::CryptoType type, CK_ATTRIBUTE_TYPE operation)
262 CK_MECHANISM_TYPE mechanism =
static_cast<CK_ULONG
>(-1);
265 ivItem.type = siBuffer;
267 ivItem.data =
nullptr;
269 ivItem.data = iv.data();
270 ivItem.len = iv.size();
272 SECItem* pIvItem =
nullptr;
276 case Crypto::CryptoType::AES_128_ECB:
277 mechanism = CKM_AES_ECB;
279 case Crypto::CryptoType::AES_128_CBC:
280 mechanism = CKM_AES_CBC;
283 case Crypto::CryptoType::AES_256_CBC:
284 mechanism = CKM_AES_CBC;
291 mSlot = PK11_GetBestSlot(mechanism,
nullptr);
294 throw css::uno::RuntimeException(
"NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
297 keyItem.type = siBuffer;
298 keyItem.data = key.data();
299 keyItem.len = key.size();
301 mSymKey = ImportSymKey(mechanism, CKA_ENCRYPT, &keyItem);
303 throw css::uno::RuntimeException(
"NSS SymKey failure", css::uno::Reference<css::uno::XInterface>());
305 mSecParam = PK11_ParamFromIV(mechanism, pIvItem);
306 mContext = PK11_CreateContextBySymKey(mechanism, operation, mSymKey, mSecParam);
309 void setupCryptoHashContext(std::vector<sal_uInt8>& rKey,
CryptoHashType eType)
311 CK_MECHANISM_TYPE aMechanism =
static_cast<CK_ULONG
>(-1);
316 aMechanism = CKM_SHA_1_HMAC;
319 aMechanism = CKM_SHA256_HMAC;
322 aMechanism = CKM_SHA512_HMAC;
326 mSlot = PK11_GetBestSlot(aMechanism,
nullptr);
329 throw css::uno::RuntimeException(
"NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
332 aKeyItem.data = rKey.data();
333 aKeyItem.len = rKey.size();
335 mSymKey = ImportSymKey(aMechanism, CKA_SIGN, &aKeyItem);
337 throw css::uno::RuntimeException(
"NSS SymKey failure", css::uno::Reference<css::uno::XInterface>());
340 param.data =
nullptr;
342 mContext = PK11_CreateContextBySymKey(aMechanism, CKA_SIGN, mSymKey, ¶m);
363#if USE_TLS_OPENSSL + USE_TLS_NSS == 0
374 mpImpl->setupCryptoContext(key, iv,
type, CKA_DECRYPT);
378sal_uInt32
Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength)
380 int outputLength = 0;
382#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
383 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
391 (void)EVP_DecryptUpdate(
mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength);
397 (void)PK11_CipherOp(
mpImpl->mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength);
400 return static_cast<sal_uInt32
>(outputLength);
403sal_uInt32
Decrypt::aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, std::vector<sal_uInt8>& key)
405 sal_uInt32 outputLength = 0;
406 std::vector<sal_uInt8> iv;
408 outputLength = crypto.
update(output, input);
416#if USE_TLS_OPENSSL + USE_TLS_NSS == 0
425 mpImpl->setupCryptoContext(key, iv,
type, CKA_ENCRYPT);
429sal_uInt32
Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength)
431 int outputLength = 0;
433#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
434 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
442 (void)EVP_EncryptUpdate(
mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength);
446 (void)PK11_CipherOp(
mpImpl->mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength);
449 return static_cast<sal_uInt32
>(outputLength);
471 : mnHashSize(getSizeForHashType(
eType))
477 PK11_DigestBegin(
mpImpl->mContext);
485#if USE_TLS_OPENSSL + USE_TLS_NSS > 0
486 sal_uInt32 nActualInputLength = (nInputLength == 0 || nInputLength > rInput.size()) ? rInput.size() : nInputLength;
493 return HMAC_Update(
mpImpl->mpHmacContext.get(), rInput.data(), nActualInputLength) != 0;
495 return PK11_DigestOp(
mpImpl->mContext, rInput.data(), nActualInputLength) == SECSuccess;
504 unsigned int nSizeWritten;
506 (void) HMAC_Final(
mpImpl->mpHmacContext.get(), aHash.data(), &nSizeWritten);
508 PK11_DigestFinal(
mpImpl->mContext, aHash.data(), &nSizeWritten, aHash.size());
std::vector< sal_uInt8 > finalize()
bool update(std::vector< sal_uInt8 > &rInput, sal_uInt32 nInputLength=0)
CryptoHash(std::vector< sal_uInt8 > &rKey, CryptoHashType eType)
std::unique_ptr< CryptoImpl > mpImpl
Decrypt(std::vector< sal_uInt8 > &key, std::vector< sal_uInt8 > &iv, CryptoType type)
sal_uInt32 update(std::vector< sal_uInt8 > &output, std::vector< sal_uInt8 > &input, sal_uInt32 inputLength=0)
static sal_uInt32 aes128ecb(std::vector< sal_uInt8 > &output, std::vector< sal_uInt8 > &input, std::vector< sal_uInt8 > &key)
sal_uInt32 update(std::vector< sal_uInt8 > &output, std::vector< sal_uInt8 > &input, sal_uInt32 inputLength=0)
Encrypt(std::vector< sal_uInt8 > &key, std::vector< sal_uInt8 > &iv, CryptoType type)
ParserContextSharedPtr mpContext