On Thu, Oct 6, 2016 at 10:25 AM, Andy Lutomirski <l...@kernel.org> wrote: > Pointing an sg list at the stack is verboten and, with > CONFIG_VMAP_STACK=y, will malfunction. Use kmalloc for the wusb > crypto stack space instead. > > Untested -- I'm not entirely convinced that this hardware exists in > the wild.
Greg, could you queue this up for 4.9? I can't guarantee that it works, but I can pretty much guarantee that the driver is busted without it. > > Signed-off-by: Andy Lutomirski <l...@kernel.org> > --- > > This is needed for 4.9 for wusb to have a chance of working on default x86 > configurations. > > drivers/usb/wusbcore/crypto.c | 59 > +++++++++++++++++++++++++++---------------- > 1 file changed, 37 insertions(+), 22 deletions(-) > > diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c > index 33acd1599e99..2db79d64e66c 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, > bo[itr] = bi1[itr] ^ bi2[itr]; > } > > +/* Scratch space for MAC calculations. */ > +struct wusb_mac_scratch { > + struct aes_ccm_b0 b0; > + struct aes_ccm_b1 b1; > + struct aes_ccm_a ax; > +}; > + > /* > * CC-MAC function WUSB1.0[6.5] > * > @@ -197,16 +204,15 @@ static void bytewise_xor(void *_bo, const void *_bi1, > const void *_bi2, > * what sg[4] is for. Maybe there is a smarter way to do this. > */ > static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, > - struct crypto_cipher *tfm_aes, void *mic, > + struct crypto_cipher *tfm_aes, > + struct wusb_mac_scratch *scratch, > + void *mic, > const struct aes_ccm_nonce *n, > const struct aes_ccm_label *a, const void *b, > size_t blen) > { > int result = 0; > SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc); > - struct aes_ccm_b0 b0; > - struct aes_ccm_b1 b1; > - struct aes_ccm_a ax; > struct scatterlist sg[4], sg_dst; > void *dst_buf; > size_t dst_size; > @@ -218,16 +224,17 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, > * These checks should be compile time optimized out > * ensure @a fills b1's mac_header and following fields > */ > - WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la)); > - WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block)); > - WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block)); > - WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block)); > + WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la)); > + WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block)); > + WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block)); > + WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block)); > > result = -ENOMEM; > zero_padding = blen % sizeof(struct aes_ccm_block); > if (zero_padding) > zero_padding = sizeof(struct aes_ccm_block) - zero_padding; > - dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding; > + dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) + > + zero_padding; > dst_buf = kzalloc(dst_size, GFP_KERNEL); > if (dst_buf == NULL) { > printk(KERN_ERR "E: can't alloc destination buffer\n"); > @@ -237,9 +244,9 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, > memset(iv, 0, sizeof(iv)); > > /* Setup B0 */ > - b0.flags = 0x59; /* Format B0 */ > - b0.ccm_nonce = *n; > - b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */ > + scratch->b0.flags = 0x59; /* Format B0 */ > + scratch->b0.ccm_nonce = *n; > + scratch->b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 > */ > > /* Setup B1 > * > @@ -248,12 +255,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, > * 14'--after clarification, it means to use A's contents > * for MAC Header, EO, sec reserved and padding. > */ > - b1.la = cpu_to_be16(blen + 14); > - memcpy(&b1.mac_header, a, sizeof(*a)); > + scratch->b1.la = cpu_to_be16(blen + 14); > + memcpy(&scratch->b1.mac_header, a, sizeof(*a)); > > sg_init_table(sg, ARRAY_SIZE(sg)); > - sg_set_buf(&sg[0], &b0, sizeof(b0)); > - sg_set_buf(&sg[1], &b1, sizeof(b1)); > + sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0)); > + sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1)); > sg_set_buf(&sg[2], b, blen); > /* 0 if well behaved :) */ > sg_set_buf(&sg[3], bzero, zero_padding); > @@ -278,11 +285,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, > * POS Crypto API: size is assumed to be AES's block size. > * Thanks for documenting it -- tip taken from airo.c > */ > - ax.flags = 0x01; /* as per WUSB 1.0 spec */ > - ax.ccm_nonce = *n; > - ax.counter = 0; > - crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); > - bytewise_xor(mic, &ax, iv, 8); > + scratch->ax.flags = 0x01; /* as per WUSB 1.0 spec */ > + scratch->ax.ccm_nonce = *n; > + scratch->ax.counter = 0; > + crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax, > + (void *)&scratch->ax); > + bytewise_xor(mic, &scratch->ax, iv, 8); > result = 8; > error_cbc_crypt: > kfree(dst_buf); > @@ -305,6 +313,7 @@ ssize_t wusb_prf(void *out, size_t out_size, > struct aes_ccm_nonce n = *_n; > struct crypto_skcipher *tfm_cbc; > struct crypto_cipher *tfm_aes; > + struct wusb_mac_scratch *scratch; > u64 sfn = 0; > __le64 sfn_le; > > @@ -331,17 +340,23 @@ ssize_t wusb_prf(void *out, size_t out_size, > printk(KERN_ERR "E: can't set AES key: %d\n", (int)result); > goto error_setkey_aes; > } > + scratch = kmalloc(sizeof(*scratch), GFP_KERNEL); > + if (!scratch) > + goto error_alloc_scratch; > > for (bitr = 0; bitr < (len + 63) / 64; bitr++) { > sfn_le = cpu_to_le64(sfn++); > memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */ > - result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes, > + result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes, > &n, a, b, blen); > if (result < 0) > goto error_ccm_mac; > bytes += result; > } > result = bytes; > + > + kfree(scratch); > +error_alloc_scratch: > error_ccm_mac: > error_setkey_aes: > crypto_free_cipher(tfm_aes); > -- > 2.7.4 > -- Andy Lutomirski AMA Capital Management, LLC -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html