1/*-
2 * Copyright (c) 2004 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") version 2 as published by the Free
18 * Software Foundation.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34/*
35 * CCMP test module.
36 *
37 * Test vectors come from section I.7.4 of P802.11i/D7.0, October 2003.
38 *
39 * To use this tester load the net80211 layer (either as a module or
40 * by statically configuring it into your kernel), then kldload this
41 * module.  It should automatically run all test cases and print
42 * information for each.  To run one or more tests you can specify a
43 * tests parameter to the module that is a bit mask of the set of tests
44 * you want; e.g. insmod ccmp_test tests=7 will run only test mpdu's
45 * 1, 2, and 3.
46 */
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/mbuf.h>
51#include <sys/module.h>
52
53#include <sys/socket.h>
54
55#include <net/if.h>
56#include <net/if_var.h>
57#include <net/if_media.h>
58
59#include <net80211/ieee80211_var.h>
60
61/*
62==== CCMP test mpdu   1 ====
63
64-- MPDU Fields
65
667  Version  = 0
678  Type     = 2   SubType  = 0  Data
689  ToDS     = 0   FromDS   = 0
6910  MoreFrag = 0   Retry    = 1
7011  PwrMgt   = 0   moreData = 0
7112  Encrypt  = 1
7213  Order    = 0
7314  Duration = 11459
7415  A1 = 0f-d2-e1-28-a5-7c    DA
7516  A2 = 50-30-f1-84-44-08    SA
7617  A3 = ab-ae-a5-b8-fc-ba    BSSID
7718  SC = 0x3380
7819  seqNum = 824 (0x0338)  fraqNum = 0 (0x00)
7920  Algorithm = AES_CCM
8021  Key ID = 0
8122  TK = c9 7c 1f 67 ce 37 11 85  51 4a 8a 19 f2 bd d5 2f
8223  PN = 199027030681356  (0xB5039776E70C)
8324  802.11 Header =  08 48 c3 2c 0f d2 e1 28 a5 7c 50 30 f1 84 44 08
8425  	ab ae a5 b8 fc ba 80 33
8526  Muted 802.11 Header =  08 40 0f d2 e1 28 a5 7c 50 30 f1 84 44 08
8627  	ab ae a5 b8 fc ba 00 00
8728  CCMP Header =  0c e7 00 20 76 97 03 b5
8829  CCM Nonce = 00 50 30 f1 84 44 08 b5  03 97 76 e7 0c
8930 Plaintext Data = f8 ba 1a 55 d0 2f 85 ae 96 7b b6 2f b6 cd a8 eb
901	7e 78 a0 50
912  CCM MIC =  78 45 ce 0b 16 f9 76 23
923  -- Encrypted MPDU with FCS
934  08 48 c3 2c 0f d2 e1 28 a5 7c 50 30 f1 84 44 08 ab ae a5 b8 fc ba
945  80 33 0c e7 00 20 76 97 03 b5 f3 d0 a2 fe 9a 3d bf 23 42 a6 43 e4
956  32 46 e8 0c 3c 04 d0 19 78 45 ce 0b 16 f9 76 23 1d 99 f0 66
96*/
97static const u_int8_t test1_key[] = {		/* TK */
98	0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85,  0x51, 0x4a, 0x8a,
99	0x19, 0xf2, 0xbd, 0xd5, 0x2f
100};
101static const u_int8_t test1_plaintext[] = {	/* Plaintext MPDU w/o MIC */
102	0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,	/* 802.11 Header */
103	0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
104	0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
105	0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,	/* Plaintext Data */
106	0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
107	0x7e, 0x78, 0xa0, 0x50,
108};
109static const u_int8_t test1_encrypted[] = {	/* Encrypted MPDU with MIC */
110	0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
111	0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
112	0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
113	0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5,
114	0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23,
115	0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c,
116	0x3c, 0x04, 0xd0, 0x19, 0x78, 0x45, 0xce, 0x0b,
117	0x16, 0xf9, 0x76, 0x23,
118};
119
120/*
121==== CCMP test mpdu   2 ====
122
123-- MPDU Fields
124
125 9  Version  = 0
12610  Type     = 2   SubType  = 3  Data+CF-Ack+CF-Poll
12711  ToDS     = 0   FromDS   = 0
12812  MoreFrag = 0   Retry    = 0
12913  PwrMgt   = 0   moreData = 0
13014  Encrypt  = 1
13115  Order    = 1
13216  Duration = 20842
13317  A1 = ea-10-0c-84-68-50    DA
13418  A2 = ee-c1-76-2c-88-de    SA
13519  A3 = af-2e-e9-f4-6a-07    BSSID
13620  SC = 0xCCE0
13721  seqNum = 3278 (0x0CCE)  fraqNum = 0 (0x00)
13822  Algorithm = AES_CCM
13923  Key ID = 2
14024  TK = 8f 7a 05 3f a5 77 a5 59  75 29 27 20 97 a6 03 d5
14125  PN = 54923164817386  (0x31F3CBBA97EA)
14226  802.11 Header =  38 c0 6a 51 ea 10 0c 84 68 50 ee c1 76 2c 88 de
14327  	af 2e e9 f4 6a 07 e0 cc
14428  Muted 802.11 Header =  08 c0 ea 10 0c 84 68 50 ee c1 76 2c 88 de
14529  	af 2e e9 f4 6a 07 00 00
14630  CCMP Header =  ea 97 00 a0 ba cb f3 31
14731  CCM Nonce = 00 ee c1 76 2c 88 de 31  f3 cb ba 97 ea
14832  Plaintext Data = 83 a0 63 4b 5e d7 62 7e b9 df 22 5e 05 74 03 42
14933  	de 19 41 17
15034  CCM MIC =  54 2f bf 8d a0 6a a4 ae
15135  -- Encrypted MPDU with FCS
15236  38 c0 6a 51 ea 10 0c 84 68 50 ee c1 76 2c 88 de af 2e e9 f4 6a 07
15337  e0 cc ea 97 00 a0 ba cb f3 31 81 4b 69 65 d0 5b f2 b2 ed 38 d4 be
15438  b0 69 fe 82 71 4a 61 0b 54 2f bf 8d a0 6a a4 ae 25 3c 47 38
155*/
156static const u_int8_t test2_key[] = {		/* TK */
157	0x8f, 0x7a, 0x05, 0x3f, 0xa5, 0x77, 0xa5, 0x59,  0x75, 0x29, 0x27,
158	0x20, 0x97, 0xa6, 0x03, 0xd5
159};
160static const u_int8_t test2_plaintext[] = {	/* Plaintext MPDU w/o MIC */
161	0x38, 0xc0, 0x6a, 0x51, 0xea, 0x10, 0x0c, 0x84, 0x68, 0x50, 0xee,
162	0xc1, 0x76, 0x2c, 0x88, 0xde, 0xaf, 0x2e, 0xe9, 0xf4, 0x6a, 0x07,
163	0xe0, 0xcc,
164	0x83, 0xa0, 0x63, 0x4b, 0x5e, 0xd7, 0x62, 0x7e, 0xb9, 0xdf, 0x22,
165	0x5e, 0x05, 0x74, 0x03, 0x42, 0xde, 0x19, 0x41, 0x17
166};
167static const u_int8_t test2_encrypted[] = {	/* Encrypted MPDU with MIC */
168	0x38, 0xc0, 0x6a, 0x51, 0xea, 0x10, 0x0c, 0x84, 0x68, 0x50, 0xee,
169	0xc1, 0x76, 0x2c, 0x88, 0xde, 0xaf, 0x2e, 0xe9, 0xf4, 0x6a, 0x07,
170	0xe0, 0xcc, 0xea, 0x97, 0x00, 0xa0, 0xba, 0xcb, 0xf3, 0x31, 0x81,
171	0x4b, 0x69, 0x65, 0xd0, 0x5b, 0xf2, 0xb2, 0xed, 0x38, 0xd4, 0xbe,
172	0xb0, 0x69, 0xfe, 0x82, 0x71, 0x4a, 0x61, 0x0b, 0x54, 0x2f, 0xbf,
173	0x8d, 0xa0, 0x6a, 0xa4, 0xae,
174};
175
176/*
177==== CCMP test mpdu   3 ====
178
179-- MPDU Fields
180
18141  Version  = 0
18242  Type     = 2   SubType  = 11
18343  ToDS     = 0   FromDS   = 0
18444  MoreFrag = 0   Retry    = 1
18545  PwrMgt   = 0   moreData = 0
18646  Encrypt  = 1
18747  Order    = 1
18848  Duration = 25052
18949  A1 = d9-57-7d-f7-63-c8    DA
19050 A2 = b6-a8-8a-df-36-91    SA
1911  A3 = dc-4a-8b-ca-94-dd    BSSID
1922  SC = 0x8260
1933  seqNum = 2086 (0x0826)  fraqNum = 0 (0x00)
1944  QC = 0x0000
1955  MSDU Priority = 0 (0x0)
1966  Algorithm = AES_CCM
1977  Key ID = 2
1988  TK = 40 cf b7 a6 2e 88 01 3b  d6 d3 af fc c1 91 04 1e
1999  PN = 52624639632814  (0x2FDCA0F3A5AE)
20010  802.11 Header =  b8 c8 dc 61 d9 57 7d f7 63 c8 b6 a8 8a df 36 91
20111  	dc 4a 8b ca 94 dd 60 82 20 85
20212  Muted 802.11 Header =  88 c0 d9 57 7d f7 63 c8 b6 a8 8a df 36 91
20313  	dc 4a 8b ca 94 dd 00 00 00 00
20414  CCMP Header =  ae a5 00 a0 f3 a0 dc 2f
20515  CCM Nonce = 00 b6 a8 8a df 36 91 2f dc a0 f3 a5 ae
20616  Plaintext Data  = 2c 1b d0 36 83 1c 95 49 6c 5f 4d bf 3d 55 9e 72
20717  	de 80 2a 18
20818  CCM MIC =  fd 1f 1f 61 a9 fb 4b b3
20919  -- Encrypted MPDU with FCS
21020  b8 c8 dc 61 d9 57 7d f7 63 c8 b6 a8 8a df 36 91 dc 4a 8b ca 94 dd
21121  60 82 20 85 ae a5 00 a0 f3 a0 dc 2f 89 d8 58 03 40 b6 26 a0 b6 d4
21222  d0 13 bf 18 f2 91 b8 96 46 c8 fd 1f 1f 61 a9 fb 4b b3 60 3f 5a ad
213*/
214static const u_int8_t test3_key[] = {		/* TK */
215	0x40, 0xcf, 0xb7, 0xa6, 0x2e, 0x88, 0x01, 0x3b,  0xd6, 0xd3,
216	0xaf, 0xfc, 0xc1, 0x91, 0x04, 0x1e
217};
218static const u_int8_t test3_plaintext[] = {	/* Plaintext MPDU w/o MIC */
219	0xb8, 0xc8, 0xdc, 0x61, 0xd9, 0x57, 0x7d, 0xf7, 0x63, 0xc8,
220	0xb6, 0xa8, 0x8a, 0xdf, 0x36, 0x91, 0xdc, 0x4a, 0x8b, 0xca,
221	0x94, 0xdd, 0x60, 0x82, 0x20, 0x85,
222	0x2c, 0x1b, 0xd0, 0x36, 0x83, 0x1c, 0x95, 0x49, 0x6c, 0x5f,
223	0x4d, 0xbf, 0x3d, 0x55, 0x9e, 0x72, 0xde, 0x80, 0x2a, 0x18
224};
225static const u_int8_t test3_encrypted[] = {	/* Encrypted MPDU with MIC */
226	0xb8, 0xc8, 0xdc, 0x61, 0xd9, 0x57, 0x7d, 0xf7, 0x63, 0xc8,
227	0xb6, 0xa8, 0x8a, 0xdf, 0x36, 0x91, 0xdc, 0x4a, 0x8b, 0xca,
228	0x94, 0xdd, 0x60, 0x82, 0x20, 0x85, 0xae, 0xa5, 0x00, 0xa0,
229	0xf3, 0xa0, 0xdc, 0x2f, 0x89, 0xd8, 0x58, 0x03, 0x40, 0xb6,
230	0x26, 0xa0, 0xb6, 0xd4, 0xd0, 0x13, 0xbf, 0x18, 0xf2, 0x91,
231	0xb8, 0x96, 0x46, 0xc8, 0xfd, 0x1f, 0x1f, 0x61, 0xa9, 0xfb,
232	0x4b, 0xb3,
233};
234
235/*
236==== CCMP test mpdu  4 ====
237
238-- MPDU Fields
23925  Version  = 0
24026  Type     = 2   SubType  = 10
24127  ToDS     = 0   FromDS   = 1
24228  MoreFrag = 0   Retry    = 1
24329  PwrMgt   = 0   moreData = 0
24430  Encrypt  = 1
24531  Order    = 1
24632  Duration = 4410
24733  A1 = 71-2a-9d-df-11-db    DA
24834  A2 = 8e-f8-22-73-47-01    BSSID
24935  A3 = 59-14-0d-d6-46-a2    SA
25036  SC = 0x2FC0
25137  seqNum = 764 (0x02FC)  fraqNum = 0 (0x00)
25238  QC = 0x0007
25339  MSDU Priority = 7 (0x0)
25440  Algorithm = AES_CCM
25541  Key ID = 0
25642  TK = 8c 89 a2 eb c9 6c 76 02  70 7f cf 24 b3 2d 38 33
25743  PN = 270963670912995  (0xF670A55A0FE3)
25844  802.11 Header =  a8 ca 3a 11 71 2a 9d df 11 db 8e f8 22 73 47 01
25945  	59 14 0d d6 46 a2 c0 2f 67 a5
26046  Muted 802.11 Header =  88 c2 71 2a 9d df 11 db 8e f8 22 73 47 01
26147  	59 14 0d d6 46 a2 00 00 07 00
26248  CCMP Header =  e3 0f 00 20 5a a5 70 f6
26349  CCM Nonce = 07 8e f8 22 73 47 01 f6  70 a5 5a 0f e3
26450  Plaintext Data = 4f ad 2b 1c 29 0f a5 eb d8 72 fb c3 f3 a0 74 89
26551  	8f 8b 2f bb
26652  CCM MIC =  31 fc 88 00 4f 35 ee 3d
267-- Encrypted MPDU with FCS
2682  a8 ca 3a 11 71 2a 9d df 11 db 8e f8 22 73 47 01 59 14 0d d6 46 a2
2693  c0 2f 67 a5 e3 0f 00 20 5a a5 70 f6 9d 59 b1 5f 37 14 48 c2 30 f4
2704  d7 39 05 2e 13 ab 3b 1a 7b 10 31 fc 88 00 4f 35 ee 3d 45 a7 4a 30
271*/
272static const u_int8_t test4_key[] = {		/* TK */
273	0x8c, 0x89, 0xa2, 0xeb, 0xc9, 0x6c, 0x76, 0x02,
274	0x70, 0x7f, 0xcf, 0x24, 0xb3, 0x2d, 0x38, 0x33,
275};
276static const u_int8_t test4_plaintext[] = {	/* Plaintext MPDU w/o MIC */
277	0xa8, 0xca, 0x3a, 0x11, 0x71, 0x2a, 0x9d, 0xdf, 0x11, 0xdb,
278	0x8e, 0xf8, 0x22, 0x73, 0x47, 0x01, 0x59, 0x14, 0x0d, 0xd6,
279	0x46, 0xa2, 0xc0, 0x2f, 0x67, 0xa5,
280	0x4f, 0xad, 0x2b, 0x1c, 0x29, 0x0f, 0xa5, 0xeb, 0xd8, 0x72,
281	0xfb, 0xc3, 0xf3, 0xa0, 0x74, 0x89, 0x8f, 0x8b, 0x2f, 0xbb,
282};
283static const u_int8_t test4_encrypted[] = {	/* Encrypted MPDU with MIC */
284	0xa8, 0xca, 0x3a, 0x11, 0x71, 0x2a, 0x9d, 0xdf, 0x11, 0xdb,
285	0x8e, 0xf8, 0x22, 0x73, 0x47, 0x01, 0x59, 0x14, 0x0d, 0xd6,
286	0x46, 0xa2, 0xc0, 0x2f, 0x67, 0xa5, 0xe3, 0x0f, 0x00, 0x20,
287	0x5a, 0xa5, 0x70, 0xf6, 0x9d, 0x59, 0xb1, 0x5f, 0x37, 0x14,
288	0x48, 0xc2, 0x30, 0xf4, 0xd7, 0x39, 0x05, 0x2e, 0x13, 0xab,
289	0x3b, 0x1a, 0x7b, 0x10, 0x31, 0xfc, 0x88, 0x00, 0x4f, 0x35,
290	0xee, 0x3d,
291};
292
293/*
294==== CCMP test mpdu   5 ====
295
296-- MPDU Fields
297
2987  Version  = 0
2998  Type     = 2   SubType  = 8
3009  ToDS     = 0   FromDS   = 1
30110  MoreFrag = 0   Retry    = 1
30211  PwrMgt   = 1   moreData = 0
30312  Encrypt  = 1
30413  Order    = 1
30514  Duration = 16664
30615  A1 = 45-de-c6-9a-74-80    DA
30716  A2 = f3-51-94-6b-c9-6b    BSSID
30817  A3 = e2-76-fb-e6-c1-27    SA
30918  SC = 0xF280
31019  seqNum = 3880 (0x0F28)  fraqNum = 0 (0x00)
31120  QC = 0x000b
31221  MSDU Priority = 0 (0x0)
31322  Algorithm = AES_CCM
31423  Key ID = 2
31524  TK = a5 74 d5 14 3b b2 5e fd  de ff 30 12 2f df d0 66
31625  PN = 184717420531255  (0xA7FFE03C0E37)
31726  802.11 Header =  88 da 18 41 45 de c6 9a 74 80 f3 51 94 6b c9 6b
31827  	e2 76 fb e6 c1 27 80 f2 4b 19
31928  Muted 802.11 Header =  88 c2 45 de c6 9a 74 80 f3 51 94 6b c9 6b
32029  	e2 76 fb e6 c1 27 00 00 0b 00
32130  CCMP Header =  37 0e 00 a0 3c e0 ff a7
32231  CCM Nonce = 0b f3 51 94 6b c9 6b a7 ff e0 3c 0e 37
32332  Plaintext Data = 28 96 9b 95 4f 26 3a 80 18 a9 ef 70 a8 b0 51 46
32433  	24 81 92 2e
32534  CCM MIC =  ce 0c 3b e1 97 d3 05 eb
32635  -- Encrypted MPDU with FCS
32736  88 da 18 41 45 de c6 9a 74 80 f3 51 94 6b c9 6b e2 76 fb e6 c1 27
32837  80 f2 4b 19 37 0e 00 a0 3c e0 ff a7 eb 4a e4 95 6a 80 1d a9 62 4b
32938  7e 0c 18 b2 3e 61 5e c0 3a f6 ce 0c 3b e1 97 d3 05 eb c8 9e a1 b5
330*/
331static const u_int8_t test5_key[] = {		/* TK */
332	0xa5, 0x74, 0xd5, 0x14, 0x3b, 0xb2, 0x5e, 0xfd,
333	0xde, 0xff, 0x30, 0x12, 0x2f, 0xdf, 0xd0, 0x66,
334};
335static const u_int8_t test5_plaintext[] = {	/* Plaintext MPDU w/o MIC */
336	0x88, 0xda, 0x18, 0x41, 0x45, 0xde, 0xc6, 0x9a, 0x74, 0x80,
337	0xf3, 0x51, 0x94, 0x6b, 0xc9, 0x6b, 0xe2, 0x76, 0xfb, 0xe6,
338	0xc1, 0x27, 0x80, 0xf2, 0x4b, 0x19,
339	0x28, 0x96, 0x9b, 0x95, 0x4f, 0x26, 0x3a, 0x80, 0x18, 0xa9,
340	0xef, 0x70, 0xa8, 0xb0, 0x51, 0x46, 0x24, 0x81, 0x92, 0x2e,
341};
342static const u_int8_t test5_encrypted[] = {	/* Encrypted MPDU with MIC */
343	0x88, 0xda, 0x18, 0x41, 0x45, 0xde, 0xc6, 0x9a, 0x74, 0x80,
344	0xf3, 0x51, 0x94, 0x6b, 0xc9, 0x6b, 0xe2, 0x76, 0xfb, 0xe6,
345	0xc1, 0x27, 0x80, 0xf2, 0x4b, 0x19, 0x37, 0x0e, 0x00, 0xa0,
346	0x3c, 0xe0, 0xff, 0xa7, 0xeb, 0x4a, 0xe4, 0x95, 0x6a, 0x80,
347	0x1d, 0xa9, 0x62, 0x4b, 0x7e, 0x0c, 0x18, 0xb2, 0x3e, 0x61,
348	0x5e, 0xc0, 0x3a, 0xf6, 0xce, 0x0c, 0x3b, 0xe1, 0x97, 0xd3,
349	0x05, 0xeb,
350};
351
352/*
353==== CCMP test mpdu   6 ====
354
355-- MPDU Fields
356
35741  Version  = 0
35842  Type     = 2   SubType  = 8
35943  ToDS     = 0   FromDS   = 1
36044  MoreFrag = 0   Retry    = 0
36145  PwrMgt   = 1   moreData = 0
36246  Encrypt  = 1
36347  Order    = 0
36448  Duration = 8161
36549  A1 = 5a-f2-84-30-fd-ab    DA
36650  A2 = bf-f9-43-b9-f9-a6    BSSID
3671   A3 = ab-1d-98-c7-fe-73    SA
3682  SC = 0x7150
3693  seqNum = 1813 (0x0715)  fraqNum = 0 (0x00)
3704  QC = 0x000d
3715  PSDU Priority = 13 (0xd)
3726  Algorithm = AES_CCM
3737  Key ID = 1
3748  TK = f7 1e ea 4e 1f 58 80 4b 97 17 23 0a d0 61 46 41
3759  PN    = 118205765159305  (0x6B81ECA48989)
37610  802.11 Header =  88 52 e1 1f 5a f2 84 30 fd ab bf f9 43 b9 f9 a6
37711  	ab 1d 98 c7 fe 73 50 71  3d 6a
37812  Muted 802.11 Header =  88 42 5a f2 84 30 fd ab bf f9 43 b9 f9 a6
37913  	ab 1d 98 c7 fe 73 00 00 0d 00
38014  CCMP Header =  89 89 00 60 a4 ec 81 6b
38115  CCM Nonce = 0d bf f9 43 b9 f9 a6 6b  81 ec a4 89 89
38216  Plaintext Data = ab fd a2 2d 3a 0b fc 9c c1 fc 07 93 63 c2 fc a1
38317  	43 e6 eb 1d
38418  CCM MIC =  30 9a 8d 5c 46 6b bb 71
38519  -- Encrypted MPDU with FCS
38620  88 52 e1 1f 5a f2 84 30 fd ab bf f9 43 b9 f9 a6 ab 1d 98 c7 fe 73
38721  50 71 3d 6a 89 89 00 60 a4 ec 81 6b 9a 70 9b 60 a3 9d 40 b1 df b6
38822  12 e1 8b 5f 11 4b ad b6 cc 86 30 9a 8d 5c 46 6b bb 71 86 c0 4e 97
389*/
390static const u_int8_t test6_key[] = {		/* TK */
391	0xf7, 0x1e, 0xea, 0x4e, 0x1f, 0x58, 0x80, 0x4b,
392	0x97, 0x17, 0x23, 0x0a, 0xd0, 0x61, 0x46, 0x41,
393};
394static const u_int8_t test6_plaintext[] = {	/* Plaintext MPDU w/o MIC */
395	0x88, 0x52, 0xe1, 0x1f, 0x5a, 0xf2, 0x84, 0x30, 0xfd, 0xab,
396	0xbf, 0xf9, 0x43, 0xb9, 0xf9, 0xa6, 0xab, 0x1d, 0x98, 0xc7,
397	0xfe, 0x73, 0x50, 0x71, 0x3d, 0x6a,
398	0xab, 0xfd, 0xa2, 0x2d, 0x3a, 0x0b, 0xfc, 0x9c, 0xc1, 0xfc,
399	0x07, 0x93, 0x63, 0xc2, 0xfc, 0xa1, 0x43, 0xe6, 0xeb, 0x1d,
400};
401static const u_int8_t test6_encrypted[] = {	/* Encrypted MPDU with MIC */
402	0x88, 0x52, 0xe1, 0x1f, 0x5a, 0xf2, 0x84, 0x30, 0xfd, 0xab,
403	0xbf, 0xf9, 0x43, 0xb9, 0xf9, 0xa6, 0xab, 0x1d, 0x98, 0xc7,
404	0xfe, 0x73, 0x50, 0x71, 0x3d, 0x6a, 0x89, 0x89, 0x00, 0x60,
405	0xa4, 0xec, 0x81, 0x6b, 0x9a, 0x70, 0x9b, 0x60, 0xa3, 0x9d,
406	0x40, 0xb1, 0xdf, 0xb6, 0x12, 0xe1, 0x8b, 0x5f, 0x11, 0x4b,
407	0xad, 0xb6, 0xcc, 0x86, 0x30, 0x9a, 0x8d, 0x5c, 0x46, 0x6b,
408	0xbb, 0x71,
409};
410
411/*
412==== CCMP test mpdu   7 ====
413
414-- MPDU Fields
415
41625  Version  = 0
41726  Type     = 2   SubType  = 1  Data+CF-Ack
41827  ToDS     = 1   FromDS   = 0
41928  MoreFrag = 0   Retry    = 1
42029  PwrMgt   = 1   moreData = 1
42130  Encrypt  = 1
42231  Order    = 0
42332  Duration = 18049
42433  A1 = 9b-50-f4-fd-56-f6    BSSID
42534  A2 = ef-ec-95-20-16-91    SA
42635  A3 = 83-57-0c-4c-cd-ee    DA
42736  SC = 0xA020
42837  seqNum = 2562 (0x0A02)  fraqNum = 0 (0x00)
42938  Algorithm = AES_CCM
43039  Key ID = 3
43140  TK = 1b db 34 98 0e 03 81 24 a1 db 1a 89 2b ec 36 6a
43241  PN = 104368786630435  (0x5EEC4073E723)
43342  Header =  18 79 81 46 9b 50 f4 fd 56 f6 ef ec 95 20 16 91 83 57
43443  	0c 4c cd ee 20 a0
43544  Muted MAC Header =  08 41 9b 50 f4 fd 56 f6 ef ec 95 20 16 91
43645  	83 57 0c 4c cd ee 00 00
43746  CCMP Header =  23 e7 00 e0 73 40 ec 5e
43847  CCM Nonce = 00 ef ec 95 20 16 91 5e ec 40 73 e7 23
43948  Plaintext Data = 98 be ca 86 f4 b3 8d a2 0c fd f2 47 24 c5 8e b8
44049  	35 66 53 39
44150  CCM MIC =  2d 09 57 ec fa be 95 b9
442-- Encrypted MPDU with FCS
4431  18 79 81 46 9b 50 f4 fd 56 f6 ef ec 95 20 16 91 83 57 0c 4c cd ee
4442  20 a0 23 e7 00 e0 73 40 ec 5e 12 c5 37 eb f3 ab 58 4e f1 fe f9 a1
4453  f3 54 7a 8c 13 b3 22 5a 2d 09 57 ec fa be 95 b9 aa fa 0c c8
446*/
447static const u_int8_t test7_key[] = {		/* TK */
448	0x1b, 0xdb, 0x34, 0x98, 0x0e, 0x03, 0x81, 0x24,
449	0xa1, 0xdb, 0x1a, 0x89, 0x2b, 0xec, 0x36, 0x6a,
450};
451static const u_int8_t test7_plaintext[] = {	/* Plaintext MPDU w/o MIC */
452	0x18, 0x79, 0x81, 0x46, 0x9b, 0x50, 0xf4, 0xfd, 0x56, 0xf6,
453	0xef, 0xec, 0x95, 0x20, 0x16, 0x91, 0x83, 0x57, 0x0c, 0x4c,
454	0xcd, 0xee, 0x20, 0xa0,
455	0x98, 0xbe, 0xca, 0x86, 0xf4, 0xb3, 0x8d, 0xa2, 0x0c, 0xfd,
456	0xf2, 0x47, 0x24, 0xc5, 0x8e, 0xb8, 0x35, 0x66, 0x53, 0x39,
457};
458static const u_int8_t test7_encrypted[] = {	/* Encrypted MPDU with MIC */
459	0x18, 0x79, 0x81, 0x46, 0x9b, 0x50, 0xf4, 0xfd, 0x56, 0xf6,
460	0xef, 0xec, 0x95, 0x20, 0x16, 0x91, 0x83, 0x57, 0x0c, 0x4c,
461	0xcd, 0xee, 0x20, 0xa0, 0x23, 0xe7, 0x00, 0xe0, 0x73, 0x40,
462	0xec, 0x5e, 0x12, 0xc5, 0x37, 0xeb, 0xf3, 0xab, 0x58, 0x4e,
463	0xf1, 0xfe, 0xf9, 0xa1, 0xf3, 0x54, 0x7a, 0x8c, 0x13, 0xb3,
464	0x22, 0x5a, 0x2d, 0x09, 0x57, 0xec, 0xfa, 0xbe, 0x95, 0xb9,
465};
466
467/*
468==== CCMP test mpdu   8 ====
469
470-- MPDU Fields
471
4726  Version  = 0
4737  Type     = 2   SubType  = 11
4748  ToDS     = 1   FromDS   = 0
4759  MoreFrag = 0   Retry    = 1
47610  PwrMgt   = 1   moreData = 0
47711  Encrypt  = 1
47812  Order    = 1
47913  Duration = 29260
48014  A1 = 55-2d-5f-72-bb-70    BSSID
48115  A2 = ca-3f-3a-ae-60-c4    SA
48216  A3 = 8b-a9-b5-f8-2c-2f    DA
48317  SC = 0xEB50
48418  seqNum = 3765 (0x0EB5)  fraqNum = 0 (0x00)
48519  QC = 0x000a
48620  MSDU Priority = 10 (0xa)
48721  Algorithm = AES_CCM
48822  Key ID = 2
48923  TK = 6e ac 1b f5 4b d5 4e db 23 21 75 43 03 02 4c 71
49024  PN    = 227588596223197  (0xCEFD996ECCDD)
49125  802.11 Header =  b8 d9 4c 72 55 2d 5f 72 bb 70 ca 3f 3a ae 60 c4
49226  	8b a9 b5 f8 2c 2f 50 eb 2a 55
49327  Muted 802.11 Header =  88 c1 55 2d 5f 72 bb 70 ca 3f 3a ae 60 c4
49428  	8b a9 b5 f8 2c 2f 00 00 0a 00
49529  CCMP Header =  dd cc 00 a0 6e 99 fd ce
49630  CCM Nonce = 0a ca 3f 3a ae 60 c4 ce fd 99 6e cc dd
49731  Plaintext Data = 57 cb 5c 0e 5f cd 88 5e 9a 42 39 e9 b9 ca d6 0d
49832  	64 37 59 79
49933  CCM MIC =  6d ba 8e f7 f0 80 87 dd
500-- Encrypted MPDU with FCS
50135  b8 d9 4c 72 55 2d 5f 72 bb 70 ca 3f 3a ae 60 c4 8b a9 b5 f8 2c 2f
50236  50 eb 2a 55 dd cc 00 a0 6e 99 fd ce 4b f2 81 ef 8e c7 73 9f 91 59
50337  1b 97 a8 7d c1 4b 3f a1 74 62 6d ba 8e f7 f0 80 87 dd 0c 65 74 3f
504*/
505static const u_int8_t test8_key[] = {		/* TK */
506	0x6e, 0xac, 0x1b, 0xf5, 0x4b, 0xd5, 0x4e, 0xdb,
507	0x23, 0x21, 0x75, 0x43, 0x03, 0x02, 0x4c, 0x71,
508};
509static const u_int8_t test8_plaintext[] = {	/* Plaintext MPDU w/o MIC */
510	0xb8, 0xd9, 0x4c, 0x72, 0x55, 0x2d, 0x5f, 0x72, 0xbb, 0x70,
511	0xca, 0x3f, 0x3a, 0xae, 0x60, 0xc4, 0x8b, 0xa9, 0xb5, 0xf8,
512	0x2c, 0x2f, 0x50, 0xeb, 0x2a, 0x55,
513	0x57, 0xcb, 0x5c, 0x0e, 0x5f, 0xcd, 0x88, 0x5e, 0x9a, 0x42,
514	0x39, 0xe9, 0xb9, 0xca, 0xd6, 0x0d, 0x64, 0x37, 0x59, 0x79,
515};
516static const u_int8_t test8_encrypted[] = {	/* Encrypted MPDU with MIC */
517	0xb8, 0xd9, 0x4c, 0x72, 0x55, 0x2d, 0x5f, 0x72, 0xbb, 0x70,
518	0xca, 0x3f, 0x3a, 0xae, 0x60, 0xc4, 0x8b, 0xa9, 0xb5, 0xf8,
519	0x2c, 0x2f, 0x50, 0xeb, 0x2a, 0x55, 0xdd, 0xcc, 0x00, 0xa0,
520	0x6e, 0x99, 0xfd, 0xce, 0x4b, 0xf2, 0x81, 0xef, 0x8e, 0xc7,
521	0x73, 0x9f, 0x91, 0x59, 0x1b, 0x97, 0xa8, 0x7d, 0xc1, 0x4b,
522	0x3f, 0xa1, 0x74, 0x62, 0x6d, 0xba, 0x8e, 0xf7, 0xf0, 0x80,
523	0x87, 0xdd,
524};
525
526#define	TEST(n,name,cipher,keyix,pn) { \
527	name, IEEE80211_CIPHER_##cipher,keyix, pn##LL, \
528	test##n##_key,   sizeof(test##n##_key), \
529	test##n##_plaintext, sizeof(test##n##_plaintext), \
530	test##n##_encrypted, sizeof(test##n##_encrypted) \
531}
532
533struct ciphertest {
534	const char	*name;
535	int		cipher;
536	int		keyix;
537	u_int64_t	pn;
538	const u_int8_t	*key;
539	size_t		key_len;
540	const u_int8_t	*plaintext;
541	size_t		plaintext_len;
542	const u_int8_t	*encrypted;
543	size_t		encrypted_len;
544} ccmptests[] = {
545	TEST(1, "CCMP test mpdu 1", AES_CCM, 0, 199027030681356),
546	TEST(2, "CCMP test mpdu 2", AES_CCM, 2, 54923164817386),
547	TEST(3, "CCMP test mpdu 3", AES_CCM, 2, 52624639632814),
548	TEST(4, "CCMP test mpdu 4", AES_CCM, 0, 270963670912995),
549	TEST(5, "CCMP test mpdu 5", AES_CCM, 2, 184717420531255),
550	TEST(6, "CCMP test mpdu 6", AES_CCM, 1, 118205765159305),
551	TEST(7, "CCMP test mpdu 7", AES_CCM, 3, 104368786630435),
552	TEST(8, "CCMP test mpdu 8", AES_CCM, 2, 227588596223197),
553};
554
555static void
556dumpdata(const char *tag, const void *p, size_t len)
557{
558	int i;
559
560	printf("%s: 0x%p len %u", tag, p, len);
561	for (i = 0; i < len; i++) {
562		if ((i % 16) == 0)
563			printf("\n%03d:", i);
564		printf(" %02x", ((const u_int8_t *)p)[i]);
565	}
566	printf("\n");
567}
568
569static void
570cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen)
571{
572	int i;
573
574	for (i = 0; i < genlen; i++)
575		if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) {
576			printf("first difference at byte %u\n", i);
577			break;
578		}
579	dumpdata("Generated", gen, genlen);
580	dumpdata("Reference", ref, reflen);
581}
582
583static void
584printtest(const struct ciphertest *t)
585{
586	printf("keyix %u pn %llu key_len %u plaintext_len %u\n"
587		, t->keyix
588		, t->pn
589		, t->key_len
590		, t->plaintext_len
591	);
592}
593
594static int
595runtest(struct ieee80211vap *vap, struct ciphertest *t)
596{
597	struct ieee80211_key *key = &vap->iv_nw_keys[t->keyix];
598	struct mbuf *m = NULL;
599	const struct ieee80211_cipher *cip;
600	int hdrlen;
601
602	printf("%s: ", t->name);
603
604	/*
605	 * Setup key.
606	 */
607	memset(key, 0, sizeof(*key));
608	key->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
609	key->wk_cipher = &ieee80211_cipher_none;
610	if (!ieee80211_crypto_newkey(vap, t->cipher,
611	    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) {
612		printf("FAIL: ieee80211_crypto_newkey failed\n");
613		goto bad;
614	}
615
616	memcpy(key->wk_key, t->key, t->key_len);
617	key->wk_keylen = t->key_len;
618	memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc));
619	key->wk_keytsc = t->pn-1;	/* PN-1 since we do encap */
620	if (!ieee80211_crypto_setkey(vap, key)) {
621		printf("FAIL: ieee80211_crypto_setkey failed\n");
622		goto bad;
623	}
624
625	/*
626	 * Craft frame from plaintext data.
627	 */
628	cip = key->wk_cipher;
629	m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
630	m->m_data += cip->ic_header;
631	memcpy(mtod(m, void *), t->plaintext, t->plaintext_len);
632	m->m_len = t->plaintext_len;
633	m->m_pkthdr.len = m->m_len;
634	hdrlen = ieee80211_anyhdrsize(mtod(m, void *));
635
636	/*
637	 * Encrypt frame w/ MIC.
638	 */
639	if (!cip->ic_encap(key, m)) {
640		printtest(t);
641		printf("FAIL: ccmp encap failed\n");
642		goto bad;
643	}
644	/*
645	 * Verify: frame length, frame contents.
646	 */
647	if (m->m_pkthdr.len != t->encrypted_len) {
648		printf("FAIL: encap data length mismatch\n");
649		printtest(t);
650		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
651			t->encrypted, t->encrypted_len);
652		goto bad;
653	} else if (memcmp(mtod(m, const void *), t->encrypted, t->encrypted_len)) {
654		printf("FAIL: encrypt data does not compare\n");
655		printtest(t);
656		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
657			t->encrypted, t->encrypted_len);
658		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
659		goto bad;
660	}
661
662	/*
663	 * Decrypt frame; strip MIC.
664	 */
665	if (!cip->ic_decap(key, m, hdrlen)) {
666		printf("FAIL: ccmp decap failed\n");
667		printtest(t);
668		cmpfail(mtod(m, const void *), m->m_len,
669			t->plaintext, t->plaintext_len);
670		goto bad;
671	}
672	/*
673	 * Verify: frame length, frame contents.
674	 */
675	if (m->m_pkthdr.len != t->plaintext_len) {
676		printf("FAIL: decap botch; length mismatch\n");
677		printtest(t);
678		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
679			t->plaintext, t->plaintext_len);
680		goto bad;
681	} else if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
682		printf("FAIL: decap botch; data does not compare\n");
683		printtest(t);
684		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
685			t->plaintext, t->plaintext_len);
686		goto bad;
687	}
688	m_freem(m);
689	ieee80211_crypto_delkey(vap, key);
690	printf("PASS\n");
691	return 1;
692bad:
693	if (m != NULL)
694		m_freem(m);
695	ieee80211_crypto_delkey(vap, key);
696	return 0;
697}
698
699/*
700 * Module glue.
701 */
702
703static	int tests = -1;
704static	int debug = 0;
705
706static int
707init_crypto_ccmp_test(void)
708{
709	struct ieee80211com ic;
710	struct ieee80211vap vap;
711	struct ifnet ifp;
712	int i, pass, total;
713
714	memset(&ic, 0, sizeof(ic));
715	memset(&vap, 0, sizeof(vap));
716	memset(&ifp, 0, sizeof(ifp));
717
718	ieee80211_crypto_attach(&ic);
719
720	/* some minimal initialization */
721	strncpy(ifp.if_xname, "test_ccmp", sizeof(ifp.if_xname));
722	vap.iv_ic = &ic;
723	vap.iv_ifp = &ifp;
724	if (debug)
725		vap.iv_debug = IEEE80211_MSG_CRYPTO;
726	ieee80211_crypto_vattach(&vap);
727
728	pass = 0;
729	total = 0;
730	for (i = 0; i < nitems(ccmptests); i++)
731		if (tests & (1<<i)) {
732			total++;
733			pass += runtest(&vap, &ccmptests[i]);
734		}
735	printf("%u of %u 802.11i AES-CCMP test vectors passed\n", pass, total);
736
737	ieee80211_crypto_vdetach(&vap);
738	ieee80211_crypto_detach(&ic);
739
740	return (pass == total ? 0 : -1);
741}
742
743static int
744test_ccmp_modevent(module_t mod, int type, void *unused)
745{
746	switch (type) {
747	case MOD_LOAD:
748		(void) init_crypto_ccmp_test();
749		return 0;
750	case MOD_UNLOAD:
751		return 0;
752	}
753	return EINVAL;
754}
755
756static moduledata_t test_ccmp_mod = {
757	"test_ccmp",
758	test_ccmp_modevent,
759	0
760};
761DECLARE_MODULE(test_ccmp, test_ccmp_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
762MODULE_VERSION(test_ccmp, 1);
763MODULE_DEPEND(test_ccmp, wlan, 1, 1, 1);
764