Files
loongoffice/oox/source/crypto/CryptTools.cxx
Michael Stahl c980d4970b warning C4245 signed/unsigned mismatch
Change-Id: If28543252ee2265e9edd7d7963c1751bd21e754d
2014-08-13 23:01:01 +02:00

344 lines
8.0 KiB
C++

/* -*- 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 "oox/crypto/CryptTools.hxx"
#include <com/sun/star/uno/RuntimeException.hpp>
namespace oox {
namespace core {
using namespace std;
Crypto::Crypto(CryptoType type)
: mType(type)
#if USE_TLS_NSS
, mContext(NULL)
, mSecParam(NULL)
, mSymKey(NULL)
#endif
{
#if USE_TLS_NSS
// Initialize NSS, database functions are not needed
NSS_NoDB_Init(NULL);
#endif // USE_TLS_NSS
}
Crypto::~Crypto()
{
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX_cleanup( &mContext );
#endif
#if USE_TLS_NSS
PK11_DestroyContext( mContext, PR_TRUE );
PK11_FreeSymKey( mSymKey );
SECITEM_FreeItem( mSecParam, PR_TRUE );
#endif
}
#if USE_TLS_OPENSSL
const EVP_CIPHER* Crypto::getCipher(CryptoType type)
{
switch(type)
{
case AES_128_ECB:
return EVP_aes_128_ecb();
case AES_128_CBC:
return EVP_aes_128_cbc();
case AES_256_CBC:
return EVP_aes_256_cbc();
default:
break;
}
return NULL;
}
#endif
#if USE_TLS_NSS
void Crypto::setupContext(vector<sal_uInt8>& key, 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 = NULL;
else
ivItem.data = &iv[0];
ivItem.len = iv.size();
SECItem* pIvItem = NULL;
switch(type)
{
case AES_128_ECB:
mechanism = CKM_AES_ECB;
break;
case AES_128_CBC:
mechanism = CKM_AES_CBC;
pIvItem = &ivItem;
break;
case AES_256_CBC:
mechanism = CKM_AES_CBC;
pIvItem = &ivItem;
break;
default:
break;
}
PK11SlotInfo* pSlot( PK11_GetBestSlot( mechanism, NULL ) );
if (!pSlot)
throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
SECItem keyItem;
keyItem.type = siBuffer;
keyItem.data = &key[0];
keyItem.len = key.size();
mSymKey = PK11_ImportSymKey( pSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL );
mSecParam = PK11_ParamFromIV( mechanism, pIvItem );
mContext = PK11_CreateContextBySymKey( mechanism, operation, mSymKey, mSecParam );
}
#endif // USE_TLS_NSS
// DECRYPT
Decrypt::Decrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
Crypto(type)
{
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX_init( &mContext );
const EVP_CIPHER* cipher = getCipher(type);
if (iv.empty())
EVP_DecryptInit_ex( &mContext, cipher, NULL, &key[0], 0 );
else
EVP_DecryptInit_ex( &mContext, cipher, NULL, &key[0], &iv[0] );
EVP_CIPHER_CTX_set_padding( &mContext, 0 );
#endif
#if USE_TLS_NSS
setupContext(key, iv, type, CKA_DECRYPT);
#endif // USE_TLS_NSS
}
sal_uInt32 Decrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
{
int outputLength = 0;
sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
#if USE_TLS_OPENSSL
EVP_DecryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
#endif // USE_TLS_NSS
return static_cast<sal_uInt32>(outputLength);
}
sal_uInt32 Decrypt::aes128ecb(vector<sal_uInt8>& output, vector<sal_uInt8>& input, vector<sal_uInt8>& key)
{
sal_uInt32 outputLength = 0;
vector<sal_uInt8> iv;
Decrypt crypto(key, iv, Crypto::AES_128_ECB);
outputLength = crypto.update(output, input);
return outputLength;
}
// ENCRYPT
Encrypt::Encrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
Crypto(type)
{
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX_init( &mContext );
const EVP_CIPHER* cipher = getCipher(type);
if (iv.empty())
EVP_EncryptInit_ex( &mContext, cipher, NULL, &key[0], 0 );
else
EVP_EncryptInit_ex( &mContext, cipher, NULL, &key[0], &iv[0] );
EVP_CIPHER_CTX_set_padding( &mContext, 0 );
#endif
#if USE_TLS_NSS
setupContext(key, iv, type, CKA_ENCRYPT);
#endif // USE_TLS_NSS
}
sal_uInt32 Encrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
{
int outputLength = 0;
sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
#if USE_TLS_OPENSSL
EVP_EncryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
#endif // USE_TLS_NSS
return static_cast<sal_uInt32>(outputLength);
}
// Digest
#if USE_TLS_OPENSSL
const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA_DIGEST_LENGTH;
const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_DIGEST_LENGTH;
#endif
#if USE_TLS_NSS
const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA1_LENGTH;
const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_LENGTH;
#endif
namespace
{
#if USE_TLS_OPENSSL
const EVP_MD* lclOpenSSLgetEngine(Digest::DigestType eType)
{
switch(eType)
{
case Digest::SHA1:
return EVP_sha1();
case Digest::SHA512:
return EVP_sha512();
default:
break;
}
return NULL;
}
#endif
#if USE_TLS_NSS
HASH_HashType lclNSSgetHashType(Digest::DigestType eType)
{
switch(eType)
{
case Digest::SHA1:
return HASH_AlgSHA1;
case Digest::SHA512:
return HASH_AlgSHA512;
default:
break;
}
return HASH_AlgNULL;
}
#endif
}
Digest::Digest(DigestType eType) :
meType(eType)
{
#if USE_TLS_OPENSSL
mpContext = EVP_MD_CTX_create();
EVP_DigestInit_ex(mpContext, lclOpenSSLgetEngine(eType), NULL);
#endif
#if USE_TLS_NSS
NSS_NoDB_Init(NULL);
mpContext = HASH_Create(lclNSSgetHashType(eType));
HASH_Begin(mpContext);
#endif
}
Digest::~Digest()
{
#if USE_TLS_OPENSSL
if(mpContext)
EVP_MD_CTX_destroy(mpContext);
#endif
#if USE_TLS_NSS
if(mpContext)
HASH_Destroy(mpContext);
#endif
}
sal_uInt32 Digest::getLength()
{
switch(meType)
{
case SHA1:
return DIGEST_LENGTH_SHA1;
case SHA512:
return DIGEST_LENGTH_SHA512;
default:
break;
}
return 0;
}
bool Digest::update(std::vector<sal_uInt8>& input)
{
#if USE_TLS_OPENSSL
EVP_DigestUpdate(mpContext, &input[0], input.size());
#endif
#if USE_TLS_NSS
HASH_Update(mpContext, &input[0], input.size());
#endif
return true;
}
bool Digest::finalize(std::vector<sal_uInt8>& digest)
{
digest.clear();
#if USE_TLS_OPENSSL
unsigned int digestWrittenLength;
digest.resize(getLength(), 0);
EVP_DigestFinal_ex(mpContext, &digest[0], &digestWrittenLength);
#endif
#if USE_TLS_NSS
unsigned int digestWrittenLength;
unsigned int digestLength = static_cast<unsigned int>(getLength());
digest.resize(digestLength, 0);
HASH_End(mpContext, &digest[0], &digestWrittenLength, digestLength);
#endif
return true;
}
bool Digest::sha1(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
{
bool aResult = false;
Digest aDigest(SHA1);
aDigest.update(input);
aDigest.finalize(output);
aResult = true;
return aResult;
}
bool Digest::sha512(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
{
bool aResult = false;
Digest aDigest(SHA512);
aDigest.update(input);
aDigest.finalize(output);
aResult = true;
return aResult;
}
} // namespace core
} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */