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 #include <sys/time.h> 37 #define _SHA2_IMPL 38 #include <sys/sha2.h> 39 #include <sys/stdtypes.h> 40 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 if (argc == 2) 178 cpu_mhz = atoi(argv[1]); 179 180 #define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \ 181 do { \ 182 SHA2_CTX ctx; \ 183 uint8_t digest[diglen / 8]; \ 184 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 185 SHA2Update(&ctx, _m, strlen(_m)); \ 186 SHA2Final(digest, &ctx); \ 187 (void) printf("SHA%-9sMessage: " #_m \ 188 "\tResult: ", #mode); \ 189 if (memcmp(digest, testdigest, diglen / 8) == 0) { \ 190 (void) printf("OK\n"); \ 191 } else { \ 192 (void) printf("FAILED!\n"); \ 193 failed = B_TRUE; \ 194 } \ 195 } while (0) 196 197 #define SHA2_PERF_TEST(mode, diglen) \ 198 do { \ 199 SHA2_CTX ctx; \ 200 uint8_t digest[diglen / 8]; \ 201 uint8_t block[131072]; \ 202 uint64_t delta; \ 203 double cpb = 0; \ 204 int i; \ 205 struct timeval start, end; \ 206 memset(block, 0, sizeof (block)); \ 207 (void) gettimeofday(&start, NULL); \ 208 SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ 209 for (i = 0; i < 8192; i++) \ 210 SHA2Update(&ctx, block, sizeof (block)); \ 211 SHA2Final(digest, &ctx); \ 212 (void) gettimeofday(&end, NULL); \ 213 delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ 214 (start.tv_sec * 1000000llu + start.tv_usec); \ 215 if (cpu_mhz != 0) { \ 216 cpb = (cpu_mhz * 1e6 * ((double)delta / \ 217 1000000)) / (8192 * 128 * 1024); \ 218 } \ 219 (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \ 220 (u_longlong_t)delta, cpb); \ 221 } while (0) 222 223 (void) printf("Running algorithm correctness tests:\n"); 224 SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]); 225 SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]); 226 SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]); 227 SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]); 228 SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]); 229 SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]); 230 SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]); 231 SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]); 232 SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]); 233 SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]); 234 235 if (failed) 236 return (1); 237 238 (void) printf("Running performance tests (hashing 1024 MiB of " 239 "data):\n"); 240 SHA2_PERF_TEST(256, 256); 241 SHA2_PERF_TEST(512, 512); 242 243 return (0); 244 } 245