xref: /aosp_15_r20/external/boringssl/src/crypto/fipsmodule/aes/aes_test.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1 /* Copyright (c) 2015, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
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 #if defined(VPAES_CTR32)
320         CHECK_ABI(vpaes_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
321 #endif
322       }
323 
324       ASSERT_EQ(CHECK_ABI(vpaes_set_decrypt_key, kKey, bits, &key), 0);
325       CHECK_ABI(vpaes_decrypt, block, block, &key);
326 #if defined(VPAES_CBC)
327       for (size_t blocks : block_counts) {
328         SCOPED_TRACE(blocks);
329         CHECK_ABI(vpaes_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
330                   block, AES_DECRYPT);
331       }
332 #endif  // VPAES_CBC
333     }
334 
335     if (hwaes_capable()) {
336       ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key, kKey, bits, &key), 0);
337       CHECK_ABI(aes_hw_encrypt, block, block, &key);
338       for (size_t blocks : block_counts) {
339         SCOPED_TRACE(blocks);
340         CHECK_ABI(aes_hw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
341                   block, AES_ENCRYPT);
342         CHECK_ABI(aes_hw_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
343 #if defined(HWAES_ECB)
344         CHECK_ABI(aes_hw_ecb_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
345                   AES_ENCRYPT);
346 #endif
347       }
348 
349 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
350       ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key_base, kKey, bits, &key), 0);
351       if (aes_hw_set_encrypt_key_alt_capable()) {
352         AES_KEY alt;
353         ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key_alt, kKey, bits, &alt),
354                   0);
355         EXPECT_EQ(alt.rounds, key.rounds);
356         for (unsigned i = 0; i <= alt.rounds; i++) {
357           EXPECT_EQ(alt.rd_key[i], key.rd_key[i]);
358         }
359       }
360       CHECK_ABI_SEH(aes_hw_encrypt_key_to_decrypt_key, &key);
361 #else
362       ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_decrypt_key, kKey, bits, &key), 0);
363 #endif
364       CHECK_ABI(aes_hw_decrypt, block, block, &key);
365       for (size_t blocks : block_counts) {
366         SCOPED_TRACE(blocks);
367         CHECK_ABI(aes_hw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
368                   block, AES_DECRYPT);
369 #if defined(HWAES_ECB)
370         CHECK_ABI(aes_hw_ecb_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
371                   AES_DECRYPT);
372 #endif
373       }
374     }
375   }
376 }
377 #endif  // SUPPORTS_ABI_TEST
378 
379 #if defined(BSAES) && !defined(BORINGSSL_SHARED_LIBRARY)
AESKeyToBytes(const AES_KEY * key)380 static Bytes AESKeyToBytes(const AES_KEY *key) {
381   return Bytes(reinterpret_cast<const uint8_t *>(key), sizeof(*key));
382 }
383 
aes_ref_sub_byte(uint8_t b)384 static uint8_t aes_ref_sub_byte(uint8_t b) {
385   static const uint8_t kSBox[256] = {
386       0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
387       0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
388       0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
389       0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
390       0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
391       0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
392       0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
393       0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
394       0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
395       0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
396       0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
397       0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
398       0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
399       0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
400       0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
401       0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
402       0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
403       0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
404       0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
405       0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
406       0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
407       0xb0, 0x54, 0xbb, 0x16,
408   };
409   return kSBox[b];
410 }
411 
aes_ref_sub_word(uint32_t in)412 static uint32_t aes_ref_sub_word(uint32_t in) {
413   uint32_t a0 = aes_ref_sub_byte(in);
414   uint32_t a1 = aes_ref_sub_byte(in >> 8);
415   uint32_t a2 = aes_ref_sub_byte(in >> 16);
416   uint32_t a3 = aes_ref_sub_byte(in >> 24);
417   return a0 | (a1 << 8) | (a2 << 16) | (a3 << 24);
418 }
419 
aes_ref_set_encrypt_key(const uint8_t * key,int key_bits,AES_KEY * out)420 static int aes_ref_set_encrypt_key(const uint8_t *key, int key_bits,
421                                    AES_KEY *out) {
422   static const uint32_t kRCon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
423                                      0x20, 0x40, 0x80, 0x1b, 0x36};
424   switch (key_bits) {
425     case 128:
426       out->rounds = 10;
427       break;
428     case 192:
429       out->rounds = 12;
430       break;
431     case 256:
432       out->rounds = 14;
433       break;
434     default:
435       return 1;
436   }
437 
438   size_t words = key_bits / 32;
439   size_t num_subkey_words = (out->rounds + 1) * 4;
440   OPENSSL_memcpy(out->rd_key, key, words * sizeof(uint32_t));
441   for (size_t i = words; i < num_subkey_words; i++) {
442     uint32_t tmp = out->rd_key[i - 1];
443     if (i % words == 0) {
444       tmp = aes_ref_sub_word(CRYPTO_rotr_u32(tmp, 8)) ^ kRCon[(i / words) - 1];
445     } else if (key_bits == 256 && i % 4 == 0) {
446       tmp = aes_ref_sub_word(tmp);
447     }
448     out->rd_key[i] = tmp ^ out->rd_key[i - words];
449   }
450 
451   // The ARM bsaes implementation expects all the keys to be byteswapped.
452   for (size_t i = 0; i < num_subkey_words; i++) {
453     out->rd_key[i] = CRYPTO_bswap4(out->rd_key[i]);
454   }
455 
456   return 0;
457 }
458 
aes_ref_inv_mix_columns(uint32_t block[4])459 static void aes_ref_inv_mix_columns(uint32_t block[4]) {
460   // This tables was generated with the following Python script:
461   // clang-format off
462 /*
463 def mul_unreduced(a, b):
464   c = 0
465   for i in range(8):
466     if b & (1 << i):
467       c ^= a << i
468   return c
469 
470 def mul(a, b):
471   c = mul_unreduced(a, b)
472   # c's highest term is at most x^14.
473   c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
474   # c's highest term is at most x^10.
475   c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
476   # c's highest term is at most x^7.
477   assert (c >> 8) == 0
478   return c
479 
480 def inv_mix_column(a):
481   ret = 0
482   for b in [0x0e, 0x09, 0x0d, 0x0b]:
483     ret <<= 8
484     ret |= mul(a, b)
485   return ret
486 
487 body = ", ".join("0x%08x" % inv_mix_column(a) for a in range(256))
488 print("static const uint32_t kTable[256] = {%s};\n" % body)
489 */
490   // clang-format on
491 
492   // kInvMixColumn[i] is the result of InvMixColumns applied to a column
493   // containing [i, 0, 0, 0]. (The contributions of the other positions are
494   // computed by rotating bytes.)
495   static const uint32_t kInvMixColumn[256] = {
496       0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
497       0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
498       0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
499       0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
500       0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
501       0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
502       0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
503       0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
504       0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
505       0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
506       0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
507       0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
508       0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
509       0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
510       0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
511       0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
512       0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
513       0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
514       0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
515       0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
516       0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
517       0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
518       0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
519       0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
520       0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
521       0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
522       0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
523       0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
524       0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
525       0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
526       0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
527       0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
528       0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
529       0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
530       0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
531       0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
532       0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
533       0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
534       0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
535       0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
536       0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
537       0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
538       0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3};
539 
540   // Note |block| is byte-swapped so block[i] >> 24 is the first element of
541   // block[i]. (See |aes_ref_set_encrypt_key|).
542   for (size_t i = 0; i < 4; i++) {
543     uint32_t in = block[i];
544     block[i] = kInvMixColumn[in >> 24];
545     block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[(in >> 16) & 0xff], 8);
546     block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[(in >> 8) & 0xff], 16);
547     block[i] ^= CRYPTO_rotr_u32(kInvMixColumn[in & 0xff], 24);
548   }
549 }
550 
aes_ref_set_decrypt_key(const uint8_t * key,int bits,AES_KEY * out)551 static int aes_ref_set_decrypt_key(const uint8_t *key, int bits, AES_KEY *out) {
552   if (aes_ref_set_encrypt_key(key, bits, out) != 0) {
553     return 1;
554   }
555 
556   // bsaes expects the decryption round keys in reverse order. Note there are
557   // |out->rounds + 1| round keys.
558   for (size_t i = 0; i < out->rounds / 2; i++) {
559     std::swap(out->rd_key[4 * i], out->rd_key[4 * (out->rounds - i)]);
560     std::swap(out->rd_key[4 * i + 1], out->rd_key[4 * (out->rounds - i) + 1]);
561     std::swap(out->rd_key[4 * i + 2], out->rd_key[4 * (out->rounds - i) + 2]);
562     std::swap(out->rd_key[4 * i + 3], out->rd_key[4 * (out->rounds - i) + 3]);
563   }
564 
565   // bsaes expects round keys other than the first and last to have
566   // InvMixColumns applied.
567   for (size_t i = 1; i < out->rounds; i++) {
568     aes_ref_inv_mix_columns(out->rd_key + 4 * i);
569   }
570 
571   return 0;
572 }
573 
574 
TEST(AESTest,VPAESToBSAESConvert)575 TEST(AESTest, VPAESToBSAESConvert) {
576   if (!vpaes_capable()) {
577     GTEST_SKIP();
578   }
579 
580   const int kNumIterations = 1000;
581   for (int i = 0; i < kNumIterations; i++) {
582     uint8_t key[256 / 8];
583     RAND_bytes(key, sizeof(key));
584     SCOPED_TRACE(Bytes(key));
585     for (unsigned bits : {128u, 192u, 256u}) {
586       SCOPED_TRACE(bits);
587       for (bool enc : {false, true}) {
588         SCOPED_TRACE(enc);
589         AES_KEY ref, vpaes, bsaes;
590         OPENSSL_memset(&ref, 0xaa, sizeof(ref));
591         OPENSSL_memset(&vpaes, 0xaa, sizeof(vpaes));
592         OPENSSL_memset(&bsaes, 0xaa, sizeof(bsaes));
593 
594         if (enc) {
595           ASSERT_EQ(0, aes_ref_set_encrypt_key(key, bits, &ref));
596           ASSERT_EQ(0, vpaes_set_encrypt_key(key, bits, &vpaes));
597           vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
598         } else {
599           ASSERT_EQ(0, aes_ref_set_decrypt_key(key, bits, &ref));
600           ASSERT_EQ(0, vpaes_set_decrypt_key(key, bits, &vpaes));
601           vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
602         }
603 
604         // Although not fatal, stop running if this fails, otherwise we'll spam
605         // the user's console.
606         ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
607 
608         // Repeat the test in-place.
609         OPENSSL_memcpy(&bsaes, &vpaes, sizeof(AES_KEY));
610         if (enc) {
611           vpaes_encrypt_key_to_bsaes(&bsaes, &bsaes);
612         } else {
613           vpaes_decrypt_key_to_bsaes(&bsaes, &bsaes);
614         }
615 
616         ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
617       }
618     }
619   }
620 }
621 #endif  // BSAES && !SHARED_LIBRARY
622