1716fd348SMartin Matuska /* 2716fd348SMartin Matuska * CDDL HEADER START 3716fd348SMartin Matuska * 4716fd348SMartin Matuska * The contents of this file are subject to the terms of the 5716fd348SMartin Matuska * Common Development and Distribution License (the "License"). 6716fd348SMartin Matuska * You may not use this file except in compliance with the License. 7716fd348SMartin Matuska * 8716fd348SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9716fd348SMartin Matuska * or http://opensource.org/licenses/CDDL-1.0. 10716fd348SMartin Matuska * See the License for the specific language governing permissions 11716fd348SMartin Matuska * and limitations under the License. 12716fd348SMartin Matuska * 13716fd348SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14716fd348SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15716fd348SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16716fd348SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17716fd348SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18716fd348SMartin Matuska * 19716fd348SMartin Matuska * CDDL HEADER END 20716fd348SMartin Matuska */ 21716fd348SMartin Matuska 22716fd348SMartin Matuska /* 23716fd348SMartin Matuska * Copyright 2013 Saso Kiselkov. All rights reserved. 24716fd348SMartin Matuska */ 25716fd348SMartin Matuska 26716fd348SMartin Matuska /* 27716fd348SMartin Matuska * This is just to keep the compiler happy about sys/time.h not declaring 28716fd348SMartin Matuska * gettimeofday due to -D_KERNEL (we can do this since we're actually 29716fd348SMartin Matuska * running in userspace, but we need -D_KERNEL for the remaining SHA2 code). 30716fd348SMartin Matuska */ 31716fd348SMartin Matuska 32716fd348SMartin Matuska #include <stdarg.h> 33716fd348SMartin Matuska #include <stdlib.h> 34716fd348SMartin Matuska #include <string.h> 35716fd348SMartin Matuska #include <stdio.h> 362a58b312SMartin Matuska 37716fd348SMartin Matuska #include <sys/time.h> 38716fd348SMartin Matuska #include <sys/sha2.h> 39716fd348SMartin Matuska #include <sys/stdtypes.h> 402a58b312SMartin Matuska #include <sys/zfs_impl.h> 41716fd348SMartin Matuska 42716fd348SMartin Matuska /* 43716fd348SMartin Matuska * Test messages from: 44716fd348SMartin Matuska * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf 45716fd348SMartin Matuska */ 46716fd348SMartin Matuska 47dbd5678dSMartin Matuska static const char *test_msg0 = "abc"; 48dbd5678dSMartin Matuska static const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklm" 49dbd5678dSMartin Matuska "nlmnomnopnopq"; 50dbd5678dSMartin Matuska static const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh" 51dbd5678dSMartin Matuska "ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; 52716fd348SMartin Matuska 53716fd348SMartin Matuska /* 54716fd348SMartin Matuska * Test digests from: 55716fd348SMartin Matuska * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf 56716fd348SMartin Matuska */ 57dbd5678dSMartin Matuska static const uint8_t sha256_test_digests[][32] = { 58716fd348SMartin Matuska { 59716fd348SMartin Matuska /* for test_msg0 */ 60716fd348SMartin Matuska 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 61716fd348SMartin Matuska 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 62716fd348SMartin Matuska 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 63716fd348SMartin Matuska 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD 64716fd348SMartin Matuska }, 65716fd348SMartin Matuska { 66716fd348SMartin Matuska /* for test_msg1 */ 67716fd348SMartin Matuska 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 68716fd348SMartin Matuska 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 69716fd348SMartin Matuska 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 70716fd348SMartin Matuska 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 71716fd348SMartin Matuska } 72716fd348SMartin Matuska /* no test vector for test_msg2 */ 73716fd348SMartin Matuska }; 74716fd348SMartin Matuska 75dbd5678dSMartin Matuska static const uint8_t sha512_test_digests[][64] = { 76716fd348SMartin Matuska { 77716fd348SMartin Matuska /* for test_msg0 */ 78716fd348SMartin Matuska 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 79716fd348SMartin Matuska 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 80716fd348SMartin Matuska 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, 81716fd348SMartin Matuska 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 82716fd348SMartin Matuska 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, 83716fd348SMartin Matuska 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, 84716fd348SMartin Matuska 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 85716fd348SMartin Matuska 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F 86716fd348SMartin Matuska }, 87716fd348SMartin Matuska { 88716fd348SMartin Matuska /* no test vector for test_msg1 */ 89716fd348SMartin Matuska 0 90716fd348SMartin Matuska }, 91716fd348SMartin Matuska { 92716fd348SMartin Matuska /* for test_msg2 */ 93716fd348SMartin Matuska 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 94716fd348SMartin Matuska 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 95716fd348SMartin Matuska 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 96716fd348SMartin Matuska 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 97716fd348SMartin Matuska 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 98716fd348SMartin Matuska 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 99716fd348SMartin Matuska 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 100716fd348SMartin Matuska 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 101716fd348SMartin Matuska } 102716fd348SMartin Matuska }; 103716fd348SMartin Matuska 104dbd5678dSMartin Matuska static const uint8_t sha512_256_test_digests[][32] = { 105716fd348SMartin Matuska { 106716fd348SMartin Matuska /* for test_msg0 */ 107716fd348SMartin Matuska 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 108716fd348SMartin Matuska 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, 109716fd348SMartin Matuska 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, 110716fd348SMartin Matuska 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 111716fd348SMartin Matuska }, 112716fd348SMartin Matuska { 113716fd348SMartin Matuska /* no test vector for test_msg1 */ 114716fd348SMartin Matuska 0 115716fd348SMartin Matuska }, 116716fd348SMartin Matuska { 117716fd348SMartin Matuska /* for test_msg2 */ 118716fd348SMartin Matuska 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 119716fd348SMartin Matuska 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, 120716fd348SMartin Matuska 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, 121716fd348SMartin Matuska 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A 122716fd348SMartin Matuska } 123716fd348SMartin Matuska }; 124716fd348SMartin Matuska 125716fd348SMartin Matuska int 126716fd348SMartin Matuska main(int argc, char *argv[]) 127716fd348SMartin Matuska { 128716fd348SMartin Matuska boolean_t failed = B_FALSE; 129716fd348SMartin Matuska uint64_t cpu_mhz = 0; 130716fd348SMartin Matuska 1312a58b312SMartin Matuska const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256"); 1322a58b312SMartin Matuska const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512"); 1332a58b312SMartin Matuska uint32_t id; 1342a58b312SMartin Matuska 135716fd348SMartin Matuska if (argc == 2) 136716fd348SMartin Matuska cpu_mhz = atoi(argv[1]); 137716fd348SMartin Matuska 1382a58b312SMartin Matuska if (!sha256) 1392a58b312SMartin Matuska return (1); 1402a58b312SMartin Matuska 1412a58b312SMartin Matuska if (!sha512) 1422a58b312SMartin Matuska return (1); 1432a58b312SMartin Matuska 144716fd348SMartin Matuska #define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \ 145716fd348SMartin Matuska do { \ 146716fd348SMartin Matuska SHA2_CTX ctx; \ 147716fd348SMartin Matuska uint8_t digest[diglen / 8]; \ 148*75e1fea6SMartin Matuska SHA2Init(mode, &ctx); \ 149716fd348SMartin Matuska SHA2Update(&ctx, _m, strlen(_m)); \ 150716fd348SMartin Matuska SHA2Final(digest, &ctx); \ 151716fd348SMartin Matuska (void) printf("SHA%-9sMessage: " #_m \ 152716fd348SMartin Matuska "\tResult: ", #mode); \ 153716fd348SMartin Matuska if (memcmp(digest, testdigest, diglen / 8) == 0) { \ 154716fd348SMartin Matuska (void) printf("OK\n"); \ 155716fd348SMartin Matuska } else { \ 156716fd348SMartin Matuska (void) printf("FAILED!\n"); \ 157716fd348SMartin Matuska failed = B_TRUE; \ 158716fd348SMartin Matuska } \ 159716fd348SMartin Matuska } while (0) 160716fd348SMartin Matuska 1612a58b312SMartin Matuska #define SHA2_PERF_TEST(mode, diglen, name) \ 162716fd348SMartin Matuska do { \ 163716fd348SMartin Matuska SHA2_CTX ctx; \ 164716fd348SMartin Matuska uint8_t digest[diglen / 8]; \ 165716fd348SMartin Matuska uint8_t block[131072]; \ 166716fd348SMartin Matuska uint64_t delta; \ 167716fd348SMartin Matuska double cpb = 0; \ 168716fd348SMartin Matuska int i; \ 169716fd348SMartin Matuska struct timeval start, end; \ 170716fd348SMartin Matuska memset(block, 0, sizeof (block)); \ 171716fd348SMartin Matuska (void) gettimeofday(&start, NULL); \ 172*75e1fea6SMartin Matuska SHA2Init(mode, &ctx); \ 173716fd348SMartin Matuska for (i = 0; i < 8192; i++) \ 174716fd348SMartin Matuska SHA2Update(&ctx, block, sizeof (block)); \ 175716fd348SMartin Matuska SHA2Final(digest, &ctx); \ 176716fd348SMartin Matuska (void) gettimeofday(&end, NULL); \ 177716fd348SMartin Matuska delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ 178716fd348SMartin Matuska (start.tv_sec * 1000000llu + start.tv_usec); \ 179716fd348SMartin Matuska if (cpu_mhz != 0) { \ 180716fd348SMartin Matuska cpb = (cpu_mhz * 1e6 * ((double)delta / \ 181716fd348SMartin Matuska 1000000)) / (8192 * 128 * 1024); \ 182716fd348SMartin Matuska } \ 1832a58b312SMartin Matuska (void) printf("sha%s-%-9s%7llu us (%.02f CPB)\n", #mode,\ 1842a58b312SMartin Matuska name, (u_longlong_t)delta, cpb); \ 185716fd348SMartin Matuska } while (0) 186716fd348SMartin Matuska 187716fd348SMartin Matuska (void) printf("Running algorithm correctness tests:\n"); 188*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg0, SHA256, 256, sha256_test_digests[0]); 189*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg1, SHA256, 256, sha256_test_digests[1]); 190*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg0, SHA512, 512, sha512_test_digests[0]); 191*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg2, SHA512, 512, sha512_test_digests[2]); 192*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg0, SHA512_256, 256, sha512_256_test_digests[0]); 193*75e1fea6SMartin Matuska SHA2_ALGO_TEST(test_msg2, SHA512_256, 256, sha512_256_test_digests[2]); 194716fd348SMartin Matuska 195716fd348SMartin Matuska if (failed) 196716fd348SMartin Matuska return (1); 197716fd348SMartin Matuska 198716fd348SMartin Matuska (void) printf("Running performance tests (hashing 1024 MiB of " 199716fd348SMartin Matuska "data):\n"); 2002a58b312SMartin Matuska 2012a58b312SMartin Matuska for (id = 0; id < sha256->getcnt(); id++) { 2022a58b312SMartin Matuska sha256->setid(id); 2032a58b312SMartin Matuska const char *name = sha256->getname(); 204*75e1fea6SMartin Matuska SHA2_PERF_TEST(SHA256, 256, name); 2052a58b312SMartin Matuska } 2062a58b312SMartin Matuska 2072a58b312SMartin Matuska for (id = 0; id < sha512->getcnt(); id++) { 2082a58b312SMartin Matuska sha512->setid(id); 2092a58b312SMartin Matuska const char *name = sha512->getname(); 210*75e1fea6SMartin Matuska SHA2_PERF_TEST(SHA512, 512, name); 2112a58b312SMartin Matuska } 212716fd348SMartin Matuska 213716fd348SMartin Matuska return (0); 214716fd348SMartin Matuska } 215