~ubuntu-branches/ubuntu/hardy/linux-backports-modules-2.6.24/hardy-security

« back to all changes in this revision

Viewing changes to updates/wireless/iwlwifi/mac80211/compatible/net/mac80211/aes_ccm.c

  • Committer: Bazaar Package Importer
  • Author(s): , Ben Collins
  • Date: 2008-04-02 06:59:04 UTC
  • Revision ID: james.westby@ubuntu.com-20080402065904-e5knh2gn2hms3xbb
Tags: 2.6.24-14.11
[Ben Collins]

* iwlwifi: Update to iwlwifi-1.2.25 and mac80211-10.0.4
  - LP: #200950
* ubuntu: Slight cleanups to module hiearchy and Makefiles
* mac80211: Enable LED triggers
* iwlwifi: Add LED trigger support (rx and tx only)
  - LP: #176090

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2003-2004, Instant802 Networks, Inc.
 
3
 * Copyright 2005-2006, Devicescape Software, 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
 
 
10
#include <linux/types.h>
 
11
#include <linux/crypto.h>
 
12
#include <linux/err.h>
 
13
#include <asm/scatterlist.h>
 
14
 
 
15
#include <net/mac80211.h>
 
16
#include "ieee80211_key.h"
 
17
#include "aes_ccm.h"
 
18
 
 
19
 
 
20
static void ieee80211_aes_encrypt(struct crypto_cipher *tfm,
 
21
                                  const u8 pt[16], u8 ct[16])
 
22
{
 
23
        crypto_cipher_encrypt_one(tfm, ct, pt);
 
24
}
 
25
 
 
26
 
 
27
static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
 
28
                                   u8 *b, u8 *s_0, u8 *a)
 
29
{
 
30
        int i;
 
31
 
 
32
        ieee80211_aes_encrypt(tfm, b_0, b);
 
33
 
 
34
        /* Extra Authenticate-only data (always two AES blocks) */
 
35
        for (i = 0; i < AES_BLOCK_LEN; i++)
 
36
                aad[i] ^= b[i];
 
37
        ieee80211_aes_encrypt(tfm, aad, b);
 
38
 
 
39
        aad += AES_BLOCK_LEN;
 
40
 
 
41
        for (i = 0; i < AES_BLOCK_LEN; i++)
 
42
                aad[i] ^= b[i];
 
43
        ieee80211_aes_encrypt(tfm, aad, a);
 
44
 
 
45
        /* Mask out bits from auth-only-b_0 */
 
46
        b_0[0] &= 0x07;
 
47
 
 
48
        /* S_0 is used to encrypt T (= MIC) */
 
49
        b_0[14] = 0;
 
50
        b_0[15] = 0;
 
51
        ieee80211_aes_encrypt(tfm, b_0, s_0);
 
52
}
 
53
 
 
54
 
 
55
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 
56
                               u8 *b_0, u8 *aad, u8 *data, size_t data_len,
 
57
                               u8 *cdata, u8 *mic)
 
58
{
 
59
        int i, j, last_len, num_blocks;
 
60
        u8 *pos, *cpos, *b, *s_0, *e;
 
61
 
 
62
        b = scratch;
 
63
        s_0 = scratch + AES_BLOCK_LEN;
 
64
        e = scratch + 2 * AES_BLOCK_LEN;
 
65
 
 
66
        num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
 
67
        last_len = data_len % AES_BLOCK_LEN;
 
68
        aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
 
69
 
 
70
        /* Process payload blocks */
 
71
        pos = data;
 
72
        cpos = cdata;
 
73
        for (j = 1; j <= num_blocks; j++) {
 
74
                int blen = (j == num_blocks && last_len) ?
 
75
                        last_len : AES_BLOCK_LEN;
 
76
 
 
77
                /* Authentication followed by encryption */
 
78
                for (i = 0; i < blen; i++)
 
79
                        b[i] ^= pos[i];
 
80
                ieee80211_aes_encrypt(tfm, b, b);
 
81
 
 
82
                b_0[14] = (j >> 8) & 0xff;
 
83
                b_0[15] = j & 0xff;
 
84
                ieee80211_aes_encrypt(tfm, b_0, e);
 
85
                for (i = 0; i < blen; i++)
 
86
                        *cpos++ = *pos++ ^ e[i];
 
87
        }
 
88
 
 
89
        for (i = 0; i < CCMP_MIC_LEN; i++)
 
90
                mic[i] = b[i] ^ s_0[i];
 
91
}
 
92
 
 
93
 
 
94
int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
 
95
                              u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
 
96
                              u8 *mic, u8 *data)
 
97
{
 
98
        int i, j, last_len, num_blocks;
 
99
        u8 *pos, *cpos, *b, *s_0, *a;
 
100
 
 
101
        b = scratch;
 
102
        s_0 = scratch + AES_BLOCK_LEN;
 
103
        a = scratch + 2 * AES_BLOCK_LEN;
 
104
 
 
105
        num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
 
106
        last_len = data_len % AES_BLOCK_LEN;
 
107
        aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
 
108
 
 
109
        /* Process payload blocks */
 
110
        cpos = cdata;
 
111
        pos = data;
 
112
        for (j = 1; j <= num_blocks; j++) {
 
113
                int blen = (j == num_blocks && last_len) ?
 
114
                        last_len : AES_BLOCK_LEN;
 
115
 
 
116
                /* Decryption followed by authentication */
 
117
                b_0[14] = (j >> 8) & 0xff;
 
118
                b_0[15] = j & 0xff;
 
119
                ieee80211_aes_encrypt(tfm, b_0, b);
 
120
                for (i = 0; i < blen; i++) {
 
121
                        *pos = *cpos++ ^ b[i];
 
122
                        a[i] ^= *pos++;
 
123
                }
 
124
 
 
125
                ieee80211_aes_encrypt(tfm, a, a);
 
126
        }
 
127
 
 
128
        for (i = 0; i < CCMP_MIC_LEN; i++) {
 
129
                if ((mic[i] ^ s_0[i]) != a[i])
 
130
                        return -1;
 
131
        }
 
132
 
 
133
        return 0;
 
134
}
 
135
 
 
136
 
 
137
struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[])
 
138
{
 
139
        struct crypto_cipher *tfm;
 
140
 
 
141
        tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
 
142
        if (IS_ERR(tfm))
 
143
                return NULL;
 
144
 
 
145
        crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
 
146
 
 
147
        return tfm;
 
148
}
 
149
 
 
150
 
 
151
void ieee80211_aes_key_free(struct crypto_cipher *tfm)
 
152
{
 
153
        if (tfm)
 
154
                crypto_free_cipher(tfm);
 
155
}