xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/checksum/sha2_test.c (revision 53bb5613a8a15363718b6e6de8d965bf9a2c5469)
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 
37 #include <sys/time.h>
38 #include <sys/sha2.h>
39 #include <sys/stdtypes.h>
40 #include <sys/zfs_impl.h>
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	sha512_test_digests[][64] = {
76 	{
77 		/* for test_msg0 */
78 		0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
79 		0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
80 		0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
81 		0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
82 		0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
83 		0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
84 		0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
85 		0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F
86 	},
87 	{
88 		/* no test vector for test_msg1 */
89 		0
90 	},
91 	{
92 		/* for test_msg2 */
93 		0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
94 		0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
95 		0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
96 		0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
97 		0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
98 		0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
99 		0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
100 		0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
101 	}
102 };
103 
104 static const uint8_t	sha512_256_test_digests[][32] = {
105 	{
106 		/* for test_msg0 */
107 		0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
108 		0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
109 		0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
110 		0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23
111 	},
112 	{
113 		/* no test vector for test_msg1 */
114 		0
115 	},
116 	{
117 		/* for test_msg2 */
118 		0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
119 		0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
120 		0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
121 		0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A
122 	}
123 };
124 
125 int
126 main(int argc, char *argv[])
127 {
128 	boolean_t	failed = B_FALSE;
129 	uint64_t	cpu_mhz = 0;
130 
131 	const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256");
132 	const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512");
133 	uint32_t id;
134 
135 	if (argc == 2)
136 		cpu_mhz = atoi(argv[1]);
137 
138 	if (!sha256)
139 		return (1);
140 
141 	if (!sha512)
142 		return (1);
143 
144 #define	SHA2_ALGO_TEST(_m, mode, diglen, testdigest)			\
145 	do {								\
146 		SHA2_CTX		ctx;				\
147 		uint8_t			digest[diglen / 8];		\
148 		SHA2Init(mode, &ctx);					\
149 		SHA2Update(&ctx, _m, strlen(_m));			\
150 		SHA2Final(digest, &ctx);				\
151 		(void) printf("SHA%-9sMessage: " #_m			\
152 		    "\tResult: ", #mode);				\
153 		if (memcmp(digest, testdigest, diglen / 8) == 0) {	\
154 			(void) printf("OK\n");				\
155 		} else {						\
156 			(void) printf("FAILED!\n");			\
157 			failed = B_TRUE;				\
158 		}							\
159 	} while (0)
160 
161 #define	SHA2_PERF_TEST(mode, diglen, name)				\
162 	do {								\
163 		SHA2_CTX	ctx;					\
164 		uint8_t		digest[diglen / 8];			\
165 		uint8_t		block[131072];				\
166 		uint64_t	delta;					\
167 		double		cpb = 0;				\
168 		int		i;					\
169 		struct timeval	start, end;				\
170 		memset(block, 0, sizeof (block));			\
171 		(void) gettimeofday(&start, NULL);			\
172 		SHA2Init(mode, &ctx);					\
173 		for (i = 0; i < 8192; i++)				\
174 			SHA2Update(&ctx, block, sizeof (block));	\
175 		SHA2Final(digest, &ctx);				\
176 		(void) gettimeofday(&end, NULL);			\
177 		delta = (end.tv_sec * 1000000llu + end.tv_usec) -	\
178 		    (start.tv_sec * 1000000llu + start.tv_usec);	\
179 		if (cpu_mhz != 0) {					\
180 			cpb = (cpu_mhz * 1e6 * ((double)delta /		\
181 			    1000000)) / (8192 * 128 * 1024);		\
182 		}							\
183 		(void) printf("sha%s-%-9s%7llu us (%.02f CPB)\n", #mode,\
184 		    name, (u_longlong_t)delta, cpb);			\
185 	} while (0)
186 
187 	(void) printf("Running algorithm correctness tests:\n");
188 	SHA2_ALGO_TEST(test_msg0, SHA256, 256, sha256_test_digests[0]);
189 	SHA2_ALGO_TEST(test_msg1, SHA256, 256, sha256_test_digests[1]);
190 	SHA2_ALGO_TEST(test_msg0, SHA512, 512, sha512_test_digests[0]);
191 	SHA2_ALGO_TEST(test_msg2, SHA512, 512, sha512_test_digests[2]);
192 	SHA2_ALGO_TEST(test_msg0, SHA512_256, 256, sha512_256_test_digests[0]);
193 	SHA2_ALGO_TEST(test_msg2, SHA512_256, 256, sha512_256_test_digests[2]);
194 
195 	if (failed)
196 		return (1);
197 
198 	(void) printf("Running performance tests (hashing 1024 MiB of "
199 	    "data):\n");
200 
201 	for (id = 0; id < sha256->getcnt(); id++) {
202 		sha256->setid(id);
203 		const char *name = sha256->getname();
204 		SHA2_PERF_TEST(SHA256, 256, name);
205 	}
206 
207 	for (id = 0; id < sha512->getcnt(); id++) {
208 		sha512->setid(id);
209 		const char *name = sha512->getname();
210 		SHA2_PERF_TEST(SHA512, 512, name);
211 	}
212 
213 	return (0);
214 }
215