1 // Copyright 2015 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <algorithm>
20 #include <memory>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24
25 #include <openssl/aes.h>
26 #include <openssl/rand.h>
27
28 #include "internal.h"
29 #include "../../internal.h"
30 #include "../../test/abi_test.h"
31 #include "../../test/file_test.h"
32 #include "../../test/test_util.h"
33 #include "../../test/wycheproof_util.h"
34
35
TestRaw(FileTest * t)36 static void TestRaw(FileTest *t) {
37 std::vector<uint8_t> key, plaintext, ciphertext;
38 ASSERT_TRUE(t->GetBytes(&key, "Key"));
39 ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
40 ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
41
42 ASSERT_EQ(static_cast<unsigned>(AES_BLOCK_SIZE), plaintext.size());
43 ASSERT_EQ(static_cast<unsigned>(AES_BLOCK_SIZE), ciphertext.size());
44
45 AES_KEY aes_key;
46 ASSERT_EQ(0, AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key));
47
48 // Test encryption.
49 uint8_t block[AES_BLOCK_SIZE];
50 AES_encrypt(plaintext.data(), block, &aes_key);
51 EXPECT_EQ(Bytes(ciphertext), Bytes(block));
52
53 // Test in-place encryption.
54 OPENSSL_memcpy(block, plaintext.data(), AES_BLOCK_SIZE);
55 AES_encrypt(block, block, &aes_key);
56 EXPECT_EQ(Bytes(ciphertext), Bytes(block));
57
58 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key));
59
60 // Test decryption.
61 AES_decrypt(ciphertext.data(), block, &aes_key);
62 EXPECT_EQ(Bytes(plaintext), Bytes(block));
63
64 // Test in-place decryption.
65 OPENSSL_memcpy(block, ciphertext.data(), AES_BLOCK_SIZE);
66 AES_decrypt(block, block, &aes_key);
67 EXPECT_EQ(Bytes(plaintext), Bytes(block));
68 }
69
TestKeyWrap(FileTest * t)70 static void TestKeyWrap(FileTest *t) {
71 // All test vectors use the default IV, so test both with implicit and
72 // explicit IV.
73 //
74 // TODO(davidben): Find test vectors that use a different IV.
75 static const uint8_t kDefaultIV[] = {
76 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
77 };
78
79 std::vector<uint8_t> key, plaintext, ciphertext;
80 ASSERT_TRUE(t->GetBytes(&key, "Key"));
81 ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
82 ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
83
84 ASSERT_EQ(plaintext.size() + 8, ciphertext.size())
85 << "Invalid Plaintext and Ciphertext lengths.";
86
87 // Test encryption.
88 AES_KEY aes_key;
89 ASSERT_EQ(0, AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key));
90
91 // Test with implicit IV.
92 auto buf = std::make_unique<uint8_t[]>(ciphertext.size());
93 int len = AES_wrap_key(&aes_key, nullptr /* iv */, buf.get(),
94 plaintext.data(), plaintext.size());
95 ASSERT_GE(len, 0);
96 EXPECT_EQ(Bytes(ciphertext), Bytes(buf.get(), static_cast<size_t>(len)));
97
98 // Test with explicit IV.
99 OPENSSL_memset(buf.get(), 0, ciphertext.size());
100 len = AES_wrap_key(&aes_key, kDefaultIV, buf.get(), plaintext.data(),
101 plaintext.size());
102 ASSERT_GE(len, 0);
103 EXPECT_EQ(Bytes(ciphertext), Bytes(buf.get(), static_cast<size_t>(len)));
104
105 // Test decryption.
106 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key));
107
108 // Test with implicit IV.
109 buf = std::make_unique<uint8_t[]>(plaintext.size());
110 len = AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
111 ciphertext.size());
112 ASSERT_GE(len, 0);
113 EXPECT_EQ(Bytes(plaintext), Bytes(buf.get(), static_cast<size_t>(len)));
114
115 // Test with explicit IV.
116 OPENSSL_memset(buf.get(), 0, plaintext.size());
117 len = AES_unwrap_key(&aes_key, kDefaultIV, buf.get(), ciphertext.data(),
118 ciphertext.size());
119 ASSERT_GE(len, 0);
120
121 // Test corrupted ciphertext.
122 ciphertext[0] ^= 1;
123 EXPECT_EQ(-1, AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(),
124 ciphertext.data(), ciphertext.size()));
125 }
126
TestKeyWrapWithPadding(FileTest * t)127 static void TestKeyWrapWithPadding(FileTest *t) {
128 std::vector<uint8_t> key, plaintext, ciphertext;
129 ASSERT_TRUE(t->GetBytes(&key, "Key"));
130 ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
131 ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
132
133 // Test encryption.
134 AES_KEY aes_key;
135 ASSERT_EQ(0, AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key));
136 auto buf = std::make_unique<uint8_t[]>(plaintext.size() + 15);
137 size_t len;
138 ASSERT_TRUE(AES_wrap_key_padded(&aes_key, buf.get(), &len,
139 plaintext.size() + 15, plaintext.data(),
140 plaintext.size()));
141 EXPECT_EQ(Bytes(ciphertext), Bytes(buf.get(), static_cast<size_t>(len)));
142
143 // Test decryption
144 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key));
145 buf = std::make_unique<uint8_t[]>(ciphertext.size() - 8);
146 ASSERT_TRUE(AES_unwrap_key_padded(&aes_key, buf.get(), &len,
147 ciphertext.size() - 8, ciphertext.data(),
148 ciphertext.size()));
149 ASSERT_EQ(len, plaintext.size());
150 EXPECT_EQ(Bytes(plaintext), Bytes(buf.get(), static_cast<size_t>(len)));
151 }
152
TEST(AESTest,TestVectors)153 TEST(AESTest, TestVectors) {
154 FileTestGTest("crypto/fipsmodule/aes/aes_tests.txt", [](FileTest *t) {
155 if (t->GetParameter() == "Raw") {
156 TestRaw(t);
157 } else if (t->GetParameter() == "KeyWrap") {
158 TestKeyWrap(t);
159 } else if (t->GetParameter() == "KeyWrapWithPadding") {
160 TestKeyWrapWithPadding(t);
161 } else {
162 ADD_FAILURE() << "Unknown mode " << t->GetParameter();
163 }
164 });
165 }
166
TEST(AESTest,WycheproofKeyWrap)167 TEST(AESTest, WycheproofKeyWrap) {
168 FileTestGTest("third_party/wycheproof_testvectors/kw_test.txt",
169 [](FileTest *t) {
170 std::string key_size;
171 ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
172 std::vector<uint8_t> ct, key, msg;
173 ASSERT_TRUE(t->GetBytes(&ct, "ct"));
174 ASSERT_TRUE(t->GetBytes(&key, "key"));
175 ASSERT_TRUE(t->GetBytes(&msg, "msg"));
176 ASSERT_EQ(static_cast<unsigned>(atoi(key_size.c_str())), key.size() * 8);
177 WycheproofResult result;
178 ASSERT_TRUE(GetWycheproofResult(t, &result));
179
180 if (result.IsValid()) {
181 ASSERT_GE(ct.size(), 8u);
182
183 AES_KEY aes;
184 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
185 std::vector<uint8_t> out(ct.size() - 8);
186 int len = AES_unwrap_key(&aes, nullptr, out.data(), ct.data(), ct.size());
187 ASSERT_EQ(static_cast<int>(out.size()), len);
188 EXPECT_EQ(Bytes(msg), Bytes(out));
189
190 out.resize(msg.size() + 8);
191 ASSERT_EQ(0, AES_set_encrypt_key(key.data(), 8 * key.size(), &aes));
192 len = AES_wrap_key(&aes, nullptr, out.data(), msg.data(), msg.size());
193 ASSERT_EQ(static_cast<int>(out.size()), len);
194 EXPECT_EQ(Bytes(ct), Bytes(out));
195 } else {
196 AES_KEY aes;
197 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
198 std::vector<uint8_t> out(ct.size() < 8 ? 0 : ct.size() - 8);
199 int len = AES_unwrap_key(&aes, nullptr, out.data(), ct.data(), ct.size());
200 EXPECT_EQ(-1, len);
201 }
202 });
203 }
204
TEST(AESTest,WycheproofKeyWrapWithPadding)205 TEST(AESTest, WycheproofKeyWrapWithPadding) {
206 FileTestGTest("third_party/wycheproof_testvectors/kwp_test.txt",
207 [](FileTest *t) {
208 std::string key_size;
209 ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
210 std::vector<uint8_t> ct, key, msg;
211 ASSERT_TRUE(t->GetBytes(&ct, "ct"));
212 ASSERT_TRUE(t->GetBytes(&key, "key"));
213 ASSERT_TRUE(t->GetBytes(&msg, "msg"));
214 ASSERT_EQ(static_cast<unsigned>(atoi(key_size.c_str())), key.size() * 8);
215 WycheproofResult result;
216 ASSERT_TRUE(GetWycheproofResult(t, &result));
217
218 // Wycheproof contains test vectors with empty messages that it believes
219 // should pass. However, both RFC 5649 and SP 800-38F section 5.3.1 say that
220 // the minimum length is one. Therefore we consider test cases with an empty
221 // message to be invalid.
222 //
223 // Wycheproof marks various weak parameters as acceptable. We do not enforce
224 // policy in the library, so we map those flags to valid.
225 if (result.IsValid({"SmallKey", "WeakWrapping"}) && !msg.empty()) {
226 AES_KEY aes;
227 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
228 std::vector<uint8_t> out(ct.size() - 8);
229 size_t len;
230 ASSERT_TRUE(AES_unwrap_key_padded(&aes, out.data(), &len, ct.size() - 8,
231 ct.data(), ct.size()));
232 EXPECT_EQ(Bytes(msg), Bytes(out.data(), len));
233
234 out.resize(msg.size() + 15);
235 ASSERT_EQ(0, AES_set_encrypt_key(key.data(), 8 * key.size(), &aes));
236 ASSERT_TRUE(AES_wrap_key_padded(&aes, out.data(), &len, msg.size() + 15,
237 msg.data(), msg.size()));
238 EXPECT_EQ(Bytes(ct), Bytes(out.data(), len));
239 } else {
240 AES_KEY aes;
241 ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
242 std::vector<uint8_t> out(ct.size());
243 size_t len;
244 ASSERT_FALSE(AES_unwrap_key_padded(&aes, out.data(), &len, ct.size(),
245 ct.data(), ct.size()));
246 }
247 });
248 }
249
TEST(AESTest,WrapBadLengths)250 TEST(AESTest, WrapBadLengths) {
251 uint8_t key[128/8] = {0};
252 AES_KEY aes;
253 ASSERT_EQ(0, AES_set_encrypt_key(key, 128, &aes));
254
255 // Input lengths to |AES_wrap_key| must be a multiple of 8 and at least 16.
256 static const size_t kLengths[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
257 9, 10, 11, 12, 13, 14, 15, 20};
258 for (size_t len : kLengths) {
259 SCOPED_TRACE(len);
260 std::vector<uint8_t> in(len);
261 std::vector<uint8_t> out(len + 8);
262 EXPECT_EQ(-1,
263 AES_wrap_key(&aes, nullptr, out.data(), in.data(), in.size()));
264 }
265 }
266
TEST(AESTest,InvalidKeySize)267 TEST(AESTest, InvalidKeySize) {
268 static const uint8_t kZero[8] = {0};
269 AES_KEY key;
270 EXPECT_LT(AES_set_encrypt_key(kZero, 42, &key), 0);
271 EXPECT_LT(AES_set_decrypt_key(kZero, 42, &key), 0);
272 }
273
274 #if defined(SUPPORTS_ABI_TEST)
TEST(AESTest,ABI)275 TEST(AESTest, ABI) {
276 for (int bits : {128, 192, 256}) {
277 SCOPED_TRACE(bits);
278 const uint8_t kKey[256/8] = {0};
279 AES_KEY key;
280 uint8_t block[AES_BLOCK_SIZE];
281 uint8_t buf[AES_BLOCK_SIZE * 64] = {0};
282 std::vector<int> block_counts;
283 if (bits == 128) {
284 block_counts = {0, 1, 2, 3, 4, 8, 16, 31};
285 } else {
286 // Unwind tests are very slow. Assume that the various input sizes do not
287 // differ significantly by round count for ABI purposes.
288 block_counts = {0, 1, 8};
289 }
290
291 if (bsaes_capable()) {
292 ASSERT_EQ(vpaes_set_encrypt_key(kKey, bits, &key), 0);
293 CHECK_ABI(vpaes_encrypt_key_to_bsaes, &key, &key);
294 for (size_t blocks : block_counts) {
295 SCOPED_TRACE(blocks);
296 if (blocks != 0) {
297 CHECK_ABI(bsaes_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
298 }
299 }
300
301 ASSERT_EQ(vpaes_set_decrypt_key(kKey, bits, &key), 0);
302 CHECK_ABI(vpaes_decrypt_key_to_bsaes, &key, &key);
303 for (size_t blocks : block_counts) {
304 SCOPED_TRACE(blocks);
305 CHECK_ABI(bsaes_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
306 block, AES_DECRYPT);
307 }
308 }
309
310 if (vpaes_capable()) {
311 ASSERT_EQ(CHECK_ABI(vpaes_set_encrypt_key, kKey, bits, &key), 0);
312 CHECK_ABI(vpaes_encrypt, block, block, &key);
313 for (size_t blocks : block_counts) {
314 SCOPED_TRACE(blocks);
315 #if defined(VPAES_CBC)
316 CHECK_ABI(vpaes_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
317 block, AES_ENCRYPT);
318 #endif
319 CHECK_ABI(vpaes_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
320 }
321
322 ASSERT_EQ(CHECK_ABI(vpaes_set_decrypt_key, kKey, bits, &key), 0);
323 CHECK_ABI(vpaes_decrypt, block, block, &key);
324 #if defined(VPAES_CBC)
325 for (size_t blocks : block_counts) {
326 SCOPED_TRACE(blocks);
327 CHECK_ABI(vpaes_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
328 block, AES_DECRYPT);
329 }
330 #endif // VPAES_CBC
331 }
332
333 if (hwaes_capable()) {
334 ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key, kKey, bits, &key), 0);
335 CHECK_ABI(aes_hw_encrypt, block, block, &key);
336 for (size_t blocks : block_counts) {
337 SCOPED_TRACE(blocks);
338 CHECK_ABI(aes_hw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
339 block, AES_ENCRYPT);
340 CHECK_ABI(aes_hw_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
341 #if defined(HWAES_ECB)
342 CHECK_ABI(aes_hw_ecb_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
343 AES_ENCRYPT);
344 #endif
345 }
346
347 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
348 ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key_base, kKey, bits, &key), 0);
349 if (aes_hw_set_encrypt_key_alt_capable()) {
350 AES_KEY alt;
351 ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key_alt, kKey, bits, &alt),
352 0);
353 EXPECT_EQ(alt.rounds, key.rounds);
354 for (unsigned i = 0; i <= alt.rounds; i++) {
355 EXPECT_EQ(alt.rd_key[i], key.rd_key[i]);
356 }
357 }
358 CHECK_ABI_SEH(aes_hw_encrypt_key_to_decrypt_key, &key);
359 #else
360 ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_decrypt_key, kKey, bits, &key), 0);
361 #endif
362 CHECK_ABI(aes_hw_decrypt, block, block, &key);
363 for (size_t blocks : block_counts) {
364 SCOPED_TRACE(blocks);
365 CHECK_ABI(aes_hw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
366 block, AES_DECRYPT);
367 #if defined(HWAES_ECB)
368 CHECK_ABI(aes_hw_ecb_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
369 AES_DECRYPT);
370 #endif
371 }
372 }
373 }
374 }
375 #endif // SUPPORTS_ABI_TEST
376
377 #if defined(BSAES) && !defined(BORINGSSL_SHARED_LIBRARY)
AESKeyToBytes(const AES_KEY * key)378 static Bytes AESKeyToBytes(const AES_KEY *key) {
379 return Bytes(reinterpret_cast<const uint8_t *>(key), sizeof(*key));
380 }
381
aes_ref_sub_byte(uint8_t b)382 static uint8_t aes_ref_sub_byte(uint8_t b) {
383 static const uint8_t kSBox[256] = {
384 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
385 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
386 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
387 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
388 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
389 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
390 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
391 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
392 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
393 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
394 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
395 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
396 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
397 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
398 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
399 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
400 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
401 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
402 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
403 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
404 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
405 0xb0, 0x54, 0xbb, 0x16,
406 };
407 return kSBox[b];
408 }
409
aes_ref_sub_word(uint32_t in)410 static uint32_t aes_ref_sub_word(uint32_t in) {
411 uint32_t a0 = aes_ref_sub_byte(in);
412 uint32_t a1 = aes_ref_sub_byte(in >> 8);
413 uint32_t a2 = aes_ref_sub_byte(in >> 16);
414 uint32_t a3 = aes_ref_sub_byte(in >> 24);
415 return a0 | (a1 << 8) | (a2 << 16) | (a3 << 24);
416 }
417
aes_ref_set_encrypt_key(const uint8_t * key,int key_bits,AES_KEY * out)418 static int aes_ref_set_encrypt_key(const uint8_t *key, int key_bits,
419 AES_KEY *out) {
420 static const uint32_t kRCon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
421 0x20, 0x40, 0x80, 0x1b, 0x36};
422 switch (key_bits) {
423 case 128:
424 out->rounds = 10;
425 break;
426 case 192:
427 out->rounds = 12;
428 break;
429 case 256:
430 out->rounds = 14;
431 break;
432 default:
433 return 1;
434 }
435
436 size_t words = key_bits / 32;
437 size_t num_subkey_words = (out->rounds + 1) * 4;
438 OPENSSL_memcpy(out->rd_key, key, words * sizeof(uint32_t));
439 for (size_t i = words; i < num_subkey_words; i++) {
440 uint32_t tmp = out->rd_key[i - 1];
441 if (i % words == 0) {
442 tmp = aes_ref_sub_word(CRYPTO_rotr_u32(tmp, 8)) ^ kRCon[(i / words) - 1];
443 } else if (key_bits == 256 && i % 4 == 0) {
444 tmp = aes_ref_sub_word(tmp);
445 }
446 out->rd_key[i] = tmp ^ out->rd_key[i - words];
447 }
448
449 // The ARM bsaes implementation expects all the keys to be byteswapped.
450 for (size_t i = 0; i < num_subkey_words; i++) {
451 out->rd_key[i] = CRYPTO_bswap4(out->rd_key[i]);
452 }
453
454 return 0;
455 }
456
aes_ref_inv_mix_columns(uint32_t block[4])457 static void aes_ref_inv_mix_columns(uint32_t block[4]) {
458 // This tables was generated with the following Python script:
459 // clang-format off
460 /*
461 def mul_unreduced(a, b):
462 c = 0
463 for i in range(8):
464 if b & (1 << i):
465 c ^= a << i
466 return c
467
468 def mul(a, b):
469 c = mul_unreduced(a, b)
470 # c's highest term is at most x^14.
471 c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
472 # c's highest term is at most x^10.
473 c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
474 # c's highest term is at most x^7.
475 assert (c >> 8) == 0
476 return c
477
478 def inv_mix_column(a):
479 ret = 0
480 for b in [0x0e, 0x09, 0x0d, 0x0b]:
481 ret <<= 8
482 ret |= mul(a, b)
483 return ret
484
485 body = ", ".join("0x%08x" % inv_mix_column(a) for a in range(256))
486 print("static const uint32_t kTable[256] = {%s};\n" % body)
487 */
488 // clang-format on
489
490 // kInvMixColumn[i] is the result of InvMixColumns applied to a column
491 // containing [i, 0, 0, 0]. (The contributions of the other positions are
492 // computed by rotating bytes.)
493 static const uint32_t kInvMixColumn[256] = {
494 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
495 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
496 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
497 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
498 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
499 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
500 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
501 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
502 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
503 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
504 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
505 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
506 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
507 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
508 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
509 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
510 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
511 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
512 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
513 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
514 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
515 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
516 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
517 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
518 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
519 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
520 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
521 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
522 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
523 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
524 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
525 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
526 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
527 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
528 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
529 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
530 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
531 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
532 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
533 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
534 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
535 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
536 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3};
537
538 // Note |block| is byte-swapped so block[i] >> 24 is the first element of
539 // block[i]. (See |aes_ref_set_encrypt_key|).
540 for (size_t i = 0; i < 4; i++) {
541 uint32_t in = block[i];
542 block[i] = kInvMixColumn[in >> 24];
543 block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[(in >> 16) & 0xff], 8);
544 block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[(in >> 8) & 0xff], 16);
545 block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[in & 0xff], 24);
546 }
547 }
548
aes_ref_set_decrypt_key(const uint8_t * key,int bits,AES_KEY * out)549 static int aes_ref_set_decrypt_key(const uint8_t *key, int bits, AES_KEY *out) {
550 if (aes_ref_set_encrypt_key(key, bits, out) != 0) {
551 return 1;
552 }
553
554 // bsaes expects the decryption round keys in reverse order. Note there are
555 // |out->rounds + 1| round keys.
556 for (size_t i = 0; i < out->rounds / 2; i++) {
557 std::swap(out->rd_key[4 * i], out->rd_key[4 * (out->rounds - i)]);
558 std::swap(out->rd_key[4 * i + 1], out->rd_key[4 * (out->rounds - i) + 1]);
559 std::swap(out->rd_key[4 * i + 2], out->rd_key[4 * (out->rounds - i) + 2]);
560 std::swap(out->rd_key[4 * i + 3], out->rd_key[4 * (out->rounds - i) + 3]);
561 }
562
563 // bsaes expects round keys other than the first and last to have
564 // InvMixColumns applied.
565 for (size_t i = 1; i < out->rounds; i++) {
566 aes_ref_inv_mix_columns(out->rd_key + 4 * i);
567 }
568
569 return 0;
570 }
571
572
TEST(AESTest,VPAESToBSAESConvert)573 TEST(AESTest, VPAESToBSAESConvert) {
574 if (!vpaes_capable()) {
575 GTEST_SKIP();
576 }
577
578 const int kNumIterations = 1000;
579 for (int i = 0; i < kNumIterations; i++) {
580 uint8_t key[256 / 8];
581 RAND_bytes(key, sizeof(key));
582 SCOPED_TRACE(Bytes(key));
583 for (unsigned bits : {128u, 192u, 256u}) {
584 SCOPED_TRACE(bits);
585 for (bool enc : {false, true}) {
586 SCOPED_TRACE(enc);
587 AES_KEY ref, vpaes, bsaes;
588 OPENSSL_memset(&ref, 0xaa, sizeof(ref));
589 OPENSSL_memset(&vpaes, 0xaa, sizeof(vpaes));
590 OPENSSL_memset(&bsaes, 0xaa, sizeof(bsaes));
591
592 if (enc) {
593 ASSERT_EQ(0, aes_ref_set_encrypt_key(key, bits, &ref));
594 ASSERT_EQ(0, vpaes_set_encrypt_key(key, bits, &vpaes));
595 vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
596 } else {
597 ASSERT_EQ(0, aes_ref_set_decrypt_key(key, bits, &ref));
598 ASSERT_EQ(0, vpaes_set_decrypt_key(key, bits, &vpaes));
599 vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
600 }
601
602 // Although not fatal, stop running if this fails, otherwise we'll spam
603 // the user's console.
604 ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
605
606 // Repeat the test in-place.
607 OPENSSL_memcpy(&bsaes, &vpaes, sizeof(AES_KEY));
608 if (enc) {
609 vpaes_encrypt_key_to_bsaes(&bsaes, &bsaes);
610 } else {
611 vpaes_decrypt_key_to_bsaes(&bsaes, &bsaes);
612 }
613
614 ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
615 }
616 }
617 }
618 }
619 #endif // BSAES && !SHARED_LIBRARY
620