0001
0002
0003
0004
0005
0006
0007 #include <crypto/aes.h>
0008 #include <crypto/algapi.h>
0009 #include <crypto/hash.h>
0010 #include <crypto/skcipher.h>
0011
0012 #include "ieee80211_i.h"
0013 #include "aes_cmac.h"
0014 #include "fils_aead.h"
0015
0016 static void gf_mulx(u8 *pad)
0017 {
0018 u64 a = get_unaligned_be64(pad);
0019 u64 b = get_unaligned_be64(pad + 8);
0020
0021 put_unaligned_be64((a << 1) | (b >> 63), pad);
0022 put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8);
0023 }
0024
0025 static int aes_s2v(struct crypto_shash *tfm,
0026 size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
0027 {
0028 u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {};
0029 SHASH_DESC_ON_STACK(desc, tfm);
0030 size_t i;
0031
0032 desc->tfm = tfm;
0033
0034
0035 crypto_shash_digest(desc, tmp, AES_BLOCK_SIZE, d);
0036
0037 for (i = 0; i < num_elem - 1; i++) {
0038
0039 gf_mulx(d);
0040 crypto_shash_digest(desc, addr[i], len[i], tmp);
0041 crypto_xor(d, tmp, AES_BLOCK_SIZE);
0042 }
0043
0044 crypto_shash_init(desc);
0045
0046 if (len[i] >= AES_BLOCK_SIZE) {
0047
0048
0049 crypto_shash_update(desc, addr[i], len[i] - AES_BLOCK_SIZE);
0050 crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE,
0051 AES_BLOCK_SIZE);
0052 } else {
0053
0054
0055 gf_mulx(d);
0056 crypto_xor(d, addr[i], len[i]);
0057 d[len[i]] ^= 0x80;
0058 }
0059
0060 crypto_shash_finup(desc, d, AES_BLOCK_SIZE, v);
0061
0062 return 0;
0063 }
0064
0065
0066 static int aes_siv_encrypt(const u8 *key, size_t key_len,
0067 const u8 *plain, size_t plain_len,
0068 size_t num_elem, const u8 *addr[],
0069 size_t len[], u8 *out)
0070 {
0071 u8 v[AES_BLOCK_SIZE];
0072 struct crypto_shash *tfm;
0073 struct crypto_skcipher *tfm2;
0074 struct skcipher_request *req;
0075 int res;
0076 struct scatterlist src[1], dst[1];
0077 u8 *tmp;
0078
0079 key_len /= 2;
0080
0081 addr[num_elem] = plain;
0082 len[num_elem] = plain_len;
0083 num_elem++;
0084
0085
0086
0087 tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
0088 if (IS_ERR(tfm))
0089 return PTR_ERR(tfm);
0090
0091 res = crypto_shash_setkey(tfm, key, key_len);
0092 if (!res)
0093 res = aes_s2v(tfm, num_elem, addr, len, v);
0094 crypto_free_shash(tfm);
0095 if (res)
0096 return res;
0097
0098
0099
0100
0101 tmp = kmemdup(plain, plain_len, GFP_KERNEL);
0102 if (!tmp)
0103 return -ENOMEM;
0104
0105
0106 memcpy(out, v, AES_BLOCK_SIZE);
0107
0108
0109
0110
0111 v[8] &= 0x7f;
0112 v[12] &= 0x7f;
0113
0114
0115
0116 tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
0117 if (IS_ERR(tfm2)) {
0118 kfree(tmp);
0119 return PTR_ERR(tfm2);
0120 }
0121
0122 res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
0123 if (res)
0124 goto fail;
0125
0126 req = skcipher_request_alloc(tfm2, GFP_KERNEL);
0127 if (!req) {
0128 res = -ENOMEM;
0129 goto fail;
0130 }
0131
0132 sg_init_one(src, tmp, plain_len);
0133 sg_init_one(dst, out + AES_BLOCK_SIZE, plain_len);
0134 skcipher_request_set_crypt(req, src, dst, plain_len, v);
0135 res = crypto_skcipher_encrypt(req);
0136 skcipher_request_free(req);
0137 fail:
0138 kfree(tmp);
0139 crypto_free_skcipher(tfm2);
0140 return res;
0141 }
0142
0143
0144 static int aes_siv_decrypt(const u8 *key, size_t key_len,
0145 const u8 *iv_crypt, size_t iv_c_len,
0146 size_t num_elem, const u8 *addr[], size_t len[],
0147 u8 *out)
0148 {
0149 struct crypto_shash *tfm;
0150 struct crypto_skcipher *tfm2;
0151 struct skcipher_request *req;
0152 struct scatterlist src[1], dst[1];
0153 size_t crypt_len;
0154 int res;
0155 u8 frame_iv[AES_BLOCK_SIZE], iv[AES_BLOCK_SIZE];
0156 u8 check[AES_BLOCK_SIZE];
0157
0158 crypt_len = iv_c_len - AES_BLOCK_SIZE;
0159 key_len /= 2;
0160 addr[num_elem] = out;
0161 len[num_elem] = crypt_len;
0162 num_elem++;
0163
0164 memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
0165 memcpy(frame_iv, iv_crypt, AES_BLOCK_SIZE);
0166
0167
0168
0169
0170 iv[8] &= 0x7f;
0171 iv[12] &= 0x7f;
0172
0173
0174
0175 tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
0176 if (IS_ERR(tfm2))
0177 return PTR_ERR(tfm2);
0178
0179 res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
0180 if (res) {
0181 crypto_free_skcipher(tfm2);
0182 return res;
0183 }
0184
0185 req = skcipher_request_alloc(tfm2, GFP_KERNEL);
0186 if (!req) {
0187 crypto_free_skcipher(tfm2);
0188 return -ENOMEM;
0189 }
0190
0191 sg_init_one(src, iv_crypt + AES_BLOCK_SIZE, crypt_len);
0192 sg_init_one(dst, out, crypt_len);
0193 skcipher_request_set_crypt(req, src, dst, crypt_len, iv);
0194 res = crypto_skcipher_decrypt(req);
0195 skcipher_request_free(req);
0196 crypto_free_skcipher(tfm2);
0197 if (res)
0198 return res;
0199
0200
0201
0202 tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
0203 if (IS_ERR(tfm))
0204 return PTR_ERR(tfm);
0205
0206 res = crypto_shash_setkey(tfm, key, key_len);
0207 if (!res)
0208 res = aes_s2v(tfm, num_elem, addr, len, check);
0209 crypto_free_shash(tfm);
0210 if (res)
0211 return res;
0212 if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0)
0213 return -EINVAL;
0214 return 0;
0215 }
0216
0217 int fils_encrypt_assoc_req(struct sk_buff *skb,
0218 struct ieee80211_mgd_assoc_data *assoc_data)
0219 {
0220 struct ieee80211_mgmt *mgmt = (void *)skb->data;
0221 u8 *capab, *ies, *encr;
0222 const u8 *addr[5 + 1];
0223 const struct element *session;
0224 size_t len[5 + 1];
0225 size_t crypt_len;
0226
0227 if (ieee80211_is_reassoc_req(mgmt->frame_control)) {
0228 capab = (u8 *)&mgmt->u.reassoc_req.capab_info;
0229 ies = mgmt->u.reassoc_req.variable;
0230 } else {
0231 capab = (u8 *)&mgmt->u.assoc_req.capab_info;
0232 ies = mgmt->u.assoc_req.variable;
0233 }
0234
0235 session = cfg80211_find_ext_elem(WLAN_EID_EXT_FILS_SESSION,
0236 ies, skb->data + skb->len - ies);
0237 if (!session || session->datalen != 1 + 8)
0238 return -EINVAL;
0239
0240 encr = (u8 *)session->data + 1 + 8;
0241
0242
0243
0244
0245 addr[0] = mgmt->sa;
0246 len[0] = ETH_ALEN;
0247
0248 addr[1] = mgmt->da;
0249 len[1] = ETH_ALEN;
0250
0251 addr[2] = assoc_data->fils_nonces;
0252 len[2] = FILS_NONCE_LEN;
0253
0254 addr[3] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
0255 len[3] = FILS_NONCE_LEN;
0256
0257
0258
0259 addr[4] = capab;
0260 len[4] = encr - capab;
0261
0262 crypt_len = skb->data + skb->len - encr;
0263 skb_put(skb, AES_BLOCK_SIZE);
0264 return aes_siv_encrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
0265 encr, crypt_len, 5, addr, len, encr);
0266 }
0267
0268 int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
0269 u8 *frame, size_t *frame_len,
0270 struct ieee80211_mgd_assoc_data *assoc_data)
0271 {
0272 struct ieee80211_mgmt *mgmt = (void *)frame;
0273 u8 *capab, *ies, *encr;
0274 const u8 *addr[5 + 1];
0275 const struct element *session;
0276 size_t len[5 + 1];
0277 int res;
0278 size_t crypt_len;
0279
0280 if (*frame_len < 24 + 6)
0281 return -EINVAL;
0282
0283 capab = (u8 *)&mgmt->u.assoc_resp.capab_info;
0284 ies = mgmt->u.assoc_resp.variable;
0285 session = cfg80211_find_ext_elem(WLAN_EID_EXT_FILS_SESSION,
0286 ies, frame + *frame_len - ies);
0287 if (!session || session->datalen != 1 + 8) {
0288 mlme_dbg(sdata,
0289 "No (valid) FILS Session element in (Re)Association Response frame from %pM",
0290 mgmt->sa);
0291 return -EINVAL;
0292 }
0293
0294 encr = (u8 *)session->data + 1 + 8;
0295
0296
0297
0298
0299 addr[0] = mgmt->sa;
0300 len[0] = ETH_ALEN;
0301
0302 addr[1] = mgmt->da;
0303 len[1] = ETH_ALEN;
0304
0305 addr[2] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
0306 len[2] = FILS_NONCE_LEN;
0307
0308 addr[3] = assoc_data->fils_nonces;
0309 len[3] = FILS_NONCE_LEN;
0310
0311
0312
0313 addr[4] = capab;
0314 len[4] = encr - capab;
0315
0316 crypt_len = frame + *frame_len - encr;
0317 if (crypt_len < AES_BLOCK_SIZE) {
0318 mlme_dbg(sdata,
0319 "Not enough room for AES-SIV data after FILS Session element in (Re)Association Response frame from %pM",
0320 mgmt->sa);
0321 return -EINVAL;
0322 }
0323 res = aes_siv_decrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
0324 encr, crypt_len, 5, addr, len, encr);
0325 if (res != 0) {
0326 mlme_dbg(sdata,
0327 "AES-SIV decryption of (Re)Association Response frame from %pM failed",
0328 mgmt->sa);
0329 return res;
0330 }
0331 *frame_len -= AES_BLOCK_SIZE;
0332 return 0;
0333 }