aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/wusbcore/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/wusbcore/crypto.c')
-rw-r--r--drivers/usb/wusbcore/crypto.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c
index 79b2b628066d..79451f7ef1b7 100644
--- a/drivers/usb/wusbcore/crypto.c
+++ b/drivers/usb/wusbcore/crypto.c
@@ -133,6 +133,13 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
133 bo[itr] = bi1[itr] ^ bi2[itr]; 133 bo[itr] = bi1[itr] ^ bi2[itr];
134} 134}
135 135
136/* Scratch space for MAC calculations. */
137struct wusb_mac_scratch {
138 struct aes_ccm_b0 b0;
139 struct aes_ccm_b1 b1;
140 struct aes_ccm_a ax;
141};
142
136/* 143/*
137 * CC-MAC function WUSB1.0[6.5] 144 * CC-MAC function WUSB1.0[6.5]
138 * 145 *
@@ -197,16 +204,15 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
197 * what sg[4] is for. Maybe there is a smarter way to do this. 204 * what sg[4] is for. Maybe there is a smarter way to do this.
198 */ 205 */
199static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, 206static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
200 struct crypto_cipher *tfm_aes, void *mic, 207 struct crypto_cipher *tfm_aes,
208 struct wusb_mac_scratch *scratch,
209 void *mic,
201 const struct aes_ccm_nonce *n, 210 const struct aes_ccm_nonce *n,
202 const struct aes_ccm_label *a, const void *b, 211 const struct aes_ccm_label *a, const void *b,
203 size_t blen) 212 size_t blen)
204{ 213{
205 int result = 0; 214 int result = 0;
206 SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc); 215 SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc);
207 struct aes_ccm_b0 b0;
208 struct aes_ccm_b1 b1;
209 struct aes_ccm_a ax;
210 struct scatterlist sg[4], sg_dst; 216 struct scatterlist sg[4], sg_dst;
211 void *dst_buf; 217 void *dst_buf;
212 size_t dst_size; 218 size_t dst_size;
@@ -218,16 +224,17 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
218 * These checks should be compile time optimized out 224 * These checks should be compile time optimized out
219 * ensure @a fills b1's mac_header and following fields 225 * ensure @a fills b1's mac_header and following fields
220 */ 226 */
221 WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la)); 227 WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la));
222 WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block)); 228 WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block));
223 WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block)); 229 WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block));
224 WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block)); 230 WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block));
225 231
226 result = -ENOMEM; 232 result = -ENOMEM;
227 zero_padding = blen % sizeof(struct aes_ccm_block); 233 zero_padding = blen % sizeof(struct aes_ccm_block);
228 if (zero_padding) 234 if (zero_padding)
229 zero_padding = sizeof(struct aes_ccm_block) - zero_padding; 235 zero_padding = sizeof(struct aes_ccm_block) - zero_padding;
230 dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding; 236 dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) +
237 zero_padding;
231 dst_buf = kzalloc(dst_size, GFP_KERNEL); 238 dst_buf = kzalloc(dst_size, GFP_KERNEL);
232 if (!dst_buf) 239 if (!dst_buf)
233 goto error_dst_buf; 240 goto error_dst_buf;
@@ -235,9 +242,9 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
235 memset(iv, 0, sizeof(iv)); 242 memset(iv, 0, sizeof(iv));
236 243
237 /* Setup B0 */ 244 /* Setup B0 */
238 b0.flags = 0x59; /* Format B0 */ 245 scratch->b0.flags = 0x59; /* Format B0 */
239 b0.ccm_nonce = *n; 246 scratch->b0.ccm_nonce = *n;
240 b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */ 247 scratch->b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */
241 248
242 /* Setup B1 249 /* Setup B1
243 * 250 *
@@ -246,12 +253,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
246 * 14'--after clarification, it means to use A's contents 253 * 14'--after clarification, it means to use A's contents
247 * for MAC Header, EO, sec reserved and padding. 254 * for MAC Header, EO, sec reserved and padding.
248 */ 255 */
249 b1.la = cpu_to_be16(blen + 14); 256 scratch->b1.la = cpu_to_be16(blen + 14);
250 memcpy(&b1.mac_header, a, sizeof(*a)); 257 memcpy(&scratch->b1.mac_header, a, sizeof(*a));
251 258
252 sg_init_table(sg, ARRAY_SIZE(sg)); 259 sg_init_table(sg, ARRAY_SIZE(sg));
253 sg_set_buf(&sg[0], &b0, sizeof(b0)); 260 sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0));
254 sg_set_buf(&sg[1], &b1, sizeof(b1)); 261 sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1));
255 sg_set_buf(&sg[2], b, blen); 262 sg_set_buf(&sg[2], b, blen);
256 /* 0 if well behaved :) */ 263 /* 0 if well behaved :) */
257 sg_set_buf(&sg[3], bzero, zero_padding); 264 sg_set_buf(&sg[3], bzero, zero_padding);
@@ -276,11 +283,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
276 * POS Crypto API: size is assumed to be AES's block size. 283 * POS Crypto API: size is assumed to be AES's block size.
277 * Thanks for documenting it -- tip taken from airo.c 284 * Thanks for documenting it -- tip taken from airo.c
278 */ 285 */
279 ax.flags = 0x01; /* as per WUSB 1.0 spec */ 286 scratch->ax.flags = 0x01; /* as per WUSB 1.0 spec */
280 ax.ccm_nonce = *n; 287 scratch->ax.ccm_nonce = *n;
281 ax.counter = 0; 288 scratch->ax.counter = 0;
282 crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); 289 crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax,
283 bytewise_xor(mic, &ax, iv, 8); 290 (void *)&scratch->ax);
291 bytewise_xor(mic, &scratch->ax, iv, 8);
284 result = 8; 292 result = 8;
285error_cbc_crypt: 293error_cbc_crypt:
286 kfree(dst_buf); 294 kfree(dst_buf);
@@ -303,6 +311,7 @@ ssize_t wusb_prf(void *out, size_t out_size,
303 struct aes_ccm_nonce n = *_n; 311 struct aes_ccm_nonce n = *_n;
304 struct crypto_skcipher *tfm_cbc; 312 struct crypto_skcipher *tfm_cbc;
305 struct crypto_cipher *tfm_aes; 313 struct crypto_cipher *tfm_aes;
314 struct wusb_mac_scratch *scratch;
306 u64 sfn = 0; 315 u64 sfn = 0;
307 __le64 sfn_le; 316 __le64 sfn_le;
308 317
@@ -329,17 +338,25 @@ ssize_t wusb_prf(void *out, size_t out_size,
329 printk(KERN_ERR "E: can't set AES key: %d\n", (int)result); 338 printk(KERN_ERR "E: can't set AES key: %d\n", (int)result);
330 goto error_setkey_aes; 339 goto error_setkey_aes;
331 } 340 }
341 scratch = kmalloc(sizeof(*scratch), GFP_KERNEL);
342 if (!scratch) {
343 result = -ENOMEM;
344 goto error_alloc_scratch;
345 }
332 346
333 for (bitr = 0; bitr < (len + 63) / 64; bitr++) { 347 for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
334 sfn_le = cpu_to_le64(sfn++); 348 sfn_le = cpu_to_le64(sfn++);
335 memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */ 349 memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */
336 result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes, 350 result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes,
337 &n, a, b, blen); 351 &n, a, b, blen);
338 if (result < 0) 352 if (result < 0)
339 goto error_ccm_mac; 353 goto error_ccm_mac;
340 bytes += result; 354 bytes += result;
341 } 355 }
342 result = bytes; 356 result = bytes;
357
358 kfree(scratch);
359error_alloc_scratch:
343error_ccm_mac: 360error_ccm_mac:
344error_setkey_aes: 361error_setkey_aes:
345 crypto_free_cipher(tfm_aes); 362 crypto_free_cipher(tfm_aes);