LCOV - code coverage report
Current view: top level - oox/source/crypto - Standard2007Engine.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 139 0.0 %
Date: 2014-04-14 Functions: 0 15 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/Standard2007Engine.hxx"
      12             : 
      13             : #include <osl/time.h>
      14             : #include <rtl/random.h>
      15             : 
      16             : namespace oox {
      17             : namespace core {
      18             : 
      19             : using namespace std;
      20             : 
      21             : /* =========================================================================== */
      22             : /*  Kudos to Caolan McNamara who provided the core decryption implementations. */
      23             : /* =========================================================================== */
      24             : namespace
      25             : {
      26             : 
      27           0 : void lclRandomGenerateValues(sal_uInt8* aArray, sal_uInt32 aSize)
      28             : {
      29             :     TimeValue aTime;
      30           0 :     osl_getSystemTime( &aTime );
      31           0 :     rtlRandomPool aRandomPool = rtl_random_createPool ();
      32           0 :     rtl_random_addBytes ( aRandomPool, &aTime, 8 );
      33           0 :     rtl_random_getBytes ( aRandomPool, aArray, aSize );
      34           0 :     rtl_random_destroyPool ( aRandomPool );
      35           0 : }
      36             : 
      37           0 : static const OUString lclCspName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
      38             : 
      39             : } // namespace
      40             : 
      41           0 : EncryptionStandardHeader::EncryptionStandardHeader()
      42             : {
      43           0 :     flags        = 0;
      44           0 :     sizeExtra    = 0;
      45           0 :     algId        = 0;
      46           0 :     algIdHash    = 0;
      47           0 :     keyBits      = 0;
      48           0 :     providedType = 0;
      49           0 :     reserved1    = 0;
      50           0 :     reserved2    = 0;
      51           0 : }
      52             : 
      53           0 : EncryptionVerifierAES::EncryptionVerifierAES() :
      54             :     saltSize(SALT_LENGTH),
      55           0 :     encryptedVerifierHashSize(Digest::DIGEST_LENGTH_SHA1)
      56             : {
      57           0 :     memset(salt, 0, sizeof(salt));
      58           0 :     memset(encryptedVerifier, 0, sizeof(encryptedVerifier));
      59           0 :     memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash));
      60           0 : }
      61             : 
      62           0 : Standard2007Engine::Standard2007Engine() :
      63           0 :     CryptoEngine()
      64           0 : {}
      65             : 
      66           0 : Standard2007Engine::~Standard2007Engine()
      67           0 : {}
      68             : 
      69           0 : StandardEncryptionInfo& Standard2007Engine::getInfo()
      70             : {
      71           0 :     return mInfo;
      72             : }
      73             : 
      74           0 : bool Standard2007Engine::generateVerifier()
      75             : {
      76             :     // only support key of size 128 bit (16 byte)
      77           0 :     if (mKey.size() != 16)
      78           0 :         return false;
      79             : 
      80             :     sal_uInt32 outputLength;
      81           0 :     vector<sal_uInt8> verifier(ENCRYPTED_VERIFIER_LENGTH);
      82           0 :     vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
      83             : 
      84           0 :     lclRandomGenerateValues(&verifier[0], verifier.size());
      85             : 
      86           0 :     vector<sal_uInt8> iv;
      87           0 :     Encrypt aEncryptorVerifier(mKey, iv, Crypto::AES_128_ECB);
      88           0 :     outputLength = aEncryptorVerifier.update(encryptedVerifier, verifier);
      89           0 :     if (outputLength != ENCRYPTED_VERIFIER_LENGTH)
      90           0 :         return false;
      91           0 :     std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier);
      92             : 
      93           0 :     vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
      94           0 :     mInfo.verifier.encryptedVerifierHashSize = RTL_DIGEST_LENGTH_SHA1;
      95           0 :     Digest::sha1(hash, verifier);
      96           0 :     hash.resize(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
      97             : 
      98           0 :     vector<sal_uInt8> encryptedHash(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
      99             : 
     100           0 :     Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB);
     101           0 :     outputLength = aEncryptorHash.update(encryptedHash, hash, hash.size());
     102           0 :     std::copy(encryptedHash.begin(), encryptedHash.end(), mInfo.verifier.encryptedVerifierHash);
     103             : 
     104           0 :     return true;
     105             : }
     106             : 
     107           0 : bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword)
     108             : {
     109           0 :     sal_uInt32 saltSize = mInfo.verifier.saltSize;
     110           0 :     sal_uInt32 passwordByteLength = rPassword.getLength() * 2;
     111           0 :     const sal_uInt8* saltArray = mInfo.verifier.salt;
     112             : 
     113             :     // Prepare initial data -> salt + password (in 16-bit chars)
     114           0 :     vector<sal_uInt8> initialData(saltSize + passwordByteLength);
     115           0 :     std::copy(saltArray, saltArray + saltSize, initialData.begin());
     116             : 
     117           0 :     const sal_uInt8* passwordByteArray = reinterpret_cast<const sal_uInt8*>(rPassword.getStr());
     118             : 
     119             :     std::copy(
     120             :         passwordByteArray,
     121             :         passwordByteArray + passwordByteLength,
     122           0 :         initialData.begin() + saltSize);
     123             : 
     124             :     // use "hash" vector for result of sha1 hashing
     125           0 :     vector<sal_uInt8> hash(Digest::DIGEST_LENGTH_SHA1, 0);
     126             : 
     127             :     // calculate SHA1 hash of initialData
     128           0 :     Digest::sha1(hash, initialData);
     129             : 
     130             :     // data = iterator (4bytes) + hash
     131           0 :     vector<sal_uInt8> data(Digest::DIGEST_LENGTH_SHA1 + 4, 0);
     132             : 
     133           0 :     for (sal_Int32 i = 0; i < 50000; ++i)
     134             :     {
     135           0 :         ByteOrderConverter::writeLittleEndian( &data[0], i );
     136           0 :         std::copy(hash.begin(), hash.end(), data.begin() + 4);
     137           0 :         Digest::sha1(hash, data);
     138             :     }
     139           0 :     std::copy(hash.begin(), hash.end(), data.begin() );
     140           0 :     std::fill(data.begin() + Digest::DIGEST_LENGTH_SHA1, data.end(), 0 );
     141             : 
     142           0 :     Digest::sha1(hash, data);
     143             : 
     144             :     // derive key
     145           0 :     vector<sal_uInt8> buffer(64, 0x36);
     146           0 :     for( sal_uInt32 i = 0; i < hash.size(); ++i )
     147           0 :         buffer[i] ^= hash[i];
     148             : 
     149           0 :     Digest::sha1(hash, buffer);
     150           0 :     std::copy(hash.begin(), hash.begin() + mKey.size(), mKey.begin());
     151             : 
     152           0 :     return true;
     153             : }
     154             : 
     155           0 : bool Standard2007Engine::generateEncryptionKey(const OUString& password)
     156             : {
     157           0 :     mKey.clear();
     158           0 :     mKey.resize(mInfo.header.keyBits / 8, 0);
     159             : 
     160           0 :     calculateEncryptionKey(password);
     161             : 
     162           0 :     vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
     163             :     std::copy(
     164             :         mInfo.verifier.encryptedVerifier,
     165             :         mInfo.verifier.encryptedVerifier + ENCRYPTED_VERIFIER_LENGTH,
     166           0 :         encryptedVerifier.begin());
     167             : 
     168           0 :     vector<sal_uInt8> encryptedHash(ENCRYPTED_VERIFIER_HASH_LENGTH);
     169             :     std::copy(
     170             :         mInfo.verifier.encryptedVerifierHash,
     171             :         mInfo.verifier.encryptedVerifierHash + ENCRYPTED_VERIFIER_HASH_LENGTH,
     172           0 :         encryptedHash.begin());
     173             : 
     174           0 :     vector<sal_uInt8> verifier(encryptedVerifier.size(), 0);
     175           0 :     Decrypt::aes128ecb(verifier, encryptedVerifier, mKey);
     176             : 
     177           0 :     vector<sal_uInt8> verifierHash(encryptedHash.size(), 0);
     178           0 :     Decrypt::aes128ecb(verifierHash, encryptedHash, mKey);
     179             : 
     180           0 :     vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
     181           0 :     Digest::sha1(hash, verifier);
     182             : 
     183           0 :     return std::equal( hash.begin(), hash.end(), verifierHash.begin() );
     184             : }
     185             : 
     186           0 : bool Standard2007Engine::decrypt(
     187             :                             BinaryXInputStream& aInputStream,
     188             :                             BinaryXOutputStream& aOutputStream)
     189             : {
     190             :     sal_uInt32 totalSize;
     191           0 :     aInputStream >> totalSize; // Document unencrypted size - 4 bytes
     192           0 :     aInputStream.skip( 4 );    // Reserved 4 Bytes
     193             : 
     194           0 :     vector<sal_uInt8> iv;
     195           0 :     Decrypt aDecryptor(mKey, iv, Crypto::AES_128_ECB);
     196           0 :     vector<sal_uInt8> inputBuffer (4096);
     197           0 :     vector<sal_uInt8> outputBuffer(4096);
     198             :     sal_uInt32 inputLength;
     199             :     sal_uInt32 outputLength;
     200             : 
     201           0 :     while( (inputLength = aInputStream.readMemory( &inputBuffer[0], inputBuffer.size() )) > 0 )
     202             :     {
     203           0 :         outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength);
     204           0 :         aOutputStream.writeMemory( &outputBuffer[0], outputLength );
     205             :     }
     206           0 :     return true;
     207             : }
     208             : 
     209           0 : bool Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOutputStream& rStream)
     210             : {
     211           0 :     mInfo.header.flags        = ENCRYPTINFO_AES | ENCRYPTINFO_CRYPTOAPI;
     212           0 :     mInfo.header.algId        = ENCRYPT_ALGO_AES128;
     213           0 :     mInfo.header.algIdHash    = ENCRYPT_HASH_SHA1;
     214           0 :     mInfo.header.keyBits      = ENCRYPT_KEY_SIZE_AES_128;
     215           0 :     mInfo.header.providedType = ENCRYPT_PROVIDER_TYPE_AES;
     216             : 
     217           0 :     lclRandomGenerateValues(mInfo.verifier.salt, mInfo.verifier.saltSize);
     218           0 :     const sal_Int32 keyLength = mInfo.header.keyBits / 8;
     219             : 
     220           0 :     mKey.clear();
     221           0 :     mKey.resize(keyLength, 0);
     222             : 
     223           0 :     if (!calculateEncryptionKey(password))
     224           0 :         return false;
     225             : 
     226           0 :     if (!generateVerifier())
     227           0 :         return false;
     228             : 
     229           0 :     rStream.writeValue(VERSION_INFO_2007_FORMAT);
     230             : 
     231           0 :     sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2;
     232             : 
     233           0 :     sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(EncryptionStandardHeader));
     234             : 
     235           0 :     rStream << mInfo.header.flags;
     236           0 :     sal_uInt32 headerSize = encryptionHeaderSize + cspNameSize;
     237           0 :     rStream << headerSize;
     238             : 
     239           0 :     rStream.writeMemory(&mInfo.header, encryptionHeaderSize);
     240           0 :     rStream.writeUnicodeArray(lclCspName);
     241           0 :     rStream.writeValue<sal_uInt16>(0);
     242             : 
     243           0 :     sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(EncryptionVerifierAES));
     244           0 :     rStream.writeMemory(&mInfo.verifier, encryptionVerifierSize);
     245             : 
     246           0 :     return true;
     247             : }
     248             : 
     249           0 : bool Standard2007Engine::encrypt(
     250             :                             BinaryXInputStream& aInputStream,
     251             :                             BinaryXOutputStream& aOutputStream)
     252             : {
     253           0 :     vector<sal_uInt8> inputBuffer(1024);
     254           0 :     vector<sal_uInt8> outputBuffer(1024);
     255             : 
     256             :     sal_uInt32 inputLength;
     257             :     sal_uInt32 outputLength;
     258             : 
     259           0 :     vector<sal_uInt8> iv;
     260           0 :     Encrypt aEncryptor(mKey, iv, Crypto::AES_128_ECB);
     261             : 
     262           0 :     while( (inputLength = aInputStream.readMemory( &inputBuffer[0], inputBuffer.size() )) > 0 )
     263             :     {
     264           0 :         inputLength = inputLength % 16 == 0 ? inputLength : ((inputLength / 16) * 16) + 16;
     265           0 :         outputLength = aEncryptor.update(outputBuffer, inputBuffer, inputLength);
     266           0 :         aOutputStream.writeMemory( &outputBuffer[0], outputLength );
     267             :     }
     268           0 :     return true;
     269             : }
     270             : 
     271             : } // namespace core
     272           0 : } // namespace oox
     273             : 
     274             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10