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