| /* Copyright 2018 The ChromiumOS Authors |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "benchmark.h" |
| #include "builtin/assert.h" |
| #include "common.h" |
| #include "console.h" |
| #include "openssl/aead.h" |
| #include "openssl/aes.h" |
| #include "openssl/cipher.h" |
| #include "openssl/err.h" |
| #include "test_util.h" |
| #include "timer.h" |
| #include "util.h" |
| #include "watchdog.h" |
| |
| #include <memory> |
| #include <span> |
| |
| /* Temporary buffer, to avoid using too much stack space. */ |
| static uint8_t tmp[512]; |
| |
| struct AesTestVector { |
| std::vector<uint8_t> key; |
| std::vector<uint8_t> plaintext; |
| std::vector<uint8_t> nonce; |
| std::vector<uint8_t> ciphertext; |
| std::vector<uint8_t> tag; |
| /* clang-format off */ |
| auto operator<=> (const AesTestVector &) const = default; |
| /* clang-format on */ |
| }; |
| |
| struct TestVectorHex { |
| std::string key; |
| std::string plaintext; |
| std::string nonce; |
| std::string ciphertext; |
| std::string tag; |
| }; |
| |
| test_static std::optional<uint8_t> HexCharToDigit(const char c) |
| { |
| if (c >= '0' && c <= '9') |
| return static_cast<uint8_t>(c - '0'); |
| |
| if (c >= 'a' && c <= 'f') |
| return static_cast<uint8_t>(c - 'a' + 10); |
| |
| if (c >= 'A' && c <= 'F') |
| return static_cast<uint8_t>(c - 'A' + 10); |
| |
| return std::nullopt; |
| } |
| |
| test_static bool HexStringToBytes(std::string input, |
| std::vector<uint8_t> *output) |
| { |
| size_t count = input.size(); |
| if ((count % 2) != 0) { |
| return false; |
| } |
| |
| if (output == nullptr) { |
| return false; |
| } |
| |
| output->clear(); |
| output->reserve(count / 2); |
| for (size_t i = 0; i < count; i += 2) { |
| // most significant 4 bits |
| std::optional<uint8_t> msb = HexCharToDigit(input[i]); |
| if (!msb) { |
| return false; |
| } |
| // least significant 4 bits |
| std::optional<uint8_t> lsb = HexCharToDigit(input[i + 1]); |
| if (!lsb) { |
| return false; |
| } |
| output->emplace_back((*msb << 4) | *lsb); |
| } |
| return true; |
| } |
| |
| test_static ec_error_list TestVectorHexToBytes(const TestVectorHex &input, |
| AesTestVector *output) |
| { |
| TEST_ASSERT(HexStringToBytes(input.key, &output->key)); |
| TEST_ASSERT(HexStringToBytes(input.plaintext, &output->plaintext)); |
| TEST_ASSERT(HexStringToBytes(input.nonce, &output->nonce)); |
| TEST_ASSERT(HexStringToBytes(input.ciphertext, &output->ciphertext)); |
| TEST_ASSERT(HexStringToBytes(input.tag, &output->tag)); |
| return EC_SUCCESS; |
| } |
| |
| /* |
| * Do encryption, put result in |result|, and compare with |ciphertext|. |
| */ |
| static int test_aes_gcm_encrypt(uint8_t *result, const uint8_t *key, |
| int key_size, const uint8_t *plaintext, |
| const uint8_t *ciphertext, int plaintext_size, |
| const uint8_t *nonce, int nonce_size, |
| const uint8_t *tag, int tag_size) |
| { |
| bssl::ScopedEVP_AEAD_CTX ctx; |
| |
| int ret = EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), key, |
| key_size, tag_size, nullptr); |
| TEST_ASSERT(ret == 1); |
| |
| std::vector<uint8_t> out_tag(tag_size); |
| size_t out_tag_len = 0; |
| |
| const std::span<uint8_t> extra_input; /* no extra input */ |
| const std::span<uint8_t> additional_data; /* no additional data */ |
| |
| ret = EVP_AEAD_CTX_seal_scatter(ctx.get(), result, out_tag.data(), |
| &out_tag_len, tag_size, nonce, |
| nonce_size, plaintext, plaintext_size, |
| extra_input.data(), extra_input.size(), |
| additional_data.data(), |
| additional_data.size()); |
| TEST_ASSERT(ret == 1); |
| TEST_ASSERT(out_tag_len == static_cast<size_t>(tag_size)); |
| |
| TEST_ASSERT_ARRAY_EQ(tag, out_tag, tag_size); |
| TEST_ASSERT_ARRAY_EQ(ciphertext, result, plaintext_size); |
| |
| return EC_SUCCESS; |
| } |
| |
| /* |
| * Do decryption, put result in |result|, and compare with |plaintext|. |
| */ |
| static int test_aes_gcm_decrypt(uint8_t *result, const uint8_t *key, |
| int key_size, const uint8_t *plaintext, |
| const uint8_t *ciphertext, int plaintext_size, |
| const uint8_t *nonce, int nonce_size, |
| const uint8_t *tag, int tag_size) |
| { |
| bssl::ScopedEVP_AEAD_CTX ctx; |
| |
| int ret = EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), key, |
| key_size, tag_size, nullptr); |
| TEST_ASSERT(ret == 1); |
| |
| std::span<uint8_t> additional_data; /* no additional data */ |
| ret = EVP_AEAD_CTX_open_gather(ctx.get(), result, nonce, nonce_size, |
| ciphertext, plaintext_size, tag, |
| tag_size, additional_data.data(), |
| additional_data.size()); |
| TEST_ASSERT(ret == 1); |
| |
| TEST_ASSERT_ARRAY_EQ(plaintext, result, plaintext_size); |
| |
| return EC_SUCCESS; |
| } |
| |
| static int test_aes_gcm_raw_inplace(const uint8_t *key, int key_size, |
| const uint8_t *plaintext, |
| const uint8_t *ciphertext, |
| int plaintext_size, const uint8_t *nonce, |
| int nonce_size, const uint8_t *tag, |
| int tag_size) |
| { |
| /* |
| * Make copies that will be clobbered during in-place encryption or |
| * decryption. |
| */ |
| auto plaintext_ptr = std::make_unique<uint8_t[]>(plaintext_size); |
| auto ciphertext_ptr = std::make_unique<uint8_t[]>(plaintext_size); |
| uint8_t *plaintext_copy = plaintext_ptr.get(); |
| uint8_t *ciphertext_copy = ciphertext_ptr.get(); |
| |
| memcpy(plaintext_copy, plaintext, plaintext_size); |
| memcpy(ciphertext_copy, ciphertext, plaintext_size); |
| |
| TEST_ASSERT(test_aes_gcm_encrypt(plaintext_copy, key, key_size, |
| plaintext_copy, ciphertext, |
| plaintext_size, nonce, nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| |
| TEST_ASSERT(test_aes_gcm_decrypt(ciphertext_copy, key, key_size, |
| plaintext, ciphertext_copy, |
| plaintext_size, nonce, nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| |
| return EC_SUCCESS; |
| } |
| |
| static int test_aes_gcm_raw_non_inplace(const uint8_t *key, int key_size, |
| const uint8_t *plaintext, |
| const uint8_t *ciphertext, |
| int plaintext_size, |
| const uint8_t *nonce, int nonce_size, |
| const uint8_t *tag, int tag_size) |
| { |
| TEST_ASSERT(test_aes_gcm_encrypt(tmp, key, key_size, plaintext, |
| ciphertext, plaintext_size, nonce, |
| nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| |
| TEST_ASSERT(test_aes_gcm_decrypt(tmp, key, key_size, plaintext, |
| ciphertext, plaintext_size, nonce, |
| nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| |
| return EC_SUCCESS; |
| } |
| |
| static int test_aes_gcm_raw(const uint8_t *key, int key_size, |
| const uint8_t *plaintext, const uint8_t *ciphertext, |
| std::size_t plaintext_size, const uint8_t *nonce, |
| std::size_t nonce_size, const uint8_t *tag, |
| std::size_t tag_size) |
| { |
| TEST_ASSERT(plaintext_size <= sizeof(tmp)); |
| |
| TEST_ASSERT(test_aes_gcm_raw_non_inplace(key, key_size, plaintext, |
| ciphertext, plaintext_size, |
| nonce, nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| TEST_ASSERT(test_aes_gcm_raw_inplace(key, key_size, plaintext, |
| ciphertext, plaintext_size, nonce, |
| nonce_size, tag, |
| tag_size) == EC_SUCCESS); |
| |
| return EC_SUCCESS; |
| } |
| |
| test_static int test_aes_gcm(void) |
| { |
| /* |
| * Test vectors from BoringSSL |
| * https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt |
| * (only the ones with actual data, and no additional data). |
| */ |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#4 |
| const TestVectorHex test_vector1 = { |
| .key = "d480429666d48b400633921c5407d1d1", |
| .plaintext = "", |
| .nonce = "3388c676dc754acfa66e172a", |
| .ciphertext = "", |
| .tag = "7d7daf44850921a34e636b01adeb104f", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#424 |
| const TestVectorHex test_vector2 = { |
| .key = "31323334353637383930313233343536", |
| .plaintext = "48656c6c6f2c20576f726c64", |
| .nonce = "31323334353637383930313233343536", |
| .ciphertext = "cec189d0e8419b90fb16d555", |
| .tag = "32893832a8d609224d77c2e56a922282", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#433 |
| const TestVectorHex test_vector3 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = "", |
| .nonce = "000000000000000000000000", |
| .ciphertext = "", |
| .tag = "58e2fccefa7e3061367f1d57a4e7455a", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#440 |
| const TestVectorHex test_vector4 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = "", |
| .nonce = "000000000000000000000000", |
| .ciphertext = "", |
| .tag = "58e2fccefa7e3061367f1d57a4e7455a", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#447 |
| const TestVectorHex test_vector5 = { |
| .key = "feffe9928665731c6d6a8f9467308308", |
| .plaintext = |
| "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", |
| .nonce = "cafebabefacedbaddecaf888", |
| .ciphertext = |
| "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", |
| .tag = "4d5c2af327cd64a62cf35abd2ba6fab4", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#485 |
| const TestVectorHex test_vector6 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = |
| "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .nonce = "000000000000000000000000", |
| .ciphertext = |
| "0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0", |
| .tag = "9dd0a376b08e40eb00c35f29f9ea61a4", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#493 |
| const TestVectorHex test_vector7 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = |
| "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .nonce = "000000000000000000000000", |
| .ciphertext = |
| "0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291", |
| .tag = "98885a3a22bd4742fe7b72172193b163", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#501 |
| const TestVectorHex test_vector8 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = |
| "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .nonce = "000000000000000000000000", |
| .ciphertext = |
| "0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40", |
| .tag = "cac45f60e31efd3b5a43b98a22ce1aa1", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#509 |
| const TestVectorHex test_vector9 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = |
| "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .nonce = |
| "ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .ciphertext = |
| "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606", |
| .tag = "566f8ef683078bfdeeffa869d751a017", |
| }; |
| |
| // https://boringssl.googlesource.com/boringssl/+/f94f3ed3965ea033001fb9ae006084eee408b861/crypto/cipher_extra/test/aes_128_gcm_tests.txt#517 |
| const TestVectorHex test_vector10 = { |
| .key = "00000000000000000000000000000000", |
| .plaintext = |
| "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .nonce = |
| "ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
| .ciphertext = |
| "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c", |
| .tag = "8b307f6b33286d0ab026a9ed3fe1e85f", |
| }; |
| |
| const std::array hex_test_vectors = { test_vector1, test_vector2, |
| test_vector3, test_vector4, |
| test_vector5, test_vector6, |
| test_vector7, test_vector8, |
| test_vector9, test_vector10 }; |
| |
| std::vector<AesTestVector> test_vectors; |
| for (const auto &hex_test_vector : hex_test_vectors) { |
| AesTestVector test_vector; |
| TEST_ASSERT(TestVectorHexToBytes(hex_test_vector, |
| &test_vector) == EC_SUCCESS); |
| test_vectors.emplace_back(test_vector); |
| } |
| |
| constexpr size_t kExpectedNumTestVectors = 10; |
| TEST_EQ(test_vectors.size(), kExpectedNumTestVectors, "%zu"); |
| for (const auto &test_vector : test_vectors) { |
| TEST_ASSERT(!test_aes_gcm_raw( |
| test_vector.key.data(), test_vector.key.size(), |
| test_vector.plaintext.data(), |
| test_vector.ciphertext.data(), |
| test_vector.plaintext.size(), test_vector.nonce.data(), |
| test_vector.nonce.size(), test_vector.tag.data(), |
| test_vector.tag.size())); |
| } |
| |
| return EC_SUCCESS; |
| } |
| |
| static void test_aes_gcm_speed(void) |
| { |
| Benchmark benchmark({ .num_iterations = 1000 }); |
| constexpr auto key = std::to_array<uint8_t>({ |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| }); |
| std::array<uint8_t, 512> plaintext{}; |
| |
| constexpr auto nonce = std::to_array<uint8_t>({ |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| 0x00, |
| }); |
| std::array<uint8_t, 16> tag{}; |
| |
| uint8_t *encrypted_data = tmp; |
| |
| ASSERT(plaintext.size() <= sizeof(tmp)); |
| |
| benchmark.run("AES-GCM encrypt", [&]() { |
| bssl::ScopedEVP_AEAD_CTX ctx; |
| |
| int ret = EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), |
| key.data(), key.size(), tag.size(), |
| nullptr); |
| ASSERT(ret == 1); |
| |
| size_t out_tag_len = 0; |
| |
| const std::span<uint8_t> extra_input; /* no extra input */ |
| const std::span<uint8_t> additional_data; /* no additional data |
| */ |
| |
| ret = EVP_AEAD_CTX_seal_scatter( |
| ctx.get(), encrypted_data, tag.data(), &out_tag_len, |
| tag.size(), nonce.data(), nonce.size(), |
| plaintext.data(), plaintext.size(), extra_input.data(), |
| extra_input.size(), additional_data.data(), |
| additional_data.size()); |
| ASSERT(ret == 1); |
| ASSERT(out_tag_len == tag.size()); |
| }); |
| |
| benchmark.run("AES-GCM decrypt", [&]() { |
| bssl::ScopedEVP_AEAD_CTX ctx; |
| |
| int ret = EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), |
| key.data(), key.size(), tag.size(), |
| nullptr); |
| ASSERT(ret == 1); |
| |
| std::span<uint8_t> additional_data; /* no additional data */ |
| ret = EVP_AEAD_CTX_open_gather(ctx.get(), plaintext.data(), |
| nonce.data(), nonce.size(), |
| encrypted_data, plaintext.size(), |
| tag.data(), tag.size(), |
| additional_data.data(), |
| additional_data.size()); |
| ASSERT(ret == 1); |
| }); |
| benchmark.print_results(); |
| } |
| |
| static int test_aes_raw(const uint8_t *key, int key_size, |
| const uint8_t *plaintext, const uint8_t *ciphertext) |
| { |
| AES_KEY aes_key; |
| uint8_t *block = tmp; |
| |
| TEST_ASSERT(AES_BLOCK_SIZE <= sizeof(tmp)); |
| |
| TEST_ASSERT(AES_set_encrypt_key(key, 8 * key_size, &aes_key) == 0); |
| |
| /* Test encryption. */ |
| AES_encrypt(plaintext, block, &aes_key); |
| TEST_ASSERT_ARRAY_EQ(ciphertext, block, AES_BLOCK_SIZE); |
| |
| /* Test in-place encryption. */ |
| memcpy(block, plaintext, AES_BLOCK_SIZE); |
| AES_encrypt(block, block, &aes_key); |
| TEST_ASSERT_ARRAY_EQ(ciphertext, block, AES_BLOCK_SIZE); |
| |
| TEST_ASSERT(AES_set_decrypt_key(key, 8 * key_size, &aes_key) == 0); |
| |
| /* Test decryption. */ |
| AES_decrypt(ciphertext, block, &aes_key); |
| TEST_ASSERT_ARRAY_EQ(plaintext, block, AES_BLOCK_SIZE); |
| |
| /* Test in-place decryption. */ |
| memcpy(block, ciphertext, AES_BLOCK_SIZE); |
| AES_decrypt(block, block, &aes_key); |
| TEST_ASSERT_ARRAY_EQ(plaintext, block, AES_BLOCK_SIZE); |
| |
| return EC_SUCCESS; |
| } |
| |
| static int test_aes(void) |
| { |
| /* Test vectors from FIPS-197, Appendix C. */ |
| static const uint8_t key1[] = { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| }; |
| static const uint8_t plain1[] = { |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, |
| }; |
| static const uint8_t cipher1[] = { |
| 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, |
| 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a, |
| }; |
| |
| static const uint8_t key2[] = { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| }; |
| static const uint8_t plain2[] = { |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, |
| }; |
| static const uint8_t cipher2[] = { |
| 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, |
| 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91, |
| }; |
| |
| static const uint8_t key3[] = { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| }; |
| static const uint8_t plain3[] = { |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, |
| }; |
| static const uint8_t cipher3[] = { |
| 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, |
| 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89, |
| }; |
| |
| TEST_ASSERT(!test_aes_raw(key1, sizeof(key1), plain1, cipher1)); |
| TEST_ASSERT(!test_aes_raw(key2, sizeof(key2), plain2, cipher2)); |
| TEST_ASSERT(!test_aes_raw(key3, sizeof(key3), plain3, cipher3)); |
| |
| return EC_SUCCESS; |
| } |
| |
| static void test_aes_speed(void) |
| { |
| Benchmark benchmark({ .num_iterations = 1000 }); |
| /* Test vectors from FIPS-197, Appendix C. */ |
| static const uint8_t key[] __aligned(4) = { |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| }; |
| const int key_size = sizeof(key); |
| static const uint8_t plaintext[] __aligned(4) = { |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, |
| }; |
| |
| AES_KEY aes_key; |
| uint8_t block[AES_BLOCK_SIZE]; |
| |
| AES_set_encrypt_key(key, 8 * key_size, &aes_key); |
| AES_encrypt(plaintext, block, &aes_key); |
| benchmark.run("AES", [&block, &aes_key]() { |
| AES_encrypt(block, block, &aes_key); |
| }); |
| benchmark.print_results(); |
| } |
| |
| void run_test(int argc, const char **argv) |
| { |
| watchdog_reload(); |
| |
| /* do not check result, just as a benchmark */ |
| test_aes_speed(); |
| |
| watchdog_reload(); |
| RUN_TEST(test_aes); |
| |
| /* do not check result, just as a benchmark */ |
| test_aes_gcm_speed(); |
| |
| watchdog_reload(); |
| RUN_TEST(test_aes_gcm); |
| |
| test_print_result(); |
| } |