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 #ifdef _KERNEL 32 #undef _KERNEL 33 #endif 34 35 #include <sys/varargs.h> 36 #include <stdlib.h> 37 #include <strings.h> 38 #include <stdio.h> 39 #include <sys/time.h> 40 #define _SHA2_IMPL 41 #include <sys/sha2.h> 42 #include <note.h> 43 44 /* 45 * Test messages from: 46 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf 47 */ 48 49 const char *test_msg0 = "abc"; 50 const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn" 51 "lmnomnopnopq"; 52 const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" 53 "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; 54 55 /* 56 * Test digests from: 57 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf 58 */ 59 const uint8_t sha256_test_digests[][32] = { 60 { 61 /* for test_msg0 */ 62 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 63 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 64 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 65 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD 66 }, 67 { 68 /* for test_msg1 */ 69 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 70 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 71 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 72 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 73 } 74 /* no test vector for test_msg2 */ 75 }; 76 77 const uint8_t sha384_test_digests[][48] = { 78 { 79 /* for test_msg0 */ 80 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 81 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 82 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 83 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, 84 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, 85 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 86 }, 87 { 88 /* no test vector for test_msg1 */ 89 0 90 }, 91 { 92 /* for test_msg2 */ 93 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 94 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 95 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 96 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, 97 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, 98 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 99 } 100 }; 101 102 const uint8_t sha512_test_digests[][64] = { 103 { 104 /* for test_msg0 */ 105 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 106 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 107 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, 108 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 109 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, 110 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, 111 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 112 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F 113 }, 114 { 115 /* no test vector for test_msg1 */ 116 0 117 }, 118 { 119 /* for test_msg2 */ 120 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 121 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 122 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 123 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 124 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 125 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 126 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 127 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 128 } 129 }; 130 131 const uint8_t sha512_224_test_digests[][28] = { 132 { 133 /* for test_msg0 */ 134 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, 135 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, 136 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, 137 0x3E, 0x89, 0x24, 0xAA 138 }, 139 { 140 /* no test vector for test_msg1 */ 141 0 142 }, 143 { 144 /* for test_msg2 */ 145 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, 146 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, 147 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, 148 0x68, 0x67, 0x4A, 0xF9 149 } 150 }; 151 152 const uint8_t sha512_256_test_digests[][32] = { 153 { 154 /* for test_msg0 */ 155 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 156 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, 157 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, 158 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 159 }, 160 { 161 /* no test vector for test_msg1 */ 162 0 163 }, 164 { 165 /* for test_msg2 */ 166 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 167 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, 168 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, 169 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A 170 } 171 }; 172 173 /* 174 * Local reimplementation of cmn_err, since it's used in sha2.c. 175 */ 176 /*ARGSUSED*/ 177 void 178 cmn_err(int level, char *format, ...) 179 { 180 va_list ap; 181 va_start(ap, format); 182 /* LINTED: E_SEC_PRINTF_VAR_FMT */ 183 (void) vfprintf(stderr, format, ap); 184 va_end(ap); 185 } 186 187 int 188 main(int argc, char *argv[]) 189 { 190 boolean_t failed = B_FALSE; 191 uint64_t cpu_mhz = 0; 192 193 if (argc == 2) 194 cpu_mhz = atoi(argv[1]); 195 196 #define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \ 197 do { \ 198 SHA2_CTX ctx; \ 199 uint8_t digest[diglen / 8]; \ 200 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 201 SHA2Update(&ctx, _m, strlen(_m)); \ 202 SHA2Final(digest, &ctx); \ 203 (void) printf("SHA%-9sMessage: " #_m \ 204 "\tResult: ", #mode); \ 205 if (bcmp(digest, testdigest, diglen / 8) == 0) { \ 206 (void) printf("OK\n"); \ 207 } else { \ 208 (void) printf("FAILED!\n"); \ 209 failed = B_TRUE; \ 210 } \ 211 NOTE(CONSTCOND) \ 212 } while (0) 213 214 #define SHA2_PERF_TEST(mode, diglen) \ 215 do { \ 216 SHA2_CTX ctx; \ 217 uint8_t digest[diglen / 8]; \ 218 uint8_t block[131072]; \ 219 uint64_t delta; \ 220 double cpb = 0; \ 221 int i; \ 222 struct timeval start, end; \ 223 bzero(block, sizeof (block)); \ 224 (void) gettimeofday(&start, NULL); \ 225 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 226 for (i = 0; i < 8192; i++) \ 227 SHA2Update(&ctx, block, sizeof (block)); \ 228 SHA2Final(digest, &ctx); \ 229 (void) gettimeofday(&end, NULL); \ 230 delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ 231 (start.tv_sec * 1000000llu + start.tv_usec); \ 232 if (cpu_mhz != 0) { \ 233 cpb = (cpu_mhz * 1e6 * ((double)delta / \ 234 1000000)) / (8192 * 128 * 1024); \ 235 } \ 236 (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \ 237 (u_longlong_t)delta, cpb); \ 238 NOTE(CONSTCOND) \ 239 } while (0) 240 241 (void) printf("Running algorithm correctness tests:\n"); 242 SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]); 243 SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]); 244 SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]); 245 SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]); 246 SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]); 247 SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]); 248 SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]); 249 SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]); 250 SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]); 251 SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]); 252 253 if (failed) 254 return (1); 255 256 (void) printf("Running performance tests (hashing 1024 MiB of " 257 "data):\n"); 258 SHA2_PERF_TEST(256, 256); 259 SHA2_PERF_TEST(512, 512); 260 261 return (0); 262 } 263