blake2b_unittest.cc (9831B)
1 /* 2 * blake2b_unittest.cc - unittests for blake2b hash function 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "blapi.h" 9 #include "nspr.h" 10 #include "nss.h" 11 #include "secerr.h" 12 13 #include <cstdlib> 14 #include <iostream> 15 #include <memory> 16 17 #define GTEST_HAS_RTTI 0 18 #include "gtest/gtest.h" 19 20 #include "kat/blake2b_kat.h" 21 22 template <class T> 23 struct ScopedDelete { 24 void operator()(T* ptr) { 25 if (ptr) { 26 BLAKE2B_DestroyContext(ptr, PR_TRUE); 27 } 28 } 29 }; 30 31 typedef std::unique_ptr<BLAKE2BContext, ScopedDelete<BLAKE2BContext>> 32 ScopedBLAKE2BContext; 33 34 class Blake2BTests : public ::testing::Test {}; 35 36 class Blake2BKAT 37 : public ::testing::TestWithParam<std::pair<int, std::vector<uint8_t>>> {}; 38 39 class Blake2BKATUnkeyed : public Blake2BKAT {}; 40 class Blake2BKATKeyed : public Blake2BKAT {}; 41 42 TEST_P(Blake2BKATUnkeyed, Unkeyed) { 43 std::vector<uint8_t> values(BLAKE2B512_LENGTH); 44 SECStatus rv = 45 BLAKE2B_HashBuf(values.data(), kat_data.data(), std::get<0>(GetParam())); 46 ASSERT_EQ(SECSuccess, rv); 47 EXPECT_EQ(values, std::get<1>(GetParam())); 48 } 49 50 TEST_P(Blake2BKATKeyed, Keyed) { 51 std::vector<uint8_t> values(BLAKE2B512_LENGTH); 52 SECStatus rv = BLAKE2B_MAC_HashBuf(values.data(), kat_data.data(), 53 std::get<0>(GetParam()), kat_key.data(), 54 BLAKE2B_KEY_SIZE); 55 ASSERT_EQ(SECSuccess, rv); 56 EXPECT_EQ(values, std::get<1>(GetParam())); 57 } 58 59 INSTANTIATE_TEST_SUITE_P(UnkeyedKAT, Blake2BKATUnkeyed, 60 ::testing::ValuesIn(TestcasesUnkeyed)); 61 INSTANTIATE_TEST_SUITE_P(KeyedKAT, Blake2BKATKeyed, 62 ::testing::ValuesIn(TestcasesKeyed)); 63 64 TEST_F(Blake2BTests, ContextTest) { 65 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 66 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 67 68 SECStatus rv = BLAKE2B_Begin(ctx.get()); 69 ASSERT_EQ(SECSuccess, rv); 70 71 size_t src_length = 252; 72 const size_t quarter = 63; 73 74 for (int i = 0; i < 4 && src_length > 0; i++) { 75 rv = BLAKE2B_Update(ctx.get(), kat_data.data() + i * quarter, 76 PR_MIN(quarter, src_length)); 77 ASSERT_EQ(SECSuccess, rv); 78 79 size_t len = BLAKE2B_FlattenSize(ctx.get()); 80 std::vector<unsigned char> ctxbytes(len); 81 rv = BLAKE2B_Flatten(ctx.get(), ctxbytes.data()); 82 ASSERT_EQ(SECSuccess, rv); 83 ScopedBLAKE2BContext ctx_cpy(BLAKE2B_Resurrect(ctxbytes.data(), NULL)); 84 ASSERT_TRUE(ctx_cpy) << "BLAKE2B_Resurrect failed!"; 85 ASSERT_EQ(SECSuccess, PORT_Memcmp(ctx.get(), ctx_cpy.get(), len)); 86 src_length -= quarter; 87 } 88 ASSERT_EQ(0U, src_length); 89 90 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 91 rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); 92 ASSERT_EQ(SECSuccess, rv); 93 ASSERT_EQ(std::get<1>(TestcasesUnkeyed[252]), digest) 94 << "BLAKE2B_End failed!"; 95 } 96 97 TEST_F(Blake2BTests, ContextTest2) { 98 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 99 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 100 101 SECStatus rv = BLAKE2B_Begin(ctx.get()); 102 ASSERT_EQ(SECSuccess, rv); 103 104 rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); 105 ASSERT_EQ(SECSuccess, rv); 106 rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); 107 ASSERT_EQ(SECSuccess, rv); 108 109 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 110 rv = BLAKE2B_End(ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); 111 ASSERT_EQ(SECSuccess, rv); 112 ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest) 113 << "BLAKE2B_End failed!"; 114 } 115 116 TEST_F(Blake2BTests, NullContextTest) { 117 SECStatus rv = BLAKE2B_Begin(nullptr); 118 ASSERT_EQ(SECFailure, rv); 119 120 rv = BLAKE2B_Update(nullptr, kat_data.data(), 128); 121 ASSERT_EQ(SECFailure, rv); 122 123 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 124 rv = BLAKE2B_End(nullptr, digest.data(), nullptr, BLAKE2B512_LENGTH); 125 ASSERT_EQ(SECFailure, rv); 126 } 127 128 TEST_F(Blake2BTests, CloneTest) { 129 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 130 ScopedBLAKE2BContext cloned_ctx(BLAKE2B_NewContext()); 131 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 132 ASSERT_TRUE(cloned_ctx) << "BLAKE2B_NewContext failed!"; 133 134 SECStatus rv = BLAKE2B_Begin(ctx.get()); 135 ASSERT_EQ(SECSuccess, rv); 136 rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 255); 137 ASSERT_EQ(SECSuccess, rv); 138 BLAKE2B_Clone(cloned_ctx.get(), ctx.get()); 139 140 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 141 rv = BLAKE2B_End(cloned_ctx.get(), digest.data(), nullptr, BLAKE2B512_LENGTH); 142 ASSERT_EQ(SECSuccess, rv); 143 ASSERT_EQ(std::get<1>(TestcasesUnkeyed[255]), digest) 144 << "BLAKE2B_End failed!"; 145 } 146 147 TEST_F(Blake2BTests, NullTest) { 148 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 149 SECStatus rv = BLAKE2B_HashBuf(digest.data(), nullptr, 0); 150 ASSERT_EQ(SECSuccess, rv); 151 EXPECT_EQ(std::get<1>(TestcasesUnkeyed[0]), digest); 152 153 digest = std::vector<uint8_t>(BLAKE2B512_LENGTH); 154 rv = BLAKE2B_MAC_HashBuf(digest.data(), nullptr, 0, kat_key.data(), 155 BLAKE2B_KEY_SIZE); 156 ASSERT_EQ(SECSuccess, rv); 157 EXPECT_EQ(std::get<1>(TestcasesKeyed[0]), digest); 158 } 159 160 TEST_F(Blake2BTests, HashTest) { 161 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 162 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 163 164 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 165 SECStatus rv = BLAKE2B_Hash(digest.data(), "abc"); 166 std::vector<uint8_t> expected = { 167 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, 0x6a, 0x27, 0x97, 168 0xb6, 0x9f, 0x12, 0xf6, 0xe9, 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 169 0xc4, 0xb7, 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, 0x7d, 170 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, 0xc2, 0x52, 0xd5, 0xde, 171 0x45, 0x33, 0xcc, 0x95, 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 172 0x5a, 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23}; 173 ASSERT_EQ(SECSuccess, rv); 174 EXPECT_EQ(expected, digest); 175 } 176 177 TEST_F(Blake2BTests, LongHashTest) { 178 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 179 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 180 181 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 182 SECStatus rv = BLAKE2B_Hash( 183 digest.data(), 184 "qwertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qw" 185 "ertzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwer" 186 "tzuiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789qwertz" 187 "uiopasdfghjklyxcvbnm123456789qwertzuiopasdfghjklyxcvbnm123456789"); 188 std::vector<uint8_t> expected = { 189 0x1f, 0x9e, 0xe6, 0x5a, 0xa0, 0x36, 0x05, 0xfc, 0x41, 0x0e, 0x2f, 190 0x55, 0x96, 0xfd, 0xb5, 0x9d, 0x85, 0x95, 0x5e, 0x24, 0x37, 0xe7, 191 0x0d, 0xe4, 0xa0, 0x22, 0x4a, 0xe1, 0x59, 0x1f, 0x97, 0x03, 0x57, 192 0x54, 0xf0, 0xca, 0x92, 0x75, 0x2f, 0x9e, 0x86, 0xeb, 0x82, 0x4f, 193 0x9c, 0xf4, 0x02, 0x17, 0x7f, 0x76, 0x56, 0x26, 0x46, 0xf4, 0x07, 194 0xfd, 0x1f, 0x78, 0xdb, 0x7b, 0x0d, 0x24, 0x43, 0xf0}; 195 ASSERT_EQ(SECSuccess, rv); 196 EXPECT_EQ(expected, digest); 197 } 198 199 TEST_F(Blake2BTests, TruncatedHashTest) { 200 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 201 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 202 203 SECStatus rv = BLAKE2B_Begin(ctx.get()); 204 ASSERT_EQ(SECSuccess, rv); 205 206 rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); 207 ASSERT_EQ(SECSuccess, rv); 208 rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); 209 ASSERT_EQ(SECSuccess, rv); 210 211 size_t max_digest_len = BLAKE2B512_LENGTH - 5; 212 std::vector<uint8_t> digest(max_digest_len); 213 unsigned int digest_len; 214 rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len); 215 ASSERT_EQ(SECSuccess, rv); 216 ASSERT_EQ(digest.size(), digest_len); 217 ASSERT_EQ(0, memcmp(std::get<1>(TestcasesUnkeyed[255]).data(), digest.data(), 218 max_digest_len)) 219 << "BLAKE2B_End failed!"; 220 } 221 222 TEST_F(Blake2BTests, TruncatedHashTest2) { 223 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 224 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 225 226 SECStatus rv = BLAKE2B_Begin(ctx.get()); 227 ASSERT_EQ(SECSuccess, rv); 228 229 rv = BLAKE2B_Update(ctx.get(), kat_data.data(), 128); 230 ASSERT_EQ(SECSuccess, rv); 231 rv = BLAKE2B_Update(ctx.get(), kat_data.data() + 128, 127); 232 ASSERT_EQ(SECSuccess, rv); 233 234 size_t max_digest_len = BLAKE2B512_LENGTH - 60; 235 std::vector<uint8_t> digest(max_digest_len); 236 unsigned int digest_len; 237 rv = BLAKE2B_End(ctx.get(), digest.data(), &digest_len, max_digest_len); 238 ASSERT_EQ(SECSuccess, rv); 239 ASSERT_EQ(digest.size(), digest_len); 240 } 241 242 TEST_F(Blake2BTests, OverlongKeyTest) { 243 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 244 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 245 246 std::vector<uint8_t> key = { 247 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 248 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 249 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 250 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 251 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 252 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35}; 253 std::vector<uint8_t> data = {0x61, 0x62, 0x63}; 254 255 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 256 SECStatus rv = 257 BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key.data(), 65); 258 EXPECT_EQ(SECFailure, rv); 259 EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); 260 } 261 262 TEST_F(Blake2BTests, EmptyKeyTest) { 263 ScopedBLAKE2BContext ctx(BLAKE2B_NewContext()); 264 ASSERT_TRUE(ctx) << "BLAKE2B_NewContext failed!"; 265 266 uint8_t key[1]; // A vector.data() would give us a nullptr. 267 std::vector<uint8_t> data = {0x61, 0x62, 0x63}; 268 269 std::vector<uint8_t> digest(BLAKE2B512_LENGTH); 270 SECStatus rv = BLAKE2B_MAC_HashBuf(digest.data(), data.data(), 3, key, 0); 271 EXPECT_EQ(SECFailure, rv); 272 EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); 273 }