static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */, const u8 *data /* Z */, size_t data_len, u8 *buf, size_t len /* X */) { u8 *opos; size_t i, n, hashlen, left, clen; u8 ibuf[2], hash[16]; const u8 *addr[2]; size_t vlen[2]; hashlen = sizeof(hash); /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */ addr[0] = ibuf; vlen[0] = sizeof(ibuf); addr[1] = data; vlen[1] = data_len; opos = buf; left = len; n = (len + hashlen - 1) / hashlen; for (i = 1; i <= n; i++) { WPA_PUT_BE16(ibuf, i); if (omac1_aes_128_vector(psk, 2, addr, vlen, hash)) return -1; clen = left > hashlen ? hashlen : left; os_memcpy(opos, hash, clen); opos += clen; left -= clen; } return 0; }
int main(int argc, char *argv[]) { u8 kek[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; u8 plain[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; u8 crypt[] = { 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 }; u8 result[24]; int ret = 0; unsigned int i; struct omac1_test_vector *tv; if (aes_wrap(kek, 2, plain, result)) { printf("AES-WRAP-128-128 reported failure\n"); ret++; } if (memcmp(result, crypt, 24) != 0) { printf("AES-WRAP-128-128 failed\n"); ret++; } if (aes_unwrap(kek, 2, crypt, result)) { printf("AES-UNWRAP-128-128 reported failure\n"); ret++; } if (memcmp(result, plain, 16) != 0) { printf("AES-UNWRAP-128-128 failed\n"); ret++; for (i = 0; i < 16; i++) printf(" %02x", result[i]); printf("\n"); } test_aes_perf(); for (i = 0; i < ARRAY_SIZE(test_vectors); i++) { tv = &test_vectors[i]; if (omac1_aes_128(tv->k, tv->msg, tv->msg_len, result) || memcmp(result, tv->tag, 16) != 0) { printf("OMAC1-AES-128 test vector %d failed\n", i); ret++; } if (tv->msg_len > 1) { const u8 *addr[2]; size_t len[2]; addr[0] = tv->msg; len[0] = 1; addr[1] = tv->msg + 1; len[1] = tv->msg_len - 1; if (omac1_aes_128_vector(tv->k, 2, addr, len, result) || memcmp(result, tv->tag, 16) != 0) { printf("OMAC1-AES-128(vector) test vector %d " "failed\n", i); ret++; } } } ret += test_eax(); ret += test_cbc(); ret += test_gcm(); if (ret) printf("FAILED!\n"); return ret; }
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic) { const u8 *addr[9]; size_t len[9]; size_t i, num_elem = 0; u8 zero_mic[16]; if (kck_len != 16) { wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u", (unsigned int) kck_len); return -1; } addr[num_elem] = sta_addr; len[num_elem] = ETH_ALEN; num_elem++; addr[num_elem] = ap_addr; len[num_elem] = ETH_ALEN; num_elem++; addr[num_elem] = &transaction_seqnum; len[num_elem] = 1; num_elem++; if (rsnie) { addr[num_elem] = rsnie; len[num_elem] = rsnie_len; num_elem++; } if (mdie) { addr[num_elem] = mdie; len[num_elem] = mdie_len; num_elem++; } if (ftie) { if (ftie_len < 2 + sizeof(struct rsn_ftie)) return -1; /* IE hdr and mic_control */ addr[num_elem] = ftie; len[num_elem] = 2 + 2; num_elem++; /* MIC field with all zeros */ os_memset(zero_mic, 0, sizeof(zero_mic)); addr[num_elem] = zero_mic; len[num_elem] = sizeof(zero_mic); num_elem++; /* Rest of FTIE */ addr[num_elem] = ftie + 2 + 2 + 16; len[num_elem] = ftie_len - (2 + 2 + 16); num_elem++; } if (ric) { addr[num_elem] = ric; len[num_elem] = ric_len; num_elem++; } for (i = 0; i < num_elem; i++) wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]); if (omac1_aes_128_vector(kck, num_elem, addr, len, mic)) return -1; return 0; }