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