differential code coverage report with master
Current view: top level - source/detail/cryptography - encryption_info.cpp (source / functions) Coverage Total Hit CBC
Current: coverage.info Lines: 100.0 % 69 69 69
Current Date: 2025-12-15 23:01:28 Functions: 100.0 % 4 4 4
Baseline: coverage_master.info Branches: 100.0 % 74 74 148
Baseline Date: 2025-12-15 23:01:27

             Branch data    TLA  Line data    Source code
       1                 :                : // Copyright (c) 2017-2022 Thomas Fussell
       2                 :                : // Copyright (c) 2024-2025 xlnt-community
       3                 :                : //
       4                 :                : // Permission is hereby granted, free of charge, to any person obtaining a copy
       5                 :                : // of this software and associated documentation files (the "Software"), to deal
       6                 :                : // in the Software without restriction, including without limitation the rights
       7                 :                : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8                 :                : // copies of the Software, and to permit persons to whom the Software is
       9                 :                : // furnished to do so, subject to the following conditions:
      10                 :                : //
      11                 :                : // The above copyright notice and this permission notice shall be included in
      12                 :                : // all copies or substantial portions of the Software.
      13                 :                : //
      14                 :                : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15                 :                : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16                 :                : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17                 :                : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18                 :                : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19                 :                : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20                 :                : // THE SOFTWARE
      21                 :                : //
      22                 :                : // @license: http://www.opensource.org/licenses/mit-license.php
      23                 :                : // @author: see AUTHORS file
      24                 :                : 
      25                 :                : #include <array>
      26                 :                : 
      27                 :                : #include <detail/binary.hpp>
      28                 :                : #include <detail/cryptography/aes.hpp>
      29                 :                : #include <detail/cryptography/encryption_info.hpp>
      30                 :                : 
      31                 :                : namespace {
      32                 :                : 
      33                 :                : using xlnt::detail::encryption_info;
      34                 :                : 
      35                 :CBC          15 : std::vector<std::uint8_t> calculate_standard_key(
      36                 :                :     encryption_info::standard_encryption_info info,
      37                 :                :     const std::u16string &password)
      38                 :                : {
      39                 :                :     // H_0 = H(salt + password)
      40            [ + ]:             15 :     auto salt_plus_password = info.salt;
      41            [ + ]:             15 :     auto password_bytes = xlnt::detail::string_to_bytes(password);
      42         [ +  + ]:             15 :     std::copy(password_bytes.begin(),
      43                 :                :         password_bytes.end(),
      44                 :                :         std::back_inserter(salt_plus_password));
      45            [ + ]:             15 :     auto h_0 = hash(info.hash, salt_plus_password);
      46                 :                : 
      47                 :                :     // H_n = H(iterator + H_n-1)
      48            [ + ]:             15 :     std::vector<std::uint8_t> iterator_plus_h_n(4, 0);
      49            [ + ]:             15 :     iterator_plus_h_n.insert(iterator_plus_h_n.end(), h_0.begin(), h_0.end());
      50                 :             15 :     std::uint32_t &iterator = *reinterpret_cast<std::uint32_t *>(iterator_plus_h_n.data());
      51                 :             15 :     std::vector<std::uint8_t> h_n;
      52         [ +  + ]:         750015 :     for (iterator = 0; iterator < info.spin_count; ++iterator)
      53                 :                :     {
      54            [ + ]:         750000 :         hash(info.hash, iterator_plus_h_n, h_n);
      55            [ + ]:         750000 :         std::copy(h_n.begin(), h_n.end(), iterator_plus_h_n.begin() + 4);
      56                 :                :     }
      57                 :                : 
      58                 :                :     // H_final = H(H_n + block)
      59            [ + ]:             15 :     auto h_n_plus_block = h_n;
      60                 :             15 :     const std::uint32_t block_number = 0;
      61            [ + ]:             15 :     h_n_plus_block.insert(
      62                 :             15 :         h_n_plus_block.end(),
      63                 :                :         reinterpret_cast<const std::uint8_t *>(&block_number),
      64                 :                :         reinterpret_cast<const std::uint8_t *>(&block_number) + sizeof(std::uint32_t));
      65            [ + ]:             15 :     auto h_final = hash(info.hash, h_n_plus_block);
      66                 :                : 
      67                 :                :     // X1 = H(h_final ^ 0x36)
      68            [ + ]:             15 :     std::vector<std::uint8_t> buffer(64, 0x36);
      69         [ +  + ]:            315 :     for (std::size_t i = 0; i < h_final.size(); ++i)
      70                 :                :     {
      71                 :            300 :         buffer[i] = static_cast<std::uint8_t>(0x36 ^ h_final[i]);
      72                 :                :     }
      73            [ + ]:             15 :     auto X1 = hash(info.hash, buffer);
      74                 :                : 
      75                 :                :     // X2 = H(h_final ^ 0x5C)
      76            [ + ]:             15 :     buffer.assign(64, 0x5c);
      77         [ +  + ]:            315 :     for (std::size_t i = 0; i < h_final.size(); ++i)
      78                 :                :     {
      79                 :            300 :         buffer[i] = static_cast<std::uint8_t>(0x5c ^ h_final[i]);
      80                 :                :     }
      81            [ + ]:             15 :     auto X2 = hash(info.hash, buffer);
      82                 :                : 
      83            [ + ]:             15 :     auto X3 = X1;
      84            [ + ]:             15 :     X3.insert(X3.end(), X2.begin(), X2.end());
      85                 :                : 
      86                 :                :     auto key = std::vector<std::uint8_t>(X3.begin(),
      87            [ + ]:             15 :         X3.begin() + static_cast<std::ptrdiff_t>(info.key_bytes));
      88                 :                : 
      89                 :                :     using xlnt::detail::aes_ecb_decrypt;
      90                 :                : 
      91                 :                :     auto calculated_verifier_hash = hash(info.hash,
      92         [ +  + ]:             15 :         aes_ecb_decrypt(info.encrypted_verifier, key));
      93                 :                :     auto decrypted_verifier_hash = aes_ecb_decrypt(
      94            [ + ]:             15 :         info.encrypted_verifier_hash, key);
      95            [ + ]:             15 :     decrypted_verifier_hash.resize(calculated_verifier_hash.size());
      96                 :                : 
      97      [ +  +  + ]:             15 :     if (calculated_verifier_hash != decrypted_verifier_hash)
      98                 :                :     {
      99         [ +  + ]:              9 :         throw xlnt::exception("bad password");
     100                 :                :     }
     101                 :                : 
     102                 :             12 :     return key;
     103                 :             54 : }
     104                 :                : 
     105                 :             10 : std::vector<std::uint8_t> calculate_agile_key(
     106                 :                :     encryption_info::agile_encryption_info info,
     107                 :                :     const std::u16string &password)
     108                 :                : {
     109                 :                :     // H_0 = H(salt + password)
     110            [ + ]:             10 :     auto salt_plus_password = info.key_encryptor.salt_value;
     111            [ + ]:             10 :     auto password_bytes = xlnt::detail::string_to_bytes(password);
     112         [ +  + ]:             10 :     std::copy(password_bytes.begin(),
     113                 :                :         password_bytes.end(),
     114                 :                :         std::back_inserter(salt_plus_password));
     115                 :                : 
     116            [ + ]:             10 :     auto h_0 = hash(info.key_encryptor.hash, salt_plus_password);
     117                 :                : 
     118                 :                :     // H_n = H(iterator + H_n-1)
     119            [ + ]:             10 :     std::vector<std::uint8_t> iterator_plus_h_n(4, 0);
     120            [ + ]:             10 :     iterator_plus_h_n.insert(iterator_plus_h_n.end(), h_0.begin(), h_0.end());
     121                 :             10 :     std::uint32_t &iterator = *reinterpret_cast<std::uint32_t *>(iterator_plus_h_n.data());
     122                 :             10 :     std::vector<std::uint8_t> h_n;
     123         [ +  + ]:        1000010 :     for (iterator = 0; iterator < info.key_encryptor.spin_count; ++iterator)
     124                 :                :     {
     125            [ + ]:        1000000 :         hash(info.key_encryptor.hash, iterator_plus_h_n, h_n);
     126            [ + ]:        1000000 :         std::copy(h_n.begin(), h_n.end(), iterator_plus_h_n.begin() + 4);
     127                 :                :     }
     128                 :                : 
     129                 :                :     static const std::size_t block_size = 8;
     130                 :                : 
     131                 :             28 :     auto calculate_block = [&info](
     132                 :                :                                const std::vector<std::uint8_t> &raw_key,
     133                 :                :                                const std::array<std::uint8_t, block_size> &block,
     134                 :                :                                const std::vector<std::uint8_t> &encrypted) {
     135            [ + ]:             28 :         auto combined = raw_key;
     136            [ + ]:             28 :         combined.insert(combined.end(), block.begin(), block.end());
     137                 :                : 
     138            [ + ]:             28 :         auto key = hash(info.key_encryptor.hash, combined);
     139            [ + ]:             28 :         key.resize(info.key_encryptor.key_bits / 8);
     140                 :                : 
     141                 :                :         using xlnt::detail::aes_cbc_decrypt;
     142                 :                : 
     143            [ + ]:             56 :         return aes_cbc_decrypt(encrypted, key, info.key_encryptor.salt_value);
     144                 :             28 :     };
     145                 :                : 
     146                 :             10 :     const std::array<std::uint8_t, block_size> input_block_key = {{0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79}};
     147            [ + ]:             10 :     auto hash_input = calculate_block(h_n, input_block_key, info.key_encryptor.verifier_hash_input);
     148            [ + ]:             10 :     auto calculated_verifier = hash(info.key_encryptor.hash, hash_input);
     149                 :                : 
     150                 :             10 :     const std::array<std::uint8_t, block_size> verifier_block_key = {
     151                 :                :         {0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e}};
     152            [ + ]:             10 :     auto expected_verifier = calculate_block(h_n, verifier_block_key, info.key_encryptor.verifier_hash_value);
     153            [ + ]:             10 :     expected_verifier.resize(calculated_verifier.size());
     154                 :                : 
     155      [ +  +  + ]:             10 :     if (calculated_verifier != expected_verifier)
     156                 :                :     {
     157         [ +  + ]:              6 :         throw xlnt::exception("bad password");
     158                 :                :     }
     159                 :                : 
     160                 :              8 :     const std::array<std::uint8_t, block_size> key_value_block_key =
     161                 :                :         {
     162                 :                :             {0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6}};
     163                 :                : 
     164            [ + ]:             16 :     return calculate_block(h_n, key_value_block_key, info.key_encryptor.encrypted_key_value);
     165                 :             24 : }
     166                 :                : 
     167                 :                : } // namespace
     168                 :                : 
     169                 :                : namespace xlnt {
     170                 :                : namespace detail {
     171                 :                : 
     172                 :             25 : std::vector<std::uint8_t> encryption_info::calculate_key() const
     173                 :                : {
     174                 :             25 :     return is_agile
     175      [ +  +  + ]:             35 :         ? calculate_agile_key(agile, password)
     176   [ +  +  +  +  :             80 :         : calculate_standard_key(standard, password);
          +  +  +  +  +  
                   +  + ]
     177                 :                : }
     178                 :                : 
     179                 :                : } // namespace detail
     180                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta