1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #include <sys/param.h> 31 #include <sys/random.h> 32 33 #include <errno.h> 34 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdbool.h> 37 38 #include <crypto/chacha20/chacha.h> 39 #include <crypto/rijndael/rijndael-api-fst.h> 40 #include <crypto/sha2/sha256.h> 41 42 #include <dev/random/hash.h> 43 #include <dev/random/uint128.h> 44 45 #include <atf-c.h> 46 47 static void 48 vec_u32_tole128(uint8_t dst[static 16], const uint32_t src[static 4]) 49 { 50 le32enc(dst, src[0]); 51 le32enc(&dst[4], src[1]); 52 le32enc(&dst[8], src[2]); 53 le32enc(&dst[12], src[3]); 54 } 55 56 static void 57 le128_to_vec_u32(uint32_t dst[static 4], const uint8_t src[static 16]) 58 { 59 dst[0] = le32dec(src); 60 dst[1] = le32dec(&src[4]); 61 dst[2] = le32dec(&src[8]); 62 dst[3] = le32dec(&src[12]); 63 } 64 65 static void 66 formatu128(char buf[static 52], uint128_t x) 67 { 68 uint8_t le128x[16]; 69 uint32_t vx[4]; 70 size_t sz, i; 71 int rc; 72 73 le128enc(le128x, x); 74 le128_to_vec_u32(vx, le128x); 75 76 sz = 52; 77 for (i = 0; i < 4; i++) { 78 rc = snprintf(buf, sz, "0x%x ", vx[i]); 79 ATF_REQUIRE(rc > 0 && (size_t)rc < sz); 80 81 buf += rc; 82 sz -= rc; 83 } 84 /* Delete last trailing space */ 85 buf[-1] = '\0'; 86 } 87 88 static void 89 u128_check_equality(uint128_t a, uint128_t b, const char *descr) 90 { 91 char fmtbufa[52], fmtbufb[52]; 92 93 formatu128(fmtbufa, a); 94 formatu128(fmtbufb, b); 95 96 ATF_CHECK_MSG(uint128_equals(a, b), 97 "Expected: [%s] != Actual: [%s]: %s", fmtbufa, fmtbufb, descr); 98 } 99 100 ATF_TC_WITHOUT_HEAD(uint128_inc); 101 ATF_TC_BODY(uint128_inc, tc) 102 { 103 static const struct u128_inc_tc { 104 uint32_t input[4]; 105 uint32_t expected[4]; 106 const char *descr; 107 } tests[] = { 108 { 109 .input = { 0, 0, 0, 0 }, 110 .expected = { 1, 0, 0, 0 }, 111 .descr = "0 -> 1", 112 }, 113 { 114 .input = { 1, 0, 0, 0 }, 115 .expected = { 2, 0, 0, 0 }, 116 .descr = "0 -> 2", 117 }, 118 { 119 .input = { 0xff, 0, 0, 0 }, 120 .expected = { 0x100, 0, 0, 0 }, 121 .descr = "0xff -> 0x100 (byte carry)", 122 }, 123 { 124 .input = { UINT32_MAX, 0, 0, 0 }, 125 .expected = { 0, 1, 0, 0 }, 126 .descr = "2^32 - 1 -> 2^32 (word carry)", 127 }, 128 { 129 .input = { UINT32_MAX, UINT32_MAX, 0, 0 }, 130 .expected = { 0, 0, 1, 0 }, 131 .descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)", 132 }, 133 { 134 .input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, 135 .expected = { 0, 0, 0, 1 }, 136 .descr = "2^96 - 1 -> 2^96 (word carry)", 137 }, 138 }; 139 uint8_t inputle[16], expectedle[16]; 140 uint128_t a; 141 size_t i; 142 143 for (i = 0; i < nitems(tests); i++) { 144 vec_u32_tole128(inputle, tests[i].input); 145 vec_u32_tole128(expectedle, tests[i].expected); 146 147 a = le128dec(inputle); 148 uint128_increment(&a); 149 u128_check_equality(le128dec(expectedle), a, tests[i].descr); 150 } 151 } 152 153 ATF_TC_WITHOUT_HEAD(uint128_add64); 154 ATF_TC_BODY(uint128_add64, tc) 155 { 156 static const struct u128_add64_tc { 157 uint32_t input[4]; 158 uint64_t addend; 159 uint32_t expected[4]; 160 const char *descr; 161 } tests[] = { 162 { 163 .input = { 0, 0, 0, 0 }, 164 .addend = 1, 165 .expected = { 1, 0, 0, 0 }, 166 .descr = "0 + 1 -> 1", 167 }, 168 { 169 .input = { 1, 0, 0, 0 }, 170 .addend = UINT32_MAX, 171 .expected = { 0, 1, 0, 0 }, 172 .descr = "1 + (2^32 - 1) -> 2^32 (word carry)", 173 }, 174 { 175 .input = { 1, 0, 0, 0 }, 176 .addend = UINT64_MAX, 177 .expected = { 0, 0, 1, 0 }, 178 .descr = "1 + (2^64 - 1) -> 2^64 (u128t_word0 carry)", 179 }, 180 { 181 .input = { 0x11111111, 0x11111111, 0, 0 }, 182 .addend = 0xf0123456789abcdeULL, 183 .expected = { 0x89abcdef, 0x01234567, 1, 0 }, 184 .descr = "0x1111_1111_1111_1111 +" 185 "0xf012_3456_789a_bcde ->" 186 "0x1_0123_4567_89ab_cdef", 187 }, 188 { 189 .input = { 1, 0, UINT32_MAX, 0 }, 190 .addend = UINT64_MAX, 191 .expected = { 0, 0, 0, 1 }, 192 .descr = "Carry ~2^96", 193 }, 194 }; 195 uint8_t inputle[16], expectedle[16]; 196 uint128_t a; 197 size_t i; 198 199 for (i = 0; i < nitems(tests); i++) { 200 vec_u32_tole128(inputle, tests[i].input); 201 vec_u32_tole128(expectedle, tests[i].expected); 202 203 a = le128dec(inputle); 204 uint128_add64(&a, tests[i].addend); 205 u128_check_equality(le128dec(expectedle), a, tests[i].descr); 206 } 207 } 208 209 /* 210 * Test assumptions about Chacha incrementing counter in the same way as 211 * uint128.h 212 */ 213 ATF_TC_WITHOUT_HEAD(uint128_chacha_ctr); 214 ATF_TC_BODY(uint128_chacha_ctr, tc) 215 { 216 static const struct u128_chacha_tc { 217 uint32_t input[4]; 218 uint32_t expected[4]; 219 const char *descr; 220 } tests[] = { 221 { 222 .input = { 0, 0, 0, 0 }, 223 .expected = { 1, 0, 0, 0 }, 224 .descr = "Single block", 225 }, 226 { 227 .input = { 1, 0, 0, 0 }, 228 .expected = { 2, 0, 0, 0 }, 229 .descr = "0 -> 2", 230 }, 231 { 232 .input = { 0xff, 0, 0, 0 }, 233 .expected = { 0x100, 0, 0, 0 }, 234 .descr = "0xff -> 0x100 (byte carry)", 235 }, 236 { 237 .input = { UINT32_MAX, 0, 0, 0 }, 238 .expected = { 0, 1, 0, 0 }, 239 .descr = "2^32 - 1 -> 2^32 (word carry)", 240 }, 241 { 242 .input = { UINT32_MAX, UINT32_MAX, 0, 0 }, 243 .expected = { 0, 0, 1, 0 }, 244 .descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)", 245 }, 246 { 247 .input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, 248 .expected = { 0, 0, 0, 1 }, 249 .descr = "2^96 - 1 -> 2^96 (word carry)", 250 }, 251 }; 252 union randomdev_key context; 253 uint8_t inputle[16], expectedle[16], trash[CHACHA_BLOCKLEN]; 254 uint8_t notrandomkey[RANDOM_KEYSIZE] = { 0 }; 255 uint128_t a; 256 size_t i; 257 258 random_chachamode = true; 259 randomdev_encrypt_init(&context, notrandomkey); 260 261 for (i = 0; i < nitems(tests); i++) { 262 vec_u32_tole128(inputle, tests[i].input); 263 vec_u32_tole128(expectedle, tests[i].expected); 264 265 a = le128dec(inputle); 266 randomdev_keystream(&context, &a, trash, sizeof(trash)); 267 u128_check_equality(le128dec(expectedle), a, tests[i].descr); 268 } 269 270 } 271 272 ATF_TP_ADD_TCS(tp) 273 { 274 275 ATF_TP_ADD_TC(tp, uint128_inc); 276 ATF_TP_ADD_TC(tp, uint128_add64); 277 ATF_TP_ADD_TC(tp, uint128_chacha_ctr); 278 return (atf_no_error()); 279 } 280