xref: /aosp_15_r20/external/pigweed/pw_crypto/sha256_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_crypto/sha256.h"
16 
17 #include <cstring>
18 
19 #include "pw_stream/memory_stream.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace pw::crypto::sha256 {
23 namespace {
24 
25 #define ASSERT_FAIL(expr) ASSERT_NE(OkStatus(), expr)
26 
27 #define AS_BYTES(s) as_bytes(span(s, sizeof(s) - 1))
28 
29 // Generated in Python 3 with:
30 // `hashlib.sha256('Hello, Pigweed!'.encode('ascii')).hexdigest()`.
31 #define SHA256_HASH_OF_HELLO_PIGWEED                                 \
32   "\x8d\xce\x14\xee\x2c\xd9\xfd\x9b\xbd\x8c\x8d\x57\x68\x50\x2c\x2f" \
33   "\xfb\xb3\x52\x36\xce\x93\x47\x1b\x80\xfc\xa4\x7d\xb5\xf8\x41\x9d"
34 
35 // Generated in Python with `hashlib.sha256().hexdigest()`.
36 #define SHA256_HASH_OF_EMPTY_STRING                                  \
37   "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24" \
38   "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"
39 
TEST(Hash,ComputesCorrectDigest)40 TEST(Hash, ComputesCorrectDigest) {
41   std::byte digest[kDigestSizeBytes];
42 
43   PW_TEST_ASSERT_OK(Hash(AS_BYTES("Hello, Pigweed!"), digest));
44   ASSERT_EQ(0,
45             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
46 }
47 
TEST(Hash,ComputesCorrectDigestFromReader)48 TEST(Hash, ComputesCorrectDigestFromReader) {
49   std::byte digest[kDigestSizeBytes];
50   ConstByteSpan message = AS_BYTES("Hello, Pigweed!");
51 
52   stream::MemoryReader reader(message);
53   PW_TEST_ASSERT_OK(Hash(reader, digest));
54   ASSERT_EQ(0,
55             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
56 }
57 
TEST(Hash,ComputesCorrectDigestOnEmptyMessage)58 TEST(Hash, ComputesCorrectDigestOnEmptyMessage) {
59   std::byte digest[kDigestSizeBytes];
60 
61   PW_TEST_ASSERT_OK(Hash({}, digest));
62   ASSERT_EQ(0,
63             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
64 }
65 
TEST(Hash,ComputesCorrectDigestOnEmptyMessageFromReader)66 TEST(Hash, ComputesCorrectDigestOnEmptyMessageFromReader) {
67   std::byte digest[kDigestSizeBytes];
68 
69   ConstByteSpan empty;
70   stream::MemoryReader reader(empty);
71   PW_TEST_ASSERT_OK(Hash(reader, digest));
72   ASSERT_EQ(0,
73             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
74 }
75 
TEST(Hash,DigestBufferTooSmall)76 TEST(Hash, DigestBufferTooSmall) {
77   std::array<std::byte, 31> digest = {};
78   ASSERT_FAIL(Hash({}, digest));
79 }
80 
TEST(Hash,DigestBufferTooSmallForReaderBasedAPI)81 TEST(Hash, DigestBufferTooSmallForReaderBasedAPI) {
82   std::array<std::byte, 31> digest = {};
83   ConstByteSpan empty;
84   stream::MemoryReader reader(empty);
85   ASSERT_FAIL(Hash(reader, digest));
86 }
87 
TEST(Hash,AcceptsLargerDigestBuffer)88 TEST(Hash, AcceptsLargerDigestBuffer) {
89   std::array<std::byte, 33> digest = {};
90   PW_TEST_ASSERT_OK(Hash({}, digest));
91 }
92 
TEST(Hash,AcceptsLargerDigestBufferForReaderBasedAPI)93 TEST(Hash, AcceptsLargerDigestBufferForReaderBasedAPI) {
94   std::array<std::byte, 33> digest = {};
95 
96   ConstByteSpan empty;
97   stream::MemoryReader reader(empty);
98   PW_TEST_ASSERT_OK(Hash(reader, digest));
99 }
100 
TEST(Sha256,AllowsSkippedUpdate)101 TEST(Sha256, AllowsSkippedUpdate) {
102   std::byte digest[kDigestSizeBytes];
103 
104   PW_TEST_ASSERT_OK(Sha256().Final(digest));
105   ASSERT_EQ(0,
106             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
107 }
108 
TEST(Sha256,AllowsEmptyUpdate)109 TEST(Sha256, AllowsEmptyUpdate) {
110   std::byte digest[kDigestSizeBytes];
111   PW_TEST_ASSERT_OK(Sha256().Update({}).Final(digest));
112   ASSERT_EQ(0,
113             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
114 }
115 
TEST(Sha256,AllowsMultipleUpdates)116 TEST(Sha256, AllowsMultipleUpdates) {
117   std::byte digest[kDigestSizeBytes];
118   PW_TEST_ASSERT_OK(Sha256()
119                         .Update(AS_BYTES("Hello, "))
120                         .Update(AS_BYTES("Pigweed!"))
121                         .Final(digest));
122   ASSERT_EQ(0,
123             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
124 }
125 
TEST(Sha256,NoFinalAfterFinal)126 TEST(Sha256, NoFinalAfterFinal) {
127   std::byte digest[kDigestSizeBytes];
128   auto h = Sha256();
129 
130   PW_TEST_ASSERT_OK(h.Final(digest));
131   ASSERT_FAIL(h.Final(digest));
132 }
133 
TEST(Sha256,NoUpdateAfterFinal)134 TEST(Sha256, NoUpdateAfterFinal) {
135   std::byte digest[kDigestSizeBytes];
136   auto h = Sha256();
137 
138   PW_TEST_ASSERT_OK(h.Final(digest));
139   ASSERT_FAIL(h.Update(AS_BYTES("blah")).Final(digest));
140 }
141 
142 }  // namespace
143 }  // namespace pw::crypto::sha256
144