xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/checksum/sha2_test.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://opensource.org/licenses/CDDL-1.0.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2013 Saso Kiselkov. All rights reserved.
25  */
26 
27 /*
28  * This is just to keep the compiler happy about sys/time.h not declaring
29  * gettimeofday due to -D_KERNEL (we can do this since we're actually
30  * running in userspace, but we need -D_KERNEL for the remaining SHA2 code).
31  */
32 
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdio.h>
37 
38 #include <sys/time.h>
39 #include <sys/sha2.h>
40 #include <sys/stdtypes.h>
41 #include <sys/zfs_impl.h>
42 
43 /*
44  * Test messages from:
45  * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
46  */
47 
48 static const char *test_msg0 = "abc";
49 static const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklm"
50 	"nlmnomnopnopq";
51 static const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh"
52 	"ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
53 
54 /*
55  * Test digests from:
56  * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
57  */
58 static 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 static const uint8_t	sha512_test_digests[][64] = {
77 	{
78 		/* for test_msg0 */
79 		0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
80 		0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
81 		0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
82 		0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
83 		0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
84 		0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
85 		0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
86 		0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F
87 	},
88 	{
89 		/* no test vector for test_msg1 */
90 		0
91 	},
92 	{
93 		/* for test_msg2 */
94 		0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
95 		0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
96 		0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
97 		0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
98 		0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
99 		0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
100 		0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
101 		0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
102 	}
103 };
104 
105 static const uint8_t	sha512_256_test_digests[][32] = {
106 	{
107 		/* for test_msg0 */
108 		0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
109 		0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
110 		0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
111 		0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23
112 	},
113 	{
114 		/* no test vector for test_msg1 */
115 		0
116 	},
117 	{
118 		/* for test_msg2 */
119 		0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
120 		0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
121 		0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
122 		0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A
123 	}
124 };
125 
126 int
main(int argc,char * argv[])127 main(int argc, char *argv[])
128 {
129 	boolean_t	failed = B_FALSE;
130 	uint64_t	cpu_mhz = 0;
131 
132 	const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256");
133 	const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512");
134 	uint32_t id;
135 
136 	if (argc == 2)
137 		cpu_mhz = atoi(argv[1]);
138 
139 	if (!sha256)
140 		return (1);
141 
142 	if (!sha512)
143 		return (1);
144 
145 #define	SHA2_ALGO_TEST(_m, mode, diglen, testdigest)			\
146 	do {								\
147 		SHA2_CTX		ctx;				\
148 		uint8_t			digest[diglen / 8];		\
149 		SHA2Init(mode, &ctx);					\
150 		SHA2Update(&ctx, _m, strlen(_m));			\
151 		SHA2Final(digest, &ctx);				\
152 		(void) printf("SHA%-9sMessage: " #_m			\
153 		    "\tResult: ", #mode);				\
154 		if (memcmp(digest, testdigest, diglen / 8) == 0) {	\
155 			(void) printf("OK\n");				\
156 		} else {						\
157 			(void) printf("FAILED!\n");			\
158 			failed = B_TRUE;				\
159 		}							\
160 	} while (0)
161 
162 #define	SHA2_PERF_TEST(mode, diglen, name)				\
163 	do {								\
164 		SHA2_CTX	ctx;					\
165 		uint8_t		digest[diglen / 8];			\
166 		uint8_t		block[131072];				\
167 		uint64_t	delta;					\
168 		double		cpb = 0;				\
169 		int		i;					\
170 		struct timeval	start, end;				\
171 		memset(block, 0, sizeof (block));			\
172 		(void) gettimeofday(&start, NULL);			\
173 		SHA2Init(mode, &ctx);					\
174 		for (i = 0; i < 8192; i++)				\
175 			SHA2Update(&ctx, block, sizeof (block));	\
176 		SHA2Final(digest, &ctx);				\
177 		(void) gettimeofday(&end, NULL);			\
178 		delta = (end.tv_sec * 1000000llu + end.tv_usec) -	\
179 		    (start.tv_sec * 1000000llu + start.tv_usec);	\
180 		if (cpu_mhz != 0) {					\
181 			cpb = (cpu_mhz * 1e6 * ((double)delta /		\
182 			    1000000)) / (8192 * 128 * 1024);		\
183 		}							\
184 		(void) printf("sha%s-%-9s%7llu us (%.02f CPB)\n", #mode,\
185 		    name, (u_longlong_t)delta, cpb);			\
186 	} while (0)
187 
188 	(void) printf("Running algorithm correctness tests:\n");
189 	SHA2_ALGO_TEST(test_msg0, SHA256, 256, sha256_test_digests[0]);
190 	SHA2_ALGO_TEST(test_msg1, SHA256, 256, sha256_test_digests[1]);
191 	SHA2_ALGO_TEST(test_msg0, SHA512, 512, sha512_test_digests[0]);
192 	SHA2_ALGO_TEST(test_msg2, SHA512, 512, sha512_test_digests[2]);
193 	SHA2_ALGO_TEST(test_msg0, SHA512_256, 256, sha512_256_test_digests[0]);
194 	SHA2_ALGO_TEST(test_msg2, SHA512_256, 256, sha512_256_test_digests[2]);
195 
196 	if (failed)
197 		return (1);
198 
199 	(void) printf("Running performance tests (hashing 1024 MiB of "
200 	    "data):\n");
201 
202 	for (id = 0; id < sha256->getcnt(); id++) {
203 		sha256->setid(id);
204 		const char *name = sha256->getname();
205 		SHA2_PERF_TEST(SHA256, 256, name);
206 	}
207 
208 	for (id = 0; id < sha512->getcnt(); id++) {
209 		sha512->setid(id);
210 		const char *name = sha512->getname();
211 		SHA2_PERF_TEST(SHA512, 512, name);
212 	}
213 
214 	return (0);
215 }
216