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