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