1 // SPDX-License-Identifier: GPL-2.0
4 * AES-128 CCM Encryption
6 * Copyright (C) 2007 Intel Corporation
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
9 * We don't do any encryption here; we use the Linux Kernel's AES-128
10 * crypto modules to construct keys and payload blocks in a way
11 * defined by WUSB1.0[6]. Check the erratas, as typos are are patched
14 * Thanks a zillion to John Keys for his help and clarifications over
15 * the designed-by-a-committee text.
17 * So the idea is that there is this basic Pseudo-Random-Function
18 * defined in WUSB1.0[6.5] which is the core of everything. It works
19 * by tweaking some blocks, AES crypting them and then xoring
20 * something else with them (this seems to be called CBC(AES) -- can
21 * you tell I know jack about crypto?). So we just funnel it into the
24 * We leave a crypto test module so we can verify that vectors match,
27 * Block size: 16 bytes -- AES seems to do things in 'block sizes'. I
28 * am learning a lot...
30 * Conveniently, some data structures that need to be
31 * funneled through AES are...16 bytes in size!
34 #include <crypto/skcipher.h>
35 #include <linux/crypto.h>
36 #include <linux/module.h>
37 #include <linux/err.h>
38 #include <linux/uwb.h>
39 #include <linux/slab.h>
40 #include <linux/usb/wusb.h>
41 #include <linux/scatterlist.h>
43 static int debug_crypto_verify;
45 module_param(debug_crypto_verify, int, 0);
46 MODULE_PARM_DESC(debug_crypto_verify, "verify the key generation algorithms");
48 static void wusb_key_dump(const void *buf, size_t len)
50 print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_OFFSET, 16, 1,
55 * Block of data, as understood by AES-CCM
57 * The code assumes this structure is nothing but a 16 byte array
58 * (packed in a struct to avoid common mess ups that I usually do with
59 * arrays and enforcing type checking).
61 struct aes_ccm_block {
63 } __attribute__((packed));
66 * Counter-mode Blocks (WUSB1.0[6.4])
68 * According to CCM (or so it seems), for the purpose of calculating
69 * the MIC, the message is broken in N counter-mode blocks, B0, B1,
72 * B0 contains flags, the CCM nonce and l(m).
74 * B1 contains l(a), the MAC header, the encryption offset and padding.
76 * If EO is nonzero, additional blocks are built from payload bytes
77 * until EO is exhausted (FIXME: padding to 16 bytes, I guess). The
78 * padding is not xmitted.
83 u8 flags; /* 0x59, per CCM spec */
84 struct aes_ccm_nonce ccm_nonce;
86 } __attribute__((packed));
93 u8 security_reserved; /* This is always zero */
95 } __attribute__((packed));
98 * Encryption Blocks (WUSB1.0[6.4.4])
100 * CCM uses Ax blocks to generate a keystream with which the MIC and
101 * the message's payload are encoded. A0 always encrypts/decrypts the
102 * MIC. Ax (x>0) are used for the successive payload blocks.
104 * The x is the counter, and is increased for each block.
107 u8 flags; /* 0x01, per CCM spec */
108 struct aes_ccm_nonce ccm_nonce;
109 __be16 counter; /* Value of x */
110 } __attribute__((packed));
112 static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
116 const u8 *bi1 = _bi1, *bi2 = _bi2;
118 for (itr = 0; itr < size; itr++)
119 bo[itr] = bi1[itr] ^ bi2[itr];
122 /* Scratch space for MAC calculations. */
123 struct wusb_mac_scratch {
124 struct aes_ccm_b0 b0;
125 struct aes_ccm_b1 b1;
130 * CC-MAC function WUSB1.0[6.5]
132 * Take a data string and produce the encrypted CBC Counter-mode MIC
134 * Note the names for most function arguments are made to (more or
135 * less) match those used in the pseudo-function definition given in
138 * @tfm_cbc: CBC(AES) blkcipher handle (initialized)
140 * @tfm_aes: AES cipher handle (initialized)
142 * @mic: buffer for placing the computed MIC (Message Integrity
143 * Code). This is exactly 8 bytes, and we expect the buffer to
144 * be at least eight bytes in length.
146 * @key: 128 bit symmetric key
150 * @a: ASCII string, 14 bytes long (I guess zero padded if needed;
151 * we use exactly 14 bytes).
153 * @b: data stream to be processed; cannot be a global or const local
154 * (will confuse the scatterlists)
156 * @blen: size of b...
158 * Still not very clear how this is done, but looks like this: we
159 * create block B0 (as WUSB1.0[6.5] says), then we AES-crypt it with
160 * @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we
161 * take the payload and divide it in blocks (16 bytes), xor them with
162 * 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
166 * Vector) is 16 bytes and is set to zero, so
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.
173 * (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and
174 * using the 14 bytes of @a to fill up
175 * b1.{mac_header,e0,security_reserved,padding}.
177 * NOTE: The definition of l(a) in WUSB1.0[6.5] vs the definition of
178 * l(m) is orthogonal, they bear no relationship, so it is not
179 * in conflict with the parameter's relation that
180 * WUSB1.0[6.4.2]) defines.
182 * NOTE: WUSB1.0[A.1]: Host Nonce is missing a nibble? (1e); fixed in
183 * first errata released on 2005/07.
185 * NOTE: we need to clean IV to zero at each invocation to make sure
186 * we start with a fresh empty Initial Vector, so that the CBC
189 * NOTE: blen is not aligned to a block size, we'll pad zeros, that's
190 * what sg[4] is for. Maybe there is a smarter way to do this.
192 static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
193 struct crypto_cipher *tfm_aes,
194 struct wusb_mac_scratch *scratch,
196 const struct aes_ccm_nonce *n,
197 const struct aes_ccm_label *a, const void *b,
201 SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc);
202 struct scatterlist sg[4], sg_dst;
209 * These checks should be compile time optimized out
210 * ensure @a fills b1's mac_header and following fields
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));
218 zero_padding = blen % sizeof(struct aes_ccm_block);
220 zero_padding = sizeof(struct aes_ccm_block) - zero_padding;
221 dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) +
223 dst_buf = kzalloc(dst_size, GFP_KERNEL);
227 iv = kzalloc(crypto_skcipher_ivsize(tfm_cbc), GFP_KERNEL);
232 scratch->b0.flags = 0x59; /* Format B0 */
233 scratch->b0.ccm_nonce = *n;
234 scratch->b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */
238 * The WUSB spec is anything but clear! WUSB1.0[6.5]
239 * says that to initialize B1 from A with 'l(a) = blen +
240 * 14'--after clarification, it means to use A's contents
241 * for MAC Header, EO, sec reserved and padding.
243 scratch->b1.la = cpu_to_be16(blen + 14);
244 memcpy(&scratch->b1.mac_header, a, sizeof(*a));
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);
254 skcipher_request_set_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);
260 printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n",
262 goto error_cbc_crypt;
265 /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5]
266 * The procedure is to AES crypt the A0 block and XOR the MIC
267 * Tag against it; we only do the first 8 bytes and place it
268 * directly in the destination buffer.
270 * POS Crypto API: size is assumed to be AES's block size.
271 * Thanks for documenting it -- tip taken from airo.c
273 scratch->ax.flags = 0x01; /* as per WUSB 1.0 spec */
274 scratch->ax.ccm_nonce = *n;
275 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);
289 * WUSB Pseudo Random Function (WUSB1.0[6.5])
291 * @b: buffer to the source data; cannot be a global or const local
292 * (will confuse the scatterlists)
294 ssize_t wusb_prf(void *out, size_t out_size,
295 const u8 key[16], const struct aes_ccm_nonce *_n,
296 const struct aes_ccm_label *a,
297 const void *b, size_t blen, size_t len)
299 ssize_t result, bytes = 0, bitr;
300 struct aes_ccm_nonce n = *_n;
301 struct crypto_skcipher *tfm_cbc;
302 struct crypto_cipher *tfm_aes;
303 struct wusb_mac_scratch *scratch;
307 tfm_cbc = crypto_alloc_skcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
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;
313 result = crypto_skcipher_setkey(tfm_cbc, key, 16);
315 printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result);
316 goto error_setkey_cbc;
319 tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
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;
325 result = crypto_cipher_setkey(tfm_aes, key, 16);
327 printk(KERN_ERR "E: can't set AES key: %d\n", (int)result);
328 goto error_setkey_aes;
330 scratch = kmalloc(sizeof(*scratch), GFP_KERNEL);
333 goto error_alloc_scratch;
336 for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
337 sfn_le = cpu_to_le64(sfn++);
338 memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */
339 result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes,
351 crypto_free_cipher(tfm_aes);
354 crypto_free_skcipher(tfm_cbc);
359 /* WUSB1.0[A.2] test vectors */
360 static const u8 stv_hsmic_key[16] = {
361 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d,
362 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f
365 static const struct aes_ccm_nonce stv_hsmic_n = {
367 .tkid = { 0x76, 0x98, 0x01, },
368 .dest_addr = { .data = { 0xbe, 0x00 } },
369 .src_addr = { .data = { 0x76, 0x98 } },
373 * Out-of-band MIC Generation verification code
376 static int wusb_oob_mic_verify(void)
380 /* WUSB1.0[A.2] test vectors
382 * Need to keep it in the local stack as GCC 4.1.3something
383 * messes up and generates noise.
385 struct usb_handshake stv_hsmic_hs = {
388 .tTKID = { 0x76, 0x98, 0x01 },
390 .CDID = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
391 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
392 0x3c, 0x3d, 0x3e, 0x3f },
393 .nonce = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
394 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
395 0x2c, 0x2d, 0x2e, 0x2f },
396 .MIC = { 0x75, 0x6a, 0x97, 0x51, 0x0c, 0x8c,
401 result = wusb_oob_mic(mic, stv_hsmic_key, &stv_hsmic_n, &stv_hsmic_hs);
403 printk(KERN_ERR "E: WUSB OOB MIC test: failed: %d\n", result);
404 else if (memcmp(stv_hsmic_hs.MIC, mic, sizeof(mic))) {
405 printk(KERN_ERR "E: OOB MIC test: "
406 "mismatch between MIC result and WUSB1.0[A2]\n");
407 hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC);
408 printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size);
409 wusb_key_dump(&stv_hsmic_hs, hs_size);
410 printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n",
411 sizeof(stv_hsmic_n));
412 wusb_key_dump(&stv_hsmic_n, sizeof(stv_hsmic_n));
413 printk(KERN_ERR "E: MIC out:\n");
414 wusb_key_dump(mic, sizeof(mic));
415 printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n");
416 wusb_key_dump(stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC));
424 * Test vectors for Key derivation
426 * These come from WUSB1.0[6.5.1], the vectors in WUSB1.0[A.1]
427 * (errata corrected in 2005/07).
429 static const u8 stv_key_a1[16] __attribute__ ((__aligned__(4))) = {
430 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
431 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f
434 static const struct aes_ccm_nonce stv_keydvt_n_a1 = {
436 .tkid = { 0x76, 0x98, 0x01, },
437 .dest_addr = { .data = { 0xbe, 0x00 } },
438 .src_addr = { .data = { 0x76, 0x98 } },
441 static const struct wusb_keydvt_out stv_keydvt_out_a1 = {
443 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d,
444 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f
447 0xc8, 0x70, 0x62, 0x82, 0xb6, 0x7c, 0xe9, 0x06,
448 0x7b, 0xc5, 0x25, 0x69, 0xf2, 0x36, 0x61, 0x2d
453 * Performa a test to make sure we match the vectors defined in
454 * WUSB1.0[A.1](Errata2006/12)
456 static int wusb_key_derive_verify(void)
459 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 = {
466 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
467 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
470 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
471 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
475 result = wusb_key_derive(&keydvt_out, stv_key_a1, &stv_keydvt_n_a1,
478 printk(KERN_ERR "E: WUSB key derivation test: "
479 "derivation failed: %d\n", result);
480 if (memcmp(&stv_keydvt_out_a1, &keydvt_out, sizeof(keydvt_out))) {
481 printk(KERN_ERR "E: WUSB key derivation test: "
482 "mismatch between key derivation result "
483 "and WUSB1.0[A1] Errata 2006/12\n");
484 printk(KERN_ERR "E: keydvt in: key\n");
485 wusb_key_dump(stv_key_a1, sizeof(stv_key_a1));
486 printk(KERN_ERR "E: keydvt in: nonce\n");
487 wusb_key_dump(&stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1));
488 printk(KERN_ERR "E: keydvt in: hnonce & dnonce\n");
489 wusb_key_dump(&stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1));
490 printk(KERN_ERR "E: keydvt out: KCK\n");
491 wusb_key_dump(&keydvt_out.kck, sizeof(keydvt_out.kck));
492 printk(KERN_ERR "E: keydvt out: PTK\n");
493 wusb_key_dump(&keydvt_out.ptk, sizeof(keydvt_out.ptk));
501 * Initialize crypto system
503 * FIXME: we do nothing now, other than verifying. Later on we'll
504 * cache the encryption stuff, so that's why we have a separate init.
506 int wusb_crypto_init(void)
510 if (debug_crypto_verify) {
511 result = wusb_key_derive_verify();
514 return wusb_oob_mic_verify();
519 void wusb_crypto_exit(void)
521 /* FIXME: free cached crypto transforms */