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 sha384_test_digests[][48] = { 76 { 77 /* for test_msg0 */ 78 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 79 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 80 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 81 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, 82 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, 83 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 84 }, 85 { 86 /* no test vector for test_msg1 */ 87 0 88 }, 89 { 90 /* for test_msg2 */ 91 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 92 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 93 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 94 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, 95 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, 96 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 97 } 98 }; 99 100 static const uint8_t sha512_test_digests[][64] = { 101 { 102 /* for test_msg0 */ 103 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 104 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 105 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, 106 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 107 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, 108 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, 109 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 110 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F 111 }, 112 { 113 /* no test vector for test_msg1 */ 114 0 115 }, 116 { 117 /* for test_msg2 */ 118 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 119 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 120 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 121 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 122 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 123 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 124 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 125 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 126 } 127 }; 128 129 static const uint8_t sha512_224_test_digests[][28] = { 130 { 131 /* for test_msg0 */ 132 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, 133 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, 134 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, 135 0x3E, 0x89, 0x24, 0xAA 136 }, 137 { 138 /* no test vector for test_msg1 */ 139 0 140 }, 141 { 142 /* for test_msg2 */ 143 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, 144 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, 145 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, 146 0x68, 0x67, 0x4A, 0xF9 147 } 148 }; 149 150 static const uint8_t sha512_256_test_digests[][32] = { 151 { 152 /* for test_msg0 */ 153 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 154 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, 155 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, 156 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 157 }, 158 { 159 /* no test vector for test_msg1 */ 160 0 161 }, 162 { 163 /* for test_msg2 */ 164 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 165 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, 166 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, 167 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A 168 } 169 }; 170 171 int 172 main(int argc, char *argv[]) 173 { 174 boolean_t failed = B_FALSE; 175 uint64_t cpu_mhz = 0; 176 177 const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256"); 178 const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512"); 179 uint32_t id; 180 181 if (argc == 2) 182 cpu_mhz = atoi(argv[1]); 183 184 if (!sha256) 185 return (1); 186 187 if (!sha512) 188 return (1); 189 190 #define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \ 191 do { \ 192 SHA2_CTX ctx; \ 193 uint8_t digest[diglen / 8]; \ 194 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 195 SHA2Update(&ctx, _m, strlen(_m)); \ 196 SHA2Final(digest, &ctx); \ 197 (void) printf("SHA%-9sMessage: " #_m \ 198 "\tResult: ", #mode); \ 199 if (memcmp(digest, testdigest, diglen / 8) == 0) { \ 200 (void) printf("OK\n"); \ 201 } else { \ 202 (void) printf("FAILED!\n"); \ 203 failed = B_TRUE; \ 204 } \ 205 } while (0) 206 207 #define SHA2_PERF_TEST(mode, diglen, name) \ 208 do { \ 209 SHA2_CTX ctx; \ 210 uint8_t digest[diglen / 8]; \ 211 uint8_t block[131072]; \ 212 uint64_t delta; \ 213 double cpb = 0; \ 214 int i; \ 215 struct timeval start, end; \ 216 memset(block, 0, sizeof (block)); \ 217 (void) gettimeofday(&start, NULL); \ 218 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 219 for (i = 0; i < 8192; i++) \ 220 SHA2Update(&ctx, block, sizeof (block)); \ 221 SHA2Final(digest, &ctx); \ 222 (void) gettimeofday(&end, NULL); \ 223 delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ 224 (start.tv_sec * 1000000llu + start.tv_usec); \ 225 if (cpu_mhz != 0) { \ 226 cpb = (cpu_mhz * 1e6 * ((double)delta / \ 227 1000000)) / (8192 * 128 * 1024); \ 228 } \ 229 (void) printf("sha%s-%-9s%7llu us (%.02f CPB)\n", #mode,\ 230 name, (u_longlong_t)delta, cpb); \ 231 } while (0) 232 233 (void) printf("Running algorithm correctness tests:\n"); 234 SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]); 235 SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]); 236 SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]); 237 SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]); 238 SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]); 239 SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]); 240 SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]); 241 SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]); 242 SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]); 243 SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]); 244 245 if (failed) 246 return (1); 247 248 (void) printf("Running performance tests (hashing 1024 MiB of " 249 "data):\n"); 250 251 for (id = 0; id < sha256->getcnt(); id++) { 252 sha256->setid(id); 253 const char *name = sha256->getname(); 254 SHA2_PERF_TEST(256, 256, name); 255 } 256 257 for (id = 0; id < sha512->getcnt(); id++) { 258 sha512->setid(id); 259 const char *name = sha512->getname(); 260 SHA2_PERF_TEST(512, 512, name); 261 } 262 263 return (0); 264 } 265