1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <digest/digest.h>
6
7#include <stdlib.h>
8
9#include <zircon/status.h>
10#include <unittest/unittest.h>
11
12// These unit tests are for the Digest object in ulib/digest.
13
14namespace {
15
16////////////////
17// Test support.
18
19using digest::Digest;
20
21// echo -n | sha256sum
22const char* kZeroDigest =
23    "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
24// echo -n | sha256sum | cut -c1-64 | tr -d '\n' | xxd -p -r | sha256sum
25const char* kDoubleZeroDigest =
26    "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456";
27
28////////////////
29// Test cases
30
31bool DigestStrings(void) {
32    BEGIN_TEST;
33    Digest actual;
34    zx_status_t rc = actual.Parse(kZeroDigest, strlen(kZeroDigest));
35    char buf[(Digest::kLength * 2) + 1];
36    rc = actual.ToString(buf, sizeof(buf));
37    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
38    ASSERT_EQ(strncmp(kZeroDigest, buf, sizeof(buf)), 0, __FUNCTION__);
39    END_TEST;
40}
41
42bool DigestZero(void) {
43    BEGIN_TEST;
44    Digest actual, expected;
45    zx_status_t rc = expected.Parse(kZeroDigest, strlen(kZeroDigest));
46    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
47    actual.Hash(nullptr, 0);
48    ASSERT_TRUE(actual == expected, __FUNCTION__);
49    END_TEST;
50}
51
52bool DigestSelf(void) {
53    BEGIN_TEST;
54    Digest actual, expected;
55    zx_status_t rc =
56        expected.Parse(kDoubleZeroDigest, strlen(kDoubleZeroDigest));
57    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
58    rc = actual.Parse(kZeroDigest, strlen(kZeroDigest));
59    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
60    uint8_t buf[Digest::kLength];
61    rc = actual.CopyTo(buf, sizeof(buf));
62    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
63    actual.Hash(buf, Digest::kLength);
64    ASSERT_TRUE(actual == expected, __FUNCTION__);
65    END_TEST;
66}
67
68bool DigestSplit(void) {
69    BEGIN_TEST;
70    Digest actual, expected;
71    actual.Init();
72    size_t n = strlen(kZeroDigest);
73    expected.Hash(kZeroDigest, n);
74    for (size_t i = 1; i < n; ++i) {
75        actual.Init();
76        actual.Update(kZeroDigest, i);
77        actual.Update(kZeroDigest + i, n - i);
78        actual.Final();
79        ASSERT_TRUE(actual == expected, __FUNCTION__);
80    }
81    END_TEST;
82}
83
84bool DigestCWrappers(void) {
85    BEGIN_TEST;
86    uint8_t buf[Digest::kLength];
87    zx_status_t rc = digest_hash(nullptr, 0, buf, sizeof(buf) - 1);
88    ASSERT_EQ(rc, ZX_ERR_BUFFER_TOO_SMALL, "Small buffer should be rejected");
89    rc = digest_hash(nullptr, 0, buf, sizeof(buf));
90    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
91    Digest expected;
92    rc = expected.Parse(kZeroDigest, strlen(kZeroDigest));
93    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
94    ASSERT_TRUE(expected == buf, __FUNCTION__);
95    digest_t* digest = nullptr;
96    rc = digest_init(&digest);
97    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
98    expected.Hash(buf, sizeof(buf));
99    digest_update(digest, buf, sizeof(buf));
100    rc = digest_final(digest, buf, sizeof(buf));
101    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
102    ASSERT_TRUE(expected == buf, __FUNCTION__);
103    END_TEST;
104}
105
106bool DigestEquality(void) {
107    BEGIN_TEST;
108    Digest actual, expected;
109    zx_status_t rc = expected.Parse(kZeroDigest, strlen(kZeroDigest));
110    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
111    rc = actual.Parse(kZeroDigest, strlen(kZeroDigest));
112    ASSERT_EQ(rc, ZX_OK, zx_status_get_string(rc));
113    ASSERT_FALSE(actual == nullptr, "Does not equal NULL");
114    ASSERT_TRUE(actual == actual, "Equals self");
115    const uint8_t* actual_bytes = actual.AcquireBytes();
116    const uint8_t* expected_bytes = expected.AcquireBytes();
117    ASSERT_TRUE(actual == actual_bytes, "Equals self.bytes_");
118    ASSERT_TRUE(actual == expected, "Equals expected");
119    ASSERT_TRUE(actual == expected_bytes, "Equals expected.bytes_");
120    ASSERT_TRUE(actual != nullptr, "Doesn't equal NULL");
121    ASSERT_FALSE(actual != actual, "Doesn't not equal self");
122    ASSERT_FALSE(actual != actual_bytes, "Doesn't not equal self.bytes_");
123    ASSERT_FALSE(actual != expected, "Doesn't not equal expected");
124    ASSERT_FALSE(actual != expected_bytes, "Doesn't not equal expected.bytes_");
125    expected.ReleaseBytes();
126    actual.ReleaseBytes();
127    END_TEST;
128}
129
130} // namespace
131BEGIN_TEST_CASE(DigestTests)
132RUN_TEST(DigestStrings)
133RUN_TEST(DigestZero)
134RUN_TEST(DigestSelf)
135RUN_TEST(DigestSplit)
136RUN_TEST(DigestCWrappers)
137RUN_TEST(DigestEquality)
138END_TEST_CASE(DigestTests)
139