1/*
2 * IEEE 802.1X-2010 Key Hierarchy
3 * Copyright (c) 2013, Qualcomm Atheros, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * SAK derivation specified in IEEE Std 802.1X-2010, Clause 6.2
9*/
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "crypto/md5.h"
15#include "crypto/sha1.h"
16#include "crypto/aes_wrap.h"
17#include "crypto/crypto.h"
18#include "ieee802_1x_key.h"
19
20
21static void joint_two_mac(const u8 *mac1, const u8 *mac2, u8 *out)
22{
23	if (os_memcmp(mac1, mac2, ETH_ALEN) < 0) {
24		os_memcpy(out, mac1, ETH_ALEN);
25		os_memcpy(out + ETH_ALEN, mac2, ETH_ALEN);
26	} else {
27		os_memcpy(out, mac2, ETH_ALEN);
28		os_memcpy(out + ETH_ALEN, mac1, ETH_ALEN);
29	}
30}
31
32
33/* IEEE Std 802.1X-2010, 6.2.1 KDF */
34static int aes_kdf_128(const u8 *kdk, const char *label, const u8 *context,
35		       int ctx_bits, int ret_bits, u8 *ret)
36{
37	const int h = 128;
38	const int r = 8;
39	int i, n;
40	int lab_len, ctx_len, ret_len, buf_len;
41	u8 *buf;
42
43	lab_len = os_strlen(label);
44	ctx_len = (ctx_bits + 7) / 8;
45	ret_len = ((ret_bits & 0xffff) + 7) / 8;
46	buf_len = lab_len + ctx_len + 4;
47
48	os_memset(ret, 0, ret_len);
49
50	n = (ret_bits + h - 1) / h;
51	if (n > ((0x1 << r) - 1))
52		return -1;
53
54	buf = os_zalloc(buf_len);
55	if (buf == NULL)
56		return -1;
57
58	os_memcpy(buf + 1, label, lab_len);
59	os_memcpy(buf + lab_len + 2, context, ctx_len);
60	WPA_PUT_BE16(&buf[buf_len - 2], ret_bits);
61
62	for (i = 0; i < n; i++) {
63		buf[0] = (u8) (i + 1);
64		if (omac1_aes_128(kdk, buf, buf_len, ret)) {
65			os_free(buf);
66			return -1;
67		}
68		ret = ret + h / 8;
69	}
70	os_free(buf);
71	return 0;
72}
73
74
75/********** AES-CMAC-128 **********/
76/**
77 * ieee802_1x_cak_128bits_aes_cmac
78 *
79 * IEEE Std 802.1X-2010, 6.2.2
80 * CAK = KDF(Key, Label, mac1 | mac2, CAKlength)
81 */
82int ieee802_1x_cak_128bits_aes_cmac(const u8 *msk, const u8 *mac1,
83				    const u8 *mac2, u8 *cak)
84{
85	u8 context[2 * ETH_ALEN];
86
87	joint_two_mac(mac1, mac2, context);
88	return aes_kdf_128(msk, "IEEE8021 EAP CAK",
89			   context, sizeof(context) * 8, 128, cak);
90}
91
92
93/**
94 * ieee802_1x_ckn_128bits_aes_cmac
95 *
96 * IEEE Std 802.1X-2010, 6.2.2
97 * CKN = KDF(Key, Label, ID | mac1 | mac2, CKNlength)
98 */
99int ieee802_1x_ckn_128bits_aes_cmac(const u8 *msk, const u8 *mac1,
100				    const u8 *mac2, const u8 *sid,
101				    size_t sid_bytes, u8 *ckn)
102{
103	int res;
104	u8 *context;
105	size_t ctx_len = sid_bytes + ETH_ALEN * 2;
106
107	context = os_zalloc(ctx_len);
108	if (!context) {
109		wpa_printf(MSG_ERROR, "MKA-%s: out of memory", __func__);
110		return -1;
111	}
112	os_memcpy(context, sid, sid_bytes);
113	joint_two_mac(mac1, mac2, context + sid_bytes);
114
115	res = aes_kdf_128(msk, "IEEE8021 EAP CKN", context, ctx_len * 8,
116			  128, ckn);
117	os_free(context);
118	return res;
119}
120
121
122/**
123 * ieee802_1x_kek_128bits_aes_cmac
124 *
125 * IEEE Std 802.1X-2010, 9.3.3
126 * KEK = KDF(Key, Label, Keyid, KEKLength)
127 */
128int ieee802_1x_kek_128bits_aes_cmac(const u8 *cak, const u8 *ckn,
129				    size_t ckn_bytes, u8 *kek)
130{
131	u8 context[16];
132
133	/* First 16 octets of CKN, with null octets appended to pad if needed */
134	os_memset(context, 0, sizeof(context));
135	os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16);
136
137	return aes_kdf_128(cak, "IEEE8021 KEK", context, sizeof(context) * 8,
138			   128, kek);
139}
140
141
142/**
143 * ieee802_1x_ick_128bits_aes_cmac
144 *
145 * IEEE Std 802.1X-2010, 9.3.3
146 * ICK = KDF(Key, Label, Keyid, ICKLength)
147 */
148int ieee802_1x_ick_128bits_aes_cmac(const u8 *cak, const u8 *ckn,
149				    size_t ckn_bytes, u8 *ick)
150{
151	u8 context[16];
152
153	/* First 16 octets of CKN, with null octets appended to pad if needed */
154	os_memset(context, 0, sizeof(context));
155	os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16);
156
157	return aes_kdf_128(cak, "IEEE8021 ICK", context, sizeof(context) * 8,
158			   128, ick);
159}
160
161
162/**
163 * ieee802_1x_icv_128bits_aes_cmac
164 *
165 * IEEE Std 802.1X-2010, 9.4.1
166 * ICV = AES-CMAC(ICK, M, 128)
167 */
168int ieee802_1x_icv_128bits_aes_cmac(const u8 *ick, const u8 *msg,
169				    size_t msg_bytes, u8 *icv)
170{
171	if (omac1_aes_128(ick, msg, msg_bytes, icv)) {
172		wpa_printf(MSG_ERROR, "MKA: omac1_aes_128 failed");
173		return -1;
174	}
175	return 0;
176}
177
178
179/**
180 * ieee802_1x_sak_128bits_aes_cmac
181 *
182 * IEEE Std 802.1X-2010, 9.8.1
183 * SAK = KDF(Key, Label, KS-nonce | MI-value list | KN, SAKLength)
184 */
185int ieee802_1x_sak_128bits_aes_cmac(const u8 *cak, const u8 *ctx,
186				    size_t ctx_bytes, u8 *sak)
187{
188	return aes_kdf_128(cak, "IEEE8021 SAK", ctx, ctx_bytes * 8, 128, sak);
189}
190