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 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 */ 34 static 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 */ 82 int 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 */ 99 int 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 */ 128 int 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 */ 148 int 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 */ 168 int 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 */ 185 int 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