aes_gcm_unittest.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include "base/types/expected.h"
  7. #include "components/webcrypto/algorithm_dispatch.h"
  8. #include "components/webcrypto/algorithms/test_helpers.h"
  9. #include "components/webcrypto/status.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
  12. #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
  13. namespace webcrypto {
  14. namespace {
  15. // Creates an AES-GCM algorithm.
  16. blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
  17. const std::vector<uint8_t>& iv,
  18. const std::vector<uint8_t>& additional_data,
  19. unsigned int tag_length_bits) {
  20. return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
  21. blink::kWebCryptoAlgorithmIdAesGcm,
  22. new blink::WebCryptoAesGcmParams(iv, true, additional_data, true,
  23. tag_length_bits));
  24. }
  25. blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
  26. uint16_t key_length_bits) {
  27. return CreateAesKeyGenAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm,
  28. key_length_bits);
  29. }
  30. base::expected<std::vector<uint8_t>, Status> AesGcmEncrypt(
  31. const blink::WebCryptoKey& key,
  32. const std::vector<uint8_t>& iv,
  33. const std::vector<uint8_t>& additional_data,
  34. size_t tag_length_bits,
  35. const std::vector<uint8_t>& plain_text) {
  36. blink::WebCryptoAlgorithm algorithm =
  37. CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
  38. std::vector<uint8_t> output;
  39. Status status = Encrypt(algorithm, key, plain_text, &output);
  40. if (status.IsError()) {
  41. return base::unexpected(status);
  42. } else {
  43. return output;
  44. }
  45. }
  46. base::expected<std::vector<uint8_t>, Status> AesGcmDecrypt(
  47. const blink::WebCryptoKey& key,
  48. const std::vector<uint8_t>& iv,
  49. const std::vector<uint8_t>& additional_data,
  50. unsigned int tag_length_bits,
  51. const std::vector<uint8_t>& ciphertext) {
  52. blink::WebCryptoAlgorithm algorithm =
  53. CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
  54. std::vector<uint8_t> output;
  55. Status status = Decrypt(algorithm, key, ciphertext, &output);
  56. if (status.IsError()) {
  57. return base::unexpected(status);
  58. } else {
  59. return output;
  60. }
  61. }
  62. class WebCryptoAesGcmTest : public WebCryptoTestBase {};
  63. TEST_F(WebCryptoAesGcmTest, GenerateKeyBadLength) {
  64. auto generate_key = [](size_t len) {
  65. blink::WebCryptoKey key;
  66. return GenerateSecretKey(CreateAesGcmKeyGenAlgorithm(len), true,
  67. blink::kWebCryptoKeyUsageDecrypt, &key);
  68. };
  69. EXPECT_EQ(generate_key(0), Status::ErrorGenerateAesKeyLength());
  70. EXPECT_EQ(generate_key(127), Status::ErrorGenerateAesKeyLength());
  71. EXPECT_EQ(generate_key(257), Status::ErrorGenerateAesKeyLength());
  72. }
  73. TEST_F(WebCryptoAesGcmTest, GenerateKeyEmptyUsage) {
  74. blink::WebCryptoKey key;
  75. EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  76. GenerateSecretKey(CreateAesGcmKeyGenAlgorithm(256), true, 0, &key));
  77. }
  78. TEST_F(WebCryptoAesGcmTest, ImportExportJwk) {
  79. const blink::WebCryptoAlgorithm algorithm =
  80. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm);
  81. // AES-GCM 128
  82. ImportExportJwkSymmetricKey(
  83. 128, algorithm,
  84. blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt,
  85. "A128GCM");
  86. // AES-GCM 256
  87. ImportExportJwkSymmetricKey(256, algorithm, blink::kWebCryptoKeyUsageDecrypt,
  88. "A256GCM");
  89. }
  90. struct AesGcmKnownAnswer {
  91. const char* key;
  92. const char* iv;
  93. const char* plaintext;
  94. const char* additional;
  95. const char* ciphertext;
  96. size_t tagbits;
  97. };
  98. // NIST GCM test vectors:
  99. // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
  100. const AesGcmKnownAnswer kAesGcmKnownAnswers[] = {
  101. {"cf063a34d4a9a76c2c86787d3f96db71", "113b9785971864c83b01c787", "", "",
  102. "72ac8493e3a5228b5d130a69d2510e42", 128},
  103. {"6dfa1a07c14f978020ace450ad663d18", "34edfa462a14c6969a680ec1", "",
  104. "2a35c7f5f8578e919a581c60500c04f6", "751f3098d59cf4ea1d2fb0853bde1c", 120},
  105. {"ed6cd876ceba555706674445c229c12d", "92ecbf74b765bc486383ca2e",
  106. "bfaaaea3880d72d4378561e2597a9b35", "95bd10d77dbe0e87fb34217f1a2e5efe",
  107. "bdd2ed6c66fa087dce617d7fd1ff6d93ba82e49c55a22ed02ca67da4ec6f", 112},
  108. {"e03548984a7ec8eaf0870637df0ac6bc17f7159315d0ae26a764fd224e483810",
  109. "f4feb26b846be4cd224dbc5133a5ae13814ebe19d3032acdd3a006463fdb71e83a9d5d966"
  110. "79f26cc1719dd6b4feb3bab5b4b7993d0c0681f36d105ad3002fb66b201538e2b7479838a"
  111. "b83402b0d816cd6e0fe5857e6f4adf92de8ee72b122ba1ac81795024943b7d0151bbf84ce"
  112. "87c8911f512c397d14112296da7ecdd0da52a",
  113. "69fd0c9da10b56ec6786333f8d76d4b74f8a434195f2f241f088b2520fb5fa29455df9893"
  114. "164fb1638abe6617915d9497a8fe2",
  115. "aab26eb3e7acd09a034a9e2651636ab3868e51281590ecc948355e457da42b7ad1391c7be"
  116. "0d9e82895e506173a81857c3226829fbd6dfb3f9657a71a2934445d7c05fa9401cddd5109"
  117. "016ba32c3856afaadc48de80b8a01b57cb",
  118. "fda718aa1ec163487e21afc34f5a3a34795a9ee71dd3e7ee9a18fdb24181dc982b29c6ec7"
  119. "23294a130ca2234952bb0ef68c0f34795fbe0",
  120. 32},
  121. };
  122. // TODO(eroman):
  123. // * Test decryption when the tag length exceeds input size
  124. // * Test decryption with empty input
  125. // * Test decryption with tag length of 0.
  126. TEST_F(WebCryptoAesGcmTest, KnownAnswers) {
  127. // Note that WebCrypto appends the authentication tag to the ciphertext.
  128. for (const auto& test : kAesGcmKnownAnswers) {
  129. SCOPED_TRACE(&test - &kAesGcmKnownAnswers[0]);
  130. auto key_bytes = HexStringToBytes(test.key);
  131. auto iv_bytes = HexStringToBytes(test.iv);
  132. auto plaintext_bytes = HexStringToBytes(test.plaintext);
  133. auto additional_bytes = HexStringToBytes(test.additional);
  134. auto ciphertext_bytes = HexStringToBytes(test.ciphertext);
  135. blink::WebCryptoKey key = ImportSecretKeyFromRaw(
  136. key_bytes, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesGcm),
  137. blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt);
  138. {
  139. std::vector<uint8_t> exported_key;
  140. EXPECT_EQ(Status::Success(),
  141. ExportKey(blink::kWebCryptoKeyFormatRaw, key, &exported_key));
  142. EXPECT_BYTES_EQ(key_bytes, exported_key);
  143. }
  144. auto encrypt_result = AesGcmEncrypt(key, iv_bytes, additional_bytes,
  145. test.tagbits, plaintext_bytes);
  146. ASSERT_TRUE(encrypt_result.has_value())
  147. << encrypt_result.error().error_details();
  148. EXPECT_BYTES_EQ(encrypt_result.value(), ciphertext_bytes);
  149. auto decrypt_result = AesGcmDecrypt(key, iv_bytes, additional_bytes,
  150. test.tagbits, ciphertext_bytes);
  151. ASSERT_TRUE(decrypt_result.has_value())
  152. << decrypt_result.error().error_details();
  153. EXPECT_BYTES_EQ(decrypt_result.value(), plaintext_bytes);
  154. // Decryption should fail if any of the inputs are tampered with.
  155. EXPECT_EQ(base::unexpected(Status::OperationError()),
  156. AesGcmDecrypt(key, Corrupted(iv_bytes), additional_bytes,
  157. test.tagbits, ciphertext_bytes));
  158. EXPECT_EQ(base::unexpected(Status::OperationError()),
  159. AesGcmDecrypt(key, iv_bytes, Corrupted(additional_bytes),
  160. test.tagbits, ciphertext_bytes));
  161. EXPECT_EQ(base::unexpected(Status::OperationError()),
  162. AesGcmDecrypt(key, iv_bytes, additional_bytes, test.tagbits,
  163. Corrupted(ciphertext_bytes)));
  164. // Try different incorrect tag lengths
  165. for (unsigned int length : {0, 8, 96, 120, 128, 160, 255}) {
  166. if (test.tagbits == length)
  167. continue;
  168. auto result = AesGcmDecrypt(key, iv_bytes, additional_bytes, length,
  169. ciphertext_bytes);
  170. EXPECT_FALSE(result.has_value());
  171. }
  172. }
  173. }
  174. } // namespace
  175. } // namespace webcrypto