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