100-revert_aes_ccm_port.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. --- a/net/mac80211/Kconfig
  2. +++ b/net/mac80211/Kconfig
  3. @@ -5,7 +5,6 @@ config MAC80211
  4. depends on CRYPTO
  5. depends on CRYPTO_ARC4
  6. depends on CRYPTO_AES
  7. - depends on CRYPTO_CCM
  8. depends on CRC32
  9. select BACKPORT_AVERAGE
  10. ---help---
  11. --- a/net/mac80211/aes_ccm.c
  12. +++ b/net/mac80211/aes_ccm.c
  13. @@ -2,8 +2,6 @@
  14. * Copyright 2003-2004, Instant802 Networks, Inc.
  15. * Copyright 2005-2006, Devicescape Software, Inc.
  16. *
  17. - * Rewrite: Copyright (C) 2013 Linaro Ltd <[email protected]>
  18. - *
  19. * This program is free software; you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License version 2 as
  21. * published by the Free Software Foundation.
  22. @@ -19,75 +17,134 @@
  23. #include "key.h"
  24. #include "aes_ccm.h"
  25. -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
  26. - u8 *data, size_t data_len, u8 *mic)
  27. +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
  28. {
  29. - struct scatterlist assoc, pt, ct[2];
  30. - struct {
  31. - struct aead_request req;
  32. - u8 priv[crypto_aead_reqsize(tfm)];
  33. - } aead_req;
  34. -
  35. - memset(&aead_req, 0, sizeof(aead_req));
  36. -
  37. - sg_init_one(&pt, data, data_len);
  38. - sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
  39. - sg_init_table(ct, 2);
  40. - sg_set_buf(&ct[0], data, data_len);
  41. - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
  42. -
  43. - aead_request_set_tfm(&aead_req.req, tfm);
  44. - aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
  45. - aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
  46. + int i;
  47. + u8 *b_0, *aad, *b, *s_0;
  48. - crypto_aead_encrypt(&aead_req.req);
  49. + b_0 = scratch + 3 * AES_BLOCK_SIZE;
  50. + aad = scratch + 4 * AES_BLOCK_SIZE;
  51. + b = scratch;
  52. + s_0 = scratch + AES_BLOCK_SIZE;
  53. +
  54. + crypto_cipher_encrypt_one(tfm, b, b_0);
  55. +
  56. + /* Extra Authenticate-only data (always two AES blocks) */
  57. + for (i = 0; i < AES_BLOCK_SIZE; i++)
  58. + aad[i] ^= b[i];
  59. + crypto_cipher_encrypt_one(tfm, b, aad);
  60. +
  61. + aad += AES_BLOCK_SIZE;
  62. +
  63. + for (i = 0; i < AES_BLOCK_SIZE; i++)
  64. + aad[i] ^= b[i];
  65. + crypto_cipher_encrypt_one(tfm, a, aad);
  66. +
  67. + /* Mask out bits from auth-only-b_0 */
  68. + b_0[0] &= 0x07;
  69. +
  70. + /* S_0 is used to encrypt T (= MIC) */
  71. + b_0[14] = 0;
  72. + b_0[15] = 0;
  73. + crypto_cipher_encrypt_one(tfm, s_0, b_0);
  74. }
  75. -int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
  76. - u8 *data, size_t data_len, u8 *mic)
  77. +
  78. +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
  79. + u8 *data, size_t data_len,
  80. + u8 *cdata, u8 *mic)
  81. {
  82. - struct scatterlist assoc, pt, ct[2];
  83. - struct {
  84. - struct aead_request req;
  85. - u8 priv[crypto_aead_reqsize(tfm)];
  86. - } aead_req;
  87. -
  88. - memset(&aead_req, 0, sizeof(aead_req));
  89. -
  90. - sg_init_one(&pt, data, data_len);
  91. - sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
  92. - sg_init_table(ct, 2);
  93. - sg_set_buf(&ct[0], data, data_len);
  94. - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
  95. -
  96. - aead_request_set_tfm(&aead_req.req, tfm);
  97. - aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
  98. - aead_request_set_crypt(&aead_req.req, ct, &pt,
  99. - data_len + IEEE80211_CCMP_MIC_LEN, b_0);
  100. + int i, j, last_len, num_blocks;
  101. + u8 *pos, *cpos, *b, *s_0, *e, *b_0;
  102. +
  103. + b = scratch;
  104. + s_0 = scratch + AES_BLOCK_SIZE;
  105. + e = scratch + 2 * AES_BLOCK_SIZE;
  106. + b_0 = scratch + 3 * AES_BLOCK_SIZE;
  107. +
  108. + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
  109. + last_len = data_len % AES_BLOCK_SIZE;
  110. + aes_ccm_prepare(tfm, scratch, b);
  111. +
  112. + /* Process payload blocks */
  113. + pos = data;
  114. + cpos = cdata;
  115. + for (j = 1; j <= num_blocks; j++) {
  116. + int blen = (j == num_blocks && last_len) ?
  117. + last_len : AES_BLOCK_SIZE;
  118. +
  119. + /* Authentication followed by encryption */
  120. + for (i = 0; i < blen; i++)
  121. + b[i] ^= pos[i];
  122. + crypto_cipher_encrypt_one(tfm, b, b);
  123. +
  124. + b_0[14] = (j >> 8) & 0xff;
  125. + b_0[15] = j & 0xff;
  126. + crypto_cipher_encrypt_one(tfm, e, b_0);
  127. + for (i = 0; i < blen; i++)
  128. + *cpos++ = *pos++ ^ e[i];
  129. + }
  130. - return crypto_aead_decrypt(&aead_req.req);
  131. + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
  132. + mic[i] = b[i] ^ s_0[i];
  133. }
  134. -struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
  135. +
  136. +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
  137. + u8 *cdata, size_t data_len, u8 *mic, u8 *data)
  138. {
  139. - struct crypto_aead *tfm;
  140. - int err;
  141. + int i, j, last_len, num_blocks;
  142. + u8 *pos, *cpos, *b, *s_0, *a, *b_0;
  143. - tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
  144. - if (IS_ERR(tfm))
  145. - return tfm;
  146. -
  147. - err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
  148. - if (!err)
  149. - err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
  150. - if (!err)
  151. - return tfm;
  152. + b = scratch;
  153. + s_0 = scratch + AES_BLOCK_SIZE;
  154. + a = scratch + 2 * AES_BLOCK_SIZE;
  155. + b_0 = scratch + 3 * AES_BLOCK_SIZE;
  156. +
  157. + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
  158. + last_len = data_len % AES_BLOCK_SIZE;
  159. + aes_ccm_prepare(tfm, scratch, a);
  160. +
  161. + /* Process payload blocks */
  162. + cpos = cdata;
  163. + pos = data;
  164. + for (j = 1; j <= num_blocks; j++) {
  165. + int blen = (j == num_blocks && last_len) ?
  166. + last_len : AES_BLOCK_SIZE;
  167. +
  168. + /* Decryption followed by authentication */
  169. + b_0[14] = (j >> 8) & 0xff;
  170. + b_0[15] = j & 0xff;
  171. + crypto_cipher_encrypt_one(tfm, b, b_0);
  172. + for (i = 0; i < blen; i++) {
  173. + *pos = *cpos++ ^ b[i];
  174. + a[i] ^= *pos++;
  175. + }
  176. + crypto_cipher_encrypt_one(tfm, a, a);
  177. + }
  178. +
  179. + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
  180. + if ((mic[i] ^ s_0[i]) != a[i])
  181. + return -1;
  182. + }
  183. - crypto_free_aead(tfm);
  184. - return ERR_PTR(err);
  185. + return 0;
  186. }
  187. -void ieee80211_aes_key_free(struct crypto_aead *tfm)
  188. +
  189. +struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
  190. +{
  191. + struct crypto_cipher *tfm;
  192. +
  193. + tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
  194. + if (!IS_ERR(tfm))
  195. + crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
  196. +
  197. + return tfm;
  198. +}
  199. +
  200. +
  201. +void ieee80211_aes_key_free(struct crypto_cipher *tfm)
  202. {
  203. - crypto_free_aead(tfm);
  204. + crypto_free_cipher(tfm);
  205. }
  206. --- a/net/mac80211/aes_ccm.h
  207. +++ b/net/mac80211/aes_ccm.h
  208. @@ -12,11 +12,13 @@
  209. #include <linux/crypto.h>
  210. -struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]);
  211. -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
  212. - u8 *data, size_t data_len, u8 *mic);
  213. -int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
  214. - u8 *data, size_t data_len, u8 *mic);
  215. -void ieee80211_aes_key_free(struct crypto_aead *tfm);
  216. +struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
  217. +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
  218. + u8 *data, size_t data_len,
  219. + u8 *cdata, u8 *mic);
  220. +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
  221. + u8 *cdata, size_t data_len,
  222. + u8 *mic, u8 *data);
  223. +void ieee80211_aes_key_free(struct crypto_cipher *tfm);
  224. #endif /* AES_CCM_H */
  225. --- a/net/mac80211/key.h
  226. +++ b/net/mac80211/key.h
  227. @@ -84,7 +84,7 @@ struct ieee80211_key {
  228. * Management frames.
  229. */
  230. u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
  231. - struct crypto_aead *tfm;
  232. + struct crypto_cipher *tfm;
  233. u32 replays; /* dot11RSNAStatsCCMPReplays */
  234. } ccmp;
  235. struct {
  236. --- a/net/mac80211/wpa.c
  237. +++ b/net/mac80211/wpa.c
  238. @@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
  239. }
  240. -static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
  241. +static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
  242. int encrypted)
  243. {
  244. __le16 mask_fc;
  245. int a4_included, mgmt;
  246. u8 qos_tid;
  247. - u16 len_a;
  248. + u8 *b_0, *aad;
  249. + u16 data_len, len_a;
  250. unsigned int hdrlen;
  251. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  252. + memset(scratch, 0, 6 * AES_BLOCK_SIZE);
  253. +
  254. + b_0 = scratch + 3 * AES_BLOCK_SIZE;
  255. + aad = scratch + 4 * AES_BLOCK_SIZE;
  256. +
  257. /*
  258. * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
  259. * Retry, PwrMgt, MoreData; set Protected
  260. @@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s
  261. else
  262. qos_tid = 0;
  263. - /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
  264. - * mode authentication are not allowed to collide, yet both are derived
  265. - * from this vector b_0. We only set L := 1 here to indicate that the
  266. - * data size can be represented in (L+1) bytes. The CCM layer will take
  267. - * care of storing the data length in the top (L+1) bytes and setting
  268. - * and clearing the other bits as is required to derive the two IVs.
  269. - */
  270. - b_0[0] = 0x1;
  271. + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
  272. + if (encrypted)
  273. + data_len -= IEEE80211_CCMP_MIC_LEN;
  274. + /* First block, b_0 */
  275. + b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
  276. /* Nonce: Nonce Flags | A2 | PN
  277. * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
  278. */
  279. b_0[1] = qos_tid | (mgmt << 4);
  280. memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
  281. memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
  282. + /* l(m) */
  283. + put_unaligned_be16(data_len, &b_0[14]);
  284. /* AAD (extra authenticate-only data) / masked 802.11 header
  285. * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
  286. @@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
  287. u8 *pos;
  288. u8 pn[6];
  289. u64 pn64;
  290. - u8 aad[2 * AES_BLOCK_SIZE];
  291. - u8 b_0[AES_BLOCK_SIZE];
  292. + u8 scratch[6 * AES_BLOCK_SIZE];
  293. if (info->control.hw_key &&
  294. !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
  295. @@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
  296. return 0;
  297. pos += IEEE80211_CCMP_HDR_LEN;
  298. - ccmp_special_blocks(skb, pn, b_0, aad, 0);
  299. - ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
  300. - skb_put(skb, IEEE80211_CCMP_MIC_LEN));
  301. + ccmp_special_blocks(skb, pn, scratch, 0);
  302. + ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
  303. + pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
  304. return 0;
  305. }
  306. @@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
  307. }
  308. if (!(status->flag & RX_FLAG_DECRYPTED)) {
  309. - u8 aad[2 * AES_BLOCK_SIZE];
  310. - u8 b_0[AES_BLOCK_SIZE];
  311. + u8 scratch[6 * AES_BLOCK_SIZE];
  312. /* hardware didn't decrypt/verify MIC */
  313. - ccmp_special_blocks(skb, pn, b_0, aad, 1);
  314. + ccmp_special_blocks(skb, pn, scratch, 1);
  315. if (ieee80211_aes_ccm_decrypt(
  316. - key->u.ccmp.tfm, b_0, aad,
  317. + key->u.ccmp.tfm, scratch,
  318. skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
  319. data_len,
  320. - skb->data + skb->len - IEEE80211_CCMP_MIC_LEN))
  321. + skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
  322. + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
  323. return RX_DROP_UNUSABLE;
  324. }