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 <stddef.h>
6#include <stdint.h>
7
8#include <crypto/bytes.h>
9#include <unittest/unittest.h>
10#include <zircon/types.h>
11
12#include "utils.h"
13
14namespace crypto {
15namespace testing {
16namespace {
17
18const size_t kSize = 1024;
19
20
21bool AllEqual(const void* buf, uint8_t val, zx_off_t off, size_t len) {
22    BEGIN_HELPER;
23    const uint8_t* u8 = static_cast<const uint8_t*>(buf);
24    size_t end;
25    ASSERT_FALSE(add_overflow(off, len, &end));
26    for (size_t i = off; i < end; ++i) {
27        if(u8[i] != val) {
28            return false;
29        }
30    }
31    END_HELPER;
32}
33
34// This test only checks that the routine basically functions; it does NOT assure anything about the
35// quality of the entropy.  That topic is beyond the scope of a deterministic unit test.
36bool TestRandomize(void) {
37    BEGIN_TEST;
38    Bytes bytes;
39
40    ASSERT_OK(bytes.Resize(kSize));
41    ASSERT_TRUE(AllEqual(bytes.get(), 0, 0, kSize));
42
43    EXPECT_OK(bytes.Randomize(kSize));
44    EXPECT_FALSE(AllEqual(bytes.get(), 0, 0, kSize));
45
46    END_TEST;
47}
48
49bool TestResize(void) {
50    BEGIN_TEST;
51    Bytes bytes;
52    EXPECT_OK(bytes.Resize(kSize, 0xff));
53    EXPECT_EQ(bytes.len(), kSize);
54    EXPECT_NONNULL(bytes.get());
55
56#if !__has_feature(address_sanitizer)
57    // The ASan allocator reports errors for unreasonable allocation sizes.
58    EXPECT_ZX(bytes.Resize(size_t(-1)), ZX_ERR_NO_MEMORY);
59    EXPECT_EQ(bytes.len(), kSize);
60    EXPECT_NONNULL(bytes.get());
61    EXPECT_TRUE(AllEqual(bytes.get(), 0xff, 0, kSize));
62#endif
63
64    EXPECT_OK(bytes.Resize(kSize));
65    EXPECT_EQ(bytes.len(), kSize);
66    EXPECT_NONNULL(bytes.get());
67    EXPECT_TRUE(AllEqual(bytes.get(), 0xff, 0, kSize));
68
69    EXPECT_OK(bytes.Resize(kSize / 2));
70    EXPECT_EQ(bytes.len(), kSize / 2);
71    EXPECT_NONNULL(bytes.get());
72    EXPECT_TRUE(AllEqual(bytes.get(), 0xff, 0, kSize / 2));
73
74    EXPECT_OK(bytes.Resize(kSize));
75    EXPECT_EQ(bytes.len(), kSize);
76    EXPECT_NONNULL(bytes.get());
77    EXPECT_TRUE(AllEqual(bytes.get(), 0xff, 0, kSize / 2));
78    EXPECT_TRUE(AllEqual(bytes.get(), 0, kSize / 2, kSize / 2));
79
80    EXPECT_OK(bytes.Resize(0));
81    EXPECT_EQ(bytes.len(), 0U);
82    EXPECT_NULL(bytes.get());
83    END_TEST;
84}
85
86bool TestCopy(void) {
87    BEGIN_TEST;
88    Bytes bytes, copy;
89    ASSERT_OK(bytes.Resize(kSize));
90
91    uint8_t buf[kSize];
92    memset(buf, 2, kSize);
93    EXPECT_ZX(bytes.Copy(nullptr, kSize, kSize), ZX_ERR_INVALID_ARGS);
94    EXPECT_OK(bytes.Copy(buf, 0, kSize * 10));
95    EXPECT_EQ(bytes.len(), kSize);
96    EXPECT_TRUE(AllEqual(bytes.get(), 0, 0, kSize));
97
98    EXPECT_OK(bytes.Copy(buf, kSize, kSize));
99    EXPECT_TRUE(AllEqual(bytes.get(), 0, 0, kSize));
100    EXPECT_TRUE(AllEqual(bytes.get(), 2, kSize, kSize));
101
102    memset(buf, 1, kSize);
103    EXPECT_OK(bytes.Copy(buf, kSize / 2, kSize / 2));
104    EXPECT_TRUE(AllEqual(bytes.get(), 0, 0, kSize / 2));
105    EXPECT_TRUE(AllEqual(bytes.get(), 1, kSize / 2, kSize / 2));
106    EXPECT_TRUE(AllEqual(bytes.get(), 2, kSize, kSize));
107
108    ASSERT_OK(bytes.Resize(0));
109    EXPECT_OK(bytes.Copy(buf, kSize));
110    EXPECT_EQ(bytes.len(), kSize);
111    EXPECT_TRUE(AllEqual(bytes.get(), 1, 0, kSize));
112
113    EXPECT_OK(copy.Copy(bytes));
114    EXPECT_TRUE(AllEqual(copy.get(), 1, 0, kSize));
115
116    EXPECT_OK(copy.Copy(bytes, kSize));
117    EXPECT_TRUE(AllEqual(copy.get(), 1, 0, kSize * 2));
118
119    END_TEST;
120}
121
122bool TestArrayAccess(void) {
123    BEGIN_TEST;
124    Bytes bytes;
125    ASSERT_OK(bytes.Resize(kSize, 1));
126    for (size_t i = 0; i < kSize; ++i) {
127        EXPECT_EQ(bytes[i], 1);
128        bytes[i] = 2;
129    }
130    EXPECT_TRUE(AllEqual(bytes.get(), 2, 0, kSize));
131    END_TEST;
132}
133
134bool TestComparison(void) {
135    BEGIN_TEST;
136    Bytes bytes1, bytes2;
137    ASSERT_OK(bytes1.Randomize(kSize));
138    ASSERT_OK(bytes2.Copy(bytes1.get(), bytes1.len()));
139    EXPECT_TRUE(bytes1 == bytes1);
140    EXPECT_TRUE(bytes2 == bytes2);
141    EXPECT_FALSE(bytes1 != bytes1);
142    EXPECT_FALSE(bytes2 != bytes2);
143    EXPECT_TRUE(bytes1 == bytes2);
144    EXPECT_TRUE(bytes2 == bytes1);
145    EXPECT_FALSE(bytes1 != bytes2);
146    EXPECT_FALSE(bytes2 != bytes1);
147
148    ASSERT_OK(bytes2.Randomize(kSize));
149    EXPECT_TRUE(bytes1 == bytes1);
150    EXPECT_TRUE(bytes2 == bytes2);
151    EXPECT_FALSE(bytes1 != bytes1);
152    EXPECT_FALSE(bytes2 != bytes2);
153    EXPECT_FALSE(bytes1 == bytes2);
154    EXPECT_FALSE(bytes2 == bytes1);
155    EXPECT_TRUE(bytes1 != bytes2);
156    EXPECT_TRUE(bytes2 != bytes1);
157    END_TEST;
158}
159
160BEGIN_TEST_CASE(BytesTest)
161RUN_TEST(TestRandomize)
162RUN_TEST(TestResize)
163RUN_TEST(TestCopy)
164RUN_TEST(TestArrayAccess)
165RUN_TEST(TestComparison)
166END_TEST_CASE(BytesTest)
167
168} // namespace
169} // namespace testing
170} // namespace crypto
171