Kaydet (Commit) 4323c668 authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

fdo#35422 Support to open encrypted Office 2010 and 2013 formats

Additionally encryption and decryption has been refactored.
2 engines have been added: AgileEngine and Standard2007Engine,
which contain core functions for encryption and decryption.
Standard2007Engine refers to encryption and decryption as used
in Office 2007 and AgileEngine refers to encryption and decryption
as used in Office 2010 and 2013. AgileEngine does not yet support
encryption.

Change-Id: Ica1d4d5a109fb204012b92a0c39325fe0b99b793
üst 4d688beb
/* -*- 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/.
*
*/
#ifndef AGILE_ENGINE_HXX
#define AGILE_ENGINE_HXX
#include "CryptTools.hxx"
#include "CryptoEngine.hxx"
namespace oox {
namespace core {
const sal_uInt32 SEGMENT_LENGTH = 4096;
struct AgileEncryptionInfo
{
sal_Int32 spinCount;
sal_Int32 saltSize;
sal_Int32 keyBits;
sal_Int32 hashSize;
sal_Int32 blockSize;
OUString cipherAlgorithm;
OUString cipherChaining;
OUString hashAlgorithm;
std::vector<sal_uInt8> keyDataSalt;
std::vector<sal_uInt8> saltValue;
std::vector<sal_uInt8> encryptedVerifierHashInput;
std::vector<sal_uInt8> encryptedVerifierHashValue;
std::vector<sal_uInt8> encryptedKeyValue;
};
class AgileEngine : public CryptoEngine
{
AgileEncryptionInfo mInfo;
bool calculateHashFinal(const OUString& rPassword, std::vector<sal_uInt8>& aHashFinal);
bool calculateBlock(
const std::vector<sal_uInt8>& rBlock,
std::vector<sal_uInt8>& rHashFinal,
std::vector<sal_uInt8>& rInput,
std::vector<sal_uInt8>& rOutput);
Crypto::CryptoType cryptoType(const AgileEncryptionInfo& rInfo);
public:
AgileEngine();
virtual ~AgileEngine();
AgileEncryptionInfo& getInfo();
virtual bool writeEncryptionInfo(
const OUString& rPassword,
BinaryXOutputStream& rStream);
virtual bool generateEncryptionKey(const OUString& rPassword);
virtual bool decrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream);
virtual bool encrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream);
};
} // namespace core
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef CRYPT_TOOLS_HXX
#define CRYPT_TOOLS_HXX
#include <config_oox.h>
#include <rtl/ustring.hxx>
#if USE_TLS_OPENSSL
#include <openssl/evp.h>
#include <openssl/sha.h>
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
#include <nss.h>
#include <pk11pub.h>
#endif // USE_TLS_NSS
#include <rtl/digest.h>
#include <vector>
namespace oox {
namespace core {
class Crypto
{
public:
enum CryptoType
{
UNKNOWN,
AES_128_ECB,
AES_128_CBC,
AES_256_CBC,
};
protected:
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX mContext;
#endif
#if USE_TLS_NSS
PK11Context* mContext;
SECItem* mSecParam;
PK11SymKey* mSymKey;
#endif
CryptoType mType;
#if USE_TLS_OPENSSL
const EVP_CIPHER* getCipher(CryptoType type);
#endif
#if USE_TLS_NSS
void setupContext(
std::vector<sal_uInt8>& key,
std::vector<sal_uInt8>& iv,
CryptoType type,
CK_ATTRIBUTE_TYPE operation);
#endif
public:
Crypto(CryptoType type);
virtual ~Crypto();
virtual sal_uInt32 update(
std::vector<sal_uInt8>& output,
std::vector<sal_uInt8>& input,
sal_uInt32 inputLength = 0) = 0;
};
class Decrypt : public Crypto
{
public:
Decrypt(std::vector<sal_uInt8>& key, CryptoType type);
Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type);
virtual 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 );
static sal_uInt32 aes128cbc(
std::vector<sal_uInt8>& output,
std::vector<sal_uInt8>& input,
std::vector<sal_uInt8>& key,
std::vector<sal_uInt8>& iv );
};
class Encrypt : public Crypto
{
public:
Encrypt(std::vector<sal_uInt8>& key, CryptoType type);
Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type);
virtual sal_uInt32 update(
std::vector<sal_uInt8>& output,
std::vector<sal_uInt8>& input,
sal_uInt32 inputLength = 0);
};
const sal_uInt32 SHA1_LENGTH = 20;
const sal_uInt32 SHA512_LENGTH = 64;
bool sha1( std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input );
bool sha512( std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input );
} // namespace core
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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/.
*
*/
#ifndef CRYPTO_ENGINE_HXX
#define CRYPTO_ENGINE_HXX
#include <vector>
#include "oox/helper/binaryinputstream.hxx"
#include "oox/helper/binaryoutputstream.hxx"
namespace oox {
namespace core {
class CryptoEngine
{
protected:
std::vector<sal_uInt8> mKey;
public:
CryptoEngine()
{}
virtual ~CryptoEngine()
{}
virtual std::vector<sal_uInt8>& getKey()
{
return mKey;
}
virtual bool writeEncryptionInfo(
const OUString& rPassword,
BinaryXOutputStream& rStream) = 0;
virtual bool generateEncryptionKey(const OUString& rPassword) = 0;
virtual bool decrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream) = 0;
virtual bool encrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream) = 0;
};
} // namespace core
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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/.
*
*/
#ifndef DOCUMENT_DECRYPTION_HXX
#define DOCUMENT_DECRYPTION_HXX
#include "oox/dllapi.h"
#include "oox/ole/olestorage.hxx"
#include "oox/helper/binaryinputstream.hxx"
#include "oox/helper/binaryoutputstream.hxx"
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include "CryptTools.hxx"
#include "AgileEngine.hxx"
#include "Standard2007Engine.hxx"
#include <boost/scoped_ptr.hpp>
#include <vector>
namespace oox {
namespace core {
class OOX_DLLPUBLIC DocumentDecryption
{
private:
com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > mxContext;
enum CryptoType
{
UNKNOWN,
STANDARD_2007,
AGILE
};
oox::ole::OleStorage& mrOleStorage;
boost::scoped_ptr<CryptoEngine> mEngine;
CryptoType mCryptoType;
bool readAgileEncryptionInfo( com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& rStream );
bool readStandard2007EncryptionInfo( BinaryInputStream& rStream );
public:
DocumentDecryption(
oox::ole::OleStorage& rOleStorage,
com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > xContext);
bool decrypt(com::sun::star::uno::Reference< com::sun::star::io::XStream > xDocumentStream);
bool readEncryptionInfo();
bool generateEncryptionKey(const OUString& rPassword);
com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue > createEncryptionData();
static bool checkEncryptionData( const com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue >& rEncryptionData );
};
} // namespace core
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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/.
*
*/
#ifndef DOCUMENT_ENCRYPTION_HXX
#define DOCUMENT_ENCRYPTION_HXX
#include "oox/dllapi.h"
#include "oox/ole/olestorage.hxx"
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include "CryptTools.hxx"
#include "Standard2007Engine.hxx"
#include <vector>
namespace oox {
namespace core {
class OOX_DLLPUBLIC DocumentEncryption
{
private:
com::sun::star::uno::Reference< com::sun::star::io::XStream > mxDocumentStream;
oox::ole::OleStorage& mrOleStorage;
OUString maPassword;
Standard2007Engine mEngine;
public:
DocumentEncryption(
com::sun::star::uno::Reference< com::sun::star::io::XStream > xDocumentStream,
oox::ole::OleStorage& rOleStorage,
OUString aPassword);
bool encrypt();
};
} // namespace core
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -6,32 +6,13 @@
* 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef DOCUMENTCRYPTO_HXX
#define DOCUMENTCRYPTO_HXX
#include "oox/dllapi.h"
#include "oox/ole/olestorage.hxx"
#include "oox/helper/binaryinputstream.hxx"
#include "oox/helper/binaryoutputstream.hxx"
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <vector>
#ifndef STANDARD_2007_ENGINE_HXX
#define STANDARD_2007_ENGINE_HXX
#include "CryptTools.hxx"
#include "CryptoEngine.hxx"
namespace oox {
namespace core {
......@@ -56,11 +37,13 @@ const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES = 0x00000018;
const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4 = 0x00000001;
// version of encryption info used in MS Office 2007 (major = 3, minor = 2)
const sal_uInt32 VERSION_INFO_2007_FORMAT = 0x00030002;
const sal_uInt32 VERSION_INFO_2007_FORMAT = 0x00020003;
// version of encryption info - agile (major = 4, minor = 4)
const sal_uInt32 VERSION_INFO_AGILE = 0x00040004;
const sal_Int32 SALT_LENGTH = 16;
const sal_Int32 ENCRYPTED_VERIFIER_LENGTH = 16;
const sal_Int32 ENCRYPTED_VERIFIER_HASH_LENGTH = 32;
const sal_uInt32 SALT_LENGTH = 16;
const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH = 16;
const sal_uInt32 ENCRYPTED_VERIFIER_HASH_LENGTH = 32;
struct EncryptionStandardHeader
{
......@@ -68,7 +51,7 @@ struct EncryptionStandardHeader
sal_uInt32 sizeExtra; // 0
sal_uInt32 algId; // if flag AES && CRYPTOAPI this defaults to 128-bit AES
sal_uInt32 algIdHash; // 0: determine by flags - defaults to SHA-1 if not external
sal_uInt32 keySize; // key size in bits: 0 (determine by flags), 128, 192, 256
sal_uInt32 keyBits; // key size in bits: 0 (determine by flags), 128, 192, 256
sal_uInt32 providedType; // AES or RC4
sal_uInt32 reserved1; // 0
sal_uInt32 reserved2; // 0
......@@ -76,7 +59,6 @@ struct EncryptionStandardHeader
EncryptionStandardHeader();
};
struct EncryptionVerifierAES
{
sal_uInt32 saltSize; // must be 0x00000010
......@@ -88,56 +70,44 @@ struct EncryptionVerifierAES
EncryptionVerifierAES();
};
struct PackageEncryptionInfo
struct StandardEncryptionInfo
{
EncryptionStandardHeader header;
EncryptionVerifierAES verifier;
};
class OOX_DLLPUBLIC AesEncoder
class Standard2007Engine : public CryptoEngine
{
private:
com::sun::star::uno::Reference< com::sun::star::io::XStream > mxDocumentStream;
oox::ole::OleStorage& mrOleStorage;
OUString maPassword;
StandardEncryptionInfo mInfo;
PackageEncryptionInfo mEncryptionInfo;
bool checkEncryptionInfo(std::vector<sal_uInt8>& aKey, sal_uInt32 aKeyLength);
bool writeEncryptionInfo( BinaryOutputStream& rStream );
bool generateVerifier();
bool calculateEncryptionKey(const OUString& rPassword);
public:
AesEncoder(
com::sun::star::uno::Reference< com::sun::star::io::XStream > xDocumentStream,
oox::ole::OleStorage& rOleStorage,
OUString aPassword);
bool encode();
};
Standard2007Engine();
virtual ~Standard2007Engine();
class OOX_DLLPUBLIC AesDecoder
{
private:
oox::ole::OleStorage& mrOleStorage;
PackageEncryptionInfo mEncryptionInfo;
std::vector<sal_uInt8> mKey;
sal_uInt32 mKeyLength;
StandardEncryptionInfo& getInfo();
bool readEncryptionInfoFromStream( BinaryInputStream& rStream );
static bool checkEncryptionData(
std::vector<sal_uInt8> key, sal_uInt32 keySize,
std::vector<sal_uInt8> encryptedVerifier, sal_uInt32 verifierSize,
std::vector<sal_uInt8> encryptedHash, sal_uInt32 hashSize );
public:
AesDecoder(oox::ole::OleStorage& rOleStorage);
virtual bool generateEncryptionKey(const OUString& rPassword);
bool decode(com::sun::star::uno::Reference< com::sun::star::io::XStream > xDocumentStream);
bool readEncryptionInfo();
bool generateEncryptionKey(const OUString& rPassword);
virtual bool writeEncryptionInfo(
const OUString& rPassword,
BinaryXOutputStream& rStream);
com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue > createEncryptionData();
virtual bool decrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream);
bool checkCurrentEncryptionData();
virtual bool encrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream);
static bool checkEncryptionData( const com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue >& rEncryptionData );
};
} // namespace core
......
......@@ -78,7 +78,6 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
oox/source/core/binarycodec \
oox/source/core/contexthandler2 \
oox/source/core/contexthandler \
oox/source/core/DocumentCrypt \
oox/source/core/fastparser \
oox/source/core/fasttokenhandler \
oox/source/core/filterbase \
......@@ -90,6 +89,11 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
oox/source/core/relationshandler \
oox/source/core/services \
oox/source/core/xmlfilterbase \
oox/source/crypto/AgileEngine \
oox/source/crypto/CryptTools \
oox/source/crypto/DocumentEncryption \
oox/source/crypto/DocumentDecryption \
oox/source/crypto/Standard2007Engine \
oox/source/docprop/docprophandler \
oox/source/docprop/ooxmldocpropimport \
oox/source/drawingml/chart/axiscontext \
......
This diff is collapsed.
......@@ -24,12 +24,13 @@
#include <comphelper/docpasswordhelper.hxx>
#include <comphelper/mediadescriptor.hxx>
#include "oox/core/DocumentCrypt.hxx"
#include "oox/core/fastparser.hxx"
#include "oox/helper/attributelist.hxx"
#include "oox/helper/zipstorage.hxx"
#include "oox/ole/olestorage.hxx"
#include "oox/crypto/DocumentDecryption.hxx"
#include <com/sun/star/uri/UriReferenceFactory.hpp>
namespace oox {
......@@ -270,23 +271,23 @@ bool lclIsZipPackage( const Reference< XComponentContext >& rxContext, const Ref
class PasswordVerifier : public IDocPasswordVerifier
{
public:
explicit PasswordVerifier( AesDecoder& decoder );
explicit PasswordVerifier( DocumentDecryption& aDecryptor );
virtual DocPasswordVerifierResult verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData );
virtual DocPasswordVerifierResult verifyEncryptionData( const Sequence<NamedValue>& rEncryptionData );
private:
AesDecoder& mDecoder;
DocumentDecryption& mDecryptor;
};
PasswordVerifier::PasswordVerifier( AesDecoder& decoder ) :
mDecoder(decoder)
PasswordVerifier::PasswordVerifier( DocumentDecryption& aDecryptor ) :
mDecryptor(aDecryptor)
{}
comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData )
{
if( mDecoder.generateEncryptionKey(rPassword) && mDecoder.checkCurrentEncryptionData() )
rEncryptionData = mDecoder.createEncryptionData();
if( mDecryptor.generateEncryptionKey(rPassword) )
rEncryptionData = mDecryptor.createEncryptionData();
return rEncryptionData.hasElements() ? comphelper::DocPasswordVerifierResult_OK : comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
}
......@@ -294,7 +295,7 @@ comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OU
comphelper::DocPasswordVerifierResult PasswordVerifier::verifyEncryptionData( const Sequence<NamedValue>& rEncryptionData )
{
comphelper::DocPasswordVerifierResult aResult = comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
if (AesDecoder::checkEncryptionData(rEncryptionData))
if (DocumentDecryption::checkEncryptionData(rEncryptionData))
aResult = comphelper::DocPasswordVerifierResult_OK;
return aResult;
}
......@@ -324,9 +325,9 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
{
try
{
AesDecoder aDecoder(aOleStorage);
DocumentDecryption aDecryptor(aOleStorage, mxContext);
if( aDecoder.readEncryptionInfo() )
if( aDecryptor.readEncryptionInfo() )
{
/* "VelvetSweatshop" is the built-in default encryption
password used by MS Excel for the "workbook protection"
......@@ -339,7 +340,7 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
This helper returns either with the correct password
(according to the verifier), or with an empty string if
user has cancelled the password input dialog. */
PasswordVerifier aVerifier( aDecoder );
PasswordVerifier aVerifier( aDecryptor );
Sequence<NamedValue> aEncryptionData;
aEncryptionData = comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
aVerifier, rMediaDescriptor,
......@@ -354,7 +355,7 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
{
// create temporary file for unencrypted package
Reference<XStream> xTempFile( TempFile::create(mxContext), UNO_QUERY_THROW );
aDecoder.decode( xTempFile );
aDecryptor.decrypt( xTempFile );
// store temp file in media descriptor to keep it alive
rMediaDescriptor.setComponentDataEntry( "DecryptedPackage", Any( xTempFile ) );
......
......@@ -49,7 +49,7 @@
#include <oox/core/filterdetect.hxx>
#include <comphelper/storagehelper.hxx>
#include <oox/core/DocumentCrypt.hxx>
#include <oox/crypto/DocumentEncryption.hxx>
using ::com::sun::star::xml::dom::DocumentBuilder;
using ::com::sun::star::xml::dom::XDocument;
......@@ -704,8 +704,8 @@ bool XmlFilterBase::implFinalizeExport( MediaDescriptor& rMediaDescriptor )
Reference< XStream> xDocumentStream (FilterBase::implGetOutputStream(rMediaDescriptor));
oox::ole::OleStorage aOleStorage( getComponentContext(), xDocumentStream, true );
AesEncoder encoder(getMainDocumentStream(), aOleStorage, aPassword);
bRet = encoder.encode();
DocumentEncryption encryptor(getMainDocumentStream(), aOleStorage, aPassword);
bRet = encryptor.encrypt();
if (bRet)
aOleStorage.commit();
}
......
/* -*- 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/AgileEngine.hxx"
namespace oox {
namespace core {
using namespace std;
namespace {
static const vector<sal_uInt8> vectorBlock1({ 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 });
static const vector<sal_uInt8> vectorBlock2({ 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e });
static const vector<sal_uInt8> vectorBlock3({ 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6 });
bool hashCalc( std::vector<sal_uInt8>& output,
std::vector<sal_uInt8>& input,
const OUString& algorithm )
{
if (algorithm == "SHA1")
return sha1(output, input);
else if (algorithm == "SHA512")
return sha512(output, input);
return false;
}
} // namespace
AgileEngine::AgileEngine() :
CryptoEngine()
{}
AgileEngine::~AgileEngine()
{}
AgileEncryptionInfo& AgileEngine::getInfo()
{
return mInfo;
}
Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo)
{
if (rInfo.keyBits == 128 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
return Crypto::AES_128_CBC;
else if (rInfo.keyBits == 256 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
return Crypto::AES_256_CBC;
return Crypto::UNKNOWN;
}
bool AgileEngine::calculateBlock(
const vector<sal_uInt8>& rBlock,
vector<sal_uInt8>& rHashFinal,
vector<sal_uInt8>& rInput,
vector<sal_uInt8>& rOutput)
{
vector<sal_uInt8> hash(mInfo.hashSize, 0);
vector<sal_uInt8> salt = mInfo.saltValue;
vector<sal_uInt8> dataFinal(mInfo.hashSize + rBlock.size(), 0);
std::copy(rHashFinal.begin(), rHashFinal.end(), dataFinal.begin());
std::copy(
rBlock.begin(),
rBlock.begin() + rBlock.size(),
dataFinal.begin() + mInfo.hashSize);
hashCalc(hash, dataFinal, mInfo.hashAlgorithm);
sal_Int32 keySize = mInfo.keyBits / 8;
vector<sal_uInt8> key(keySize, 0);
std::copy(hash.begin(), hash.begin() + keySize, key.begin());
Decrypt aDecryptor(key, salt, cryptoType(mInfo));
aDecryptor.update(rOutput, rInput);
return true;
}
bool AgileEngine::calculateHashFinal(const OUString& rPassword, vector<sal_uInt8>& aHashFinal)
{
sal_Int32 saltSize = mInfo.saltSize;
vector<sal_uInt8> salt = mInfo.saltValue;
sal_uInt32 passwordByteLength = rPassword.getLength() * 2;
vector<sal_uInt8> initialData(saltSize + passwordByteLength);
std::copy(salt.begin(), salt.end(), initialData.begin());
const sal_uInt8* passwordByteArray = reinterpret_cast<const sal_uInt8*>(rPassword.getStr());
std::copy(
passwordByteArray,
passwordByteArray + passwordByteLength,
initialData.begin() + saltSize);
vector<sal_uInt8> hash(mInfo.hashSize, 0);
hashCalc(hash, initialData, mInfo.hashAlgorithm);
vector<sal_uInt8> data(mInfo.hashSize + 4, 0);
for (int i = 0; i < mInfo.spinCount; i++)
{
ByteOrderConverter::writeLittleEndian( &data[0], i );
std::copy(hash.begin(), hash.end(), data.begin() + 4);
hashCalc(hash, data, mInfo.hashAlgorithm);
}
std::copy(hash.begin(), hash.end(), aHashFinal.begin());
return true;
}
bool AgileEngine::generateEncryptionKey(const OUString& rPassword)
{
mKey.clear();
mKey.resize(mInfo.keyBits / 8, 0);
vector<sal_uInt8> hashFinal(mInfo.hashSize, 0);
calculateHashFinal(rPassword, hashFinal);
vector<sal_uInt8> encryptedHashInput = mInfo.encryptedVerifierHashInput;
vector<sal_uInt8> hashInput(mInfo.saltSize, 0);
calculateBlock(vectorBlock1, hashFinal, encryptedHashInput, hashInput);
vector<sal_uInt8> encryptedHashValue = mInfo.encryptedVerifierHashValue;
vector<sal_uInt8> hashValue(encryptedHashValue.size(), 0);
calculateBlock(vectorBlock2, hashFinal, encryptedHashValue, hashValue);
vector<sal_uInt8> hash(mInfo.hashSize, 0);
hashCalc(hash, hashInput, mInfo.hashAlgorithm);
if (std::equal (hash.begin(), hash.end(), hashValue.begin()) )
{
vector<sal_uInt8> encryptedKeyValue = mInfo.encryptedKeyValue;
calculateBlock(vectorBlock3, hashFinal, encryptedKeyValue, mKey);
return true;
}
return false;
}
bool AgileEngine::decrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream)
{
sal_uInt32 totalSize;
aInputStream >> totalSize; // Document unencrypted size - 4 bytes
aInputStream.skip( 4 ); // Reserved 4 Bytes
vector<sal_uInt8> keyDataSalt = mInfo.keyDataSalt;
sal_uInt32 saltSize = mInfo.saltSize;
sal_uInt32 keySize = mInfo.keyBits / 8;
sal_uInt32 segment = 0;
vector<sal_uInt8> saltWithBlockKey(saltSize + sizeof(segment), 0);
std::copy(keyDataSalt.begin(), keyDataSalt.end(), saltWithBlockKey.begin());
vector<sal_uInt8> hash(mInfo.hashSize, 0);
vector<sal_uInt8> iv(keySize, 0);
vector<sal_uInt8> inputBuffer (SEGMENT_LENGTH);
vector<sal_uInt8> outputBuffer(SEGMENT_LENGTH);
sal_uInt32 inputLength;
sal_uInt32 outputLength;
sal_uInt32 remaining = totalSize;
while( (inputLength = aInputStream.readMemory( &inputBuffer[0], SEGMENT_LENGTH )) > 0 )
{
sal_uInt8* segmentBegin = reinterpret_cast<sal_uInt8*>(&segment);
sal_uInt8* segmentEnd = segmentBegin + sizeof(segment);
std::copy(segmentBegin, segmentEnd, saltWithBlockKey.begin() + saltSize);
hashCalc(hash, saltWithBlockKey, mInfo.hashAlgorithm);
// Only if hash > keySize
std::copy(hash.begin(), hash.begin() + keySize, iv.begin());
Decrypt aDecryptor(mKey, iv, AgileEngine::cryptoType(mInfo));
outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength);
sal_uInt32 writeLength = outputLength > remaining ? remaining : outputLength;
aOutputStream.writeMemory( &outputBuffer[0], writeLength );
remaining -= outputLength;
segment++;
}
return true;
}
bool AgileEngine::writeEncryptionInfo(
const OUString& /*aPassword*/,
BinaryXOutputStream& /*rStream*/)
{
return false; // Agile encrypting is not supported for now
}
bool AgileEngine::encrypt(
BinaryXInputStream& /*aInputStream*/,
BinaryXOutputStream& /*aOutputStream*/)
{
return false; // Agile encrypting is not supported for now
}
} // namespace core
} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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"
namespace oox {
namespace core {
using namespace std;
Crypto::Crypto(CryptoType type) :
mType(type)
{
#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 = -1;
SECItem ivItem;
ivItem.type = siBuffer;
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* aSlot( PK11_GetBestSlot( mechanism, NULL ) );
SECItem keyItem;
keyItem.type = siBuffer;
keyItem.data = &key[0];
keyItem.len = key.size();
mSymKey = PK11_ImportSymKey( aSlot, 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;
}
sal_uInt32 Decrypt::aes128cbc(vector<sal_uInt8>& output, vector<sal_uInt8>& input, vector<sal_uInt8>& key, vector<sal_uInt8>& iv)
{
sal_uInt32 outputLength = 0;
Decrypt crypto(key, iv, Crypto::AES_128_CBC);
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);
}
bool sha1(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
{
output.clear();
output.resize(RTL_DIGEST_LENGTH_SHA1, 0);
rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
rtl_digest_update( aDigest, &input[0], input.size() );
rtl_digest_get( aDigest, &output[0], RTL_DIGEST_LENGTH_SHA1 );
rtl_digest_destroy( aDigest );
return true;
}
bool sha512(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
{
bool aResult = false;
#if USE_TLS_OPENSSL
output.clear();
output.resize(SHA512_DIGEST_LENGTH, 0);
SHA512_CTX context;
SHA512_Init(&context);
SHA512_Update(&context, &input[0], input.size());
SHA512_Final(&output[0], &context);
aResult = true;
#endif
#if USE_TLS_NSS
output.clear();
output.resize(SHA512_LENGTH, 0);
// Initialize NSS, database functions are not needed
NSS_NoDB_Init(NULL);
SECStatus status;
PK11Context* mContext = PK11_CreateDigestContext(SEC_OID_SHA512);
status = PK11_DigestBegin(mContext);
if (status != SECSuccess)
return false;
status = PK11_DigestOp(mContext, &input[0], input.size());
if (status != SECSuccess)
return false;
sal_uInt32 outputLength = 0;
status = PK11_DigestFinal(mContext, &output[0], &outputLength, SHA512_LENGTH);
if (status != SECSuccess || outputLength != SHA512_LENGTH)
return false;
PK11_DestroyContext(mContext, PR_TRUE);
aResult = true;
#endif
return aResult;
}
} // namespace core
} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
This diff is collapsed.
/* -*- 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/DocumentEncryption.hxx"
#include <com/sun/star/io/XSeekable.hpp>
#include "oox/helper/binaryinputstream.hxx"
#include "oox/helper/binaryoutputstream.hxx"
namespace oox {
namespace core {
using namespace css::beans;
using namespace css::io;
using namespace css::lang;
using namespace css::uno;
using namespace std;
DocumentEncryption::DocumentEncryption(Reference< XStream > xDocumentStream, oox::ole::OleStorage& rOleStorage, OUString aPassword) :
mxDocumentStream(xDocumentStream),
mrOleStorage(rOleStorage),
maPassword(aPassword)
{}
bool DocumentEncryption::encrypt()
{
Reference< XInputStream > xInputStream ( mxDocumentStream->getInputStream(), UNO_SET_THROW );
Reference< XSeekable > xSeekable( xInputStream, UNO_QUERY );
if (!xSeekable.is())
return false;
sal_uInt32 aLength = xSeekable->getLength();
if (!mrOleStorage.isStorage())
return false;
Reference< XOutputStream > xEncryptionInfo( mrOleStorage.openOutputStream( "EncryptionInfo" ), UNO_SET_THROW );
BinaryXOutputStream aEncryptionInfoBinaryOutputStream( xEncryptionInfo, false );
mEngine.writeEncryptionInfo(maPassword, aEncryptionInfoBinaryOutputStream);
aEncryptionInfoBinaryOutputStream.close();
xEncryptionInfo->flush();
xEncryptionInfo->closeOutput();
Reference< XOutputStream > xEncryptedPackage( mrOleStorage.openOutputStream( "EncryptedPackage" ), UNO_SET_THROW );
BinaryXOutputStream aEncryptedPackageStream( xEncryptedPackage, false );
BinaryXInputStream aDocumentInputStream( xInputStream, false );
aDocumentInputStream.seekToStart();
aEncryptedPackageStream.writeValue<sal_uInt32>( aLength ); // size
aEncryptedPackageStream.writeValue<sal_uInt32>( 0 ); // reserved
mEngine.encrypt(aDocumentInputStream, aEncryptedPackageStream);
aEncryptedPackageStream.close();
aDocumentInputStream.close();
xEncryptedPackage->flush();
xEncryptedPackage->closeOutput();
return true;
}
} // namespace core
} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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/Standard2007Engine.hxx"
#include <osl/time.h>
#include <rtl/random.h>
namespace oox {
namespace core {
using namespace std;
/* =========================================================================== */
/* Kudos to Caolan McNamara who provided the core decryption implementations. */
/* =========================================================================== */
namespace
{
void lclRandomGenerateValues(sal_uInt8* aArray, sal_uInt32 aSize)
{
TimeValue aTime;
osl_getSystemTime( &aTime );
rtlRandomPool aRandomPool = rtl_random_createPool ();
rtl_random_addBytes ( aRandomPool, &aTime, 8 );
rtl_random_getBytes ( aRandomPool, aArray, aSize );
rtl_random_destroyPool ( aRandomPool );
}
static const OUString lclCspName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
} // namespace
EncryptionStandardHeader::EncryptionStandardHeader()
{
flags = 0;
sizeExtra = 0;
algId = 0;
algIdHash = 0;
keyBits = 0;
providedType = 0;
reserved1 = 0;
reserved2 = 0;
}
EncryptionVerifierAES::EncryptionVerifierAES()
{
saltSize = SALT_LENGTH;
memset(salt, 0, sizeof(salt));
memset(encryptedVerifier, 0, sizeof(encryptedVerifier));
memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash));
}
Standard2007Engine::Standard2007Engine() :
CryptoEngine()
{}
Standard2007Engine::~Standard2007Engine()
{}
StandardEncryptionInfo& Standard2007Engine::getInfo()
{
return mInfo;
}
bool Standard2007Engine::generateVerifier()
{
// only support key of size 128 bit (16 byte)
if (mKey.size() != 16)
return false;
sal_uInt32 outputLength;
vector<sal_uInt8> verifier(ENCRYPTED_VERIFIER_LENGTH);
vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
lclRandomGenerateValues(&verifier[0], verifier.size());
vector<sal_uInt8> iv;
Encrypt aEncryptorVerifier(mKey, iv, Crypto::AES_128_ECB);
outputLength = aEncryptorVerifier.update(encryptedVerifier, verifier);
if (outputLength != ENCRYPTED_VERIFIER_LENGTH)
return false;
std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier);
vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
mInfo.verifier.encryptedVerifierHashSize = RTL_DIGEST_LENGTH_SHA1;
sha1(hash, verifier);
hash.resize(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
vector<sal_uInt8> encryptedHash(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB);
outputLength = aEncryptorHash.update(encryptedHash, hash, hash.size());
std::copy(encryptedHash.begin(), encryptedHash.end(), mInfo.verifier.encryptedVerifierHash);
return true;
}
bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword)
{
sal_uInt32 saltSize = mInfo.verifier.saltSize;
sal_uInt32 passwordByteLength = rPassword.getLength() * 2;
const sal_uInt8* saltArray = mInfo.verifier.salt;
// Prepare initial data -> salt + password (in 16-bit chars)
vector<sal_uInt8> initialData(saltSize + passwordByteLength);
std::copy(saltArray, saltArray + saltSize, initialData.begin());
const sal_uInt8* passwordByteArray = reinterpret_cast<const sal_uInt8*>(rPassword.getStr());
std::copy(
passwordByteArray,
passwordByteArray + passwordByteLength,
initialData.begin() + saltSize);
// use "hash" vector for result of sha1 hashing
vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
// calculate SHA1 hash of initialData
sha1(hash, initialData);
// data = iterator (4bytes) + hash
vector<sal_uInt8> data(RTL_DIGEST_LENGTH_SHA1 + 4, 0);
for (int i = 0; i < 50000; i++)
{
ByteOrderConverter::writeLittleEndian( &data[0], i );
std::copy(hash.begin(), hash.end(), data.begin() + 4);
sha1(hash, data);
}
std::copy(hash.begin(), hash.end(), data.begin() );
std::fill(data.begin() + RTL_DIGEST_LENGTH_SHA1, data.end(), 0 );
sha1(hash, data);
// derive key
vector<sal_uInt8> buffer(64, 0x36);
for( sal_uInt32 i = 0; i < hash.size(); ++i )
buffer[i] ^= hash[i];
sha1(hash, buffer);
std::copy(hash.begin(), hash.begin() + mKey.size(), mKey.begin());
return true;
}
bool Standard2007Engine::generateEncryptionKey(const OUString& password)
{
mKey.clear();
mKey.resize(mInfo.header.keyBits / 8, 0);
calculateEncryptionKey(password);
vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
std::copy(
mInfo.verifier.encryptedVerifier,
mInfo.verifier.encryptedVerifier + ENCRYPTED_VERIFIER_LENGTH,
encryptedVerifier.begin());
vector<sal_uInt8> encryptedVerifierHash(ENCRYPTED_VERIFIER_HASH_LENGTH);
std::copy(
mInfo.verifier.encryptedVerifierHash,
mInfo.verifier.encryptedVerifierHash + ENCRYPTED_VERIFIER_HASH_LENGTH,
encryptedVerifierHash.begin());
return checkEncryptionData(
mKey, mKey.size(),
encryptedVerifier, encryptedVerifier.size(),
encryptedVerifierHash, encryptedVerifierHash.size() );
}
bool Standard2007Engine::decrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream)
{
sal_uInt32 totalSize;
aInputStream >> totalSize; // Document unencrypted size - 4 bytes
aInputStream.skip( 4 ); // Reserved 4 Bytes
vector<sal_uInt8> iv;
Decrypt aDecryptor(mKey, iv, Crypto::AES_128_ECB);
vector<sal_uInt8> inputBuffer (4096);
vector<sal_uInt8> outputBuffer(4096);
sal_uInt32 inputLength;
sal_uInt32 outputLength;
while( (inputLength = aInputStream.readMemory( &inputBuffer[0], inputBuffer.size() )) > 0 )
{
outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength);
aOutputStream.writeMemory( &outputBuffer[0], outputLength );
}
return true;
}
bool Standard2007Engine::checkEncryptionData(
vector<sal_uInt8> key, sal_uInt32 keySize,
vector<sal_uInt8> encryptedVerifier, sal_uInt32 verifierSize,
vector<sal_uInt8> encryptedHash, sal_uInt32 hashSize )
{
// the only currently supported algorithm needs key size 128
if ( keySize != 16 || verifierSize != 16 )
return false;
vector<sal_uInt8> verifier(verifierSize, 0);
Decrypt::aes128ecb(verifier, encryptedVerifier, key);
vector<sal_uInt8> verifierHash(hashSize, 0);
Decrypt::aes128ecb(verifierHash, encryptedHash, key);
vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
sha1(hash, verifier);
return std::equal( hash.begin(), hash.end(), verifierHash.begin() );
}
bool Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOutputStream& rStream)
{
mInfo.header.flags = ENCRYPTINFO_AES | ENCRYPTINFO_CRYPTOAPI;
mInfo.header.algId = ENCRYPT_ALGO_AES128;
mInfo.header.algIdHash = ENCRYPT_HASH_SHA1;
mInfo.header.keyBits = ENCRYPT_KEY_SIZE_AES_128;
mInfo.header.providedType = ENCRYPT_PROVIDER_TYPE_AES;
lclRandomGenerateValues(mInfo.verifier.salt, mInfo.verifier.saltSize);
const sal_Int32 keyLength = mInfo.header.keyBits / 8;
mKey.clear();
mKey.resize(keyLength, 0);
if (!calculateEncryptionKey(password))
return false;
if (!generateVerifier())
return false;
rStream.writeValue(VERSION_INFO_2007_FORMAT);
sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2;
sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(EncryptionStandardHeader));
rStream << mInfo.header.flags;
sal_uInt32 headerSize = encryptionHeaderSize + cspNameSize;
rStream << headerSize;
rStream.writeMemory(&mInfo.header, encryptionHeaderSize);
rStream.writeUnicodeArray(lclCspName);
rStream.writeValue<sal_uInt16>(0);
sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(EncryptionVerifierAES));
rStream.writeMemory(&mInfo.verifier, encryptionVerifierSize);
return true;
}
bool Standard2007Engine::encrypt(
BinaryXInputStream& aInputStream,
BinaryXOutputStream& aOutputStream)
{
vector<sal_uInt8> inputBuffer(1024);
vector<sal_uInt8> outputBuffer(1024);
sal_uInt32 inputLength;
sal_uInt32 outputLength;
vector<sal_uInt8> iv;
Encrypt aEncryptor(mKey, iv, Crypto::AES_128_ECB);
while( (inputLength = aInputStream.readMemory( &inputBuffer[0], inputBuffer.size() )) > 0 )
{
inputLength = inputLength % 16 == 0 ? inputLength : ((inputLength / 16) * 16) + 16;
outputLength = aEncryptor.update(outputBuffer, inputBuffer, inputLength);
aOutputStream.writeMemory( &outputBuffer[0], outputLength );
}
return true;
}
} // namespace core
} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment