LCOV - code coverage report
Current view: top level - oox/source/crypto - AgileEngine.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 99 0.0 %
Date: 2014-04-14 Functions: 0 12 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 : AgileEncryptionInfo& AgileEngine::getInfo()
      45             : {
      46           0 :     return mInfo;
      47             : }
      48             : 
      49           0 : Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo)
      50             : {
      51           0 :     if (rInfo.keyBits == 128 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
      52           0 :         return Crypto::AES_128_CBC;
      53           0 :     else if (rInfo.keyBits == 256 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
      54           0 :         return Crypto::AES_256_CBC;
      55           0 :     return Crypto::UNKNOWN;
      56             : }
      57             : 
      58           0 : bool AgileEngine::calculateBlock(
      59             :     const sal_uInt8* rBlock,
      60             :     sal_uInt32 aBlockSize,
      61             :     vector<sal_uInt8>& rHashFinal,
      62             :     vector<sal_uInt8>& rInput,
      63             :     vector<sal_uInt8>& rOutput)
      64             : {
      65           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
      66           0 :     vector<sal_uInt8> salt = mInfo.saltValue;
      67           0 :     vector<sal_uInt8> dataFinal(mInfo.hashSize + aBlockSize, 0);
      68           0 :     std::copy(rHashFinal.begin(), rHashFinal.end(), dataFinal.begin());
      69             :     std::copy(
      70             :             rBlock,
      71             :             rBlock + aBlockSize,
      72           0 :             dataFinal.begin() + mInfo.hashSize);
      73             : 
      74           0 :     hashCalc(hash, dataFinal, mInfo.hashAlgorithm);
      75             : 
      76           0 :     sal_Int32 keySize = mInfo.keyBits / 8;
      77           0 :     vector<sal_uInt8> key(keySize, 0);
      78             : 
      79           0 :     std::copy(hash.begin(), hash.begin() + keySize, key.begin());
      80             : 
      81           0 :     Decrypt aDecryptor(key, salt, cryptoType(mInfo));
      82           0 :     aDecryptor.update(rOutput, rInput);
      83             : 
      84           0 :     return true;
      85             : }
      86             : 
      87           0 : bool AgileEngine::calculateHashFinal(const OUString& rPassword, vector<sal_uInt8>& aHashFinal)
      88             : {
      89           0 :     sal_Int32 saltSize = mInfo.saltSize;
      90           0 :     vector<sal_uInt8> salt = mInfo.saltValue;
      91           0 :     sal_uInt32 passwordByteLength = rPassword.getLength() * 2;
      92             : 
      93           0 :     vector<sal_uInt8> initialData(saltSize + passwordByteLength);
      94           0 :     std::copy(salt.begin(), salt.end(), initialData.begin());
      95             : 
      96           0 :     const sal_uInt8* passwordByteArray = reinterpret_cast<const sal_uInt8*>(rPassword.getStr());
      97             : 
      98             :     std::copy(
      99             :         passwordByteArray,
     100             :         passwordByteArray + passwordByteLength,
     101           0 :         initialData.begin() + saltSize);
     102             : 
     103           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
     104             : 
     105           0 :     hashCalc(hash, initialData, mInfo.hashAlgorithm);
     106             : 
     107           0 :     vector<sal_uInt8> data(mInfo.hashSize + 4, 0);
     108             : 
     109           0 :     for (sal_Int32 i = 0; i < mInfo.spinCount; i++)
     110             :     {
     111           0 :         ByteOrderConverter::writeLittleEndian( &data[0], i );
     112           0 :         std::copy(hash.begin(), hash.end(), data.begin() + 4);
     113           0 :         hashCalc(hash, data, mInfo.hashAlgorithm);
     114             :     }
     115             : 
     116           0 :     std::copy(hash.begin(), hash.end(), aHashFinal.begin());
     117             : 
     118           0 :     return true;
     119             : }
     120             : 
     121           0 : bool AgileEngine::generateEncryptionKey(const OUString& rPassword)
     122             : {
     123           0 :     mKey.clear();
     124           0 :     mKey.resize(mInfo.keyBits / 8, 0);
     125             : 
     126           0 :     vector<sal_uInt8> hashFinal(mInfo.hashSize, 0);
     127           0 :     calculateHashFinal(rPassword, hashFinal);
     128             : 
     129           0 :     vector<sal_uInt8> encryptedHashInput = mInfo.encryptedVerifierHashInput;
     130           0 :     vector<sal_uInt8> hashInput(mInfo.saltSize, 0);
     131           0 :     calculateBlock(constBlock1, sizeof(constBlock1), hashFinal, encryptedHashInput, hashInput);
     132             : 
     133           0 :     vector<sal_uInt8> encryptedHashValue = mInfo.encryptedVerifierHashValue;
     134           0 :     vector<sal_uInt8> hashValue(encryptedHashValue.size(), 0);
     135           0 :     calculateBlock(constBlock2, sizeof(constBlock2), hashFinal, encryptedHashValue, hashValue);
     136             : 
     137           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
     138           0 :     hashCalc(hash, hashInput, mInfo.hashAlgorithm);
     139             : 
     140           0 :     if (std::equal (hash.begin(), hash.end(), hashValue.begin()) )
     141             :     {
     142           0 :         vector<sal_uInt8> encryptedKeyValue = mInfo.encryptedKeyValue;
     143           0 :         calculateBlock(constBlock3, sizeof(constBlock3), hashFinal, encryptedKeyValue, mKey);
     144           0 :         return true;
     145             :     }
     146             : 
     147           0 :     return false;
     148             : }
     149             : 
     150           0 : bool AgileEngine::decrypt(
     151             :                     BinaryXInputStream& aInputStream,
     152             :                     BinaryXOutputStream& aOutputStream)
     153             : {
     154             :     sal_uInt32 totalSize;
     155           0 :     aInputStream >> totalSize; // Document unencrypted size - 4 bytes
     156           0 :     aInputStream.skip( 4 );    // Reserved 4 Bytes
     157             : 
     158           0 :     vector<sal_uInt8> keyDataSalt = mInfo.keyDataSalt;
     159             : 
     160           0 :     sal_uInt32 saltSize = mInfo.saltSize;
     161           0 :     sal_uInt32 keySize = mInfo.keyBits / 8;
     162             : 
     163           0 :     sal_uInt32 segment = 0;
     164             : 
     165           0 :     vector<sal_uInt8> saltWithBlockKey(saltSize + sizeof(segment), 0);
     166           0 :     std::copy(keyDataSalt.begin(), keyDataSalt.end(), saltWithBlockKey.begin());
     167             : 
     168           0 :     vector<sal_uInt8> hash(mInfo.hashSize, 0);
     169           0 :     vector<sal_uInt8> iv(keySize, 0);
     170             : 
     171           0 :     vector<sal_uInt8> inputBuffer (SEGMENT_LENGTH);
     172           0 :     vector<sal_uInt8> outputBuffer(SEGMENT_LENGTH);
     173             :     sal_uInt32 inputLength;
     174             :     sal_uInt32 outputLength;
     175           0 :     sal_uInt32 remaining = totalSize;
     176             : 
     177           0 :     while( (inputLength = aInputStream.readMemory( &inputBuffer[0], SEGMENT_LENGTH )) > 0 )
     178             :     {
     179           0 :         sal_uInt8* segmentBegin = reinterpret_cast<sal_uInt8*>(&segment);
     180           0 :         sal_uInt8* segmentEnd   = segmentBegin + sizeof(segment);
     181           0 :         std::copy(segmentBegin, segmentEnd, saltWithBlockKey.begin() + saltSize);
     182             : 
     183           0 :         hashCalc(hash, saltWithBlockKey, mInfo.hashAlgorithm);
     184             : 
     185             :         // Only if hash > keySize
     186           0 :         std::copy(hash.begin(), hash.begin() + keySize, iv.begin());
     187             : 
     188           0 :         Decrypt aDecryptor(mKey, iv, AgileEngine::cryptoType(mInfo));
     189           0 :         outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength);
     190             : 
     191           0 :         sal_uInt32 writeLength = outputLength > remaining ? remaining : outputLength;
     192           0 :         aOutputStream.writeMemory( &outputBuffer[0], writeLength );
     193             : 
     194           0 :         remaining -= outputLength;
     195           0 :         segment++;
     196           0 :     }
     197             : 
     198           0 :     return true;
     199             : }
     200             : 
     201           0 : bool AgileEngine::writeEncryptionInfo(
     202             :                         const OUString& /*aPassword*/,
     203             :                         BinaryXOutputStream& /*rStream*/)
     204             : {
     205           0 :     return false; // Agile encrypting is not supported for now
     206             : }
     207             : 
     208           0 : bool AgileEngine::encrypt(
     209             :                     BinaryXInputStream& /*aInputStream*/,
     210             :                     BinaryXOutputStream& /*aOutputStream*/)
     211             : {
     212           0 :     return false; // Agile encrypting is not supported for now
     213             : }
     214             : 
     215             : 
     216             : } // namespace core
     217             : } // namespace oox
     218             : 
     219             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10