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