1 /*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <memory>
11 #include <string>
12 #include <vector>
13
14 #include <gtest/gtest.h>
15
16 #include <openssl/digest.h>
17 #include <openssl/hmac.h>
18
19 #include "../test/file_test.h"
20 #include "../test/test_util.h"
21 #include "../test/wycheproof_util.h"
22
23
GetDigest(const std::string & name)24 static const EVP_MD *GetDigest(const std::string &name) {
25 if (name == "MD5") {
26 return EVP_md5();
27 } else if (name == "SHA1") {
28 return EVP_sha1();
29 } else if (name == "SHA224") {
30 return EVP_sha224();
31 } else if (name == "SHA256") {
32 return EVP_sha256();
33 } else if (name == "SHA384") {
34 return EVP_sha384();
35 } else if (name == "SHA512") {
36 return EVP_sha512();
37 }
38 return nullptr;
39 }
40
TEST(HMACTest,TestVectors)41 TEST(HMACTest, TestVectors) {
42 FileTestGTest("crypto/hmac_extra/hmac_tests.txt", [](FileTest *t) {
43 std::string digest_str;
44 ASSERT_TRUE(t->GetAttribute(&digest_str, "HMAC"));
45 const EVP_MD *digest = GetDigest(digest_str);
46 ASSERT_TRUE(digest) << "Unknown digest: " << digest_str;
47
48 std::vector<uint8_t> key, input, output;
49 ASSERT_TRUE(t->GetBytes(&key, "Key"));
50 ASSERT_TRUE(t->GetBytes(&input, "Input"));
51 ASSERT_TRUE(t->GetBytes(&output, "Output"));
52 ASSERT_EQ(EVP_MD_size(digest), output.size());
53
54 // Test using the one-shot API.
55 auto mac = std::make_unique<uint8_t[]>(EVP_MD_size(digest));
56 unsigned mac_len;
57 ASSERT_TRUE(HMAC(digest, key.data(), key.size(), input.data(), input.size(),
58 mac.get(), &mac_len));
59 EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
60
61 // Test using HMAC_CTX.
62 bssl::ScopedHMAC_CTX ctx;
63 ASSERT_TRUE(
64 HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr));
65 ASSERT_TRUE(HMAC_Update(ctx.get(), input.data(), input.size()));
66 ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
67 EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
68
69 // Test that an HMAC_CTX may be reset with the same key.
70 ASSERT_TRUE(HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr));
71 ASSERT_TRUE(HMAC_Update(ctx.get(), input.data(), input.size()));
72 ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
73 EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
74
75 // Test feeding the input in byte by byte.
76 ASSERT_TRUE(HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr));
77 for (size_t i = 0; i < input.size(); i++) {
78 ASSERT_TRUE(HMAC_Update(ctx.get(), &input[i], 1));
79 }
80 ASSERT_TRUE(HMAC_Final(ctx.get(), mac.get(), &mac_len));
81 EXPECT_EQ(Bytes(output), Bytes(mac.get(), mac_len));
82 });
83 }
84
RunWycheproofTest(const char * path,const EVP_MD * md)85 static void RunWycheproofTest(const char *path, const EVP_MD *md) {
86 SCOPED_TRACE(path);
87 FileTestGTest(path, [&](FileTest *t) {
88 t->IgnoreInstruction("keySize");
89 t->IgnoreInstruction("tagSize");
90 std::vector<uint8_t> key, msg, tag;
91 ASSERT_TRUE(t->GetBytes(&key, "key"));
92 ASSERT_TRUE(t->GetBytes(&msg, "msg"));
93 ASSERT_TRUE(t->GetBytes(&tag, "tag"));
94 WycheproofResult result;
95 ASSERT_TRUE(GetWycheproofResult(t, &result));
96
97 if (!result.IsValid()) {
98 // Wycheproof tests assume the HMAC implementation checks the MAC. Ours
99 // simply computes the HMAC, so skip the tests with invalid outputs.
100 return;
101 }
102
103 uint8_t out[EVP_MAX_MD_SIZE];
104 unsigned out_len;
105 ASSERT_TRUE(HMAC(md, key.data(), key.size(), msg.data(), msg.size(), out,
106 &out_len));
107 // Wycheproof tests truncate the tags down to |tagSize|.
108 ASSERT_LE(tag.size(), out_len);
109 EXPECT_EQ(Bytes(out, tag.size()), Bytes(tag));
110 });
111 }
112
TEST(HMACTest,WycheproofSHA1)113 TEST(HMACTest, WycheproofSHA1) {
114 RunWycheproofTest("third_party/wycheproof_testvectors/hmac_sha1_test.txt",
115 EVP_sha1());
116 }
117
TEST(HMACTest,WycheproofSHA224)118 TEST(HMACTest, WycheproofSHA224) {
119 RunWycheproofTest("third_party/wycheproof_testvectors/hmac_sha224_test.txt",
120 EVP_sha224());
121 }
122
TEST(HMACTest,WycheproofSHA256)123 TEST(HMACTest, WycheproofSHA256) {
124 RunWycheproofTest("third_party/wycheproof_testvectors/hmac_sha256_test.txt",
125 EVP_sha256());
126 }
127
TEST(HMACTest,WycheproofSHA384)128 TEST(HMACTest, WycheproofSHA384) {
129 RunWycheproofTest("third_party/wycheproof_testvectors/hmac_sha384_test.txt",
130 EVP_sha384());
131 }
132
TEST(HMACTest,WycheproofSHA512)133 TEST(HMACTest, WycheproofSHA512) {
134 RunWycheproofTest("third_party/wycheproof_testvectors/hmac_sha512_test.txt",
135 EVP_sha512());
136 }
137