Skip to content

Commit ae748b9

Browse files
Ard Biesheuvelgregkh
Ard Biesheuvel
authored andcommittedJun 18, 2019
wusb: switch to cbcmac transform
The wusb code takes a very peculiar approach at implementing CBC-MAC, by using plain CBC into a scratch buffer, and taking the output IV as the MAC. We can clean up this code substantially by switching to the cbcmac shash, as exposed by the CCM template. To ensure that the module is loaded on demand, add the cbcmac template name as a module alias. Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b640990 commit ae748b9

File tree

3 files changed

+48
-130
lines changed

3 files changed

+48
-130
lines changed
 

‎crypto/ccm.c

+1
Original file line numberDiff line numberDiff line change
@@ -1009,3 +1009,4 @@ MODULE_DESCRIPTION("Counter with CBC MAC");
10091009
MODULE_ALIAS_CRYPTO("ccm_base");
10101010
MODULE_ALIAS_CRYPTO("rfc4309");
10111011
MODULE_ALIAS_CRYPTO("ccm");
1012+
MODULE_ALIAS_CRYPTO("cbcmac");

‎drivers/usb/wusbcore/Kconfig

+3-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
config USB_WUSB
66
tristate "Enable Wireless USB extensions"
77
depends on UWB
8-
select CRYPTO
9-
select CRYPTO_BLKCIPHER
10-
select CRYPTO_CBC
11-
select CRYPTO_MANAGER
12-
select CRYPTO_AES
8+
select CRYPTO
9+
select CRYPTO_AES
10+
select CRYPTO_CCM
1311
help
1412
Enable the host-side support for Wireless USB.
1513

‎drivers/usb/wusbcore/crypto.c

+44-125
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
* funneled through AES are...16 bytes in size!
3232
*/
3333

34+
#include <crypto/aes.h>
35+
#include <crypto/algapi.h>
36+
#include <crypto/hash.h>
3437
#include <crypto/skcipher.h>
3538
#include <linux/crypto.h>
3639
#include <linux/module.h>
@@ -109,16 +112,6 @@ struct aes_ccm_a {
109112
__be16 counter; /* Value of x */
110113
} __attribute__((packed));
111114

112-
static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
113-
size_t size)
114-
{
115-
u8 *bo = _bo;
116-
const u8 *bi1 = _bi1, *bi2 = _bi2;
117-
size_t itr;
118-
for (itr = 0; itr < size; itr++)
119-
bo[itr] = bi1[itr] ^ bi2[itr];
120-
}
121-
122115
/* Scratch space for MAC calculations. */
123116
struct wusb_mac_scratch {
124117
struct aes_ccm_b0 b0;
@@ -150,8 +143,7 @@ struct wusb_mac_scratch {
150143
* @a: ASCII string, 14 bytes long (I guess zero padded if needed;
151144
* we use exactly 14 bytes).
152145
*
153-
* @b: data stream to be processed; cannot be a global or const local
154-
* (will confuse the scatterlists)
146+
* @b: data stream to be processed
155147
*
156148
* @blen: size of b...
157149
*
@@ -160,16 +152,10 @@ struct wusb_mac_scratch {
160152
* @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we
161153
* take the payload and divide it in blocks (16 bytes), xor them with
162154
* the previous crypto result (16 bytes) and crypt it, repeat the next
163-
* block with the output of the previous one, rinse wash (I guess this
164-
* is what AES CBC mode means...but I truly have no idea). So we use
165-
* the CBC(AES) blkcipher, that does precisely that. The IV (Initial
155+
* block with the output of the previous one, rinse wash. So we use
156+
* the CBC-MAC(AES) shash, that does precisely that. The IV (Initial
166157
* Vector) is 16 bytes and is set to zero, so
167158
*
168-
* See rfc3610. Linux crypto has a CBC implementation, but the
169-
* documentation is scarce, to say the least, and the example code is
170-
* so intricated that is difficult to understand how things work. Most
171-
* of this is guess work -- bite me.
172-
*
173159
* (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and
174160
* using the 14 bytes of @a to fill up
175161
* b1.{mac_header,e0,security_reserved,padding}.
@@ -189,44 +175,24 @@ struct wusb_mac_scratch {
189175
* NOTE: blen is not aligned to a block size, we'll pad zeros, that's
190176
* what sg[4] is for. Maybe there is a smarter way to do this.
191177
*/
192-
static int wusb_ccm_mac(struct crypto_sync_skcipher *tfm_cbc,
193-
struct crypto_cipher *tfm_aes,
178+
static int wusb_ccm_mac(struct crypto_shash *tfm_cbcmac,
194179
struct wusb_mac_scratch *scratch,
195180
void *mic,
196181
const struct aes_ccm_nonce *n,
197182
const struct aes_ccm_label *a, const void *b,
198183
size_t blen)
199184
{
200-
int result = 0;
201-
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc);
202-
struct scatterlist sg[4], sg_dst;
203-
void *dst_buf;
204-
size_t dst_size;
205-
u8 *iv;
206-
size_t zero_padding;
185+
SHASH_DESC_ON_STACK(desc, tfm_cbcmac);
186+
u8 iv[AES_BLOCK_SIZE];
207187

208188
/*
209189
* These checks should be compile time optimized out
210190
* ensure @a fills b1's mac_header and following fields
211191
*/
212-
WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la));
213-
WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block));
214-
WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block));
215-
WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block));
216-
217-
result = -ENOMEM;
218-
zero_padding = blen % sizeof(struct aes_ccm_block);
219-
if (zero_padding)
220-
zero_padding = sizeof(struct aes_ccm_block) - zero_padding;
221-
dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) +
222-
zero_padding;
223-
dst_buf = kzalloc(dst_size, GFP_KERNEL);
224-
if (!dst_buf)
225-
goto error_dst_buf;
226-
227-
iv = kzalloc(crypto_sync_skcipher_ivsize(tfm_cbc), GFP_KERNEL);
228-
if (!iv)
229-
goto error_iv;
192+
BUILD_BUG_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la));
193+
BUILD_BUG_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block));
194+
BUILD_BUG_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block));
195+
BUILD_BUG_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block));
230196

231197
/* Setup B0 */
232198
scratch->b0.flags = 0x59; /* Format B0 */
@@ -243,46 +209,28 @@ static int wusb_ccm_mac(struct crypto_sync_skcipher *tfm_cbc,
243209
scratch->b1.la = cpu_to_be16(blen + 14);
244210
memcpy(&scratch->b1.mac_header, a, sizeof(*a));
245211

246-
sg_init_table(sg, ARRAY_SIZE(sg));
247-
sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0));
248-
sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1));
249-
sg_set_buf(&sg[2], b, blen);
250-
/* 0 if well behaved :) */
251-
sg_set_page(&sg[3], ZERO_PAGE(0), zero_padding, 0);
252-
sg_init_one(&sg_dst, dst_buf, dst_size);
253-
254-
skcipher_request_set_sync_tfm(req, tfm_cbc);
255-
skcipher_request_set_callback(req, 0, NULL, NULL);
256-
skcipher_request_set_crypt(req, sg, &sg_dst, dst_size, iv);
257-
result = crypto_skcipher_encrypt(req);
258-
skcipher_request_zero(req);
259-
if (result < 0) {
260-
printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n",
261-
result);
262-
goto error_cbc_crypt;
263-
}
212+
desc->tfm = tfm_cbcmac;
213+
crypto_shash_init(desc);
214+
crypto_shash_update(desc, (u8 *)&scratch->b0, sizeof(scratch->b0) +
215+
sizeof(scratch->b1));
216+
crypto_shash_finup(desc, b, blen, iv);
264217

265218
/* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5]
266219
* The procedure is to AES crypt the A0 block and XOR the MIC
267220
* Tag against it; we only do the first 8 bytes and place it
268221
* directly in the destination buffer.
269-
*
270-
* POS Crypto API: size is assumed to be AES's block size.
271-
* Thanks for documenting it -- tip taken from airo.c
272222
*/
273223
scratch->ax.flags = 0x01; /* as per WUSB 1.0 spec */
274224
scratch->ax.ccm_nonce = *n;
275225
scratch->ax.counter = 0;
276-
crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax,
277-
(void *)&scratch->ax);
278-
bytewise_xor(mic, &scratch->ax, iv, 8);
279-
result = 8;
280-
error_cbc_crypt:
281-
kfree(iv);
282-
error_iv:
283-
kfree(dst_buf);
284-
error_dst_buf:
285-
return result;
226+
227+
/* reuse the CBC-MAC transform to perform the single block encryption */
228+
crypto_shash_digest(desc, (u8 *)&scratch->ax, sizeof(scratch->ax),
229+
(u8 *)&scratch->ax);
230+
231+
crypto_xor_cpy(mic, (u8 *)&scratch->ax, iv, 8);
232+
233+
return 8;
286234
}
287235

288236
/*
@@ -298,61 +246,39 @@ ssize_t wusb_prf(void *out, size_t out_size,
298246
{
299247
ssize_t result, bytes = 0, bitr;
300248
struct aes_ccm_nonce n = *_n;
301-
struct crypto_sync_skcipher *tfm_cbc;
302-
struct crypto_cipher *tfm_aes;
303-
struct wusb_mac_scratch *scratch;
249+
struct crypto_shash *tfm_cbcmac;
250+
struct wusb_mac_scratch scratch;
304251
u64 sfn = 0;
305252
__le64 sfn_le;
306253

307-
tfm_cbc = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0);
308-
if (IS_ERR(tfm_cbc)) {
309-
result = PTR_ERR(tfm_cbc);
310-
printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result);
311-
goto error_alloc_cbc;
312-
}
313-
result = crypto_sync_skcipher_setkey(tfm_cbc, key, 16);
314-
if (result < 0) {
315-
printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result);
316-
goto error_setkey_cbc;
254+
tfm_cbcmac = crypto_alloc_shash("cbcmac(aes)", 0, 0);
255+
if (IS_ERR(tfm_cbcmac)) {
256+
result = PTR_ERR(tfm_cbcmac);
257+
printk(KERN_ERR "E: can't load CBCMAC-AES: %d\n", (int)result);
258+
goto error_alloc_cbcmac;
317259
}
318260

319-
tfm_aes = crypto_alloc_cipher("aes", 0, 0);
320-
if (IS_ERR(tfm_aes)) {
321-
result = PTR_ERR(tfm_aes);
322-
printk(KERN_ERR "E: can't load AES: %d\n", (int)result);
323-
goto error_alloc_aes;
324-
}
325-
result = crypto_cipher_setkey(tfm_aes, key, 16);
261+
result = crypto_shash_setkey(tfm_cbcmac, key, AES_BLOCK_SIZE);
326262
if (result < 0) {
327-
printk(KERN_ERR "E: can't set AES key: %d\n", (int)result);
328-
goto error_setkey_aes;
329-
}
330-
scratch = kmalloc(sizeof(*scratch), GFP_KERNEL);
331-
if (!scratch) {
332-
result = -ENOMEM;
333-
goto error_alloc_scratch;
263+
printk(KERN_ERR "E: can't set CBCMAC-AES key: %d\n", (int)result);
264+
goto error_setkey_cbcmac;
334265
}
335266

336267
for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
337268
sfn_le = cpu_to_le64(sfn++);
338269
memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */
339-
result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes,
270+
result = wusb_ccm_mac(tfm_cbcmac, &scratch, out + bytes,
340271
&n, a, b, blen);
341272
if (result < 0)
342273
goto error_ccm_mac;
343274
bytes += result;
344275
}
345276
result = bytes;
346277

347-
kfree(scratch);
348-
error_alloc_scratch:
349278
error_ccm_mac:
350-
error_setkey_aes:
351-
crypto_free_cipher(tfm_aes);
352-
error_alloc_aes:
353-
error_setkey_cbc:
354-
crypto_free_sync_skcipher(tfm_cbc);
355-
error_alloc_cbc:
279+
error_setkey_cbcmac:
280+
crypto_free_shash(tfm_cbcmac);
281+
error_alloc_cbcmac:
356282
return result;
357283
}
358284

@@ -377,12 +303,8 @@ static int wusb_oob_mic_verify(void)
377303
{
378304
int result;
379305
u8 mic[8];
380-
/* WUSB1.0[A.2] test vectors
381-
*
382-
* Need to keep it in the local stack as GCC 4.1.3something
383-
* messes up and generates noise.
384-
*/
385-
struct usb_handshake stv_hsmic_hs = {
306+
/* WUSB1.0[A.2] test vectors */
307+
static const struct usb_handshake stv_hsmic_hs = {
386308
.bMessageNumber = 2,
387309
.bStatus = 00,
388310
.tTKID = { 0x76, 0x98, 0x01 },
@@ -457,11 +379,8 @@ static int wusb_key_derive_verify(void)
457379
{
458380
int result = 0;
459381
struct wusb_keydvt_out keydvt_out;
460-
/* These come from WUSB1.0[A.1] + 2006/12 errata
461-
* NOTE: can't make this const or global -- somehow it seems
462-
* the scatterlists for crypto get confused and we get
463-
* bad data. There is no doc on this... */
464-
struct wusb_keydvt_in stv_keydvt_in_a1 = {
382+
/* These come from WUSB1.0[A.1] + 2006/12 errata */
383+
static const struct wusb_keydvt_in stv_keydvt_in_a1 = {
465384
.hnonce = {
466385
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
467386
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f

0 commit comments

Comments
 (0)
Please sign in to comment.