diff options
Diffstat (limited to 'drivers/usb/wusbcore/crypto.c')
-rw-r--r-- | drivers/usb/wusbcore/crypto.c | 61 |
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. */ | ||
137 | struct 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 | */ |
199 | static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, | 206 | static 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; |
285 | error_cbc_crypt: | 293 | error_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); | ||
359 | error_alloc_scratch: | ||
343 | error_ccm_mac: | 360 | error_ccm_mac: |
344 | error_setkey_aes: | 361 | error_setkey_aes: |
345 | crypto_free_cipher(tfm_aes); | 362 | crypto_free_cipher(tfm_aes); |