49 #include <linux/module.h>
52 #include <linux/slab.h>
56 static int debug_crypto_verify = 0;
59 MODULE_PARM_DESC(debug_crypto_verify,
"verify the key generation algorithms");
61 static void wusb_key_dump(
const void *
buf,
size_t len)
125 static void bytewise_xor(
void *_bo,
const void *_bi1,
const void *_bi2,
129 const u8 *bi1 = _bi1, *bi2 = _bi2;
131 for (itr = 0; itr <
size; itr++)
132 bo[itr] = bi1[itr] ^ bi2[itr];
212 const u8 bzero[16] = { 0 };
219 WARN_ON(
sizeof(*a) !=
sizeof(b1) -
sizeof(b1.la));
230 dst_size = blen +
sizeof(b0) +
sizeof(b1) + zero_padding;
232 if (dst_buf ==
NULL) {
237 iv = crypto_blkcipher_crt(tfm_cbc)->iv;
238 ivsize = crypto_blkcipher_ivsize(tfm_cbc);
254 memcpy(&b1.mac_header, a,
sizeof(*a));
257 sg_set_buf(&
sg[0], &b0,
sizeof(b0));
258 sg_set_buf(&
sg[1], &b1,
sizeof(b1));
259 sg_set_buf(&
sg[2], b, blen);
261 sg_set_buf(&
sg[3], bzero, zero_padding);
266 result = crypto_blkcipher_encrypt(&
desc, &sg_dst,
sg, dst_size);
270 goto error_cbc_crypt;
284 crypto_cipher_encrypt_one(tfm_aes, (
void *)&ax, (
void *)&ax);
285 bytewise_xor(mic, &ax, iv, 8);
302 const void *b,
size_t blen,
size_t len)
312 if (IS_ERR(tfm_cbc)) {
313 result = PTR_ERR(tfm_cbc);
315 goto error_alloc_cbc;
317 result = crypto_blkcipher_setkey(tfm_cbc, key, 16);
320 goto error_setkey_cbc;
324 if (IS_ERR(tfm_aes)) {
325 result = PTR_ERR(tfm_aes);
327 goto error_alloc_aes;
329 result = crypto_cipher_setkey(tfm_aes, key, 16);
332 goto error_setkey_aes;
335 for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
338 result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes,
347 crypto_free_cipher(tfm_aes);
350 crypto_free_blkcipher(tfm_cbc);
356 static const u8 stv_hsmic_key[16] = {
357 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d,
358 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f
363 .tkid = { 0x76, 0x98, 0x01, },
364 .dest_addr = { .data = { 0xbe, 0x00 } },
365 .src_addr = { .data = { 0x76, 0x98 } },
372 static int wusb_oob_mic_verify(
void)
384 .tTKID = { 0x76, 0x98, 0x01 },
386 .CDID = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
387 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
388 0x3c, 0x3d, 0x3e, 0x3f },
389 .nonce = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
390 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
391 0x2c, 0x2d, 0x2e, 0x2f },
392 .MIC = { 0x75, 0x6a, 0x97, 0x51, 0x0c, 0x8c,
397 result = wusb_oob_mic(mic, stv_hsmic_key, &stv_hsmic_n, &stv_hsmic_hs);
400 else if (
memcmp(stv_hsmic_hs.
MIC, mic,
sizeof(mic))) {
402 "mismatch between MIC result and WUSB1.0[A2]\n");
403 hs_size =
sizeof(stv_hsmic_hs) -
sizeof(stv_hsmic_hs.
MIC);
405 wusb_key_dump(&stv_hsmic_hs, hs_size);
407 sizeof(stv_hsmic_n));
408 wusb_key_dump(&stv_hsmic_n,
sizeof(stv_hsmic_n));
410 wusb_key_dump(mic,
sizeof(mic));
412 wusb_key_dump(stv_hsmic_hs.
MIC,
sizeof(stv_hsmic_hs.
MIC));
426 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
427 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f
432 .tkid = { 0x76, 0x98, 0x01, },
433 .dest_addr = { .data = { 0xbe, 0x00 } },
434 .src_addr = { .data = { 0x76, 0x98 } },
439 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d,
440 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f
443 0xc8, 0x70, 0x62, 0x82, 0xb6, 0x7c, 0xe9, 0x06,
444 0x7b, 0xc5, 0x25, 0x69, 0xf2, 0x36, 0x61, 0x2d
452 static int wusb_key_derive_verify(
void)
462 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
463 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
466 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
467 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
471 result = wusb_key_derive(&keydvt_out, stv_key_a1, &stv_keydvt_n_a1,
475 "derivation failed: %d\n", result);
476 if (
memcmp(&stv_keydvt_out_a1, &keydvt_out,
sizeof(keydvt_out))) {
478 "mismatch between key derivation result "
479 "and WUSB1.0[A1] Errata 2006/12\n");
481 wusb_key_dump(stv_key_a1,
sizeof(stv_key_a1));
483 wusb_key_dump( &stv_keydvt_n_a1,
sizeof(stv_keydvt_n_a1));
485 wusb_key_dump(&stv_keydvt_in_a1,
sizeof(stv_keydvt_in_a1));
487 wusb_key_dump(&keydvt_out.kck,
sizeof(keydvt_out.kck));
489 wusb_key_dump(&keydvt_out.ptk,
sizeof(keydvt_out.ptk));
506 if (debug_crypto_verify) {
507 result = wusb_key_derive_verify();
510 return wusb_oob_mic_verify();