1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 * Copyright (C) 2019-2021 Matt Dunwoodie <ncon@noconroy.net> 5 */ 6 7 #define MESSAGE_LEN 64 8 #define T_FAILED_ITER(test) do { \ 9 kprintf("%s %s: FAIL, iter: %d\n", __func__, test, i); \ 10 goto cleanup; \ 11 } while (0) 12 #define T_FAILED(test) do { \ 13 kprintf("%s %s: FAIL\n", __func__, test); \ 14 goto cleanup; \ 15 } while (0) 16 #define T_PASSED kprintf("%s: pass\n", __func__) 17 18 static const struct expected_results { 19 int result; 20 uint64_t sleep_time; /* nanoseconds */ 21 } rl_expected[] = { 22 [0 ... INITIATIONS_BURSTABLE - 1] = { 0, 0 }, 23 [INITIATIONS_BURSTABLE] = { ECONNREFUSED, 0 }, 24 [INITIATIONS_BURSTABLE + 1] = { 0, INITIATION_COST }, 25 [INITIATIONS_BURSTABLE + 2] = { ECONNREFUSED, 0 }, 26 [INITIATIONS_BURSTABLE + 3] = { 0, INITIATION_COST * 2 }, 27 [INITIATIONS_BURSTABLE + 4] = { 0, 0 }, 28 [INITIATIONS_BURSTABLE + 5] = { ECONNREFUSED, 0 } 29 }; 30 31 static struct ratelimit rl; 32 33 static bool 34 cookie_ratelimit_timings_test(void) 35 { 36 bool ret = false; 37 struct sockaddr_in sin; 38 #ifdef INET6 39 struct sockaddr_in6 sin6; 40 #endif 41 uint64_t t; 42 int i; 43 44 bzero(&rl, sizeof(rl)); 45 ratelimit_init(&rl); 46 47 sin.sin_family = AF_INET; 48 #ifdef INET6 49 sin6.sin6_family = AF_INET6; 50 #endif 51 52 for (i = 0; i < sizeof(rl_expected)/sizeof(*rl_expected); i++) { 53 if ((t = rl_expected[i].sleep_time) != 0) 54 tsleep(&rl, 0, "rl", (int)(t * hz / NSEC_PER_SEC)); 55 56 /* The first v4 ratelimit_allow is against a constant address, 57 * and should be indifferent to the port. */ 58 sin.sin_addr.s_addr = 0x01020304; 59 sin.sin_port = karc4random(); 60 61 if (ratelimit_allow(&rl, sintosa(&sin)) != rl_expected[i].result) 62 T_FAILED_ITER("malicious v4"); 63 64 /* The second ratelimit_allow is to test that an arbitrary 65 * address is still allowed. */ 66 sin.sin_addr.s_addr += i + 1; 67 sin.sin_port = karc4random(); 68 69 if (ratelimit_allow(&rl, sintosa(&sin)) != 0) 70 T_FAILED_ITER("non-malicious v4"); 71 72 #ifdef INET6 73 /* The first v6 ratelimit_allow is against a constant address, 74 * and should be indifferent to the port. We also mutate the 75 * lower 64 bits of the address as we want to ensure ratelimit 76 * occurs against the higher 64 bits (/64 network). */ 77 sin6.sin6_addr.s6_addr32[0] = 0x01020304; 78 sin6.sin6_addr.s6_addr32[1] = 0x05060708; 79 sin6.sin6_addr.s6_addr32[2] = i; 80 sin6.sin6_addr.s6_addr32[3] = i; 81 sin6.sin6_port = karc4random(); 82 83 if (ratelimit_allow(&rl, sin6tosa(&sin6)) != rl_expected[i].result) 84 T_FAILED_ITER("malicious v6"); 85 86 /* Again, test that an address different to above is still 87 * allowed. */ 88 sin6.sin6_addr.s6_addr32[0] += i + 1; 89 sin6.sin6_port = karc4random(); 90 91 if (ratelimit_allow(&rl, sintosa(&sin)) != 0) 92 T_FAILED_ITER("non-malicious v6"); 93 #endif 94 } 95 T_PASSED; 96 ret = true; 97 cleanup: 98 ratelimit_deinit(&rl); 99 return ret; 100 } 101 102 static bool 103 cookie_ratelimit_capacity_test(void) 104 { 105 struct sockaddr_in sin; 106 int i; 107 bool ret = false; 108 109 bzero(&rl, sizeof(rl)); 110 ratelimit_init(&rl); 111 112 sin.sin_family = AF_INET; 113 sin.sin_port = 1234; 114 115 /* Here we test that the ratelimiter has an upper bound on the number 116 * of addresses to be limited */ 117 for (i = 0; i <= RATELIMIT_SIZE_MAX; i++) { 118 sin.sin_addr.s_addr = i; 119 if (i == RATELIMIT_SIZE_MAX) { 120 if (ratelimit_allow(&rl, sintosa(&sin)) != ECONNREFUSED) 121 T_FAILED_ITER("reject"); 122 } else { 123 if (ratelimit_allow(&rl, sintosa(&sin)) != 0) 124 T_FAILED_ITER("allow"); 125 } 126 } 127 T_PASSED; 128 ret = true; 129 cleanup: 130 ratelimit_deinit(&rl); 131 return ret; 132 } 133 134 static bool 135 cookie_ratelimit_gc_test(void) 136 { 137 struct sockaddr_in sin; 138 int i; 139 bool ret = false; 140 141 bzero(&rl, sizeof(rl)); 142 ratelimit_init(&rl); 143 144 sin.sin_family = AF_INET; 145 sin.sin_port = 1234; 146 147 /* Here we test that the garbage collect routine will run */ 148 if (rl.rl_table_num != 0) 149 T_FAILED("init not empty"); 150 151 for (i = 0; i < RATELIMIT_SIZE_MAX / 2; i++) { 152 sin.sin_addr.s_addr = i; 153 if (ratelimit_allow(&rl, sintosa(&sin)) != 0) 154 T_FAILED_ITER("insert"); 155 } 156 157 if (rl.rl_table_num != RATELIMIT_SIZE_MAX / 2) 158 T_FAILED("insert 1 not full"); 159 160 tsleep(&rl, 0, "rl", ELEMENT_TIMEOUT * hz / 2); 161 162 for (i = 0; i < RATELIMIT_SIZE_MAX / 2; i++) { 163 sin.sin_addr.s_addr = i; 164 if (ratelimit_allow(&rl, sintosa(&sin)) != 0) 165 T_FAILED_ITER("insert"); 166 } 167 168 if (rl.rl_table_num != RATELIMIT_SIZE_MAX / 2) 169 T_FAILED("insert 2 not full"); 170 171 tsleep(&rl, 0, "rl", ELEMENT_TIMEOUT * hz * 2); 172 173 if (rl.rl_table_num != 0) 174 T_FAILED("gc"); 175 T_PASSED; 176 ret = true; 177 cleanup: 178 ratelimit_deinit(&rl); 179 return ret; 180 } 181 182 static bool 183 cookie_mac_test(void) 184 { 185 struct cookie_checker checker; 186 struct cookie_maker maker; 187 struct cookie_macs cm; 188 struct sockaddr_in sin; 189 int res, i; 190 bool ret = false; 191 192 uint8_t nonce[COOKIE_NONCE_SIZE]; 193 uint8_t cookie[COOKIE_ENCRYPTED_SIZE]; 194 uint8_t shared[COOKIE_INPUT_SIZE]; 195 uint8_t message[MESSAGE_LEN]; 196 197 karc4random_buf(shared, COOKIE_INPUT_SIZE); 198 karc4random_buf(message, MESSAGE_LEN); 199 200 /* Init cookie_maker. */ 201 cookie_maker_init(&maker, shared); 202 203 cookie_checker_init(&checker); 204 cookie_checker_update(&checker, shared); 205 206 /* Create dummy sockaddr */ 207 sin.sin_family = AF_INET; 208 sin.sin_len = sizeof(sin); 209 sin.sin_addr.s_addr = 1; 210 sin.sin_port = 51820; 211 212 /* MAC message */ 213 cookie_maker_mac(&maker, &cm, message, MESSAGE_LEN); 214 215 /* Check we have a null mac2 */ 216 for (i = 0; i < sizeof(cm.mac2); i++) 217 if (cm.mac2[i] != 0) 218 T_FAILED("validate_macs_noload_mac2_zeroed"); 219 220 /* Validate all bytes are checked in mac1 */ 221 for (i = 0; i < sizeof(cm.mac1); i++) { 222 cm.mac1[i] = ~cm.mac1[i]; 223 if (cookie_checker_validate_macs(&checker, &cm, message, 224 MESSAGE_LEN, 0, sintosa(&sin)) != EINVAL) 225 T_FAILED("validate_macs_noload_munge"); 226 cm.mac1[i] = ~cm.mac1[i]; 227 } 228 229 /* Check mac2 is zeroed */ 230 res = 0; 231 for (i = 0; i < sizeof(cm.mac2); i++) 232 res |= cm.mac2[i]; 233 if (res != 0) 234 T_FAILED("validate_macs_mac2_checkzero"); 235 236 237 /* Check we can successfully validate the MAC */ 238 if (cookie_checker_validate_macs(&checker, &cm, message, 239 MESSAGE_LEN, 0, sintosa(&sin)) != 0) 240 T_FAILED("validate_macs_noload_normal"); 241 242 /* Check we get a EAGAIN if no mac2 and under load */ 243 if (cookie_checker_validate_macs(&checker, &cm, message, 244 MESSAGE_LEN, 1, sintosa(&sin)) != EAGAIN) 245 T_FAILED("validate_macs_load_normal"); 246 247 /* Simulate a cookie message */ 248 cookie_checker_create_payload(&checker, &cm, nonce, cookie, sintosa(&sin)); 249 250 /* Validate all bytes are checked in cookie */ 251 for (i = 0; i < sizeof(cookie); i++) { 252 cookie[i] = ~cookie[i]; 253 if (cookie_maker_consume_payload(&maker, nonce, cookie) != EINVAL) 254 T_FAILED("consume_payload_munge"); 255 cookie[i] = ~cookie[i]; 256 } 257 258 /* Check we can actually consume the payload */ 259 if (cookie_maker_consume_payload(&maker, nonce, cookie) != 0) 260 T_FAILED("consume_payload_normal"); 261 262 /* Check replay isn't allowed */ 263 if (cookie_maker_consume_payload(&maker, nonce, cookie) != ETIMEDOUT) 264 T_FAILED("consume_payload_normal_replay"); 265 266 /* MAC message again, with MAC2 */ 267 cookie_maker_mac(&maker, &cm, message, MESSAGE_LEN); 268 269 /* Check we added a mac2 */ 270 res = 0; 271 for (i = 0; i < sizeof(cm.mac2); i++) 272 res |= cm.mac2[i]; 273 if (res == 0) 274 T_FAILED("validate_macs_make_mac2"); 275 276 /* Check we get OK if mac2 and under load */ 277 if (cookie_checker_validate_macs(&checker, &cm, message, 278 MESSAGE_LEN, 1, sintosa(&sin)) != 0) 279 T_FAILED("validate_macs_load_normal_mac2"); 280 281 sin.sin_addr.s_addr = ~sin.sin_addr.s_addr; 282 /* Check we get EAGAIN if we munge the source IP */ 283 if (cookie_checker_validate_macs(&checker, &cm, message, 284 MESSAGE_LEN, 1, sintosa(&sin)) != EAGAIN) 285 T_FAILED("validate_macs_load_spoofip_mac2"); 286 sin.sin_addr.s_addr = ~sin.sin_addr.s_addr; 287 288 /* Check we get OK if mac2 and under load */ 289 if (cookie_checker_validate_macs(&checker, &cm, message, 290 MESSAGE_LEN, 1, sintosa(&sin)) != 0) 291 T_FAILED("validate_macs_load_normal_mac2_retry"); 292 293 T_PASSED; 294 ret = true; 295 cleanup: 296 cookie_checker_free(&checker); 297 cookie_maker_free(&maker); 298 return ret; 299 } 300 301 bool 302 cookie_selftest(void) 303 { 304 bool ret = true; 305 ret &= cookie_ratelimit_timings_test(); 306 ret &= cookie_ratelimit_capacity_test(); 307 ret &= cookie_ratelimit_gc_test(); 308 ret &= cookie_mac_test(); 309 return ret; 310 } 311