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