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