fils_aead.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * FILS AEAD for (Re)Association Request/Response frames
  3. * Copyright 2016, Qualcomm Atheros, Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <crypto/aes.h>
  10. #include <crypto/algapi.h>
  11. #include <crypto/hash.h>
  12. #include <crypto/skcipher.h>
  13. #include "ieee80211_i.h"
  14. #include "aes_cmac.h"
  15. #include "fils_aead.h"
  16. static void gf_mulx(u8 *pad)
  17. {
  18. u64 a = get_unaligned_be64(pad);
  19. u64 b = get_unaligned_be64(pad + 8);
  20. put_unaligned_be64((a << 1) | (b >> 63), pad);
  21. put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8);
  22. }
  23. static int aes_s2v(struct crypto_shash *tfm,
  24. size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
  25. {
  26. u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {};
  27. SHASH_DESC_ON_STACK(desc, tfm);
  28. size_t i;
  29. desc->tfm = tfm;
  30. /* D = AES-CMAC(K, <zero>) */
  31. crypto_shash_digest(desc, tmp, AES_BLOCK_SIZE, d);
  32. for (i = 0; i < num_elem - 1; i++) {
  33. /* D = dbl(D) xor AES_CMAC(K, Si) */
  34. gf_mulx(d); /* dbl */
  35. crypto_shash_digest(desc, addr[i], len[i], tmp);
  36. crypto_xor(d, tmp, AES_BLOCK_SIZE);
  37. }
  38. crypto_shash_init(desc);
  39. if (len[i] >= AES_BLOCK_SIZE) {
  40. /* len(Sn) >= 128 */
  41. /* T = Sn xorend D */
  42. crypto_shash_update(desc, addr[i], len[i] - AES_BLOCK_SIZE);
  43. crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE,
  44. AES_BLOCK_SIZE);
  45. } else {
  46. /* len(Sn) < 128 */
  47. /* T = dbl(D) xor pad(Sn) */
  48. gf_mulx(d); /* dbl */
  49. crypto_xor(d, addr[i], len[i]);
  50. d[len[i]] ^= 0x80;
  51. }
  52. /* V = AES-CMAC(K, T) */
  53. crypto_shash_finup(desc, d, AES_BLOCK_SIZE, v);
  54. return 0;
  55. }
  56. /* Note: addr[] and len[] needs to have one extra slot at the end. */
  57. static int aes_siv_encrypt(const u8 *key, size_t key_len,
  58. const u8 *plain, size_t plain_len,
  59. size_t num_elem, const u8 *addr[],
  60. size_t len[], u8 *out)
  61. {
  62. u8 v[AES_BLOCK_SIZE];
  63. struct crypto_shash *tfm;
  64. struct crypto_skcipher *tfm2;
  65. struct skcipher_request *req;
  66. int res;
  67. struct scatterlist src[1], dst[1];
  68. u8 *tmp;
  69. key_len /= 2; /* S2V key || CTR key */
  70. addr[num_elem] = plain;
  71. len[num_elem] = plain_len;
  72. num_elem++;
  73. /* S2V */
  74. tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
  75. if (IS_ERR(tfm))
  76. return PTR_ERR(tfm);
  77. /* K1 for S2V */
  78. res = crypto_shash_setkey(tfm, key, key_len);
  79. if (!res)
  80. res = aes_s2v(tfm, num_elem, addr, len, v);
  81. crypto_free_shash(tfm);
  82. if (res)
  83. return res;
  84. /* Use a temporary buffer of the plaintext to handle need for
  85. * overwriting this during AES-CTR.
  86. */
  87. tmp = kmemdup(plain, plain_len, GFP_KERNEL);
  88. if (!tmp)
  89. return -ENOMEM;
  90. /* IV for CTR before encrypted data */
  91. memcpy(out, v, AES_BLOCK_SIZE);
  92. /* Synthetic IV to be used as the initial counter in CTR:
  93. * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
  94. */
  95. v[8] &= 0x7f;
  96. v[12] &= 0x7f;
  97. /* CTR */
  98. tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
  99. if (IS_ERR(tfm2)) {
  100. kfree(tmp);
  101. return PTR_ERR(tfm2);
  102. }
  103. /* K2 for CTR */
  104. res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
  105. if (res)
  106. goto fail;
  107. req = skcipher_request_alloc(tfm2, GFP_KERNEL);
  108. if (!req) {
  109. res = -ENOMEM;
  110. goto fail;
  111. }
  112. sg_init_one(src, tmp, plain_len);
  113. sg_init_one(dst, out + AES_BLOCK_SIZE, plain_len);
  114. skcipher_request_set_crypt(req, src, dst, plain_len, v);
  115. res = crypto_skcipher_encrypt(req);
  116. skcipher_request_free(req);
  117. fail:
  118. kfree(tmp);
  119. crypto_free_skcipher(tfm2);
  120. return res;
  121. }
  122. /* Note: addr[] and len[] needs to have one extra slot at the end. */
  123. static int aes_siv_decrypt(const u8 *key, size_t key_len,
  124. const u8 *iv_crypt, size_t iv_c_len,
  125. size_t num_elem, const u8 *addr[], size_t len[],
  126. u8 *out)
  127. {
  128. struct crypto_shash *tfm;
  129. struct crypto_skcipher *tfm2;
  130. struct skcipher_request *req;
  131. struct scatterlist src[1], dst[1];
  132. size_t crypt_len;
  133. int res;
  134. u8 frame_iv[AES_BLOCK_SIZE], iv[AES_BLOCK_SIZE];
  135. u8 check[AES_BLOCK_SIZE];
  136. crypt_len = iv_c_len - AES_BLOCK_SIZE;
  137. key_len /= 2; /* S2V key || CTR key */
  138. addr[num_elem] = out;
  139. len[num_elem] = crypt_len;
  140. num_elem++;
  141. memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
  142. memcpy(frame_iv, iv_crypt, AES_BLOCK_SIZE);
  143. /* Synthetic IV to be used as the initial counter in CTR:
  144. * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
  145. */
  146. iv[8] &= 0x7f;
  147. iv[12] &= 0x7f;
  148. /* CTR */
  149. tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
  150. if (IS_ERR(tfm2))
  151. return PTR_ERR(tfm2);
  152. /* K2 for CTR */
  153. res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
  154. if (res) {
  155. crypto_free_skcipher(tfm2);
  156. return res;
  157. }
  158. req = skcipher_request_alloc(tfm2, GFP_KERNEL);
  159. if (!req) {
  160. crypto_free_skcipher(tfm2);
  161. return -ENOMEM;
  162. }
  163. sg_init_one(src, iv_crypt + AES_BLOCK_SIZE, crypt_len);
  164. sg_init_one(dst, out, crypt_len);
  165. skcipher_request_set_crypt(req, src, dst, crypt_len, iv);
  166. res = crypto_skcipher_decrypt(req);
  167. skcipher_request_free(req);
  168. crypto_free_skcipher(tfm2);
  169. if (res)
  170. return res;
  171. /* S2V */
  172. tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
  173. if (IS_ERR(tfm))
  174. return PTR_ERR(tfm);
  175. /* K1 for S2V */
  176. res = crypto_shash_setkey(tfm, key, key_len);
  177. if (!res)
  178. res = aes_s2v(tfm, num_elem, addr, len, check);
  179. crypto_free_shash(tfm);
  180. if (res)
  181. return res;
  182. if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0)
  183. return -EINVAL;
  184. return 0;
  185. }
  186. int fils_encrypt_assoc_req(struct sk_buff *skb,
  187. struct ieee80211_mgd_assoc_data *assoc_data)
  188. {
  189. struct ieee80211_mgmt *mgmt = (void *)skb->data;
  190. u8 *capab, *ies, *encr;
  191. const u8 *addr[5 + 1], *session;
  192. size_t len[5 + 1];
  193. size_t crypt_len;
  194. if (ieee80211_is_reassoc_req(mgmt->frame_control)) {
  195. capab = (u8 *)&mgmt->u.reassoc_req.capab_info;
  196. ies = mgmt->u.reassoc_req.variable;
  197. } else {
  198. capab = (u8 *)&mgmt->u.assoc_req.capab_info;
  199. ies = mgmt->u.assoc_req.variable;
  200. }
  201. session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
  202. ies, skb->data + skb->len - ies);
  203. if (!session || session[1] != 1 + 8)
  204. return -EINVAL;
  205. /* encrypt after FILS Session element */
  206. encr = (u8 *)session + 2 + 1 + 8;
  207. /* AES-SIV AAD vectors */
  208. /* The STA's MAC address */
  209. addr[0] = mgmt->sa;
  210. len[0] = ETH_ALEN;
  211. /* The AP's BSSID */
  212. addr[1] = mgmt->da;
  213. len[1] = ETH_ALEN;
  214. /* The STA's nonce */
  215. addr[2] = assoc_data->fils_nonces;
  216. len[2] = FILS_NONCE_LEN;
  217. /* The AP's nonce */
  218. addr[3] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
  219. len[3] = FILS_NONCE_LEN;
  220. /* The (Re)Association Request frame from the Capability Information
  221. * field to the FILS Session element (both inclusive).
  222. */
  223. addr[4] = capab;
  224. len[4] = encr - capab;
  225. crypt_len = skb->data + skb->len - encr;
  226. skb_put(skb, AES_BLOCK_SIZE);
  227. return aes_siv_encrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
  228. encr, crypt_len, 5, addr, len, encr);
  229. }
  230. int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
  231. u8 *frame, size_t *frame_len,
  232. struct ieee80211_mgd_assoc_data *assoc_data)
  233. {
  234. struct ieee80211_mgmt *mgmt = (void *)frame;
  235. u8 *capab, *ies, *encr;
  236. const u8 *addr[5 + 1], *session;
  237. size_t len[5 + 1];
  238. int res;
  239. size_t crypt_len;
  240. if (*frame_len < 24 + 6)
  241. return -EINVAL;
  242. capab = (u8 *)&mgmt->u.assoc_resp.capab_info;
  243. ies = mgmt->u.assoc_resp.variable;
  244. session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
  245. ies, frame + *frame_len - ies);
  246. if (!session || session[1] != 1 + 8) {
  247. mlme_dbg(sdata,
  248. "No (valid) FILS Session element in (Re)Association Response frame from %pM",
  249. mgmt->sa);
  250. return -EINVAL;
  251. }
  252. /* decrypt after FILS Session element */
  253. encr = (u8 *)session + 2 + 1 + 8;
  254. /* AES-SIV AAD vectors */
  255. /* The AP's BSSID */
  256. addr[0] = mgmt->sa;
  257. len[0] = ETH_ALEN;
  258. /* The STA's MAC address */
  259. addr[1] = mgmt->da;
  260. len[1] = ETH_ALEN;
  261. /* The AP's nonce */
  262. addr[2] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
  263. len[2] = FILS_NONCE_LEN;
  264. /* The STA's nonce */
  265. addr[3] = assoc_data->fils_nonces;
  266. len[3] = FILS_NONCE_LEN;
  267. /* The (Re)Association Response frame from the Capability Information
  268. * field to the FILS Session element (both inclusive).
  269. */
  270. addr[4] = capab;
  271. len[4] = encr - capab;
  272. crypt_len = frame + *frame_len - encr;
  273. if (crypt_len < AES_BLOCK_SIZE) {
  274. mlme_dbg(sdata,
  275. "Not enough room for AES-SIV data after FILS Session element in (Re)Association Response frame from %pM",
  276. mgmt->sa);
  277. return -EINVAL;
  278. }
  279. res = aes_siv_decrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
  280. encr, crypt_len, 5, addr, len, encr);
  281. if (res != 0) {
  282. mlme_dbg(sdata,
  283. "AES-SIV decryption of (Re)Association Response frame from %pM failed",
  284. mgmt->sa);
  285. return res;
  286. }
  287. *frame_len -= AES_BLOCK_SIZE;
  288. return 0;
  289. }