1a8e7a31cem/*-
2a8e7a31cem * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3a8e7a31cem *
4a8e7a31cem * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
5a8e7a31cem * All rights reserved.
6a8e7a31cem *
7a8e7a31cem * Redistribution and use in source and binary forms, with or without
8a8e7a31cem * modification, are permitted provided that the following conditions
9a8e7a31cem * are met:
10a8e7a31cem * 1. Redistributions of source code must retain the above copyright
11a8e7a31cem *    notice, this list of conditions and the following disclaimer.
12a8e7a31cem * 2. Redistributions in binary form must reproduce the above copyright
13a8e7a31cem *    notice, this list of conditions and the following disclaimer in the
14a8e7a31cem *    documentation and/or other materials provided with the distribution.
15a8e7a31cem *
16a8e7a31cem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17a8e7a31cem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18a8e7a31cem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19a8e7a31cem * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20a8e7a31cem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21a8e7a31cem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22a8e7a31cem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23a8e7a31cem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24a8e7a31cem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a8e7a31cem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a8e7a31cem * SUCH DAMAGE.
27a8e7a31cem */
28a8e7a31cem
29a8e7a31cem#include <sys/cdefs.h>
30a8e7a31cem__FBSDID("$FreeBSD$");
31a8e7a31cem
32a8e7a31cem#include <sys/param.h>
33a8e7a31cem#include <sys/random.h>
34a8e7a31cem
35a8e7a31cem#include <errno.h>
36a8e7a31cem#include <stdint.h>
37a8e7a31cem#include <stdio.h>
38a8e7a31cem#include <stdbool.h>
39a8e7a31cem
40a8e7a31cem#include <crypto/chacha20/chacha.h>
41a8e7a31cem#include <crypto/rijndael/rijndael-api-fst.h>
42a8e7a31cem#include <crypto/sha2/sha256.h>
43a8e7a31cem
44a8e7a31cem#include <dev/random/hash.h>
45a8e7a31cem#include <dev/random/uint128.h>
46a8e7a31cem
47a8e7a31cem#include <atf-c.h>
48a8e7a31cem
49a8e7a31cemstatic void
50a8e7a31cemvec_u32_tole128(uint8_t dst[static 16], const uint32_t src[static 4])
51a8e7a31cem{
52a8e7a31cem	le32enc(dst, src[0]);
53a8e7a31cem	le32enc(&dst[4], src[1]);
54a8e7a31cem	le32enc(&dst[8], src[2]);
55a8e7a31cem	le32enc(&dst[12], src[3]);
56a8e7a31cem}
57a8e7a31cem
58a8e7a31cemstatic void
59a8e7a31cemle128_to_vec_u32(uint32_t dst[static 4], const uint8_t src[static 16])
60a8e7a31cem{
61a8e7a31cem	dst[0] = le32dec(src);
62a8e7a31cem	dst[1] = le32dec(&src[4]);
63a8e7a31cem	dst[2] = le32dec(&src[8]);
64a8e7a31cem	dst[3] = le32dec(&src[12]);
65a8e7a31cem}
66a8e7a31cem
67a8e7a31cemstatic void
68a8e7a31cemformatu128(char buf[static 52], uint128_t x)
69a8e7a31cem{
70a8e7a31cem	uint8_t le128x[16];
71a8e7a31cem	uint32_t vx[4];
72a8e7a31cem	size_t sz, i;
73a8e7a31cem	int rc;
74a8e7a31cem
75a8e7a31cem	le128enc(le128x, x);
76a8e7a31cem	le128_to_vec_u32(vx, le128x);
77a8e7a31cem
78a8e7a31cem	sz = 52;
79a8e7a31cem	for (i = 0; i < 4; i++) {
80a8e7a31cem		rc = snprintf(buf, sz, "0x%x ", vx[i]);
81a8e7a31cem		ATF_REQUIRE(rc > 0 && (size_t)rc < sz);
82a8e7a31cem
83a8e7a31cem		buf += rc;
84a8e7a31cem		sz -= rc;
85a8e7a31cem	}
86a8e7a31cem	/* Delete last trailing space */
87a8e7a31cem	buf[-1] = '\0';
88a8e7a31cem}
89a8e7a31cem
90a8e7a31cemstatic void
91a8e7a31cemu128_check_equality(uint128_t a, uint128_t b, const char *descr)
92a8e7a31cem{
93a8e7a31cem	char fmtbufa[52], fmtbufb[52];
94a8e7a31cem
95a8e7a31cem	formatu128(fmtbufa, a);
96a8e7a31cem	formatu128(fmtbufb, b);
97a8e7a31cem
98a8e7a31cem	ATF_CHECK_MSG(uint128_equals(a, b),
99a8e7a31cem	    "Expected: [%s] != Actual: [%s]: %s", fmtbufa, fmtbufb, descr);
100a8e7a31cem}
101a8e7a31cem
102a8e7a31cemATF_TC_WITHOUT_HEAD(uint128_inc);
103a8e7a31cemATF_TC_BODY(uint128_inc, tc)
104a8e7a31cem{
105a8e7a31cem	static const struct u128_inc_tc {
106a8e7a31cem		uint32_t input[4];
107a8e7a31cem		uint32_t expected[4];
108a8e7a31cem		const char *descr;
109a8e7a31cem	} tests[] = {
110a8e7a31cem		{
111a8e7a31cem			.input = { 0, 0, 0, 0 },
112a8e7a31cem			.expected = { 1, 0, 0, 0 },
113a8e7a31cem			.descr = "0 -> 1",
114a8e7a31cem		},
115a8e7a31cem		{
116a8e7a31cem			.input = { 1, 0, 0, 0 },
117a8e7a31cem			.expected = { 2, 0, 0, 0 },
118a8e7a31cem			.descr = "0 -> 2",
119a8e7a31cem		},
120a8e7a31cem		{
121a8e7a31cem			.input = { 0xff, 0, 0, 0 },
122a8e7a31cem			.expected = { 0x100, 0, 0, 0 },
123a8e7a31cem			.descr = "0xff -> 0x100 (byte carry)",
124a8e7a31cem		},
125a8e7a31cem		{
126a8e7a31cem			.input = { UINT32_MAX, 0, 0, 0 },
127a8e7a31cem			.expected = { 0, 1, 0, 0 },
128a8e7a31cem			.descr = "2^32 - 1 -> 2^32 (word carry)",
129a8e7a31cem		},
130a8e7a31cem		{
131a8e7a31cem			.input = { UINT32_MAX, UINT32_MAX, 0, 0 },
132a8e7a31cem			.expected = { 0, 0, 1, 0 },
133a8e7a31cem			.descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)",
134a8e7a31cem		},
135a8e7a31cem		{
136a8e7a31cem			.input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
137a8e7a31cem			.expected = { 0, 0, 0, 1 },
138a8e7a31cem			.descr = "2^96 - 1 -> 2^96 (word carry)",
139a8e7a31cem		},
140a8e7a31cem	};
141a8e7a31cem	uint8_t inputle[16], expectedle[16];
142a8e7a31cem	uint128_t a;
143a8e7a31cem	size_t i;
144a8e7a31cem
145a8e7a31cem	for (i = 0; i < nitems(tests); i++) {
146a8e7a31cem		vec_u32_tole128(inputle, tests[i].input);
147a8e7a31cem		vec_u32_tole128(expectedle, tests[i].expected);
148a8e7a31cem
149a8e7a31cem		a = le128dec(inputle);
150a8e7a31cem		uint128_increment(&a);
151a8e7a31cem		u128_check_equality(le128dec(expectedle), a, tests[i].descr);
152a8e7a31cem	}
153a8e7a31cem}
154a8e7a31cem
155b0dcb77cemATF_TC_WITHOUT_HEAD(uint128_add64);
156b0dcb77cemATF_TC_BODY(uint128_add64, tc)
157b0dcb77cem{
158b0dcb77cem	static const struct u128_add64_tc {
159b0dcb77cem		uint32_t input[4];
160b0dcb77cem		uint64_t addend;
161b0dcb77cem		uint32_t expected[4];
162b0dcb77cem		const char *descr;
163b0dcb77cem	} tests[] = {
164b0dcb77cem		{
165b0dcb77cem			.input = { 0, 0, 0, 0 },
166b0dcb77cem			.addend = 1,
167b0dcb77cem			.expected = { 1, 0, 0, 0 },
168b0dcb77cem			.descr = "0 + 1 -> 1",
169b0dcb77cem		},
170b0dcb77cem		{
171b0dcb77cem			.input = { 1, 0, 0, 0 },
172b0dcb77cem			.addend = UINT32_MAX,
173b0dcb77cem			.expected = { 0, 1, 0, 0 },
174b0dcb77cem			.descr = "1 + (2^32 - 1) -> 2^32 (word carry)",
175b0dcb77cem		},
176b0dcb77cem		{
177b0dcb77cem			.input = { 1, 0, 0, 0 },
178b0dcb77cem			.addend = UINT64_MAX,
179b0dcb77cem			.expected = { 0, 0, 1, 0 },
180b0dcb77cem			.descr = "1 + (2^64 - 1) -> 2^64 (u128t_word0 carry)",
181b0dcb77cem		},
182b0dcb77cem		{
183b0dcb77cem			.input = { 0x11111111, 0x11111111, 0, 0 },
184b0dcb77cem			.addend = 0xf0123456789abcdeULL,
185b0dcb77cem			.expected = { 0x89abcdef, 0x01234567, 1, 0 },
186b0dcb77cem			.descr = "0x1111_1111_1111_1111 +"
187b0dcb77cem				 "0xf012_3456_789a_bcde ->"
188b0dcb77cem			       "0x1_0123_4567_89ab_cdef",
189b0dcb77cem		},
190b0dcb77cem		{
191b0dcb77cem			.input = { 1, 0, UINT32_MAX, 0 },
192b0dcb77cem			.addend = UINT64_MAX,
193b0dcb77cem			.expected = { 0, 0, 0, 1 },
194b0dcb77cem			.descr = "Carry ~2^96",
195b0dcb77cem		},
196b0dcb77cem	};
197b0dcb77cem	uint8_t inputle[16], expectedle[16];
198b0dcb77cem	uint128_t a;
199b0dcb77cem	size_t i;
200b0dcb77cem
201b0dcb77cem	for (i = 0; i < nitems(tests); i++) {
202b0dcb77cem		vec_u32_tole128(inputle, tests[i].input);
203b0dcb77cem		vec_u32_tole128(expectedle, tests[i].expected);
204b0dcb77cem
205b0dcb77cem		a = le128dec(inputle);
206b0dcb77cem		uint128_add64(&a, tests[i].addend);
207b0dcb77cem		u128_check_equality(le128dec(expectedle), a, tests[i].descr);
208b0dcb77cem	}
209b0dcb77cem}
210b0dcb77cem
211a8e7a31cem/*
212a8e7a31cem * Test assumptions about Chacha incrementing counter in the same way as
213a8e7a31cem * uint128.h
214a8e7a31cem */
215a8e7a31cemATF_TC_WITHOUT_HEAD(uint128_chacha_ctr);
216a8e7a31cemATF_TC_BODY(uint128_chacha_ctr, tc)
217a8e7a31cem{
218a8e7a31cem	static const struct u128_chacha_tc {
219a8e7a31cem		uint32_t input[4];
220a8e7a31cem		uint32_t expected[4];
221a8e7a31cem		const char *descr;
222a8e7a31cem	} tests[] = {
223a8e7a31cem		{
224a8e7a31cem			.input = { 0, 0, 0, 0 },
225a8e7a31cem			.expected = { 1, 0, 0, 0 },
226a8e7a31cem			.descr = "Single block",
227a8e7a31cem		},
228a8e7a31cem		{
229a8e7a31cem			.input = { 1, 0, 0, 0 },
230a8e7a31cem			.expected = { 2, 0, 0, 0 },
231a8e7a31cem			.descr = "0 -> 2",
232a8e7a31cem		},
233a8e7a31cem		{
234a8e7a31cem			.input = { 0xff, 0, 0, 0 },
235a8e7a31cem			.expected = { 0x100, 0, 0, 0 },
236a8e7a31cem			.descr = "0xff -> 0x100 (byte carry)",
237a8e7a31cem		},
238a8e7a31cem		{
239a8e7a31cem			.input = { UINT32_MAX, 0, 0, 0 },
240a8e7a31cem			.expected = { 0, 1, 0, 0 },
241a8e7a31cem			.descr = "2^32 - 1 -> 2^32 (word carry)",
242a8e7a31cem		},
243a8e7a31cem		{
244a8e7a31cem			.input = { UINT32_MAX, UINT32_MAX, 0, 0 },
245a8e7a31cem			.expected = { 0, 0, 1, 0 },
246a8e7a31cem			.descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)",
247a8e7a31cem		},
248a8e7a31cem		{
249a8e7a31cem			.input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 },
250a8e7a31cem			.expected = { 0, 0, 0, 1 },
251a8e7a31cem			.descr = "2^96 - 1 -> 2^96 (word carry)",
252a8e7a31cem		},
253a8e7a31cem	};
254a8e7a31cem	union randomdev_key context;
255a8e7a31cem	uint8_t inputle[16], expectedle[16], trash[CHACHA_BLOCKLEN];
256a8e7a31cem	uint8_t notrandomkey[RANDOM_KEYSIZE] = { 0 };
257a8e7a31cem	uint128_t a;
258a8e7a31cem	size_t i;
259a8e7a31cem
260a8e7a31cem	random_chachamode = true;
261a8e7a31cem	randomdev_encrypt_init(&context, notrandomkey);
262a8e7a31cem
263a8e7a31cem	for (i = 0; i < nitems(tests); i++) {
264a8e7a31cem		vec_u32_tole128(inputle, tests[i].input);
265a8e7a31cem		vec_u32_tole128(expectedle, tests[i].expected);
266a8e7a31cem
267a8e7a31cem		a = le128dec(inputle);
268a946135cem		randomdev_keystream(&context, &a, trash, sizeof(trash));
269a8e7a31cem		u128_check_equality(le128dec(expectedle), a, tests[i].descr);
270a8e7a31cem	}
271a8e7a31cem
272a8e7a31cem}
273a8e7a31cem
274a8e7a31cemATF_TP_ADD_TCS(tp)
275a8e7a31cem{
276a8e7a31cem
277a8e7a31cem	ATF_TP_ADD_TC(tp, uint128_inc);
278b0dcb77cem	ATF_TP_ADD_TC(tp, uint128_add64);
279a8e7a31cem	ATF_TP_ADD_TC(tp, uint128_chacha_ctr);
280a8e7a31cem	return (atf_no_error());
281a8e7a31cem}
282