Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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