LCOV - code coverage report
Current view: top level - oox/source/crypto - AgileEngine.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 97 0.0 %
Date: 2014-11-03 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  */
      10             : 
      11             : #include "oox/crypto/AgileEngine.hxx"
      12             : 
      13             : namespace oox {
      14             : namespace core {
      15             : 
      16             : using namespace std;
      17             : 
      18             : namespace {
      19             : 
      20             : const sal_uInt8 constBlock1[] = { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 };
      21             : const sal_uInt8 constBlock2[] = { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e };
      22             : const sal_uInt8 constBlock3[] = { 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6 };
      23             : 
      24           0 : bool hashCalc( std::vector<sal_uInt8>& output,
      25             :                std::vector<sal_uInt8>& input,
      26             :                const OUString& algorithm )
      27             : {
      28           0 :     if (algorithm == "SHA1")
      29           0 :         return Digest::sha1(output, input);
      30           0 :     else if (algorithm == "SHA512")
      31           0 :         return Digest::sha512(output, input);
      32           0 :     return false;
      33             : }
      34             : 
      35             : } // namespace
      36             : 
      37           0 : AgileEngine::AgileEngine() :
      38           0 :     CryptoEngine()
      39           0 : {}
      40             : 
      41           0 : AgileEngine::~AgileEngine()
      42           0 : {}
      43             : 
      44           0 : Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo)
      45             : {
      46           0 :     if (rInfo.keyBits == 128 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
      47           0 :         return Crypto::AES_128_CBC;
      48           0 :     else if (rInfo.keyBits == 256 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
      49           0 :         return Crypto::AES_256_CBC;
      50           0 :     return Crypto::UNKNOWN;
      51             : }
      52             : 
      53           0 : bool AgileEngine::calculateBlock(
      54             :     const sal_uInt8* rBlock,
      55             :     sal_uInt32 aBlockSize,
      56             :     vector<sal_uInt8>& rHashFinal,
      57             :     vector<sal_uInt8>& rInput,
      58             :     vector<sal_uInt8>& rOutput)
      59             : {
      60           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
      61           0 :     vector<sal_uInt8> salt = mInfo.saltValue;
      62           0 :     vector<sal_uInt8> dataFinal(mInfo.hashSize + aBlockSize, 0);
      63           0 :     std::copy(rHashFinal.begin(), rHashFinal.end(), dataFinal.begin());
      64             :     std::copy(
      65             :             rBlock,
      66             :             rBlock + aBlockSize,
      67           0 :             dataFinal.begin() + mInfo.hashSize);
      68             : 
      69           0 :     hashCalc(hash, dataFinal, mInfo.hashAlgorithm);
      70             : 
      71           0 :     sal_Int32 keySize = mInfo.keyBits / 8;
      72           0 :     vector<sal_uInt8> key(keySize, 0);
      73             : 
      74           0 :     std::copy(hash.begin(), hash.begin() + keySize, key.begin());
      75             : 
      76           0 :     Decrypt aDecryptor(key, salt, cryptoType(mInfo));
      77           0 :     aDecryptor.update(rOutput, rInput);
      78             : 
      79           0 :     return true;
      80             : }
      81             : 
      82           0 : bool AgileEngine::calculateHashFinal(const OUString& rPassword, vector<sal_uInt8>& aHashFinal)
      83             : {
      84           0 :     sal_Int32 saltSize = mInfo.saltSize;
      85           0 :     vector<sal_uInt8> salt = mInfo.saltValue;
      86           0 :     sal_uInt32 passwordByteLength = rPassword.getLength() * 2;
      87             : 
      88           0 :     vector<sal_uInt8> initialData(saltSize + passwordByteLength);
      89           0 :     std::copy(salt.begin(), salt.end(), initialData.begin());
      90             : 
      91           0 :     const sal_uInt8* passwordByteArray = reinterpret_cast<const sal_uInt8*>(rPassword.getStr());
      92             : 
      93             :     std::copy(
      94             :         passwordByteArray,
      95             :         passwordByteArray + passwordByteLength,
      96           0 :         initialData.begin() + saltSize);
      97             : 
      98           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
      99             : 
     100           0 :     hashCalc(hash, initialData, mInfo.hashAlgorithm);
     101             : 
     102           0 :     vector<sal_uInt8> data(mInfo.hashSize + 4, 0);
     103             : 
     104           0 :     for (sal_Int32 i = 0; i < mInfo.spinCount; i++)
     105             :     {
     106           0 :         ByteOrderConverter::writeLittleEndian( &data[0], i );
     107           0 :         std::copy(hash.begin(), hash.end(), data.begin() + 4);
     108           0 :         hashCalc(hash, data, mInfo.hashAlgorithm);
     109             :     }
     110             : 
     111           0 :     std::copy(hash.begin(), hash.end(), aHashFinal.begin());
     112             : 
     113           0 :     return true;
     114             : }
     115             : 
     116           0 : bool AgileEngine::generateEncryptionKey(const OUString& rPassword)
     117             : {
     118           0 :     mKey.clear();
     119           0 :     mKey.resize(mInfo.keyBits / 8, 0);
     120             : 
     121           0 :     vector<sal_uInt8> hashFinal(mInfo.hashSize, 0);
     122           0 :     calculateHashFinal(rPassword, hashFinal);
     123             : 
     124           0 :     vector<sal_uInt8> encryptedHashInput = mInfo.encryptedVerifierHashInput;
     125           0 :     vector<sal_uInt8> hashInput(mInfo.saltSize, 0);
     126           0 :     calculateBlock(constBlock1, sizeof(constBlock1), hashFinal, encryptedHashInput, hashInput);
     127             : 
     128           0 :     vector<sal_uInt8> encryptedHashValue = mInfo.encryptedVerifierHashValue;
     129           0 :     vector<sal_uInt8> hashValue(encryptedHashValue.size(), 0);
     130           0 :     calculateBlock(constBlock2, sizeof(constBlock2), hashFinal, encryptedHashValue, hashValue);
     131             : 
     132           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
     133           0 :     hashCalc(hash, hashInput, mInfo.hashAlgorithm);
     134             : 
     135           0 :     if (std::equal (hash.begin(), hash.end(), hashValue.begin()) )
     136             :     {
     137           0 :         vector<sal_uInt8> encryptedKeyValue = mInfo.encryptedKeyValue;
     138           0 :         calculateBlock(constBlock3, sizeof(constBlock3), hashFinal, encryptedKeyValue, mKey);
     139           0 :         return true;
     140             :     }
     141             : 
     142           0 :     return false;
     143             : }
     144             : 
     145           0 : bool AgileEngine::decrypt(
     146             :                     BinaryXInputStream& aInputStream,
     147             :                     BinaryXOutputStream& aOutputStream)
     148             : {
     149             :     sal_uInt32 totalSize;
     150           0 :     aInputStream >> totalSize; // Document unencrypted size - 4 bytes
     151           0 :     aInputStream.skip( 4 );    // Reserved 4 Bytes
     152             : 
     153           0 :     vector<sal_uInt8> keyDataSalt = mInfo.keyDataSalt;
     154             : 
     155           0 :     sal_uInt32 saltSize = mInfo.saltSize;
     156           0 :     sal_uInt32 keySize = mInfo.keyBits / 8;
     157             : 
     158           0 :     sal_uInt32 segment = 0;
     159             : 
     160           0 :     vector<sal_uInt8> saltWithBlockKey(saltSize + sizeof(segment), 0);
     161           0 :     std::copy(keyDataSalt.begin(), keyDataSalt.end(), saltWithBlockKey.begin());
     162             : 
     163           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
     164           0 :     vector<sal_uInt8> iv(keySize, 0);
     165             : 
     166           0 :     vector<sal_uInt8> inputBuffer (SEGMENT_LENGTH);
     167           0 :     vector<sal_uInt8> outputBuffer(SEGMENT_LENGTH);
     168             :     sal_uInt32 inputLength;
     169             :     sal_uInt32 outputLength;
     170           0 :     sal_uInt32 remaining = totalSize;
     171             : 
     172           0 :     while( (inputLength = aInputStream.readMemory( &inputBuffer[0], SEGMENT_LENGTH )) > 0 )
     173             :     {
     174           0 :         sal_uInt8* segmentBegin = reinterpret_cast<sal_uInt8*>(&segment);
     175           0 :         sal_uInt8* segmentEnd   = segmentBegin + sizeof(segment);
     176           0 :         std::copy(segmentBegin, segmentEnd, saltWithBlockKey.begin() + saltSize);
     177             : 
     178           0 :         hashCalc(hash, saltWithBlockKey, mInfo.hashAlgorithm);
     179             : 
     180             :         // Only if hash > keySize
     181           0 :         std::copy(hash.begin(), hash.begin() + keySize, iv.begin());
     182             : 
     183           0 :         Decrypt aDecryptor(mKey, iv, AgileEngine::cryptoType(mInfo));
     184           0 :         outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength);
     185             : 
     186           0 :         sal_uInt32 writeLength = outputLength > remaining ? remaining : outputLength;
     187           0 :         aOutputStream.writeMemory( &outputBuffer[0], writeLength );
     188             : 
     189           0 :         remaining -= outputLength;
     190           0 :         segment++;
     191           0 :     }
     192             : 
     193           0 :     return true;
     194             : }
     195             : 
     196           0 : bool AgileEngine::writeEncryptionInfo(
     197             :                         const OUString& /*aPassword*/,
     198             :                         BinaryXOutputStream& /*rStream*/)
     199             : {
     200           0 :     return false; // Agile encrypting is not supported for now
     201             : }
     202             : 
     203           0 : bool AgileEngine::encrypt(
     204             :                     BinaryXInputStream& /*aInputStream*/,
     205             :                     BinaryXOutputStream& /*aOutputStream*/)
     206             : {
     207           0 :     return false; // Agile encrypting is not supported for now
     208             : }
     209             : 
     210             : } // namespace core
     211             : } // namespace oox
     212             : 
     213             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10