summaryrefslogtreecommitdiffstats
path: root/security/nss/gtests/freebl_gtest/blake2b_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/gtests/freebl_gtest/blake2b_unittest.cc')
-rw-r--r--security/nss/gtests/freebl_gtest/blake2b_unittest.cc273
1 files changed, 273 insertions, 0 deletions
diff --git a/security/nss/gtests/freebl_gtest/blake2b_unittest.cc b/security/nss/gtests/freebl_gtest/blake2b_unittest.cc
new file mode 100644
index 0000000000..aaf8106aae
--- /dev/null
+++ b/security/nss/gtests/freebl_gtest/blake2b_unittest.cc
@@ -0,0 +1,273 @@
+/*
+ * blake2b_unittest.cc - unittests for blake2b hash function
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "blapi.h"
+#include "nspr.h"
+#include "nss.h"
+#include "secerr.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+#include "kat/blake2b_kat.h"
+
+template <class T>
+struct ScopedDelete {
+ void operator()(T* ptr) {
+ if (ptr) {
+ BLAKE2B_DestroyContext(ptr, PR_TRUE);
+ }
+ }
+};
+
+typedef std::unique_ptr<BLAKE2BContext, ScopedDelete<BLAKE2BContext>>
+ ScopedBLAKE2BContext;
+
+class Blake2BTests : public ::testing::Test {};
+
+class Blake2BKAT
+ : public ::testing::TestWithParam<std::pair<int, std::vector<uint8_t>>> {};
+
+class Blake2BKATUnkeyed : public Blake2BKAT {};
+class Blake2BKATKeyed : public Blake2BKAT {};
+
+TEST_P(Blake2BKATUnkeyed, Unkeyed) {
+ std::vector<uint8_t> values(BLAKE2B512_LENGTH);
+ SECStatus rv =
+ BLAKE2B_HashBuf(values.data(), kat_data.data(), std::get<0>(GetParam()));
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(values, std::get<1>(GetParam()));
+}
+
+TEST_P(Blake2BKATKeyed, Keyed) {
+ std::vector<uint8_t> values(BLAKE2B512_LENGTH);
+ SECStatus rv = BLAKE2B_MAC_HashBuf(values.data(), kat_data.data(),
+ std::get<0>(GetParam()), kat_key.data(),
+ BLAKE2B_KEY_SIZE);
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(values, std::get<1>(GetParam()));
+}
+
+INSTANTIATE_TEST_SUITE_P(UnkeyedKAT, Blake2BKATUnkeyed,
+ ::testing::ValuesIn(TestcasesUnkeyed));
+INSTANTIATE_TEST_SUITE_P(KeyedKAT, Blake2BKATKeyed,
+ ::testing::ValuesIn(TestcasesKeyed));
+
+TEST_F(Blake2BTests, ContextTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ SECStatus rv = BLAKE2B_Begin(ctx.get());
+ ASSERT_EQ(SECSuccess, rv);
+
+ size_t src_length = 252;
+ const size_t quarter = 63;
+
+ for (int i = 0; i < 4 && src_length > 0; i++) {
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data() + i * quarter,
+ PR_MIN(quarter, src_length));
+ ASSERT_EQ(SECSuccess, rv);
+
+ size_t len = BLAKE2B_FlattenSize(ctx.get());
+ std::vector<unsigned char> ctxbytes(len);
+ rv = BLAKE2B_Flatten(ctx.get(), ctxbytes.data());
+ ASSERT_EQ(SECSuccess, rv);
+ ScopedBLAKE2BContext ctx_cpy(BLAKE2B_Resurrect(ctxbytes.data(), NULL));
+ ASSERT_TRUE(ctx_cpy) << "BLAKE2B_Resurrect failed!";
+ ASSERT_EQ(SECSuccess, PORT_Memcmp(ctx.get(), ctx_cpy.get(), len));
+ src_length -= quarter;
+ }
+ ASSERT_EQ(0U, src_length);
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(std::get<1>(TestcasesUnkeyed[252]), digest)
+ << "BLAKE2B_End failed!";
+}
+
+TEST_F(Blake2BTests, ContextTest2) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ SECStatus rv = BLAKE2B_Begin(ctx.get());
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128);
+ ASSERT_EQ(SECSuccess, rv);
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127);
+ ASSERT_EQ(SECSuccess, rv);
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest)
+ << "BLAKE2B_End failed!";
+}
+
+TEST_F(Blake2BTests, NullContextTest) {
+ SECStatus rv = BLAKE2B_Begin(nullptr);
+ ASSERT_EQ(SECFailure, rv);
+
+ rv = BLAKE2B_Update(nullptr, kat_data.data(), 128);
+ ASSERT_EQ(SECFailure, rv);
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ rv = BLAKE2B_End(nullptr, digest.data(), nullptr, BLAKE2B512_LENGTH);
+ ASSERT_EQ(SECFailure, rv);
+}
+
+TEST_F(Blake2BTests, CloneTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ScopedBLAKE2BContext cloned_ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+ ASSERT_TRUE(cloned_ctx) << "BLAKE2B_NewContext failed!";
+
+ SECStatus rv = BLAKE2B_Begin(ctx.get());
+ ASSERT_EQ(SECSuccess, rv);
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 255);
+ ASSERT_EQ(SECSuccess, rv);
+ BLAKE2B_Clone(cloned_ctx.get(), ctx.get());
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ rv = BLAKE2B_End(cloned_ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest)
+ << "BLAKE2B_End failed!";
+}
+
+TEST_F(Blake2BTests, NullTest) {
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ SECStatus rv = BLAKE2B_HashBuf(digest.data(), nullptr, 0);
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(std::get<1>(TestcasesUnkeyed[0]), digest);
+
+ digest = std::vector<uint8_t>(BLAKE2B512_LENGTH);
+ rv = BLAKE2B_MAC_HashBuf(digest.data(), nullptr, 0, kat_key.data(),
+ BLAKE2B_KEY_SIZE);
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(std::get<1>(TestcasesKeyed[0]), digest);
+}
+
+TEST_F(Blake2BTests, HashTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ SECStatus rv = BLAKE2B_Hash(digest.data(), "abc");
+ std::vector<uint8_t> expected = {
+ 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, 0x6a, 0x27, 0x97,
+ 0xb6, 0x9f, 0x12, 0xf6, 0xe9, 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a,
+ 0xc4, 0xb7, 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, 0x7d,
+ 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, 0xc2, 0x52, 0xd5, 0xde,
+ 0x45, 0x33, 0xcc, 0x95, 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92,
+ 0x5a, 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23};
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(expected, digest);
+}
+
+TEST_F(Blake2BTests, LongHashTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ SECStatus rv = BLAKE2B_Hash(
+ digest.data(),
+ "qwertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qw"
+ "ertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwer"
+ "tzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwertz"
+ "uiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789");
+ std::vector<uint8_t> expected = {
+ 0x1f, 0x9e, 0xe6, 0x5a, 0xa0, 0x36, 0x05, 0xfc, 0x41, 0x0e, 0x2f,
+ 0x55, 0x96, 0xfd, 0xb5, 0x9d, 0x85, 0x95, 0x5e, 0x24, 0x37, 0xe7,
+ 0x0d, 0xe4, 0xa0, 0x22, 0x4a, 0xe1, 0x59, 0x1f, 0x97, 0x03, 0x57,
+ 0x54, 0xf0, 0xca, 0x92, 0x75, 0x2f, 0x9e, 0x86, 0xeb, 0x82, 0x4f,
+ 0x9c, 0xf4, 0x02, 0x17, 0x7f, 0x76, 0x56, 0x26, 0x46, 0xf4, 0x07,
+ 0xfd, 0x1f, 0x78, 0xdb, 0x7b, 0x0d, 0x24, 0x43, 0xf0};
+ ASSERT_EQ(SECSuccess, rv);
+ EXPECT_EQ(expected, digest);
+}
+
+TEST_F(Blake2BTests, TruncatedHashTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ SECStatus rv = BLAKE2B_Begin(ctx.get());
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128);
+ ASSERT_EQ(SECSuccess, rv);
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127);
+ ASSERT_EQ(SECSuccess, rv);
+
+ size_t max_digest_len = BLAKE2B512_LENGTH - 5;
+ std::vector<uint8_t> digest(max_digest_len);
+ unsigned int digest_len;
+ rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(digest.size(), digest_len);
+ ASSERT_EQ(0, memcmp(std::get<1>(TestcasesUnkeyed[255]).data(), digest.data(),
+ max_digest_len))
+ << "BLAKE2B_End failed!";
+}
+
+TEST_F(Blake2BTests, TruncatedHashTest2) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ SECStatus rv = BLAKE2B_Begin(ctx.get());
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128);
+ ASSERT_EQ(SECSuccess, rv);
+ rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127);
+ ASSERT_EQ(SECSuccess, rv);
+
+ size_t max_digest_len = BLAKE2B512_LENGTH - 60;
+ std::vector<uint8_t> digest(max_digest_len);
+ unsigned int digest_len;
+ rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_EQ(digest.size(), digest_len);
+}
+
+TEST_F(Blake2BTests, OverlongKeyTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ std::vector<uint8_t> key = {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35};
+ std::vector<uint8_t> data = {0x61, 0x62, 0x63};
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ SECStatus rv =
+ BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key.data(), 65);
+ EXPECT_EQ(SECFailure, rv);
+ EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
+}
+
+TEST_F(Blake2BTests, EmptyKeyTest) {
+ ScopedBLAKE2BContext ctx(BLAKE2B_NewContext());
+ ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!";
+
+ uint8_t key[1]; // A vector.data() would give us a nullptr.
+ std::vector<uint8_t> data = {0x61, 0x62, 0x63};
+
+ std::vector<uint8_t> digest(BLAKE2B512_LENGTH);
+ SECStatus rv = BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key, 0);
+ EXPECT_EQ(SECFailure, rv);
+ EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
+}