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  
joint_two_mac(const u8 * mac1,const u8 * mac2,u8 * out)21  static 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 */
aes_kdf(const u8 * kdk,size_t kdk_bits,const char * label,const u8 * context,int ctx_bits,int ret_bits,u8 * ret)34  static int aes_kdf(const u8 *kdk, size_t kdk_bits,
35  		   const char *label, const u8 *context,
36  		   int ctx_bits, int ret_bits, u8 *ret)
37  {
38  	const int h = 128;
39  	const int r = 8;
40  	int i, n;
41  	int lab_len, ctx_len, ret_len, buf_len;
42  	u8 *buf;
43  
44  	if (kdk_bits != 128 && kdk_bits != 256)
45  		return -1;
46  
47  	lab_len = os_strlen(label);
48  	ctx_len = (ctx_bits + 7) / 8;
49  	ret_len = ((ret_bits & 0xffff) + 7) / 8;
50  	buf_len = lab_len + ctx_len + 4;
51  
52  	os_memset(ret, 0, ret_len);
53  
54  	n = (ret_bits + h - 1) / h;
55  	if (n > ((0x1 << r) - 1))
56  		return -1;
57  
58  	buf = os_zalloc(buf_len);
59  	if (buf == NULL)
60  		return -1;
61  
62  	os_memcpy(buf + 1, label, lab_len);
63  	os_memcpy(buf + lab_len + 2, context, ctx_len);
64  	WPA_PUT_BE16(&buf[buf_len - 2], ret_bits);
65  
66  	for (i = 0; i < n; i++) {
67  		int res;
68  
69  		buf[0] = (u8) (i + 1);
70  		if (kdk_bits == 128)
71  			res = omac1_aes_128(kdk, buf, buf_len, ret);
72  		else
73  			res = omac1_aes_256(kdk, buf, buf_len, ret);
74  		if (res) {
75  			os_free(buf);
76  			return -1;
77  		}
78  		ret = ret + h / 8;
79  	}
80  	os_free(buf);
81  	return 0;
82  }
83  
84  
85  /**
86   * ieee802_1x_cak_aes_cmac
87   *
88   * IEEE Std 802.1X-2010, 6.2.2
89   * CAK = KDF(Key, Label, mac1 | mac2, CAKlength)
90   */
ieee802_1x_cak_aes_cmac(const u8 * msk,size_t msk_bytes,const u8 * mac1,const u8 * mac2,u8 * cak,size_t cak_bytes)91  int ieee802_1x_cak_aes_cmac(const u8 *msk, size_t msk_bytes, const u8 *mac1,
92  			    const u8 *mac2, u8 *cak, size_t cak_bytes)
93  {
94  	u8 context[2 * ETH_ALEN];
95  
96  	joint_two_mac(mac1, mac2, context);
97  	return aes_kdf(msk, 8 * msk_bytes, "IEEE8021 EAP CAK",
98  		       context, sizeof(context) * 8, 8 * cak_bytes, cak);
99  }
100  
101  
102  /**
103   * ieee802_1x_ckn_aes_cmac
104   *
105   * IEEE Std 802.1X-2010, 6.2.2
106   * CKN = KDF(Key, Label, ID | mac1 | mac2, CKNlength)
107   */
ieee802_1x_ckn_aes_cmac(const u8 * msk,size_t msk_bytes,const u8 * mac1,const u8 * mac2,const u8 * sid,size_t sid_bytes,u8 * ckn)108  int ieee802_1x_ckn_aes_cmac(const u8 *msk, size_t msk_bytes, const u8 *mac1,
109  			    const u8 *mac2, const u8 *sid,
110  			    size_t sid_bytes, u8 *ckn)
111  {
112  	int res;
113  	u8 *context;
114  	size_t ctx_len = sid_bytes + ETH_ALEN * 2;
115  
116  	context = os_zalloc(ctx_len);
117  	if (!context) {
118  		wpa_printf(MSG_ERROR, "MKA-%s: out of memory", __func__);
119  		return -1;
120  	}
121  	os_memcpy(context, sid, sid_bytes);
122  	joint_two_mac(mac1, mac2, context + sid_bytes);
123  
124  	res = aes_kdf(msk, 8 * msk_bytes, "IEEE8021 EAP CKN",
125  		      context, ctx_len * 8, 128, ckn);
126  	os_free(context);
127  	return res;
128  }
129  
130  
131  /**
132   * ieee802_1x_kek_aes_cmac
133   *
134   * IEEE Std 802.1X-2010, 9.3.3
135   * KEK = KDF(Key, Label, Keyid, KEKLength)
136   */
ieee802_1x_kek_aes_cmac(const u8 * cak,size_t cak_bytes,const u8 * ckn,size_t ckn_bytes,u8 * kek,size_t kek_bytes)137  int ieee802_1x_kek_aes_cmac(const u8 *cak, size_t cak_bytes, const u8 *ckn,
138  			    size_t ckn_bytes, u8 *kek, size_t kek_bytes)
139  {
140  	u8 context[16];
141  
142  	/* First 16 octets of CKN, with null octets appended to pad if needed */
143  	os_memset(context, 0, sizeof(context));
144  	os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16);
145  
146  	return aes_kdf(cak, 8 * cak_bytes, "IEEE8021 KEK",
147  		       context, sizeof(context) * 8,
148  		       8 * kek_bytes, kek);
149  }
150  
151  
152  /**
153   * ieee802_1x_ick_aes_cmac
154   *
155   * IEEE Std 802.1X-2010, 9.3.3
156   * ICK = KDF(Key, Label, Keyid, ICKLength)
157   */
ieee802_1x_ick_aes_cmac(const u8 * cak,size_t cak_bytes,const u8 * ckn,size_t ckn_bytes,u8 * ick,size_t ick_bytes)158  int ieee802_1x_ick_aes_cmac(const u8 *cak, size_t cak_bytes, const u8 *ckn,
159  			    size_t ckn_bytes, u8 *ick, size_t ick_bytes)
160  {
161  	u8 context[16];
162  
163  	/* First 16 octets of CKN, with null octets appended to pad if needed */
164  	os_memset(context, 0, sizeof(context));
165  	os_memcpy(context, ckn, (ckn_bytes < 16) ? ckn_bytes : 16);
166  
167  	return aes_kdf(cak, 8 *cak_bytes, "IEEE8021 ICK",
168  		       context, sizeof(context) * 8,
169  		       8 * ick_bytes, ick);
170  }
171  
172  
173  /**
174   * ieee802_1x_icv_aes_cmac
175   *
176   * IEEE Std 802.1X-2010, 9.4.1
177   * ICV = AES-CMAC(ICK, M, 128)
178   */
ieee802_1x_icv_aes_cmac(const u8 * ick,size_t ick_bytes,const u8 * msg,size_t msg_bytes,u8 * icv)179  int ieee802_1x_icv_aes_cmac(const u8 *ick, size_t ick_bytes, const u8 *msg,
180  			    size_t msg_bytes, u8 *icv)
181  {
182  	int res;
183  
184  	if (ick_bytes == 16)
185  		res = omac1_aes_128(ick, msg, msg_bytes, icv);
186  	else if (ick_bytes == 32)
187  		res = omac1_aes_256(ick, msg, msg_bytes, icv);
188  	else
189  		return -1;
190  	if (res) {
191  		wpa_printf(MSG_ERROR,
192  			   "MKA: AES-CMAC failed for ICV calculation");
193  		return -1;
194  	}
195  	return 0;
196  }
197  
198  
199  /**
200   * ieee802_1x_sak_aes_cmac
201   *
202   * IEEE Std 802.1X-2010, 9.8.1
203   * SAK = KDF(Key, Label, KS-nonce | MI-value list | KN, SAKLength)
204   */
ieee802_1x_sak_aes_cmac(const u8 * cak,size_t cak_bytes,const u8 * ctx,size_t ctx_bytes,u8 * sak,size_t sak_bytes)205  int ieee802_1x_sak_aes_cmac(const u8 *cak, size_t cak_bytes, const u8 *ctx,
206  			    size_t ctx_bytes, u8 *sak, size_t sak_bytes)
207  {
208  	return aes_kdf(cak, cak_bytes * 8, "IEEE8021 SAK", ctx, ctx_bytes * 8,
209  		       sak_bytes * 8, sak);
210  }
211