• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gtest/gtest.h"
20 #include "pw_stream/memory_stream.h"
21 
22 namespace pw::crypto::sha256 {
23 namespace {
24 
25 #define ASSERT_OK(expr) ASSERT_EQ(OkStatus(), expr)
26 #define ASSERT_FAIL(expr) ASSERT_NE(OkStatus(), expr)
27 
28 #define AS_BYTES(s) as_bytes(span(s, sizeof(s) - 1))
29 
30 // Generated in Python 3 with:
31 // `hashlib.sha256('Hello, Pigweed!'.encode('ascii')).hexdigest()`.
32 #define SHA256_HASH_OF_HELLO_PIGWEED                                 \
33   "\x8d\xce\x14\xee\x2c\xd9\xfd\x9b\xbd\x8c\x8d\x57\x68\x50\x2c\x2f" \
34   "\xfb\xb3\x52\x36\xce\x93\x47\x1b\x80\xfc\xa4\x7d\xb5\xf8\x41\x9d"
35 
36 // Generated in Python with `hashlib.sha256().hexdigest()`.
37 #define SHA256_HASH_OF_EMPTY_STRING                                  \
38   "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24" \
39   "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"
40 
TEST(Hash,ComputesCorrectDigest)41 TEST(Hash, ComputesCorrectDigest) {
42   std::byte digest[kDigestSizeBytes];
43 
44   ASSERT_OK(Hash(AS_BYTES("Hello, Pigweed!"), digest));
45   ASSERT_EQ(0,
46             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
47 }
48 
TEST(Hash,ComputesCorrectDigestFromReader)49 TEST(Hash, ComputesCorrectDigestFromReader) {
50   std::byte digest[kDigestSizeBytes];
51   ConstByteSpan message = AS_BYTES("Hello, Pigweed!");
52 
53   stream::MemoryReader reader(message);
54   ASSERT_OK(Hash(reader, digest));
55   ASSERT_EQ(0,
56             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
57 }
58 
TEST(Hash,ComputesCorrectDigestOnEmptyMessage)59 TEST(Hash, ComputesCorrectDigestOnEmptyMessage) {
60   std::byte digest[kDigestSizeBytes];
61 
62   ASSERT_OK(Hash({}, digest));
63   ASSERT_EQ(0,
64             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
65 }
66 
TEST(Hash,ComputesCorrectDigestOnEmptyMessageFromReader)67 TEST(Hash, ComputesCorrectDigestOnEmptyMessageFromReader) {
68   std::byte digest[kDigestSizeBytes];
69 
70   ConstByteSpan empty;
71   stream::MemoryReader reader(empty);
72   ASSERT_OK(Hash(reader, digest));
73   ASSERT_EQ(0,
74             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
75 }
76 
TEST(Hash,DigestBufferTooSmall)77 TEST(Hash, DigestBufferTooSmall) {
78   std::array<std::byte, 31> digest = {};
79   ASSERT_FAIL(Hash({}, digest));
80 }
81 
TEST(Hash,DigestBufferTooSmallForReaderBasedAPI)82 TEST(Hash, DigestBufferTooSmallForReaderBasedAPI) {
83   std::array<std::byte, 31> digest = {};
84   ConstByteSpan empty;
85   stream::MemoryReader reader(empty);
86   ASSERT_FAIL(Hash(reader, digest));
87 }
88 
TEST(Hash,AcceptsLargerDigestBuffer)89 TEST(Hash, AcceptsLargerDigestBuffer) {
90   std::array<std::byte, 33> digest = {};
91   ASSERT_OK(Hash({}, digest));
92 }
93 
TEST(Hash,AcceptsLargerDigestBufferForReaderBasedAPI)94 TEST(Hash, AcceptsLargerDigestBufferForReaderBasedAPI) {
95   std::array<std::byte, 33> digest = {};
96 
97   ConstByteSpan empty;
98   stream::MemoryReader reader(empty);
99   ASSERT_OK(Hash(reader, digest));
100 }
101 
TEST(Sha256,AllowsSkippedUpdate)102 TEST(Sha256, AllowsSkippedUpdate) {
103   std::byte digest[kDigestSizeBytes];
104 
105   ASSERT_OK(Sha256().Final(digest));
106   ASSERT_EQ(0,
107             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
108 }
109 
TEST(Sha256,AllowsEmptyUpdate)110 TEST(Sha256, AllowsEmptyUpdate) {
111   std::byte digest[kDigestSizeBytes];
112   ASSERT_OK(Sha256().Update({}).Final(digest));
113   ASSERT_EQ(0,
114             std::memcmp(digest, SHA256_HASH_OF_EMPTY_STRING, sizeof(digest)));
115 }
116 
TEST(Sha256,AllowsMultipleUpdates)117 TEST(Sha256, AllowsMultipleUpdates) {
118   std::byte digest[kDigestSizeBytes];
119   ASSERT_OK(Sha256()
120                 .Update(AS_BYTES("Hello, "))
121                 .Update(AS_BYTES("Pigweed!"))
122                 .Final(digest));
123   ASSERT_EQ(0,
124             std::memcmp(digest, SHA256_HASH_OF_HELLO_PIGWEED, sizeof(digest)));
125 }
126 
TEST(Sha256,NoFinalAfterFinal)127 TEST(Sha256, NoFinalAfterFinal) {
128   std::byte digest[kDigestSizeBytes];
129   auto h = Sha256();
130 
131   ASSERT_OK(h.Final(digest));
132   ASSERT_FAIL(h.Final(digest));
133 }
134 
TEST(Sha256,NoUpdateAfterFinal)135 TEST(Sha256, NoUpdateAfterFinal) {
136   std::byte digest[kDigestSizeBytes];
137   auto h = Sha256();
138 
139   ASSERT_OK(h.Final(digest));
140   ASSERT_FAIL(h.Update(AS_BYTES("blah")).Final(digest));
141 }
142 
143 }  // namespace
144 }  // namespace pw::crypto::sha256
145