Commit | Line | Data |
---|---|---|
d59db761 IPG |
1 | /* |
2 | * Ultra Wide Band | |
3 | * AES-128 CCM Encryption | |
4 | * | |
5 | * Copyright (C) 2007 Intel Corporation | |
6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License version | |
10 | * 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
20 | * 02110-1301, USA. | |
21 | * | |
22 | * | |
23 | * We don't do any encryption here; we use the Linux Kernel's AES-128 | |
24 | * crypto modules to construct keys and payload blocks in a way | |
25 | * defined by WUSB1.0[6]. Check the erratas, as typos are are patched | |
26 | * there. | |
27 | * | |
28 | * Thanks a zillion to John Keys for his help and clarifications over | |
29 | * the designed-by-a-committee text. | |
30 | * | |
31 | * So the idea is that there is this basic Pseudo-Random-Function | |
32 | * defined in WUSB1.0[6.5] which is the core of everything. It works | |
33 | * by tweaking some blocks, AES crypting them and then xoring | |
34 | * something else with them (this seems to be called CBC(AES) -- can | |
35 | * you tell I know jack about crypto?). So we just funnel it into the | |
36 | * Linux Crypto API. | |
37 | * | |
38 | * We leave a crypto test module so we can verify that vectors match, | |
39 | * every now and then. | |
40 | * | |
41 | * Block size: 16 bytes -- AES seems to do things in 'block sizes'. I | |
42 | * am learning a lot... | |
43 | * | |
44 | * Conveniently, some data structures that need to be | |
45 | * funneled through AES are...16 bytes in size! | |
46 | */ | |
47 | ||
48 | #include <linux/crypto.h> | |
49 | #include <linux/module.h> | |
50 | #include <linux/err.h> | |
51 | #include <linux/uwb.h> | |
5a0e3ad6 | 52 | #include <linux/slab.h> |
d59db761 IPG |
53 | #include <linux/usb/wusb.h> |
54 | #include <linux/scatterlist.h> | |
d59db761 | 55 | |
d409f3bf DV |
56 | static int debug_crypto_verify = 0; |
57 | ||
58 | module_param(debug_crypto_verify, int, 0); | |
59 | MODULE_PARM_DESC(debug_crypto_verify, "verify the key generation algorithms"); | |
d59db761 | 60 | |
e43ace89 DV |
61 | static void wusb_key_dump(const void *buf, size_t len) |
62 | { | |
63 | print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_OFFSET, 16, 1, | |
64 | buf, len, 0); | |
65 | } | |
66 | ||
d59db761 IPG |
67 | /* |
68 | * Block of data, as understood by AES-CCM | |
69 | * | |
70 | * The code assumes this structure is nothing but a 16 byte array | |
71 | * (packed in a struct to avoid common mess ups that I usually do with | |
72 | * arrays and enforcing type checking). | |
73 | */ | |
74 | struct aes_ccm_block { | |
75 | u8 data[16]; | |
76 | } __attribute__((packed)); | |
77 | ||
78 | /* | |
79 | * Counter-mode Blocks (WUSB1.0[6.4]) | |
80 | * | |
81 | * According to CCM (or so it seems), for the purpose of calculating | |
82 | * the MIC, the message is broken in N counter-mode blocks, B0, B1, | |
83 | * ... BN. | |
84 | * | |
85 | * B0 contains flags, the CCM nonce and l(m). | |
86 | * | |
87 | * B1 contains l(a), the MAC header, the encryption offset and padding. | |
88 | * | |
89 | * If EO is nonzero, additional blocks are built from payload bytes | |
1076e7a4 | 90 | * until EO is exhausted (FIXME: padding to 16 bytes, I guess). The |
d59db761 IPG |
91 | * padding is not xmitted. |
92 | */ | |
93 | ||
94 | /* WUSB1.0[T6.4] */ | |
95 | struct aes_ccm_b0 { | |
96 | u8 flags; /* 0x59, per CCM spec */ | |
97 | struct aes_ccm_nonce ccm_nonce; | |
98 | __be16 lm; | |
99 | } __attribute__((packed)); | |
100 | ||
101 | /* WUSB1.0[T6.5] */ | |
102 | struct aes_ccm_b1 { | |
103 | __be16 la; | |
104 | u8 mac_header[10]; | |
105 | __le16 eo; | |
106 | u8 security_reserved; /* This is always zero */ | |
107 | u8 padding; /* 0 */ | |
108 | } __attribute__((packed)); | |
109 | ||
110 | /* | |
111 | * Encryption Blocks (WUSB1.0[6.4.4]) | |
112 | * | |
113 | * CCM uses Ax blocks to generate a keystream with which the MIC and | |
114 | * the message's payload are encoded. A0 always encrypts/decrypts the | |
af901ca1 | 115 | * MIC. Ax (x>0) are used for the successive payload blocks. |
d59db761 IPG |
116 | * |
117 | * The x is the counter, and is increased for each block. | |
118 | */ | |
119 | struct aes_ccm_a { | |
120 | u8 flags; /* 0x01, per CCM spec */ | |
121 | struct aes_ccm_nonce ccm_nonce; | |
122 | __be16 counter; /* Value of x */ | |
123 | } __attribute__((packed)); | |
124 | ||
125 | static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, | |
126 | size_t size) | |
127 | { | |
128 | u8 *bo = _bo; | |
129 | const u8 *bi1 = _bi1, *bi2 = _bi2; | |
130 | size_t itr; | |
131 | for (itr = 0; itr < size; itr++) | |
132 | bo[itr] = bi1[itr] ^ bi2[itr]; | |
133 | } | |
134 | ||
135 | /* | |
136 | * CC-MAC function WUSB1.0[6.5] | |
137 | * | |
138 | * Take a data string and produce the encrypted CBC Counter-mode MIC | |
139 | * | |
140 | * Note the names for most function arguments are made to (more or | |
141 | * less) match those used in the pseudo-function definition given in | |
142 | * WUSB1.0[6.5]. | |
143 | * | |
144 | * @tfm_cbc: CBC(AES) blkcipher handle (initialized) | |
145 | * | |
146 | * @tfm_aes: AES cipher handle (initialized) | |
147 | * | |
148 | * @mic: buffer for placing the computed MIC (Message Integrity | |
149 | * Code). This is exactly 8 bytes, and we expect the buffer to | |
150 | * be at least eight bytes in length. | |
151 | * | |
152 | * @key: 128 bit symmetric key | |
153 | * | |
154 | * @n: CCM nonce | |
155 | * | |
156 | * @a: ASCII string, 14 bytes long (I guess zero padded if needed; | |
157 | * we use exactly 14 bytes). | |
158 | * | |
159 | * @b: data stream to be processed; cannot be a global or const local | |
160 | * (will confuse the scatterlists) | |
161 | * | |
162 | * @blen: size of b... | |
163 | * | |
164 | * Still not very clear how this is done, but looks like this: we | |
165 | * create block B0 (as WUSB1.0[6.5] says), then we AES-crypt it with | |
166 | * @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we | |
167 | * take the payload and divide it in blocks (16 bytes), xor them with | |
168 | * the previous crypto result (16 bytes) and crypt it, repeat the next | |
169 | * block with the output of the previous one, rinse wash (I guess this | |
170 | * is what AES CBC mode means...but I truly have no idea). So we use | |
171 | * the CBC(AES) blkcipher, that does precisely that. The IV (Initial | |
172 | * Vector) is 16 bytes and is set to zero, so | |
173 | * | |
174 | * See rfc3610. Linux crypto has a CBC implementation, but the | |
175 | * documentation is scarce, to say the least, and the example code is | |
176 | * so intricated that is difficult to understand how things work. Most | |
177 | * of this is guess work -- bite me. | |
178 | * | |
179 | * (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and | |
180 | * using the 14 bytes of @a to fill up | |
181 | * b1.{mac_header,e0,security_reserved,padding}. | |
182 | * | |
25985edc | 183 | * NOTE: The definition of l(a) in WUSB1.0[6.5] vs the definition of |
d59db761 IPG |
184 | * l(m) is orthogonal, they bear no relationship, so it is not |
185 | * in conflict with the parameter's relation that | |
186 | * WUSB1.0[6.4.2]) defines. | |
187 | * | |
188 | * NOTE: WUSB1.0[A.1]: Host Nonce is missing a nibble? (1e); fixed in | |
189 | * first errata released on 2005/07. | |
190 | * | |
191 | * NOTE: we need to clean IV to zero at each invocation to make sure | |
192 | * we start with a fresh empty Initial Vector, so that the CBC | |
193 | * works ok. | |
194 | * | |
195 | * NOTE: blen is not aligned to a block size, we'll pad zeros, that's | |
196 | * what sg[4] is for. Maybe there is a smarter way to do this. | |
197 | */ | |
198 | static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, | |
199 | struct crypto_cipher *tfm_aes, void *mic, | |
200 | const struct aes_ccm_nonce *n, | |
201 | const struct aes_ccm_label *a, const void *b, | |
202 | size_t blen) | |
203 | { | |
204 | int result = 0; | |
205 | struct blkcipher_desc desc; | |
206 | struct aes_ccm_b0 b0; | |
207 | struct aes_ccm_b1 b1; | |
208 | struct aes_ccm_a ax; | |
209 | struct scatterlist sg[4], sg_dst; | |
210 | void *iv, *dst_buf; | |
211 | size_t ivsize, dst_size; | |
212 | const u8 bzero[16] = { 0 }; | |
213 | size_t zero_padding; | |
214 | ||
d59db761 IPG |
215 | /* |
216 | * These checks should be compile time optimized out | |
217 | * ensure @a fills b1's mac_header and following fields | |
218 | */ | |
219 | WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la)); | |
220 | WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block)); | |
221 | WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block)); | |
222 | WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block)); | |
223 | ||
224 | result = -ENOMEM; | |
d59db761 IPG |
225 | zero_padding = blen % sizeof(struct aes_ccm_block); |
226 | if (zero_padding) | |
227 | zero_padding = sizeof(struct aes_ccm_block) - zero_padding; | |
228 | dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding; | |
229 | dst_buf = kzalloc(dst_size, GFP_KERNEL); | |
230 | if (dst_buf == NULL) { | |
231 | printk(KERN_ERR "E: can't alloc destination buffer\n"); | |
232 | goto error_dst_buf; | |
233 | } | |
234 | ||
235 | iv = crypto_blkcipher_crt(tfm_cbc)->iv; | |
236 | ivsize = crypto_blkcipher_ivsize(tfm_cbc); | |
237 | memset(iv, 0, ivsize); | |
238 | ||
239 | /* Setup B0 */ | |
240 | b0.flags = 0x59; /* Format B0 */ | |
241 | b0.ccm_nonce = *n; | |
242 | b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */ | |
243 | ||
244 | /* Setup B1 | |
245 | * | |
246 | * The WUSB spec is anything but clear! WUSB1.0[6.5] | |
247 | * says that to initialize B1 from A with 'l(a) = blen + | |
248 | * 14'--after clarification, it means to use A's contents | |
249 | * for MAC Header, EO, sec reserved and padding. | |
250 | */ | |
251 | b1.la = cpu_to_be16(blen + 14); | |
252 | memcpy(&b1.mac_header, a, sizeof(*a)); | |
253 | ||
d59db761 IPG |
254 | sg_init_table(sg, ARRAY_SIZE(sg)); |
255 | sg_set_buf(&sg[0], &b0, sizeof(b0)); | |
256 | sg_set_buf(&sg[1], &b1, sizeof(b1)); | |
257 | sg_set_buf(&sg[2], b, blen); | |
258 | /* 0 if well behaved :) */ | |
259 | sg_set_buf(&sg[3], bzero, zero_padding); | |
260 | sg_init_one(&sg_dst, dst_buf, dst_size); | |
261 | ||
262 | desc.tfm = tfm_cbc; | |
263 | desc.flags = 0; | |
264 | result = crypto_blkcipher_encrypt(&desc, &sg_dst, sg, dst_size); | |
265 | if (result < 0) { | |
266 | printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", | |
267 | result); | |
268 | goto error_cbc_crypt; | |
269 | } | |
d59db761 IPG |
270 | |
271 | /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] | |
272 | * The procedure is to AES crypt the A0 block and XOR the MIC | |
25985edc | 273 | * Tag against it; we only do the first 8 bytes and place it |
d59db761 IPG |
274 | * directly in the destination buffer. |
275 | * | |
276 | * POS Crypto API: size is assumed to be AES's block size. | |
277 | * Thanks for documenting it -- tip taken from airo.c | |
278 | */ | |
279 | ax.flags = 0x01; /* as per WUSB 1.0 spec */ | |
280 | ax.ccm_nonce = *n; | |
281 | ax.counter = 0; | |
282 | crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); | |
283 | bytewise_xor(mic, &ax, iv, 8); | |
d59db761 IPG |
284 | result = 8; |
285 | error_cbc_crypt: | |
286 | kfree(dst_buf); | |
287 | error_dst_buf: | |
d59db761 IPG |
288 | return result; |
289 | } | |
290 | ||
291 | /* | |
292 | * WUSB Pseudo Random Function (WUSB1.0[6.5]) | |
293 | * | |
294 | * @b: buffer to the source data; cannot be a global or const local | |
295 | * (will confuse the scatterlists) | |
296 | */ | |
297 | ssize_t wusb_prf(void *out, size_t out_size, | |
298 | const u8 key[16], const struct aes_ccm_nonce *_n, | |
299 | const struct aes_ccm_label *a, | |
300 | const void *b, size_t blen, size_t len) | |
301 | { | |
302 | ssize_t result, bytes = 0, bitr; | |
303 | struct aes_ccm_nonce n = *_n; | |
304 | struct crypto_blkcipher *tfm_cbc; | |
305 | struct crypto_cipher *tfm_aes; | |
306 | u64 sfn = 0; | |
307 | __le64 sfn_le; | |
308 | ||
d59db761 IPG |
309 | tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); |
310 | if (IS_ERR(tfm_cbc)) { | |
311 | result = PTR_ERR(tfm_cbc); | |
312 | printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result); | |
313 | goto error_alloc_cbc; | |
314 | } | |
315 | result = crypto_blkcipher_setkey(tfm_cbc, key, 16); | |
316 | if (result < 0) { | |
317 | printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result); | |
318 | goto error_setkey_cbc; | |
319 | } | |
320 | ||
321 | tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | |
322 | if (IS_ERR(tfm_aes)) { | |
323 | result = PTR_ERR(tfm_aes); | |
324 | printk(KERN_ERR "E: can't load AES: %d\n", (int)result); | |
325 | goto error_alloc_aes; | |
326 | } | |
327 | result = crypto_cipher_setkey(tfm_aes, key, 16); | |
328 | if (result < 0) { | |
329 | printk(KERN_ERR "E: can't set AES key: %d\n", (int)result); | |
330 | goto error_setkey_aes; | |
331 | } | |
332 | ||
333 | for (bitr = 0; bitr < (len + 63) / 64; bitr++) { | |
334 | sfn_le = cpu_to_le64(sfn++); | |
335 | memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */ | |
336 | result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes, | |
337 | &n, a, b, blen); | |
338 | if (result < 0) | |
339 | goto error_ccm_mac; | |
340 | bytes += result; | |
341 | } | |
342 | result = bytes; | |
343 | error_ccm_mac: | |
344 | error_setkey_aes: | |
345 | crypto_free_cipher(tfm_aes); | |
346 | error_alloc_aes: | |
347 | error_setkey_cbc: | |
348 | crypto_free_blkcipher(tfm_cbc); | |
349 | error_alloc_cbc: | |
d59db761 IPG |
350 | return result; |
351 | } | |
352 | ||
353 | /* WUSB1.0[A.2] test vectors */ | |
354 | static const u8 stv_hsmic_key[16] = { | |
355 | 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d, | |
356 | 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f | |
357 | }; | |
358 | ||
359 | static const struct aes_ccm_nonce stv_hsmic_n = { | |
360 | .sfn = { 0 }, | |
361 | .tkid = { 0x76, 0x98, 0x01, }, | |
362 | .dest_addr = { .data = { 0xbe, 0x00 } }, | |
363 | .src_addr = { .data = { 0x76, 0x98 } }, | |
364 | }; | |
365 | ||
366 | /* | |
367 | * Out-of-band MIC Generation verification code | |
368 | * | |
369 | */ | |
370 | static int wusb_oob_mic_verify(void) | |
371 | { | |
372 | int result; | |
373 | u8 mic[8]; | |
374 | /* WUSB1.0[A.2] test vectors | |
375 | * | |
376 | * Need to keep it in the local stack as GCC 4.1.3something | |
377 | * messes up and generates noise. | |
378 | */ | |
379 | struct usb_handshake stv_hsmic_hs = { | |
380 | .bMessageNumber = 2, | |
381 | .bStatus = 00, | |
382 | .tTKID = { 0x76, 0x98, 0x01 }, | |
383 | .bReserved = 00, | |
384 | .CDID = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, | |
385 | 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, | |
386 | 0x3c, 0x3d, 0x3e, 0x3f }, | |
387 | .nonce = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | |
388 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, | |
389 | 0x2c, 0x2d, 0x2e, 0x2f }, | |
390 | .MIC = { 0x75, 0x6a, 0x97, 0x51, 0x0c, 0x8c, | |
391 | 0x14, 0x7b } , | |
392 | }; | |
393 | size_t hs_size; | |
394 | ||
395 | result = wusb_oob_mic(mic, stv_hsmic_key, &stv_hsmic_n, &stv_hsmic_hs); | |
396 | if (result < 0) | |
397 | printk(KERN_ERR "E: WUSB OOB MIC test: failed: %d\n", result); | |
398 | else if (memcmp(stv_hsmic_hs.MIC, mic, sizeof(mic))) { | |
399 | printk(KERN_ERR "E: OOB MIC test: " | |
400 | "mismatch between MIC result and WUSB1.0[A2]\n"); | |
401 | hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC); | |
402 | printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size); | |
e43ace89 | 403 | wusb_key_dump(&stv_hsmic_hs, hs_size); |
d59db761 IPG |
404 | printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n", |
405 | sizeof(stv_hsmic_n)); | |
e43ace89 | 406 | wusb_key_dump(&stv_hsmic_n, sizeof(stv_hsmic_n)); |
d59db761 | 407 | printk(KERN_ERR "E: MIC out:\n"); |
e43ace89 | 408 | wusb_key_dump(mic, sizeof(mic)); |
d59db761 | 409 | printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n"); |
e43ace89 | 410 | wusb_key_dump(stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC)); |
d59db761 IPG |
411 | result = -EINVAL; |
412 | } else | |
413 | result = 0; | |
414 | return result; | |
415 | } | |
416 | ||
417 | /* | |
418 | * Test vectors for Key derivation | |
419 | * | |
420 | * These come from WUSB1.0[6.5.1], the vectors in WUSB1.0[A.1] | |
421 | * (errata corrected in 2005/07). | |
422 | */ | |
423 | static const u8 stv_key_a1[16] __attribute__ ((__aligned__(4))) = { | |
424 | 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, | |
425 | 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f | |
426 | }; | |
427 | ||
428 | static const struct aes_ccm_nonce stv_keydvt_n_a1 = { | |
429 | .sfn = { 0 }, | |
430 | .tkid = { 0x76, 0x98, 0x01, }, | |
431 | .dest_addr = { .data = { 0xbe, 0x00 } }, | |
432 | .src_addr = { .data = { 0x76, 0x98 } }, | |
433 | }; | |
434 | ||
435 | static const struct wusb_keydvt_out stv_keydvt_out_a1 = { | |
436 | .kck = { | |
437 | 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d, | |
438 | 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f | |
439 | }, | |
440 | .ptk = { | |
441 | 0xc8, 0x70, 0x62, 0x82, 0xb6, 0x7c, 0xe9, 0x06, | |
442 | 0x7b, 0xc5, 0x25, 0x69, 0xf2, 0x36, 0x61, 0x2d | |
443 | } | |
444 | }; | |
445 | ||
446 | /* | |
447 | * Performa a test to make sure we match the vectors defined in | |
448 | * WUSB1.0[A.1](Errata2006/12) | |
449 | */ | |
450 | static int wusb_key_derive_verify(void) | |
451 | { | |
452 | int result = 0; | |
453 | struct wusb_keydvt_out keydvt_out; | |
454 | /* These come from WUSB1.0[A.1] + 2006/12 errata | |
455 | * NOTE: can't make this const or global -- somehow it seems | |
456 | * the scatterlists for crypto get confused and we get | |
457 | * bad data. There is no doc on this... */ | |
458 | struct wusb_keydvt_in stv_keydvt_in_a1 = { | |
459 | .hnonce = { | |
460 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
461 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f | |
462 | }, | |
463 | .dnonce = { | |
464 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | |
465 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f | |
466 | } | |
467 | }; | |
468 | ||
469 | result = wusb_key_derive(&keydvt_out, stv_key_a1, &stv_keydvt_n_a1, | |
470 | &stv_keydvt_in_a1); | |
471 | if (result < 0) | |
472 | printk(KERN_ERR "E: WUSB key derivation test: " | |
473 | "derivation failed: %d\n", result); | |
474 | if (memcmp(&stv_keydvt_out_a1, &keydvt_out, sizeof(keydvt_out))) { | |
475 | printk(KERN_ERR "E: WUSB key derivation test: " | |
476 | "mismatch between key derivation result " | |
477 | "and WUSB1.0[A1] Errata 2006/12\n"); | |
e43ace89 DV |
478 | printk(KERN_ERR "E: keydvt in: key\n"); |
479 | wusb_key_dump(stv_key_a1, sizeof(stv_key_a1)); | |
480 | printk(KERN_ERR "E: keydvt in: nonce\n"); | |
481 | wusb_key_dump( &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1)); | |
482 | printk(KERN_ERR "E: keydvt in: hnonce & dnonce\n"); | |
483 | wusb_key_dump(&stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1)); | |
d59db761 | 484 | printk(KERN_ERR "E: keydvt out: KCK\n"); |
e43ace89 | 485 | wusb_key_dump(&keydvt_out.kck, sizeof(keydvt_out.kck)); |
d59db761 | 486 | printk(KERN_ERR "E: keydvt out: PTK\n"); |
e43ace89 | 487 | wusb_key_dump(&keydvt_out.ptk, sizeof(keydvt_out.ptk)); |
d59db761 IPG |
488 | result = -EINVAL; |
489 | } else | |
490 | result = 0; | |
491 | return result; | |
492 | } | |
493 | ||
494 | /* | |
495 | * Initialize crypto system | |
496 | * | |
497 | * FIXME: we do nothing now, other than verifying. Later on we'll | |
498 | * cache the encryption stuff, so that's why we have a separate init. | |
499 | */ | |
500 | int wusb_crypto_init(void) | |
501 | { | |
502 | int result; | |
503 | ||
d409f3bf DV |
504 | if (debug_crypto_verify) { |
505 | result = wusb_key_derive_verify(); | |
506 | if (result < 0) | |
507 | return result; | |
508 | return wusb_oob_mic_verify(); | |
509 | } | |
510 | return 0; | |
d59db761 IPG |
511 | } |
512 | ||
513 | void wusb_crypto_exit(void) | |
514 | { | |
515 | /* FIXME: free cached crypto transforms */ | |
516 | } |