// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include #include #include #include #include #include #include #include "utils.h" namespace crypto { namespace testing { namespace { bool TestInit(void) { BEGIN_TEST; HMAC hmac; Secret key; size_t key_len; ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len)); // Bad digest EXPECT_ZX(hmac.Init(digest::kUninitialized, key), ZX_ERR_INVALID_ARGS); // Bad flags EXPECT_ZX(hmac.Init(digest::kSHA256, key, 0x8000), ZX_ERR_INVALID_ARGS); // Short key ASSERT_OK(key.Generate(key_len - 1)); EXPECT_ZX(hmac.Init(digest::kSHA256, key), ZX_ERR_INVALID_ARGS); // Medium key ASSERT_OK(key.Generate(key_len)); EXPECT_OK(hmac.Init(digest::kSHA256, key)); // Long key ASSERT_OK(key.Generate(PAGE_SIZE)); EXPECT_OK(hmac.Init(digest::kSHA256, key)); END_TEST; } bool TestUpdate(void) { BEGIN_TEST; HMAC hmac; size_t key_len; Secret key; Bytes buf; ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len)); ASSERT_OK(key.Generate(key_len)); ASSERT_OK(buf.Randomize(PAGE_SIZE)); // Uninitialized EXPECT_ZX(hmac.Update(buf.get(), buf.len()), ZX_ERR_BAD_STATE); // Null data ASSERT_OK(hmac.Init(digest::kSHA256, key)); EXPECT_OK(hmac.Update(nullptr, 0)); EXPECT_ZX(hmac.Update(nullptr, buf.len()), ZX_ERR_INVALID_ARGS); // Multiple calls EXPECT_OK(hmac.Update(buf.get(), buf.len())); EXPECT_OK(hmac.Update(buf.get(), buf.len())); END_TEST; } bool TestFinal(void) { BEGIN_TEST; HMAC hmac; size_t key_len; Secret key; Bytes buf; ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len)); ASSERT_OK(key.Generate(key_len)); ASSERT_OK(buf.Randomize(PAGE_SIZE)); // Uninitialized Bytes out; EXPECT_ZX(hmac.Final(&out), ZX_ERR_BAD_STATE); // Bad parameter ASSERT_OK(hmac.Init(digest::kSHA256, key)); EXPECT_ZX(hmac.Final(nullptr), ZX_ERR_INVALID_ARGS); // No update EXPECT_OK(hmac.Final(&out)); // No update after final without init EXPECT_ZX(hmac.Update(buf.get(), buf.len()), ZX_ERR_BAD_STATE); // With update ASSERT_OK(hmac.Init(digest::kSHA256, key)); ASSERT_OK(hmac.Update(buf.get(), buf.len())); EXPECT_OK(hmac.Final(&out)); END_TEST; } bool TestCreate(void) { BEGIN_TEST; Secret key; Bytes digest1, digest2, block1, block2; ASSERT_OK(block1.Randomize(PAGE_SIZE)); size_t key_len; ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len)); // Bad parameters EXPECT_ZX(HMAC::Create(digest::kUninitialized, key, block1.get(), PAGE_SIZE, &digest1), ZX_ERR_INVALID_ARGS); ASSERT_OK(key.Generate(key_len - 1)); EXPECT_ZX(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, &digest1), ZX_ERR_INVALID_ARGS); ASSERT_OK(key.Generate(key_len)); EXPECT_ZX(HMAC::Create(digest::kSHA256, key, nullptr, PAGE_SIZE, &digest1), ZX_ERR_INVALID_ARGS); EXPECT_ZX(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, nullptr), ZX_ERR_INVALID_ARGS); // Same blocks, same HMACs ASSERT_OK(block2.Copy(block1)); EXPECT_OK(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, &digest1)); EXPECT_OK(HMAC::Create(digest::kSHA256, key, block2.get(), PAGE_SIZE, &digest2)); EXPECT_TRUE(digest1 == digest2); // Different blocks, different HMACs block2.get()[0] ^= 1; EXPECT_OK(HMAC::Create(digest::kSHA256, key, block2.get(), PAGE_SIZE, &digest2)); EXPECT_TRUE(digest1 != digest2); END_TEST; } bool TestVerify(void) { BEGIN_TEST; Secret key; Bytes out, block; ASSERT_OK(block.Randomize(PAGE_SIZE)); size_t key_len; ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len)); // Bad parameters EXPECT_ZX(HMAC::Verify(digest::kUninitialized, key, block.get(), PAGE_SIZE, out), ZX_ERR_INVALID_ARGS); ASSERT_OK(key.Generate(key_len - 1)); EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_INVALID_ARGS); ASSERT_OK(key.Generate(key_len)); EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, nullptr, PAGE_SIZE, out), ZX_ERR_INVALID_ARGS); ASSERT_OK(key.Generate(key_len)); EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_INVALID_ARGS); // Verify valid ASSERT_OK(key.Generate(key_len)); ASSERT_OK(HMAC::Create(digest::kSHA256, key, block.get(), PAGE_SIZE, &out)); EXPECT_OK(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out)); // Verify invalid block.get()[0] ^= 1; EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_IO_DATA_INTEGRITY); block.get()[0] ^= 1; EXPECT_OK(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out)); ASSERT_OK(key.Generate(key_len)); EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_IO_DATA_INTEGRITY); END_TEST; } // The following tests are taken from RFC 4231 section 4. They are intentionally formatted to be as // close to the RFC's representation as possible. bool TestRfc4231_TC(const char* xkey, const char* xdata, const char* xhmac) { BEGIN_TEST; Secret key; Bytes data, hmac; ASSERT_OK(HexToSecret(xkey, &key)); ASSERT_OK(HexToBytes(xdata, &data)); ASSERT_OK(HexToBytes(xhmac, &hmac)); EXPECT_OK(HMAC::Verify(digest::kSHA256, key, data.get(), data.len(), hmac, HMAC::ALLOW_WEAK_KEY | HMAC::ALLOW_TRUNCATION)); END_TEST; } // clang-format off bool TestRfc4231_TC1(void) { return TestRfc4231_TC( /* Key */ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" "0b0b0b0b", // 20 bytes /* Data */ "4869205468657265", // "Hi There" /* SHA256 */ "b0344c61d8db38535ca8afceaf0bf12b" "881dc200c9833da726e9376c2e32cff7"); } bool TestRfc4231_TC2(void) { return TestRfc4231_TC( /* Key */ "4a656665", // "Jefe" /* Data */ "7768617420646f2079612077616e7420" // "what do ya want " "666f72206e6f7468696e673f", // "for nothing?" /* SHA256 */ "5bdcc146bf60754e6a042426089575c7" "5a003f089d2739839dec58b964ec3843"); } bool TestRfc4231_TC3(void) { return TestRfc4231_TC( /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaa", // 20 bytes /* Data */ "dddddddddddddddddddddddddddddddd" "dddddddddddddddddddddddddddddddd" "dddddddddddddddddddddddddddddddd" "dddd", // 50 bytes /* SHA256 */ "773ea91e36800e46854db8ebd09181a7" "2959098b3ef8c122d9635514ced565fe"); } bool TestRfc4231_TC4(void) { return TestRfc4231_TC( /* Key */ "0102030405060708090a0b0c0d0e0f10" "111213141516171819", // 25 bytes /* Data */ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" "cdcd", // 50 bytes /* SHA256 */ "82558a389a443c0ea4cc819899f2083a" "85f0faa3e578f8077a2e3ff46729665b"); } bool TestRfc4231_TC5(void) { return TestRfc4231_TC( /* Key */ /* Key */ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" "0c0c0c0c", // 20 bytes /* Data */ "546573742057697468205472756e6361" // "Test With Trunca" "74696f6e", // "tion" /* SHA256 */ "a3b6167473100ee06e0c796c2955552b"); } bool TestRfc4231_TC6(void) { return TestRfc4231_TC( /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", // 131 bytes /* Data */ "54657374205573696e67204c61726765" // "Test Using Large" "72205468616e20426c6f636b2d53697a" // "r Than Block-Siz" "65204b6579202d2048617368204b6579" // "e Key - Hash Key" "204669727374", // " First" /* SHA256 */ "60e431591ee0b67f0d8a26aacbf5b77f" "8e0bc6213728c5140546040f0ee37f54"); } bool TestRfc4231_TC7(void) { return TestRfc4231_TC( /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", // 131 bytes /* Data */ "54686973206973206120746573742075" // "This is a test u" "73696e672061206c6172676572207468" // "sing a larger th" "616e20626c6f636b2d73697a65206b65" // "an block-size ke" "7920616e642061206c61726765722074" // "y and a larger t" "68616e20626c6f636b2d73697a652064" // "han block-size d" "6174612e20546865206b6579206e6565" // "ata. The key nee" "647320746f2062652068617368656420" // "ds to be hashed " "6265666f7265206265696e6720757365" // "before being use" "642062792074686520484d414320616c" // "d by the HMAC al" "676f726974686d2e", // "gorithm." /* SHA256 */ "9b09ffa71b942fcb27635fbcd5b0e944" "bfdc63644f0713938a7f51535c3a35e2"); } // clang-format on BEGIN_TEST_CASE(HmacTest) RUN_TEST(TestCreate) RUN_TEST(TestVerify) RUN_TEST(TestRfc4231_TC1) RUN_TEST(TestRfc4231_TC2) RUN_TEST(TestRfc4231_TC3) RUN_TEST(TestRfc4231_TC4) RUN_TEST(TestRfc4231_TC5) RUN_TEST(TestRfc4231_TC6) RUN_TEST(TestRfc4231_TC7) END_TEST_CASE(HmacTest) } // namespace } // namespace testing } // namespace crypto