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