1 /*- 2 * Copyright (c) 2004 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * Alternatively, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") version 2 as published by the Free 18 * Software Foundation. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 /* 35 * TKIP test module. 36 */ 37 #include <sys/param.h> 38 #include <sys/kernel.h> 39 #include <sys/systm.h> 40 #include <sys/mbuf.h> 41 #include <sys/module.h> 42 43 #include <sys/socket.h> 44 45 #include <net/if.h> 46 #include <net/if_media.h> 47 48 #include <net80211/ieee80211_var.h> 49 50 /* 51 Key 12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 52 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 34 53 PN 0x000000000001 54 IV 00 20 01 20 00 00 00 00 55 Phase1 bb 58 07 1f 9e 93 b4 38 25 4b 56 Phase2 00 20 01 4c fe 67 be d2 7c 86 7b 1b f8 02 8b 1c 57 */ 58 59 static const u_int8_t test1_key[] = { 60 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 61 0x34, 0x56, 0x78, 0x90, 0x12, 62 63 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, /* TX MIC */ 64 /* 65 * NB: 11i test vector specifies a RX MIC key different 66 * from the TX key. But this doesn't work to enmic, 67 * encrypt, then decrypt, demic. So instead we use 68 * the same key for doing the MIC in each direction. 69 * 70 * XXX need additional vectors to test alternate MIC keys 71 */ 72 #if 0 73 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, /* 11i RX MIC */ 74 #else 75 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, /* TX copy */ 76 #endif 77 }; 78 static const u_int8_t test1_phase1[] = { 79 0xbb, 0x58, 0x07, 0x1f, 0x9e, 0x93, 0xb4, 0x38, 0x25, 0x4b 80 }; 81 static const u_int8_t test1_phase2[] = { 82 0x00, 0x20, 0x01, 0x4c, 0xfe, 0x67, 0xbe, 0xd2, 0x7c, 0x86, 83 0x7b, 0x1b, 0xf8, 0x02, 0x8b, 0x1c, 84 }; 85 86 /* Plaintext MPDU with MIC */ 87 static const u_int8_t test1_plaintext[] = { 88 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07, 89 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02, 90 0xaa,0xaa,0x03,0x00,0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x00,0x40,0x00, 91 0x40,0x01,0xa5,0x55,0xc0,0xa8,0x0a,0x02,0xc0,0xa8,0x0a,0x01,0x08,0x00,0x3a,0xb0, 92 0x00,0x00,0x00,0x00,0xcd,0x4c,0x05,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0a,0x0b, 93 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, 94 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b, 95 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, 96 /* MIC */ 0x68,0x81,0xa3,0xf3,0xd6,0x48,0xd0,0x3c 97 }; 98 99 /* Encrypted MPDU with MIC and ICV */ 100 static const u_int8_t test1_encrypted[] = { 101 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07, 102 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,0x00,0x20,0x01,0x20,0x00,0x00,0x00,0x00, 103 0xc0,0x0e,0x14,0xfc,0xe7,0xcf,0xab,0xc7,0x75,0x47,0xe6,0x66,0xe5,0x7c,0x0d,0xac, 104 0x70,0x4a,0x1e,0x35,0x8a,0x88,0xc1,0x1c,0x8e,0x2e,0x28,0x2e,0x38,0x01,0x02,0x7a, 105 0x46,0x56,0x05,0x5e,0xe9,0x3e,0x9c,0x25,0x47,0x02,0xe9,0x73,0x58,0x05,0xdd,0xb5, 106 0x76,0x9b,0xa7,0x3f,0x1e,0xbb,0x56,0xe8,0x44,0xef,0x91,0x22,0x85,0xd3,0xdd,0x6e, 107 0x54,0x1e,0x82,0x38,0x73,0x55,0x8a,0xdb,0xa0,0x79,0x06,0x8a,0xbd,0x7f,0x7f,0x50, 108 0x95,0x96,0x75,0xac,0xc4,0xb4,0xde,0x9a,0xa9,0x9c,0x05,0xf2,0x89,0xa7,0xc5,0x2f, 109 0xee,0x5b,0xfc,0x14,0xf6,0xf8,0xe5,0xf8 110 }; 111 112 #define TEST(n,name,cipher,keyix,pn) { \ 113 name, IEEE80211_CIPHER_##cipher,keyix, pn##LL, \ 114 test##n##_key, sizeof(test##n##_key), \ 115 test##n##_phase1, sizeof(test##n##_phase1), \ 116 test##n##_phase2, sizeof(test##n##_phase2), \ 117 test##n##_plaintext, sizeof(test##n##_plaintext), \ 118 test##n##_encrypted, sizeof(test##n##_encrypted) \ 119 } 120 121 struct ciphertest { 122 const char *name; 123 int cipher; 124 int keyix; 125 u_int64_t pn; 126 const u_int8_t *key; 127 size_t key_len; 128 const u_int8_t *phase1; 129 size_t phase1_len; 130 const u_int8_t *phase2; 131 size_t phase2_len; 132 const u_int8_t *plaintext; 133 size_t plaintext_len; 134 const u_int8_t *encrypted; 135 size_t encrypted_len; 136 } tkiptests[] = { 137 TEST(1, "TKIP test mpdu 1", TKIP, 0, 0), 138 }; 139 140 struct tkip_ctx { 141 struct ieee80211com *tc_ic; /* for diagnostics */ 142 143 uint16_t tx_ttak[5]; 144 int tx_phase1_done; 145 uint8_t tx_rc4key[16]; 146 147 uint16_t rx_ttak[5]; 148 int rx_phase1_done; 149 uint8_t rx_rc4key[16]; 150 uint64_t rx_rsc; /* held until MIC verified */ 151 }; 152 153 static void 154 dumpdata(const char *tag, const void *p, size_t len) 155 { 156 int i; 157 158 printf("%s: 0x%p len %u", tag, p, len); 159 for (i = 0; i < len; i++) { 160 if ((i % 16) == 0) 161 printf("\n%03d:", i); 162 printf(" %02x", ((const u_int8_t *)p)[i]); 163 } 164 printf("\n"); 165 } 166 167 static void 168 cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen) 169 { 170 int i; 171 172 for (i = 0; i < genlen; i++) 173 if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) { 174 printf("first difference at byte %u\n", i); 175 break; 176 } 177 dumpdata("Generated", gen, genlen); 178 dumpdata("Reference", ref, reflen); 179 } 180 181 static int 182 runtest(struct ieee80211com *ic, struct ciphertest *t) 183 { 184 struct tkip_ctx *ctx; 185 struct ieee80211_key key; 186 struct mbuf *m = NULL; 187 const struct ieee80211_cipher *cip; 188 u_int8_t mac[IEEE80211_ADDR_LEN]; 189 u_int len; 190 191 printf("%s: ", t->name); 192 193 /* 194 * Setup key. 195 */ 196 memset(&key, 0, sizeof(key)); 197 key.wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 198 key.wk_cipher = &ieee80211_cipher_none; 199 if (!ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_TKIP, &key)) { 200 printf("FAIL: ieee80211_crypto_newkey failed\n"); 201 goto bad; 202 } 203 204 memcpy(key.wk_key, t->key, t->key_len); 205 key.wk_keylen = 128/NBBY; 206 key.wk_keyrsc = 0; 207 key.wk_keytsc = t->pn; 208 if (!ieee80211_crypto_setkey(ic, &key, mac)) { 209 printf("FAIL: ieee80211_crypto_setkey failed\n"); 210 goto bad; 211 } 212 213 /* 214 * Craft frame from plaintext data. 215 */ 216 cip = key.wk_cipher; 217 m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR); 218 m->m_data += cip->ic_header; 219 len = t->plaintext_len - IEEE80211_WEP_MICLEN; 220 memcpy(mtod(m, void *), t->plaintext, len); 221 m->m_len = len; 222 m->m_pkthdr.len = m->m_len; 223 224 /* 225 * Add MIC. 226 */ 227 if (!ieee80211_crypto_enmic(ic, &key, m)) { 228 printf("FAIL: tkip enmic failed\n"); 229 goto bad; 230 } 231 /* 232 * Verify: frame length, frame contents. 233 */ 234 if (m->m_pkthdr.len != t->plaintext_len) { 235 printf("FAIL: enmic botch; length mismatch\n"); 236 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 237 t->plaintext, t->plaintext_len); 238 goto bad; 239 } 240 if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) { 241 printf("FAIL: enmic botch\n"); 242 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 243 t->plaintext, t->plaintext_len); 244 goto bad; 245 } 246 /* 247 * Encrypt frame w/ MIC. 248 */ 249 if (!cip->ic_encap(&key, m, t->keyix<<6)) { 250 printf("FAIL: tkip encap failed\n"); 251 goto bad; 252 } 253 /* 254 * Verify: phase1, phase2, frame length, frame contents. 255 */ 256 ctx = key.wk_private; 257 if (memcmp(ctx->tx_ttak, t->phase1, t->phase1_len)) { 258 printf("FAIL: encrypt phase1 botch\n"); 259 cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak), 260 t->phase1, t->phase1_len); 261 goto bad; 262 } else if (memcmp(ctx->tx_rc4key, t->phase2, t->phase2_len)) { 263 printf("FAIL: encrypt phase2 botch\n"); 264 cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key), 265 t->phase2, t->phase2_len); 266 goto bad; 267 } else if (m->m_pkthdr.len != t->encrypted_len) { 268 printf("FAIL: encrypt data length mismatch\n"); 269 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 270 t->encrypted, t->encrypted_len); 271 goto bad; 272 } else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) { 273 printf("FAIL: encrypt data does not compare\n"); 274 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 275 t->encrypted, t->encrypted_len); 276 dumpdata("Plaintext", t->plaintext, t->plaintext_len); 277 goto bad; 278 } 279 280 /* 281 * Decrypt frame. 282 */ 283 if (!cip->ic_decap(&key, m)) { 284 printf("tkip decap failed\n"); 285 /* 286 * Check reason for failure: phase1, phase2, frame data (ICV). 287 */ 288 if (memcmp(ctx->rx_ttak, t->phase1, t->phase1_len)) { 289 printf("FAIL: decrypt phase1 botch\n"); 290 cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak), 291 t->phase1, t->phase1_len); 292 } else if (memcmp(ctx->rx_rc4key, t->phase2, t->phase2_len)) { 293 printf("FAIL: decrypt phase2 botch\n"); 294 cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key), 295 t->phase2, t->phase2_len); 296 } else { 297 printf("FAIL: decrypt data does not compare\n"); 298 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 299 t->plaintext, t->plaintext_len); 300 } 301 goto bad; 302 } 303 /* 304 * Verify: frame length, frame contents. 305 */ 306 if (m->m_pkthdr.len != t->plaintext_len) { 307 printf("FAIL: decap botch; length mismatch\n"); 308 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 309 t->plaintext, t->plaintext_len); 310 goto bad; 311 } 312 if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) { 313 printf("FAIL: decap botch; data does not compare\n"); 314 cmpfail(mtod(m, const void *), m->m_pkthdr.len, 315 t->plaintext, t->plaintext_len); 316 goto bad; 317 } 318 /* 319 * De-MIC decrypted frame. 320 */ 321 if (!ieee80211_crypto_demic(ic, &key, m)) { 322 printf("FAIL: tkip demic failed\n"); 323 goto bad; 324 } 325 /* XXX check frame length and contents... */ 326 printf("PASS\n"); 327 return 1; 328 bad: 329 if (m != NULL) 330 m_freem(m); 331 ieee80211_crypto_delkey(ic, &key); 332 return 0; 333 } 334 335 /* 336 * Module glue. 337 */ 338 339 static int debug = 0; 340 static int tests = -1; 341 342 static int 343 init_crypto_tkip_test(void) 344 { 345 #define N(a) (sizeof(a)/sizeof(a[0])) 346 struct ieee80211com ic; 347 int i, pass, total; 348 349 memset(&ic, 0, sizeof(ic)); 350 if (debug) 351 ic.ic_debug = IEEE80211_MSG_CRYPTO; 352 ieee80211_crypto_attach(&ic); 353 354 pass = 0; 355 total = 0; 356 for (i = 0; i < N(tkiptests); i++) 357 if (tests & (1<<i)) { 358 total++; 359 pass += runtest(&ic, &tkiptests[i]); 360 } 361 printf("%u of %u 802.11i TKIP test vectors passed\n", pass, total); 362 ieee80211_crypto_detach(&ic); 363 return (pass == total ? 0 : -1); 364 #undef N 365 } 366 367 static int 368 test_tkip_modevent(module_t mod, int type, void *unused) 369 { 370 switch (type) { 371 case MOD_LOAD: 372 (void) init_crypto_tkip_test(); 373 return 0; 374 case MOD_UNLOAD: 375 return 0; 376 } 377 return EINVAL; 378 } 379 380 static moduledata_t test_tkip_mod = { 381 "test_tkip", 382 test_tkip_modevent, 383 0 384 }; 385 DECLARE_MODULE(test_tkip, test_tkip_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 386 MODULE_VERSION(test_tkip, 1); 387 MODULE_DEPEND(test_tkip, wlan, 1, 1, 1); 388