145 lines
4.2 KiB
C++
145 lines
4.2 KiB
C++
// Copyright 2021 The Pigweed Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
// use this file except in compliance with the License. You may obtain a copy of
|
|
// the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations under
|
|
// the License.
|
|
|
|
#include "pw_crypto/sha256.h"
|
|
|
|
#include <cstring>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "pw_stream/memory_stream.h"
|
|
|
|
namespace pw::crypto::sha256 {
|
|
namespace {
|
|
|
|
#define ASSERT_OK(expr) ASSERT_EQ(OkStatus(), expr)
|
|
#define ASSERT_FAIL(expr) ASSERT_NE(OkStatus(), expr)
|
|
|
|
#define AS_BYTES(s) std::as_bytes(std::span(s, sizeof(s) - 1))
|
|
|
|
// Generated in Python 3 with:
|
|
// `hashlib.sha256('Hello, Pigweed!'.encode('ascii')).hexdigest()`.
|
|
#define SHA256_HASH_OF_HELLO_PIGWEED \
|
|
"\x8d\xce\x14\xee\x2c\xd9\xfd\x9b\xbd\x8c\x8d\x57\x68\x50\x2c\x2f" \
|
|
"\xfb\xb3\x52\x36\xce\x93\x47\x1b\x80\xfc\xa4\x7d\xb5\xf8\x41\x9d"
|
|
|
|
// Generated in Python with `hashlib.sha256().hexdigest()`.
|
|
#define SHA256_HASH_OF_EMPTY_STRING \
|
|
"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24" \
|
|
"\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"
|
|
|
|
TEST(Hash, ComputesCorrectDigest) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
|
|
ASSERT_OK(Hash(AS_BYTES("Hello, Pigweed!"), digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Hash, ComputesCorrectDigestFromReader) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
ConstByteSpan message = AS_BYTES("Hello, Pigweed!");
|
|
|
|
stream::MemoryReader reader(message);
|
|
ASSERT_OK(Hash(reader, digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Hash, ComputesCorrectDigestOnEmptyMessage) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
|
|
ASSERT_OK(Hash({}, digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Hash, ComputesCorrectDigestOnEmptyMessageFromReader) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
|
|
ConstByteSpan empty;
|
|
stream::MemoryReader reader(empty);
|
|
ASSERT_OK(Hash(reader, digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Hash, DigestBufferTooSmall) {
|
|
std::array<std::byte, 31> digest = {};
|
|
ASSERT_FAIL(Hash({}, digest));
|
|
}
|
|
|
|
TEST(Hash, DigestBufferTooSmallForReaderBasedAPI) {
|
|
std::array<std::byte, 31> digest = {};
|
|
ConstByteSpan empty;
|
|
stream::MemoryReader reader(empty);
|
|
ASSERT_FAIL(Hash(reader, digest));
|
|
}
|
|
|
|
TEST(Hash, AcceptsLargerDigestBuffer) {
|
|
std::array<std::byte, 33> digest = {};
|
|
ASSERT_OK(Hash({}, digest));
|
|
}
|
|
|
|
TEST(Hash, AcceptsLargerDigestBufferForReaderBasedAPI) {
|
|
std::array<std::byte, 33> digest = {};
|
|
|
|
ConstByteSpan empty;
|
|
stream::MemoryReader reader(empty);
|
|
ASSERT_OK(Hash(reader, digest));
|
|
}
|
|
|
|
TEST(Sha256, AllowsSkippedUpdate) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
|
|
ASSERT_OK(Sha256().Final(digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Sha256, AllowsEmptyUpdate) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
ASSERT_OK(Sha256().Update({}).Final(digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Sha256, AllowsMultipleUpdates) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
ASSERT_OK(Sha256()
|
|
.Update(AS_BYTES("Hello, "))
|
|
.Update(AS_BYTES("Pigweed!"))
|
|
.Final(digest));
|
|
ASSERT_EQ(0,
|
|
std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
|
|
}
|
|
|
|
TEST(Sha256, NoFinalAfterFinal) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
auto h = Sha256();
|
|
|
|
ASSERT_OK(h.Final(digest));
|
|
ASSERT_FAIL(h.Final(digest));
|
|
}
|
|
|
|
TEST(Sha256, NoUpdateAfterFinal) {
|
|
std::byte digest[kDigestSizeBytes];
|
|
auto h = Sha256();
|
|
|
|
ASSERT_OK(h.Final(digest));
|
|
ASSERT_FAIL(h.Update(AS_BYTES("blah")).Final(digest));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace pw::crypto::sha256
|