1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://opensource.org/licenses/CDDL-1.0.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2013 Saso Kiselkov. All rights reserved.
24  */
25 
26 /*
27  * This is just to keep the compiler happy about sys/time.h not declaring
28  * gettimeofday due to -D_KERNEL (we can do this since we're actually
29  * running in userspace, but we need -D_KERNEL for the remaining Skein code).
30  */
31 
32 #include <sys/skein.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <sys/time.h>
37 #include <sys/stdtypes.h>
38 
39 /*
40  * Skein test suite using values from the Skein V1.3 specification found at:
41  * http://www.skein-hash.info/sites/default/files/skein1.3.pdf
42  */
43 
44 /*
45  * Test messages from the Skein spec, Appendix C.
46  */
47 static const uint8_t	test_msg0[] = {
48 	0xFF
49 };
50 
51 static const uint8_t	test_msg1[] = {
52 	0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
53 	0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
54 	0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
55 	0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0
56 };
57 
58 static const uint8_t	test_msg2[] = {
59 	0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
60 	0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
61 	0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
62 	0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
63 	0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
64 	0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
65 	0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
66 	0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0
67 };
68 
69 static const uint8_t	test_msg3[] = {
70 	0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
71 	0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
72 	0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
73 	0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
74 	0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
75 	0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
76 	0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
77 	0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
78 	0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
79 	0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
80 	0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
81 	0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
82 	0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
83 	0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
84 	0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
85 	0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
86 };
87 
88 static const uint8_t	test_msg4[] = {
89 	0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
90 	0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
91 	0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
92 	0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
93 	0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
94 	0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
95 	0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
96 	0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
97 	0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
98 	0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
99 	0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
100 	0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
101 	0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
102 	0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
103 	0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
104 	0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
105 	0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78,
106 	0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
107 	0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68,
108 	0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
109 	0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58,
110 	0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
111 	0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
112 	0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
113 	0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
114 	0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
115 	0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28,
116 	0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
117 	0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
118 	0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
119 	0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
120 	0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
121 };
122 
123 /*
124  * Test digests from the Skein spec, Appendix C.
125  */
126 static const uint8_t	skein_256_test_digests[][32] = {
127 	{
128 		/* for test_msg0 */
129 		0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50,
130 		0xA7, 0xA2, 0x44, 0xC4, 0x44, 0xE2, 0x5C, 0x23,
131 		0xDA, 0x30, 0xC1, 0x0F, 0xC9, 0xA1, 0xF2, 0x70,
132 		0xA6, 0x63, 0x7F, 0x1F, 0x34, 0xE6, 0x7E, 0xD2
133 	},
134 	{
135 		/* for test_msg1 */
136 		0x8D, 0x0F, 0xA4, 0xEF, 0x77, 0x7F, 0xD7, 0x59,
137 		0xDF, 0xD4, 0x04, 0x4E, 0x6F, 0x6A, 0x5A, 0xC3,
138 		0xC7, 0x74, 0xAE, 0xC9, 0x43, 0xDC, 0xFC, 0x07,
139 		0x92, 0x7B, 0x72, 0x3B, 0x5D, 0xBF, 0x40, 0x8B
140 	},
141 	{
142 		/* for test_msg2 */
143 		0xDF, 0x28, 0xE9, 0x16, 0x63, 0x0D, 0x0B, 0x44,
144 		0xC4, 0xA8, 0x49, 0xDC, 0x9A, 0x02, 0xF0, 0x7A,
145 		0x07, 0xCB, 0x30, 0xF7, 0x32, 0x31, 0x82, 0x56,
146 		0xB1, 0x5D, 0x86, 0x5A, 0xC4, 0xAE, 0x16, 0x2F
147 	}
148 	/* no test digests for test_msg3 and test_msg4 */
149 };
150 
151 static const uint8_t	skein_512_test_digests[][64] = {
152 	{
153 		/* for test_msg0 */
154 		0x71, 0xB7, 0xBC, 0xE6, 0xFE, 0x64, 0x52, 0x22,
155 		0x7B, 0x9C, 0xED, 0x60, 0x14, 0x24, 0x9E, 0x5B,
156 		0xF9, 0xA9, 0x75, 0x4C, 0x3A, 0xD6, 0x18, 0xCC,
157 		0xC4, 0xE0, 0xAA, 0xE1, 0x6B, 0x31, 0x6C, 0xC8,
158 		0xCA, 0x69, 0x8D, 0x86, 0x43, 0x07, 0xED, 0x3E,
159 		0x80, 0xB6, 0xEF, 0x15, 0x70, 0x81, 0x2A, 0xC5,
160 		0x27, 0x2D, 0xC4, 0x09, 0xB5, 0xA0, 0x12, 0xDF,
161 		0x2A, 0x57, 0x91, 0x02, 0xF3, 0x40, 0x61, 0x7A
162 	},
163 	{
164 		/* no test vector for test_msg1 */
165 		0,
166 	},
167 	{
168 		/* for test_msg2 */
169 		0x45, 0x86, 0x3B, 0xA3, 0xBE, 0x0C, 0x4D, 0xFC,
170 		0x27, 0xE7, 0x5D, 0x35, 0x84, 0x96, 0xF4, 0xAC,
171 		0x9A, 0x73, 0x6A, 0x50, 0x5D, 0x93, 0x13, 0xB4,
172 		0x2B, 0x2F, 0x5E, 0xAD, 0xA7, 0x9F, 0xC1, 0x7F,
173 		0x63, 0x86, 0x1E, 0x94, 0x7A, 0xFB, 0x1D, 0x05,
174 		0x6A, 0xA1, 0x99, 0x57, 0x5A, 0xD3, 0xF8, 0xC9,
175 		0xA3, 0xCC, 0x17, 0x80, 0xB5, 0xE5, 0xFA, 0x4C,
176 		0xAE, 0x05, 0x0E, 0x98, 0x98, 0x76, 0x62, 0x5B
177 	},
178 	{
179 		/* for test_msg3 */
180 		0x91, 0xCC, 0xA5, 0x10, 0xC2, 0x63, 0xC4, 0xDD,
181 		0xD0, 0x10, 0x53, 0x0A, 0x33, 0x07, 0x33, 0x09,
182 		0x62, 0x86, 0x31, 0xF3, 0x08, 0x74, 0x7E, 0x1B,
183 		0xCB, 0xAA, 0x90, 0xE4, 0x51, 0xCA, 0xB9, 0x2E,
184 		0x51, 0x88, 0x08, 0x7A, 0xF4, 0x18, 0x87, 0x73,
185 		0xA3, 0x32, 0x30, 0x3E, 0x66, 0x67, 0xA7, 0xA2,
186 		0x10, 0x85, 0x6F, 0x74, 0x21, 0x39, 0x00, 0x00,
187 		0x71, 0xF4, 0x8E, 0x8B, 0xA2, 0xA5, 0xAD, 0xB7
188 	}
189 	/* no test digests for test_msg4 */
190 };
191 
192 static const uint8_t	skein_1024_test_digests[][128] = {
193 	{
194 		/* for test_msg0 */
195 		0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24,
196 		0x07, 0xCD, 0xD8, 0x78, 0x7F, 0xDA, 0x9E, 0x35,
197 		0x70, 0x3D, 0xE8, 0x62, 0xA4, 0xFB, 0xC1, 0x19,
198 		0xCF, 0xF8, 0x59, 0x0A, 0xFE, 0x79, 0x25, 0x0B,
199 		0xCC, 0xC8, 0xB3, 0xFA, 0xF1, 0xBD, 0x24, 0x22,
200 		0xAB, 0x5C, 0x0D, 0x26, 0x3F, 0xB2, 0xF8, 0xAF,
201 		0xB3, 0xF7, 0x96, 0xF0, 0x48, 0x00, 0x03, 0x81,
202 		0x53, 0x1B, 0x6F, 0x00, 0xD8, 0x51, 0x61, 0xBC,
203 		0x0F, 0xFF, 0x4B, 0xEF, 0x24, 0x86, 0xB1, 0xEB,
204 		0xCD, 0x37, 0x73, 0xFA, 0xBF, 0x50, 0xAD, 0x4A,
205 		0xD5, 0x63, 0x9A, 0xF9, 0x04, 0x0E, 0x3F, 0x29,
206 		0xC6, 0xC9, 0x31, 0x30, 0x1B, 0xF7, 0x98, 0x32,
207 		0xE9, 0xDA, 0x09, 0x85, 0x7E, 0x83, 0x1E, 0x82,
208 		0xEF, 0x8B, 0x46, 0x91, 0xC2, 0x35, 0x65, 0x65,
209 		0x15, 0xD4, 0x37, 0xD2, 0xBD, 0xA3, 0x3B, 0xCE,
210 		0xC0, 0x01, 0xC6, 0x7F, 0xFD, 0xE1, 0x5B, 0xA8
211 	},
212 	{
213 		/* no test vector for test_msg1 */
214 		0
215 	},
216 	{
217 		/* no test vector for test_msg2 */
218 		0
219 	},
220 	{
221 		/* for test_msg3 */
222 		0x1F, 0x3E, 0x02, 0xC4, 0x6F, 0xB8, 0x0A, 0x3F,
223 		0xCD, 0x2D, 0xFB, 0xBC, 0x7C, 0x17, 0x38, 0x00,
224 		0xB4, 0x0C, 0x60, 0xC2, 0x35, 0x4A, 0xF5, 0x51,
225 		0x18, 0x9E, 0xBF, 0x43, 0x3C, 0x3D, 0x85, 0xF9,
226 		0xFF, 0x18, 0x03, 0xE6, 0xD9, 0x20, 0x49, 0x31,
227 		0x79, 0xED, 0x7A, 0xE7, 0xFC, 0xE6, 0x9C, 0x35,
228 		0x81, 0xA5, 0xA2, 0xF8, 0x2D, 0x3E, 0x0C, 0x7A,
229 		0x29, 0x55, 0x74, 0xD0, 0xCD, 0x7D, 0x21, 0x7C,
230 		0x48, 0x4D, 0x2F, 0x63, 0x13, 0xD5, 0x9A, 0x77,
231 		0x18, 0xEA, 0xD0, 0x7D, 0x07, 0x29, 0xC2, 0x48,
232 		0x51, 0xD7, 0xE7, 0xD2, 0x49, 0x1B, 0x90, 0x2D,
233 		0x48, 0x91, 0x94, 0xE6, 0xB7, 0xD3, 0x69, 0xDB,
234 		0x0A, 0xB7, 0xAA, 0x10, 0x6F, 0x0E, 0xE0, 0xA3,
235 		0x9A, 0x42, 0xEF, 0xC5, 0x4F, 0x18, 0xD9, 0x37,
236 		0x76, 0x08, 0x09, 0x85, 0xF9, 0x07, 0x57, 0x4F,
237 		0x99, 0x5E, 0xC6, 0xA3, 0x71, 0x53, 0xA5, 0x78
238 	},
239 	{
240 		/* for test_msg4 */
241 		0x84, 0x2A, 0x53, 0xC9, 0x9C, 0x12, 0xB0, 0xCF,
242 		0x80, 0xCF, 0x69, 0x49, 0x1B, 0xE5, 0xE2, 0xF7,
243 		0x51, 0x5D, 0xE8, 0x73, 0x3B, 0x6E, 0xA9, 0x42,
244 		0x2D, 0xFD, 0x67, 0x66, 0x65, 0xB5, 0xFA, 0x42,
245 		0xFF, 0xB3, 0xA9, 0xC4, 0x8C, 0x21, 0x77, 0x77,
246 		0x95, 0x08, 0x48, 0xCE, 0xCD, 0xB4, 0x8F, 0x64,
247 		0x0F, 0x81, 0xFB, 0x92, 0xBE, 0xF6, 0xF8, 0x8F,
248 		0x7A, 0x85, 0xC1, 0xF7, 0xCD, 0x14, 0x46, 0xC9,
249 		0x16, 0x1C, 0x0A, 0xFE, 0x8F, 0x25, 0xAE, 0x44,
250 		0x4F, 0x40, 0xD3, 0x68, 0x00, 0x81, 0xC3, 0x5A,
251 		0xA4, 0x3F, 0x64, 0x0F, 0xD5, 0xFA, 0x3C, 0x3C,
252 		0x03, 0x0B, 0xCC, 0x06, 0xAB, 0xAC, 0x01, 0xD0,
253 		0x98, 0xBC, 0xC9, 0x84, 0xEB, 0xD8, 0x32, 0x27,
254 		0x12, 0x92, 0x1E, 0x00, 0xB1, 0xBA, 0x07, 0xD6,
255 		0xD0, 0x1F, 0x26, 0x90, 0x70, 0x50, 0x25, 0x5E,
256 		0xF2, 0xC8, 0xE2, 0x4F, 0x71, 0x6C, 0x52, 0xA5
257 	}
258 };
259 
260 int
261 main(int argc, char *argv[])
262 {
263 	boolean_t	failed = B_FALSE;
264 	uint64_t	cpu_mhz = 0;
265 
266 	if (argc == 2)
267 		cpu_mhz = atoi(argv[1]);
268 
269 #define	SKEIN_ALGO_TEST(_m, mode, diglen, testdigest)			\
270 	do {								\
271 		Skein ## mode ## _Ctxt_t	ctx;			\
272 		uint8_t				digest[diglen / 8];	\
273 		(void) Skein ## mode ## _Init(&ctx, diglen);		\
274 		(void) Skein ## mode ## _Update(&ctx, _m, sizeof (_m));	\
275 		(void) Skein ## mode ## _Final(&ctx, digest);		\
276 		(void) printf("Skein" #mode "/" #diglen			\
277 		    "\tMessage: " #_m "\tResult: ");			\
278 		if (memcmp(digest, testdigest, diglen / 8) == 0) {	\
279 			(void) printf("OK\n");				\
280 		} else {						\
281 			(void) printf("FAILED!\n");			\
282 			failed = B_TRUE;				\
283 		}							\
284 	} while (0)
285 
286 #define	SKEIN_PERF_TEST(mode, diglen)					\
287 	do {								\
288 		Skein ## mode ## _Ctxt_t ctx;				\
289 		uint8_t		digest[diglen / 8];			\
290 		uint8_t		block[131072];				\
291 		uint64_t	delta;					\
292 		double		cpb = 0;				\
293 		int		i;					\
294 		struct timeval	start, end;				\
295 		memset(block, 0, sizeof (block));			\
296 		(void) gettimeofday(&start, NULL);			\
297 		(void) Skein ## mode ## _Init(&ctx, diglen);		\
298 		for (i = 0; i < 8192; i++) {				\
299 			(void) Skein ## mode ## _Update(&ctx, block,	\
300 			    sizeof (block));				\
301 		}							\
302 		(void) Skein ## mode ## _Final(&ctx, digest);		\
303 		(void) gettimeofday(&end, NULL);			\
304 		delta = (end.tv_sec * 1000000llu + end.tv_usec) -	\
305 		    (start.tv_sec * 1000000llu + start.tv_usec);	\
306 		if (cpu_mhz != 0) {					\
307 			cpb = (cpu_mhz * 1e6 * ((double)delta /		\
308 			    1000000)) / (8192 * 128 * 1024);		\
309 		}							\
310 		(void) printf("Skein" #mode "/" #diglen "\t%llu us "	\
311 		    "(%.02f CPB)\n", (u_longlong_t)delta, cpb);		\
312 	} while (0)
313 
314 	(void) printf("Running algorithm correctness tests:\n");
315 	SKEIN_ALGO_TEST(test_msg0, _256, 256, skein_256_test_digests[0]);
316 	SKEIN_ALGO_TEST(test_msg1, _256, 256, skein_256_test_digests[1]);
317 	SKEIN_ALGO_TEST(test_msg2, _256, 256, skein_256_test_digests[2]);
318 	SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]);
319 	SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]);
320 	SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]);
321 	SKEIN_ALGO_TEST(test_msg0, 1024, 1024, skein_1024_test_digests[0]);
322 	SKEIN_ALGO_TEST(test_msg3, 1024, 1024, skein_1024_test_digests[3]);
323 	SKEIN_ALGO_TEST(test_msg4, 1024, 1024, skein_1024_test_digests[4]);
324 	if (failed)
325 		return (1);
326 
327 	(void) printf("Running performance tests (hashing 1024 MiB of "
328 	    "data):\n");
329 	SKEIN_PERF_TEST(_256, 256);
330 	SKEIN_PERF_TEST(_512, 512);
331 	SKEIN_PERF_TEST(1024, 1024);
332 
333 	return (0);
334 }
335