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  */
51 const uint8_t	test_msg0[] = {
52 	0xFF
53 };
54 
55 const 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 
62 const 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 
73 const 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 
92 const 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  */
130 const 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 
155 const 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 
196 const 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 
264 int
main(int argc,char * argv[])265 main(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