Harald Welte | 8bd9d5d | 2023-05-28 09:36:50 +0200 | [diff] [blame] | 1 | |
| 2 | #include <stdint.h> |
| 3 | #include <osmocom/core/utils.h> |
| 4 | #include "gsm/tuak/tuak.h" |
| 5 | |
| 6 | /* user-friendly test specification, uses hex-strings for all parameters for |
| 7 | * copy+pasting from the spec. */ |
| 8 | struct tuak_testspec { |
| 9 | const char *name; |
| 10 | struct { |
| 11 | const char *k; |
| 12 | const char *rand; |
| 13 | const char *sqn; |
| 14 | const char *amf; |
| 15 | const char *top; |
| 16 | unsigned int keccak_iterations; |
| 17 | } in; |
| 18 | struct { |
| 19 | const char *topc; |
| 20 | const char *f1; |
| 21 | const char *f1star; |
| 22 | const char *f2; |
| 23 | const char *f3; |
| 24 | const char *f4; |
| 25 | const char *f5; |
| 26 | const char *f5star; |
| 27 | } out; |
| 28 | }; |
| 29 | |
| 30 | static const struct tuak_testspec testspecs[] = { |
| 31 | { |
| 32 | .name = "TS 35.233 Section 6.3 Test Set 1", |
| 33 | .in = { |
| 34 | .k = "abababababababababababababababab", |
| 35 | .rand = "42424242424242424242424242424242", |
| 36 | .sqn = "111111111111", |
| 37 | .amf = "ffff", |
| 38 | .top = "5555555555555555555555555555555555555555555555555555555555555555", |
| 39 | .keccak_iterations = 1, |
| 40 | }, |
| 41 | .out = { |
| 42 | .topc = "bd04d9530e87513c5d837ac2ad954623a8e2330c115305a73eb45d1f40cccbff", |
| 43 | .f1 = "f9a54e6aeaa8618d", |
| 44 | .f1star = "e94b4dc6c7297df3", |
| 45 | .f2 = "657acd64", |
| 46 | .f3 = "d71a1e5c6caffe986a26f783e5c78be1", |
| 47 | .f4 = "be849fa2564f869aecee6f62d4337e72", |
| 48 | .f5 = "719f1e9b9054", |
| 49 | .f5star = "e7af6b3d0e38", |
| 50 | }, |
| 51 | }, { |
| 52 | .name = "TS 35.233 Section 6.4 Test Set 2", |
| 53 | .in = { |
| 54 | .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0", |
| 55 | .rand = "0123456789abcdef0123456789abcdef", |
| 56 | .sqn = "0123456789ab", |
| 57 | .amf = "abcd", |
| 58 | .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", |
| 59 | .keccak_iterations = 1, |
| 60 | }, |
| 61 | .out = { |
| 62 | .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524", |
| 63 | .f1 = "c0b8c2d4148ec7aa5f1d78a97e4d1d58", |
| 64 | .f1star = "ef81af7290f7842c6ceafa537fa0745b", |
| 65 | .f2 = "e9d749dc4eea0035", |
| 66 | .f3 = "a4cb6f6529ab17f8337f27baa8234d47", |
| 67 | .f4 = "2274155ccf4199d5e2abcbf621907f90", |
| 68 | .f5 = "480a9345cc1e", |
| 69 | .f5star = "f84eb338848c", |
| 70 | }, |
| 71 | }, { |
| 72 | .name = "TS 35.233 Section 6.5 Test Set 3", |
| 73 | .in = { |
| 74 | .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0", |
| 75 | .rand = "0123456789abcdef0123456789abcdef", |
| 76 | .sqn = "0123456789ab", |
| 77 | .amf = "abcd", |
| 78 | .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", |
| 79 | .keccak_iterations = 1, |
| 80 | }, |
| 81 | .out = { |
| 82 | .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524", |
| 83 | .f1 = "d97b75a1776065271b1e212bc3b1bf173f438b21e6c64a55a96c372e085e5cc5", |
| 84 | .f1star = "427bbf07c6e3a86c54f8c5216499f3909a6fd4a164c9fe235b1550258111b821", |
| 85 | .f2 = "07021c73e7635c7d", |
| 86 | .f3 = "4d59ac796834eb85d11fa148a5058c3c", |
| 87 | .f4 = "126d47500136fdc5ddfd14f19ebf16749ce4b6435323fbb5715a3a796a6082bd", |
| 88 | .f5 = "1d6622c4e59a", |
| 89 | .f5star = "f84eb338848c", |
| 90 | }, |
| 91 | }, { |
| 92 | .name = "TS 35.233 Section 6.6 Test Set 4", |
| 93 | .in = { |
| 94 | .k = "b8da837a50652d6ac7c97da14f6acc61", |
| 95 | .rand = "6887e55425a966bd86c9661a5fa72be8", |
| 96 | .sqn = "0dea2ee2c5af", |
| 97 | .amf = "df1e", |
| 98 | .top = "0952be13556c32ebc58195d9dd930493e12a9003669988ffde5fa1f0fe35cc01", |
| 99 | .keccak_iterations = 1, |
| 100 | }, |
| 101 | .out = { |
| 102 | .topc = "2bc16eb657a68e1f446f08f57c0efb1d493527a2e652ce281eb6ca0e4487760a", |
| 103 | .f1 = "749214087958dd8f58bfcdf869d8ae3f", |
| 104 | .f1star = "619e865afe80e382aee13063f9dfb56d", |
| 105 | .f2 = "4041ce438e3e38e8aa96562eed83ac43", |
| 106 | .f3 = "3e3bc01bea0cd914c4c2c83ce2d92757", |
| 107 | .f4 = "666a8e6f577b1aa77b7fd53cebb8a3d6", |
| 108 | .f5 = "1f880d005119", |
| 109 | .f5star = "45e617d77fe5", |
| 110 | }, |
| 111 | }, { |
| 112 | .name = "TS 35.233 Section 6.7 Test Set 5", |
| 113 | .in = { |
| 114 | .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5", |
| 115 | .rand = "c570aac68cde651fb1e3088322498bef", |
| 116 | .sqn = "c89bb71f3a41", |
| 117 | .amf = "297d", |
| 118 | .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e", |
| 119 | .keccak_iterations = 1, |
| 120 | }, |
| 121 | .out = { |
| 122 | .topc = "3c6052e41532a28a47aa3cbb89f223e8f3aaa976aecd48bc3e7d6165a55eff62", |
| 123 | .f1 = "d7340dad02b4cb01", |
| 124 | .f1star = "c6021e2e66accb15", |
| 125 | .f2 = "84d89b41db1867ffd4c7ba1d82163f4d526a20fbae5418fbb526940b1eeb905c", |
| 126 | .f3 = "d419676afe5ab58c1d8bee0d43523a4d2f52ef0b31a4676a0c334427a988fe65", |
| 127 | .f4 = "205533e505661b61d05cc0eac87818f4", |
| 128 | .f5 = "d7b3d2d4980a", |
| 129 | .f5star = "ca9655264986", |
| 130 | }, |
| 131 | }, { |
| 132 | .name = "TS 35.233 Section 6.8 Test Set 6", |
| 133 | .in = { |
| 134 | .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5", |
| 135 | .rand = "c570aac68cde651fb1e3088322498bef", |
| 136 | .sqn = "c89bb71f3a41", |
| 137 | .amf = "297d", |
| 138 | .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e", |
| 139 | .keccak_iterations = 2, |
| 140 | }, |
| 141 | .out = { |
| 142 | .topc = "b04a66f26c62fcd6c82de22a179ab65506ecf47f56245cd149966cfa9cec7a51", |
| 143 | .f1 = "90d2289ed1ca1c3dbc2247bb480d431ac71d2e4a7677f6e997cfddb0cbad88b7", |
| 144 | .f1star = "427355dbac30e825063aba61b556e87583abac638e3ab01c4c884ad9d458dc2f", |
| 145 | .f2 = "d67e6e64590d22eecba7324afa4af4460c93f01b24506d6e12047d789a94c867", |
| 146 | .f3 = "ede57edfc57cdffe1aae75066a1b7479bbc3837438e88d37a801cccc9f972b89", |
| 147 | .f4 = "48ed9299126e5057402fe01f9201cf25249f9c5c0ed2afcf084755daff1d3999", |
| 148 | .f5 = "6aae8d18c448", |
| 149 | .f5star = "8c5f33b61f4e", |
| 150 | }, |
| 151 | }, |
| 152 | }; |
| 153 | |
| 154 | |
| 155 | struct tuak_testset { |
| 156 | const char *name; |
| 157 | struct { |
| 158 | uint8_t k[32]; |
| 159 | uint8_t k_len_bytes; |
| 160 | uint8_t rand[16]; |
| 161 | uint8_t sqn[6]; |
| 162 | uint8_t amf[2]; |
| 163 | uint8_t top[32]; |
| 164 | unsigned int keccak_iterations; |
| 165 | } in; |
| 166 | struct { |
| 167 | uint8_t topc[32]; |
| 168 | uint8_t mac_a[32]; |
| 169 | uint8_t mac_s[32]; |
| 170 | uint8_t mac_len_bytes; |
| 171 | |
| 172 | uint8_t res[32]; |
| 173 | uint8_t res_len_bytes; |
| 174 | |
| 175 | uint8_t ck[32]; |
| 176 | uint8_t ck_len_bytes; |
| 177 | uint8_t ik[32]; |
| 178 | uint8_t ik_len_bytes; |
| 179 | uint8_t ak[6]; |
| 180 | uint8_t f5star[6]; |
| 181 | } out; |
| 182 | }; |
| 183 | |
| 184 | static void expect_equal(const char *name, const uint8_t *actual, const uint8_t *expected, size_t len) |
| 185 | { |
| 186 | if (!memcmp(actual, expected, len)) { |
| 187 | printf("\t%s: %s\r\n", name, osmo_hexdump_nospc(actual, len)); |
| 188 | } else { |
| 189 | char buf[len*2+1]; |
| 190 | printf("\t%s: %s != %s\r\n", name, osmo_hexdump_nospc(actual, len), |
| 191 | osmo_hexdump_buf(buf, sizeof(buf), expected, len, "", true)); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | static void execute_testset(const struct tuak_testset *tset) |
| 196 | { |
| 197 | uint8_t topc[32]; |
| 198 | |
| 199 | printf("==> %s\n", tset->name); |
| 200 | |
| 201 | tuak_set_keccak_iterations(tset->in.keccak_iterations); |
| 202 | tuak_opc_gen(topc, tset->in.k, tset->in.k_len_bytes, tset->in.top); |
| 203 | expect_equal("TOPc", topc, tset->out.topc, sizeof(topc)); |
| 204 | |
| 205 | if (tset->out.mac_len_bytes) { |
| 206 | uint8_t mac_a[32]; |
| 207 | uint8_t mac_s[32]; |
| 208 | |
| 209 | tuak_f1(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf, |
| 210 | mac_a, tset->out.mac_len_bytes, tset->in.keccak_iterations); |
| 211 | expect_equal("MAC_A", mac_a, tset->out.mac_a, tset->out.mac_len_bytes); |
| 212 | |
| 213 | tuak_f1star(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf, |
| 214 | mac_s, tset->out.mac_len_bytes, tset->in.keccak_iterations); |
| 215 | expect_equal("MAC_S", mac_s, tset->out.mac_s, tset->out.mac_len_bytes); |
| 216 | } |
| 217 | |
| 218 | if (tset->out.ck_len_bytes || tset->out.ik_len_bytes || tset->out.res_len_bytes) { |
| 219 | uint8_t res[32]; |
| 220 | uint8_t ck[32]; |
| 221 | uint8_t ik[32]; |
| 222 | uint8_t ak[6]; |
| 223 | |
| 224 | tuak_f2345(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, |
| 225 | tset->out.res_len_bytes ? res : NULL, tset->out.res_len_bytes, |
| 226 | tset->out.ck_len_bytes ? ck : NULL, tset->out.ck_len_bytes, |
| 227 | tset->out.ik_len_bytes ? ik : NULL, tset->out.ik_len_bytes, |
| 228 | ak, tset->in.keccak_iterations); |
| 229 | |
| 230 | if (tset->out.res_len_bytes) |
| 231 | expect_equal("RES", res, tset->out.res, tset->out.res_len_bytes); |
| 232 | |
| 233 | if (tset->out.ck_len_bytes) |
| 234 | expect_equal("CK", ck, tset->out.ck, tset->out.ck_len_bytes); |
| 235 | |
| 236 | if (tset->out.ik_len_bytes) |
| 237 | expect_equal("IK", ik, tset->out.ik, tset->out.ik_len_bytes); |
| 238 | |
| 239 | expect_equal("AK", ak, tset->out.ak, 6); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | /* convert string-testspec to binary-testset and execute it */ |
| 244 | static void execute_testspec(const struct tuak_testspec *tcase) |
| 245 | { |
| 246 | struct tuak_testset _tset, *tset = &_tset; |
| 247 | |
| 248 | tset->name = tcase->name; |
| 249 | tset->in.keccak_iterations = tcase->in.keccak_iterations; |
| 250 | |
| 251 | osmo_hexparse(tcase->in.k, tset->in.k, sizeof(tset->in.k)); |
| 252 | tset->in.k_len_bytes = strlen(tcase->in.k)/2; |
| 253 | OSMO_ASSERT(tset->in.k_len_bytes == 16 || tset->in.k_len_bytes == 32); |
| 254 | |
| 255 | osmo_hexparse(tcase->in.rand, tset->in.rand, sizeof(tset->in.rand)); |
| 256 | OSMO_ASSERT(strlen(tcase->in.rand)/2 == 16); |
| 257 | |
| 258 | osmo_hexparse(tcase->in.sqn, tset->in.sqn, sizeof(tset->in.sqn)); |
| 259 | OSMO_ASSERT(strlen(tcase->in.sqn)/2 == 6); |
| 260 | |
| 261 | osmo_hexparse(tcase->in.amf, tset->in.amf, sizeof(tset->in.amf)); |
| 262 | OSMO_ASSERT(strlen(tcase->in.amf)/2 == 2); |
| 263 | |
| 264 | osmo_hexparse(tcase->in.top, tset->in.top, sizeof(tset->in.top)); |
| 265 | OSMO_ASSERT(strlen(tcase->in.top)/2 == 32); |
| 266 | |
| 267 | osmo_hexparse(tcase->out.topc, tset->out.topc, sizeof(tset->out.topc)); |
| 268 | OSMO_ASSERT(strlen(tcase->out.topc)/2 == 32); |
| 269 | |
| 270 | osmo_hexparse(tcase->out.f1, tset->out.mac_a, sizeof(tset->out.mac_a)); |
| 271 | osmo_hexparse(tcase->out.f1star, tset->out.mac_s, sizeof(tset->out.mac_s)); |
| 272 | OSMO_ASSERT(strlen(tcase->out.f1) == strlen(tcase->out.f1star)); |
| 273 | tset->out.mac_len_bytes = strlen(tcase->out.f1)/2; |
| 274 | OSMO_ASSERT(tset->out.mac_len_bytes == 8 || tset->out.mac_len_bytes == 16 || |
| 275 | tset->out.mac_len_bytes == 32); |
| 276 | |
| 277 | osmo_hexparse(tcase->out.f2, tset->out.res, sizeof(tset->out.res)); |
| 278 | tset->out.res_len_bytes = strlen(tcase->out.f2)/2; |
| 279 | OSMO_ASSERT(tset->out.res_len_bytes == 4 || tset->out.res_len_bytes == 8 || |
| 280 | tset->out.res_len_bytes == 16 || tset->out.res_len_bytes == 32); |
| 281 | |
| 282 | osmo_hexparse(tcase->out.f3, tset->out.ck, sizeof(tset->out.ck)); |
| 283 | tset->out.ck_len_bytes = strlen(tcase->out.f3)/2; |
| 284 | OSMO_ASSERT(tset->out.ck_len_bytes == 16 || tset->out.ck_len_bytes == 32); |
| 285 | |
| 286 | osmo_hexparse(tcase->out.f4, tset->out.ik, sizeof(tset->out.ik)); |
| 287 | tset->out.ik_len_bytes = strlen(tcase->out.f4)/2; |
| 288 | OSMO_ASSERT(tset->out.ik_len_bytes == 16 || tset->out.ik_len_bytes == 32); |
| 289 | |
| 290 | osmo_hexparse(tcase->out.f5, tset->out.ak, sizeof(tset->out.ak)); |
| 291 | OSMO_ASSERT(strlen(tcase->out.f5)/2 == 6); |
| 292 | |
| 293 | osmo_hexparse(tcase->out.f5star, tset->out.f5star, sizeof(tset->out.f5star)); |
| 294 | OSMO_ASSERT(strlen(tcase->out.f5star)/2 == 6); |
| 295 | |
| 296 | execute_testset(tset); |
| 297 | } |
| 298 | |
| 299 | int main(int argc, char **argv) |
| 300 | { |
| 301 | #if 0 |
| 302 | for (unsigned int i = 0; i < ARRAY_SIZE(testsets); i++) |
| 303 | execute_testset(&testsets[i]); |
| 304 | #endif |
| 305 | |
| 306 | for (unsigned int i = 0; i < ARRAY_SIZE(testspecs); i++) |
| 307 | execute_testspec(&testspecs[i]); |
| 308 | |
| 309 | } |