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