aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/michael.c75
-rw-r--r--net/mac80211/michael.h4
2 files changed, 44 insertions, 35 deletions
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
index c1e5897fcf7..4e151e0caeb 100644
--- a/net/mac80211/michael.c
+++ b/net/mac80211/michael.c
@@ -13,46 +13,52 @@
13 13
14#include "michael.h" 14#include "michael.h"
15 15
16#define michael_block(l, r) \ 16static void michael_block(struct michael_mic_ctx *mctx, u32 val)
17do { \ 17{
18 r ^= rol32(l, 17); \ 18 mctx->l ^= val;
19 l += r; \ 19 mctx->r ^= rol32(mctx->l, 17);
20 r ^= ((l & 0xff00ff00) >> 8) | ((l & 0x00ff00ff) << 8); \ 20 mctx->l += mctx->r;
21 l += r; \ 21 mctx->r ^= ((mctx->l & 0xff00ff00) >> 8) |
22 r ^= rol32(l, 3); \ 22 ((mctx->l & 0x00ff00ff) << 8);
23 l += r; \ 23 mctx->l += mctx->r;
24 r ^= ror32(l, 2); \ 24 mctx->r ^= rol32(mctx->l, 3);
25 l += r; \ 25 mctx->l += mctx->r;
26} while (0) 26 mctx->r ^= ror32(mctx->l, 2);
27 mctx->l += mctx->r;
28}
29
30static void michael_mic_hdr(struct michael_mic_ctx *mctx,
31 u8 *key, u8 *da, u8 *sa, u8 priority)
32{
33 mctx->l = get_unaligned_le32(key);
34 mctx->r = get_unaligned_le32(key + 4);
35
36 /*
37 * A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC
38 * calculation, but it is _not_ transmitted
39 */
40 michael_block(mctx, get_unaligned_le32(da));
41 michael_block(mctx, get_unaligned_le16(&da[4]) |
42 (get_unaligned_le16(sa) << 16));
43 michael_block(mctx, get_unaligned_le32(&sa[2]));
44 michael_block(mctx, priority);
45}
27 46
28void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, 47void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
29 u8 *data, size_t data_len, u8 *mic) 48 u8 *data, size_t data_len, u8 *mic)
30{ 49{
31 u32 l, r, val; 50 u32 val;
32 size_t block, blocks, left; 51 size_t block, blocks, left;
52 struct michael_mic_ctx mctx;
33 53
34 l = get_unaligned_le32(key); 54 michael_mic_hdr(&mctx, key, da, sa, priority);
35 r = get_unaligned_le32(key + 4);
36
37 /* A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC
38 * calculation, but it is _not_ transmitted */
39 l ^= get_unaligned_le32(da);
40 michael_block(l, r);
41 l ^= get_unaligned_le16(&da[4]) | (get_unaligned_le16(sa) << 16);
42 michael_block(l, r);
43 l ^= get_unaligned_le32(&sa[2]);
44 michael_block(l, r);
45 l ^= priority;
46 michael_block(l, r);
47 55
48 /* Real data */ 56 /* Real data */
49 blocks = data_len / 4; 57 blocks = data_len / 4;
50 left = data_len % 4; 58 left = data_len % 4;
51 59
52 for (block = 0; block < blocks; block++) { 60 for (block = 0; block < blocks; block++)
53 l ^= get_unaligned_le32(&data[block * 4]); 61 michael_block(&mctx, get_unaligned_le32(&data[block * 4]));
54 michael_block(l, r);
55 }
56 62
57 /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make 63 /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make
58 * total length a multiple of 4. */ 64 * total length a multiple of 4. */
@@ -62,11 +68,10 @@ void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
62 left--; 68 left--;
63 val |= data[blocks * 4 + left]; 69 val |= data[blocks * 4 + left];
64 } 70 }
65 l ^= val;
66 michael_block(l, r);
67 /* last block is zero, so l ^ 0 = l */
68 michael_block(l, r);
69 71
70 put_unaligned_le32(l, mic); 72 michael_block(&mctx, val);
71 put_unaligned_le32(r, mic + 4); 73 michael_block(&mctx, 0);
74
75 put_unaligned_le32(mctx.l, mic);
76 put_unaligned_le32(mctx.r, mic + 4);
72} 77}
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
index 2e6aebabeea..7d5707bf884 100644
--- a/net/mac80211/michael.h
+++ b/net/mac80211/michael.h
@@ -14,6 +14,10 @@
14 14
15#define MICHAEL_MIC_LEN 8 15#define MICHAEL_MIC_LEN 8
16 16
17struct michael_mic_ctx {
18 u32 l, r;
19};
20
17void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, 21void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
18 u8 *data, size_t data_len, u8 *mic); 22 u8 *data, size_t data_len, u8 *mic);
19 23