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