00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <linux/kernel.h>
00011 #include <linux/types.h>
00012 #include <linux/crypto.h>
00013 #include <linux/err.h>
00014 #include <crypto/aes.h>
00015
00016 #include <net/mac80211.h>
00017 #include "key.h"
00018 #include "aes_ccm.h"
00019
00020 static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
00021 {
00022 int i;
00023 u8 *b_0, *aad, *b, *s_0;
00024
00025 b_0 = scratch + 3 * AES_BLOCK_SIZE;
00026 aad = scratch + 4 * AES_BLOCK_SIZE;
00027 b = scratch;
00028 s_0 = scratch + AES_BLOCK_SIZE;
00029
00030 crypto_cipher_encrypt_one(tfm, b, b_0);
00031
00032
00033 for (i = 0; i < AES_BLOCK_SIZE; i++)
00034 aad[i] ^= b[i];
00035 crypto_cipher_encrypt_one(tfm, b, aad);
00036
00037 aad += AES_BLOCK_SIZE;
00038
00039 for (i = 0; i < AES_BLOCK_SIZE; i++)
00040 aad[i] ^= b[i];
00041 crypto_cipher_encrypt_one(tfm, a, aad);
00042
00043
00044 b_0[0] &= 0x07;
00045
00046
00047 b_0[14] = 0;
00048 b_0[15] = 0;
00049 crypto_cipher_encrypt_one(tfm, s_0, b_0);
00050 }
00051
00052
00053 void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
00054 u8 *data, size_t data_len,
00055 u8 *cdata, u8 *mic)
00056 {
00057 int i, j, last_len, num_blocks;
00058 u8 *pos, *cpos, *b, *s_0, *e, *b_0;
00059
00060 b = scratch;
00061 s_0 = scratch + AES_BLOCK_SIZE;
00062 e = scratch + 2 * AES_BLOCK_SIZE;
00063 b_0 = scratch + 3 * AES_BLOCK_SIZE;
00064
00065 num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
00066 last_len = data_len % AES_BLOCK_SIZE;
00067 aes_ccm_prepare(tfm, scratch, b);
00068
00069
00070 pos = data;
00071 cpos = cdata;
00072 for (j = 1; j <= num_blocks; j++) {
00073 int blen = (j == num_blocks && last_len) ?
00074 last_len : AES_BLOCK_SIZE;
00075
00076
00077 for (i = 0; i < blen; i++)
00078 b[i] ^= pos[i];
00079 crypto_cipher_encrypt_one(tfm, b, b);
00080
00081 b_0[14] = (j >> 8) & 0xff;
00082 b_0[15] = j & 0xff;
00083 crypto_cipher_encrypt_one(tfm, e, b_0);
00084 for (i = 0; i < blen; i++)
00085 *cpos++ = *pos++ ^ e[i];
00086 }
00087
00088 for (i = 0; i < CCMP_MIC_LEN; i++)
00089 mic[i] = b[i] ^ s_0[i];
00090 }
00091
00092
00093 int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
00094 u8 *cdata, size_t data_len, u8 *mic, u8 *data)
00095 {
00096 int i, j, last_len, num_blocks;
00097 u8 *pos, *cpos, *b, *s_0, *a, *b_0;
00098
00099 b = scratch;
00100 s_0 = scratch + AES_BLOCK_SIZE;
00101 a = scratch + 2 * AES_BLOCK_SIZE;
00102 b_0 = scratch + 3 * AES_BLOCK_SIZE;
00103
00104 num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
00105 last_len = data_len % AES_BLOCK_SIZE;
00106 aes_ccm_prepare(tfm, scratch, a);
00107
00108
00109 cpos = cdata;
00110 pos = data;
00111 for (j = 1; j <= num_blocks; j++) {
00112 int blen = (j == num_blocks && last_len) ?
00113 last_len : AES_BLOCK_SIZE;
00114
00115
00116 b_0[14] = (j >> 8) & 0xff;
00117 b_0[15] = j & 0xff;
00118 crypto_cipher_encrypt_one(tfm, b, b_0);
00119 for (i = 0; i < blen; i++) {
00120 *pos = *cpos++ ^ b[i];
00121 a[i] ^= *pos++;
00122 }
00123 crypto_cipher_encrypt_one(tfm, a, a);
00124 }
00125
00126 for (i = 0; i < CCMP_MIC_LEN; i++) {
00127 if ((mic[i] ^ s_0[i]) != a[i])
00128 return -1;
00129 }
00130
00131 return 0;
00132 }
00133
00134
00135 struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
00136 {
00137 struct crypto_cipher *tfm;
00138
00139 tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
00140 if (!IS_ERR(tfm))
00141 crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
00142
00143 return tfm;
00144 }
00145
00146
00147 void ieee80211_aes_key_free(struct crypto_cipher *tfm)
00148 {
00149 crypto_free_cipher(tfm);
00150 }