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 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