1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "crypto/aes_cbc.h"
6
7 #include <cstring>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace {
13
TEST(AesCbcTests,KnownAnswers)14 TEST(AesCbcTests, KnownAnswers) {
15 struct TestCase {
16 const char* key;
17 const char* iv;
18 const char* plaintext;
19 const char* ciphertext;
20 };
21
22 constexpr auto cases = std::to_array<TestCase>({
23 // SP800-38a F.2.1, with a PKCS#5 padding block appended to it.
24 {
25 .key = "2b7e151628aed2a6abf7158809cf4f3c",
26 .iv = "000102030405060708090a0b0c0d0e0f",
27 .plaintext = "6bc1bee22e409f96e93d7e117393172a"
28 "ae2d8a571e03ac9c9eb76fac45af8e51"
29 "30c81c46a35ce411e5fbc1191a0a52ef"
30 "f69f2445df4f9b17ad2b417be66c3710",
31 .ciphertext = "7649abac8119b246cee98e9b12e9197d"
32 "5086cb9b507219ee95db113a917678b2"
33 "73bed6b8e3c1743b7116e69e22229516"
34 "3ff1caa1681fac09120eca307586e1a7"
35 "8cb82807230e1321d3fae00d18cc2012",
36 },
37
38 // Modification of SP800-38a F.2.6: stripped off a bit of plaintext, added
39 // padding block.
40 {.key =
41 "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
42 .iv = "000102030405060708090a0b0c0d0e0f",
43 .plaintext = "6bc1bee22e409f96e93d7e117393172a"
44 "ae2d8a571e03ac9c9eb76fac45af8e51"
45 "30c81c46a35ce411e5fbc1191a0a52ef"
46 "f69f2445df4f9b17ad2b417be6",
47 .ciphertext = "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
48 "9cfc4e967edb808d679f777bc6702c7d"
49 "39f23369a9d9bacfa530e26304231461"
50 "c9aaf02a6a54e9e242ccbf48c59daca6"},
51 });
52
53 for (const auto& c : cases) {
54 std::vector<uint8_t> key;
55 CHECK(base::HexStringToBytes(c.key, &key));
56
57 std::array<uint8_t, crypto::aes_cbc::kBlockSize> iv;
58 CHECK(base::HexStringToSpan(c.iv, iv));
59
60 std::vector<uint8_t> plaintext;
61 CHECK(base::HexStringToBytes(c.plaintext, &plaintext));
62
63 std::vector<uint8_t> ciphertext;
64 CHECK(base::HexStringToBytes(c.ciphertext, &ciphertext));
65
66 std::vector<uint8_t> computed_ciphertext =
67 crypto::aes_cbc::Encrypt(key, iv, plaintext);
68 EXPECT_EQ(computed_ciphertext, ciphertext);
69 std::optional<std::vector<uint8_t>> computed_plaintext =
70 crypto::aes_cbc::Decrypt(key, iv, computed_ciphertext);
71 ASSERT_TRUE(computed_plaintext.has_value());
72 EXPECT_EQ(*computed_plaintext, plaintext);
73 }
74 }
75
TEST(AesCbcTests,DecryptFailure)76 TEST(AesCbcTests, DecryptFailure) {
77 std::vector<uint8_t> key;
78 std::array<uint8_t, crypto::aes_cbc::kBlockSize> iv;
79 std::vector<uint8_t> plaintext;
80
81 CHECK(base::HexStringToBytes("2b7e151628aed2a6abf7158809cf4f3c", &key));
82 CHECK(base::HexStringToSpan("000102030405060708090a0b0c0d0e0f", iv));
83 CHECK(
84 base::HexStringToBytes("6bc1bee22e409f96e93d7e117393172a"
85 "ae2d8a571e03ac9c9eb76fac45af8e51"
86 "30c81c46a35ce411e5fbc1191a0a52ef"
87 "f69f2445df4f9b17ad2b417be66c3710",
88 &plaintext));
89
90 std::vector<uint8_t> ciphertext =
91 crypto::aes_cbc::Encrypt(key, iv, plaintext);
92 ciphertext[ciphertext.size() - 1] ^= 0x01;
93 std::optional<std::vector<uint8_t>> result =
94 crypto::aes_cbc::Decrypt(key, iv, ciphertext);
95 ASSERT_FALSE(result.has_value());
96 }
97
98 } // namespace
99