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 SHA2 code).
30 */
31 #ifdef _KERNEL
32 #undef _KERNEL
33 #endif
34
35 #include <sys/varargs.h>
36 #include <stdlib.h>
37 #include <strings.h>
38 #include <stdio.h>
39 #include <sys/time.h>
40 #define _SHA2_IMPL
41 #include <sys/sha2.h>
42 #include <note.h>
43
44 /*
45 * Test messages from:
46 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
47 */
48
49 const char *test_msg0 = "abc";
50 const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
51 "lmnomnopnopq";
52 const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
53 "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
54
55 /*
56 * Test digests from:
57 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
58 */
59 const uint8_t sha256_test_digests[][32] = {
60 {
61 /* for test_msg0 */
62 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
63 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
64 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
65 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD
66 },
67 {
68 /* for test_msg1 */
69 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
70 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
71 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
72 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1
73 }
74 /* no test vector for test_msg2 */
75 };
76
77 const uint8_t sha384_test_digests[][48] = {
78 {
79 /* for test_msg0 */
80 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
81 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
82 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
83 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
84 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
85 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7
86 },
87 {
88 /* no test vector for test_msg1 */
89 0
90 },
91 {
92 /* for test_msg2 */
93 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
94 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
95 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
96 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
97 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
98 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39
99 }
100 };
101
102 const uint8_t sha512_test_digests[][64] = {
103 {
104 /* for test_msg0 */
105 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
106 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
107 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
108 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
109 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
110 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
111 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
112 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F
113 },
114 {
115 /* no test vector for test_msg1 */
116 0
117 },
118 {
119 /* for test_msg2 */
120 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
121 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
122 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
123 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
124 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
125 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
126 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
127 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
128 }
129 };
130
131 const uint8_t sha512_224_test_digests[][28] = {
132 {
133 /* for test_msg0 */
134 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54,
135 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2,
136 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4,
137 0x3E, 0x89, 0x24, 0xAA
138 },
139 {
140 /* no test vector for test_msg1 */
141 0
142 },
143 {
144 /* for test_msg2 */
145 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23,
146 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33,
147 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72,
148 0x68, 0x67, 0x4A, 0xF9
149 }
150 };
151
152 const uint8_t sha512_256_test_digests[][32] = {
153 {
154 /* for test_msg0 */
155 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
156 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
157 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
158 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23
159 },
160 {
161 /* no test vector for test_msg1 */
162 0
163 },
164 {
165 /* for test_msg2 */
166 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
167 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
168 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
169 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A
170 }
171 };
172
173 /*
174 * Local reimplementation of cmn_err, since it's used in sha2.c.
175 */
176 /*ARGSUSED*/
177 void
cmn_err(int level,char * format,...)178 cmn_err(int level, char *format, ...)
179 {
180 va_list ap;
181 va_start(ap, format);
182 /* LINTED: E_SEC_PRINTF_VAR_FMT */
183 (void) vfprintf(stderr, format, ap);
184 va_end(ap);
185 }
186
187 int
main(int argc,char * argv[])188 main(int argc, char *argv[])
189 {
190 boolean_t failed = B_FALSE;
191 uint64_t cpu_mhz = 0;
192
193 if (argc == 2)
194 cpu_mhz = atoi(argv[1]);
195
196 #define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \
197 do { \
198 SHA2_CTX ctx; \
199 uint8_t digest[diglen / 8]; \
200 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \
201 SHA2Update(&ctx, _m, strlen(_m)); \
202 SHA2Final(digest, &ctx); \
203 (void) printf("SHA%-9sMessage: " #_m \
204 "\tResult: ", #mode); \
205 if (bcmp(digest, testdigest, diglen / 8) == 0) { \
206 (void) printf("OK\n"); \
207 } else { \
208 (void) printf("FAILED!\n"); \
209 failed = B_TRUE; \
210 } \
211 NOTE(CONSTCOND) \
212 } while (0)
213
214 #define SHA2_PERF_TEST(mode, diglen) \
215 do { \
216 SHA2_CTX ctx; \
217 uint8_t digest[diglen / 8]; \
218 uint8_t block[131072]; \
219 uint64_t delta; \
220 double cpb = 0; \
221 int i; \
222 struct timeval start, end; \
223 bzero(block, sizeof (block)); \
224 (void) gettimeofday(&start, NULL); \
225 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \
226 for (i = 0; i < 8192; i++) \
227 SHA2Update(&ctx, block, sizeof (block)); \
228 SHA2Final(digest, &ctx); \
229 (void) gettimeofday(&end, NULL); \
230 delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
231 (start.tv_sec * 1000000llu + start.tv_usec); \
232 if (cpu_mhz != 0) { \
233 cpb = (cpu_mhz * 1e6 * ((double)delta / \
234 1000000)) / (8192 * 128 * 1024); \
235 } \
236 (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \
237 (u_longlong_t)delta, cpb); \
238 NOTE(CONSTCOND) \
239 } while (0)
240
241 (void) printf("Running algorithm correctness tests:\n");
242 SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]);
243 SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]);
244 SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]);
245 SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]);
246 SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]);
247 SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]);
248 SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]);
249 SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]);
250 SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]);
251 SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]);
252
253 if (failed)
254 return (1);
255
256 (void) printf("Running performance tests (hashing 1024 MiB of "
257 "data):\n");
258 SHA2_PERF_TEST(256, 256);
259 SHA2_PERF_TEST(512, 512);
260
261 return (0);
262 }
263