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