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