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