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
|