15a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* 25a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE 802.1X-2010 Key Hierarchy 35a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * Copyright (c) 2013, Qualcomm Atheros, Inc. 45a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 55a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * This software may be distributed under the terms of the BSD license. 65a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * See README for more details. 75a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 85a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * SAK derivation specified in IEEE Std 802.1X-2010, Clause 6.2 95a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt*/ 105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "utils/includes.h" 125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "utils/common.h" 145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "crypto/md5.h" 155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "crypto/sha1.h" 165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "crypto/aes_wrap.h" 175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "crypto/crypto.h" 185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_key.h" 195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void joint_two_mac(const u8 *mac1, const u8 *mac2, u8 *out) 225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (os_memcmp(mac1, mac2, ETH_ALEN) < 0) { 245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(out, mac1, ETH_ALEN); 255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(out + ETH_ALEN, mac2, ETH_ALEN); 265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } else { 275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(out, mac2, ETH_ALEN); 285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(out + ETH_ALEN, mac1, ETH_ALEN); 295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* IEEE Std 802.1X-2010, 6.2.1 KDF */ 345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int aes_kdf_128(const u8 *kdk, const char *label, const u8 *context, 355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int ctx_bits, int ret_bits, u8 *ret) 365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const int h = 128; 385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const int r = 8; 395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int i, n; 405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int lab_len, ctx_len, ret_len, buf_len; 415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 *buf; 425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt lab_len = os_strlen(label); 445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ctx_len = (ctx_bits + 7) / 8; 455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ret_len = ((ret_bits & 0xffff) + 7) / 8; 465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt buf_len = lab_len + ctx_len + 4; 475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memset(ret, 0, ret_len); 495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt n = (ret_bits + h - 1) / h; 515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (n > ((0x1 << r) - 1)) 525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt buf = os_zalloc(buf_len); 555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (buf == NULL) 565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(buf + 1, label, lab_len); 595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(buf + lab_len + 2, context, ctx_len); 605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt WPA_PUT_BE16(&buf[buf_len - 2], ret_bits); 615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt for (i = 0; i < n; i++) { 635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt buf[0] = (u8) (i + 1); 645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (omac1_aes_128(kdk, buf, buf_len, ret)) { 655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(buf); 665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ret = ret + h / 8; 695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(buf); 715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/********** AES-CMAC-128 **********/ 765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_cak_128bits_aes_cmac 785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 6.2.2 805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * CAK = KDF(Key, Label, mac1 | mac2, CAKlength) 815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_cak_128bits_aes_cmac(const u8 *msk, const u8 *mac1, 835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *mac2, u8 *cak) 845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 context[2 * ETH_ALEN]; 865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt joint_two_mac(mac1, mac2, context); 885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return aes_kdf_128(msk, "IEEE8021 EAP CAK", 895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt context, sizeof(context) * 8, 128, cak); 905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_ckn_128bits_aes_cmac 955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 6.2.2 975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * CKN = KDF(Key, Label, ID | mac1 | mac2, CKNlength) 985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_ckn_128bits_aes_cmac(const u8 *msk, const u8 *mac1, 1005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *mac2, const u8 *sid, 1015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t sid_bytes, u8 *ckn) 1025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int res; 1045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 *context; 1055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t ctx_len = sid_bytes + ETH_ALEN * 2; 1065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt context = os_zalloc(ctx_len); 1085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!context) { 1095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, "MKA-%s: out of memory", __func__); 1105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 1115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 1125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(context, sid, sid_bytes); 1135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt joint_two_mac(mac1, mac2, context + sid_bytes); 1145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = aes_kdf_128(msk, "IEEE8021 EAP CKN", context, ctx_len * 8, 1165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 128, ckn); 1175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(context); 1185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return res; 1195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 1235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kek_128bits_aes_cmac 1245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 1255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 9.3.3 1265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * KEK = KDF(Key, Label, Keyid, KEKLength) 1275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 1285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kek_128bits_aes_cmac(const u8 *cak, const u8 *ckn, 1295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t ckn_bytes, u8 *kek) 1305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 context[16]; 1325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt /* First 16 octets of CKN, with null octets appended to pad if needed */ 1345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memset(context, 0, sizeof(context)); 1355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16); 1365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return aes_kdf_128(cak, "IEEE8021 KEK", context, sizeof(context) * 8, 1385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 128, kek); 1395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 1435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_ick_128bits_aes_cmac 1445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 1455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 9.3.3 1465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ICK = KDF(Key, Label, Keyid, ICKLength) 1475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 1485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_ick_128bits_aes_cmac(const u8 *cak, const u8 *ckn, 1495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t ckn_bytes, u8 *ick) 1505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 context[16]; 1525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt /* First 16 octets of CKN, with null octets appended to pad if needed */ 1545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memset(context, 0, sizeof(context)); 1555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16); 1565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return aes_kdf_128(cak, "IEEE8021 ICK", context, sizeof(context) * 8, 1585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 128, ick); 1595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 1635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_icv_128bits_aes_cmac 1645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 1655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 9.4.1 1665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ICV = AES-CMAC(ICK, M, 128) 1675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 1685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_icv_128bits_aes_cmac(const u8 *ick, const u8 *msg, 1695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t msg_bytes, u8 *icv) 1705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (omac1_aes_128(ick, msg, msg_bytes, icv)) { 1725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, "MKA: omac1_aes_128 failed"); 1735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 1745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 1755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 1765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/** 1805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_sak_128bits_aes_cmac 1815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 1825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE Std 802.1X-2010, 9.8.1 1835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * SAK = KDF(Key, Label, KS-nonce | MI-value list | KN, SAKLength) 1845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 1855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_sak_128bits_aes_cmac(const u8 *cak, const u8 *ctx, 1865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t ctx_bytes, u8 *sak) 1875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return aes_kdf_128(cak, "IEEE8021 SAK", ctx, ctx_bytes * 8, 128, sak); 1895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 190