aes_ccm.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2003-2004, Instant802 Networks, Inc.
00003  * Copyright 2005-2006, Devicescape Software, Inc.
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
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         /* Extra Authenticate-only data (always two AES blocks) */
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         /* Mask out bits from auth-only-b_0 */
00044         b_0[0] &= 0x07;
00045 
00046         /* S_0 is used to encrypt T (= MIC) */
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         /* Process payload blocks */
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                 /* Authentication followed by encryption */
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         /* Process payload blocks */
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                 /* Decryption followed by authentication */
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 }


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Fri Jan 3 2014 12:07:54