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 Skein code).
  30  */
  31 #ifdef  _KERNEL
  32 #undef  _KERNEL
  33 #endif
  34 
  35 #include <sys/skein.h>
  36 #include <stdlib.h>
  37 #include <strings.h>
  38 #include <stdio.h>
  39 #include <sys/time.h>
  40 
  41 /*
  42  * Skein test suite using values from the Skein V1.3 specification found at:
  43  * http://www.skein-hash.info/sites/default/files/skein1.3.pdf
  44  */
  45 
  46 /*
  47  * Test messages from the Skein spec, Appendix C.
  48  */
  49 const uint8_t   test_msg0[] = {
  50         0xFF
  51 };
  52 
  53 const uint8_t   test_msg1[] = {
  54         0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
  55         0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
  56         0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
  57         0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0
  58 };
  59 
  60 const uint8_t   test_msg2[] = {
  61         0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
  62         0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
  63         0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
  64         0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
  65         0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
  66         0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
  67         0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
  68         0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0
  69 };
  70 
  71 const uint8_t   test_msg3[] = {
  72         0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
  73         0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
  74         0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
  75         0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
  76         0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
  77         0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
  78         0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
  79         0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
  80         0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
  81         0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
  82         0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
  83         0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
  84         0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
  85         0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
  86         0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
  87         0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
  88 };
  89 
  90 const uint8_t   test_msg4[] = {
  91         0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
  92         0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
  93         0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
  94         0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
  95         0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
  96         0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
  97         0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
  98         0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
  99         0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
 100         0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
 101         0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
 102         0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
 103         0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
 104         0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
 105         0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
 106         0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
 107         0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78,
 108         0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
 109         0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68,
 110         0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
 111         0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58,
 112         0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
 113         0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
 114         0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
 115         0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
 116         0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
 117         0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28,
 118         0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
 119         0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
 120         0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
 121         0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
 122         0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
 123 };
 124 
 125 /*
 126  * Test digests from the Skein spec, Appendix C.
 127  */
 128 const uint8_t   skein_256_test_digests[][32] = {
 129         {
 130                 // for test_msg0
 131                 0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50,
 132                 0xA7, 0xA2, 0x44, 0xC4, 0x44, 0xE2, 0x5C, 0x23,
 133                 0xDA, 0x30, 0xC1, 0x0F, 0xC9, 0xA1, 0xF2, 0x70,
 134                 0xA6, 0x63, 0x7F, 0x1F, 0x34, 0xE6, 0x7E, 0xD2
 135         },
 136         {
 137                 // for test_msg1
 138                 0x8D, 0x0F, 0xA4, 0xEF, 0x77, 0x7F, 0xD7, 0x59,
 139                 0xDF, 0xD4, 0x04, 0x4E, 0x6F, 0x6A, 0x5A, 0xC3,
 140                 0xC7, 0x74, 0xAE, 0xC9, 0x43, 0xDC, 0xFC, 0x07,
 141                 0x92, 0x7B, 0x72, 0x3B, 0x5D, 0xBF, 0x40, 0x8B
 142         },
 143         {
 144                 // for test_msg2
 145                 0xDF, 0x28, 0xE9, 0x16, 0x63, 0x0D, 0x0B, 0x44,
 146                 0xC4, 0xA8, 0x49, 0xDC, 0x9A, 0x02, 0xF0, 0x7A,
 147                 0x07, 0xCB, 0x30, 0xF7, 0x32, 0x31, 0x82, 0x56,
 148                 0xB1, 0x5D, 0x86, 0x5A, 0xC4, 0xAE, 0x16, 0x2F
 149         }
 150         // no test digests for test_msg3 and test_msg4
 151 };
 152 
 153 const uint8_t   skein_512_test_digests[][64] = {
 154         {
 155                 // for test_msg0
 156                 0x71, 0xB7, 0xBC, 0xE6, 0xFE, 0x64, 0x52, 0x22,
 157                 0x7B, 0x9C, 0xED, 0x60, 0x14, 0x24, 0x9E, 0x5B,
 158                 0xF9, 0xA9, 0x75, 0x4C, 0x3A, 0xD6, 0x18, 0xCC,
 159                 0xC4, 0xE0, 0xAA, 0xE1, 0x6B, 0x31, 0x6C, 0xC8,
 160                 0xCA, 0x69, 0x8D, 0x86, 0x43, 0x07, 0xED, 0x3E,
 161                 0x80, 0xB6, 0xEF, 0x15, 0x70, 0x81, 0x2A, 0xC5,
 162                 0x27, 0x2D, 0xC4, 0x09, 0xB5, 0xA0, 0x12, 0xDF,
 163                 0x2A, 0x57, 0x91, 0x02, 0xF3, 0x40, 0x61, 0x7A
 164         },
 165         {
 166                 // no test vector for test_msg1
 167         },
 168         {
 169                 // for test_msg2
 170                 0x45, 0x86, 0x3B, 0xA3, 0xBE, 0x0C, 0x4D, 0xFC,
 171                 0x27, 0xE7, 0x5D, 0x35, 0x84, 0x96, 0xF4, 0xAC,
 172                 0x9A, 0x73, 0x6A, 0x50, 0x5D, 0x93, 0x13, 0xB4,
 173                 0x2B, 0x2F, 0x5E, 0xAD, 0xA7, 0x9F, 0xC1, 0x7F,
 174                 0x63, 0x86, 0x1E, 0x94, 0x7A, 0xFB, 0x1D, 0x05,
 175                 0x6A, 0xA1, 0x99, 0x57, 0x5A, 0xD3, 0xF8, 0xC9,
 176                 0xA3, 0xCC, 0x17, 0x80, 0xB5, 0xE5, 0xFA, 0x4C,
 177                 0xAE, 0x05, 0x0E, 0x98, 0x98, 0x76, 0x62, 0x5B
 178         },
 179         {
 180                 // for test_msg3
 181                 0x91, 0xCC, 0xA5, 0x10, 0xC2, 0x63, 0xC4, 0xDD,
 182                 0xD0, 0x10, 0x53, 0x0A, 0x33, 0x07, 0x33, 0x09,
 183                 0x62, 0x86, 0x31, 0xF3, 0x08, 0x74, 0x7E, 0x1B,
 184                 0xCB, 0xAA, 0x90, 0xE4, 0x51, 0xCA, 0xB9, 0x2E,
 185                 0x51, 0x88, 0x08, 0x7A, 0xF4, 0x18, 0x87, 0x73,
 186                 0xA3, 0x32, 0x30, 0x3E, 0x66, 0x67, 0xA7, 0xA2,
 187                 0x10, 0x85, 0x6F, 0x74, 0x21, 0x39, 0x00, 0x00,
 188                 0x71, 0xF4, 0x8E, 0x8B, 0xA2, 0xA5, 0xAD, 0xB7
 189         }
 190         // no test digests for test_msg4
 191 };
 192 
 193 const uint8_t   skein_1024_test_digests[][128] = {
 194         {
 195                 // for test_msg0
 196                 0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24,
 197                 0x07, 0xCD, 0xD8, 0x78, 0x7F, 0xDA, 0x9E, 0x35,
 198                 0x70, 0x3D, 0xE8, 0x62, 0xA4, 0xFB, 0xC1, 0x19,
 199                 0xCF, 0xF8, 0x59, 0x0A, 0xFE, 0x79, 0x25, 0x0B,
 200                 0xCC, 0xC8, 0xB3, 0xFA, 0xF1, 0xBD, 0x24, 0x22,
 201                 0xAB, 0x5C, 0x0D, 0x26, 0x3F, 0xB2, 0xF8, 0xAF,
 202                 0xB3, 0xF7, 0x96, 0xF0, 0x48, 0x00, 0x03, 0x81,
 203                 0x53, 0x1B, 0x6F, 0x00, 0xD8, 0x51, 0x61, 0xBC,
 204                 0x0F, 0xFF, 0x4B, 0xEF, 0x24, 0x86, 0xB1, 0xEB,
 205                 0xCD, 0x37, 0x73, 0xFA, 0xBF, 0x50, 0xAD, 0x4A,
 206                 0xD5, 0x63, 0x9A, 0xF9, 0x04, 0x0E, 0x3F, 0x29,
 207                 0xC6, 0xC9, 0x31, 0x30, 0x1B, 0xF7, 0x98, 0x32,
 208                 0xE9, 0xDA, 0x09, 0x85, 0x7E, 0x83, 0x1E, 0x82,
 209                 0xEF, 0x8B, 0x46, 0x91, 0xC2, 0x35, 0x65, 0x65,
 210                 0x15, 0xD4, 0x37, 0xD2, 0xBD, 0xA3, 0x3B, 0xCE,
 211                 0xC0, 0x01, 0xC6, 0x7F, 0xFD, 0xE1, 0x5B, 0xA8
 212         },
 213         {
 214                 // no test vector for test_msg1
 215         },
 216         {
 217                 // no test vector for test_msg2
 218         },
 219         {
 220                 // for test_msg3
 221                 0x1F, 0x3E, 0x02, 0xC4, 0x6F, 0xB8, 0x0A, 0x3F,
 222                 0xCD, 0x2D, 0xFB, 0xBC, 0x7C, 0x17, 0x38, 0x00,
 223                 0xB4, 0x0C, 0x60, 0xC2, 0x35, 0x4A, 0xF5, 0x51,
 224                 0x18, 0x9E, 0xBF, 0x43, 0x3C, 0x3D, 0x85, 0xF9,
 225                 0xFF, 0x18, 0x03, 0xE6, 0xD9, 0x20, 0x49, 0x31,
 226                 0x79, 0xED, 0x7A, 0xE7, 0xFC, 0xE6, 0x9C, 0x35,
 227                 0x81, 0xA5, 0xA2, 0xF8, 0x2D, 0x3E, 0x0C, 0x7A,
 228                 0x29, 0x55, 0x74, 0xD0, 0xCD, 0x7D, 0x21, 0x7C,
 229                 0x48, 0x4D, 0x2F, 0x63, 0x13, 0xD5, 0x9A, 0x77,
 230                 0x18, 0xEA, 0xD0, 0x7D, 0x07, 0x29, 0xC2, 0x48,
 231                 0x51, 0xD7, 0xE7, 0xD2, 0x49, 0x1B, 0x90, 0x2D,
 232                 0x48, 0x91, 0x94, 0xE6, 0xB7, 0xD3, 0x69, 0xDB,
 233                 0x0A, 0xB7, 0xAA, 0x10, 0x6F, 0x0E, 0xE0, 0xA3,
 234                 0x9A, 0x42, 0xEF, 0xC5, 0x4F, 0x18, 0xD9, 0x37,
 235                 0x76, 0x08, 0x09, 0x85, 0xF9, 0x07, 0x57, 0x4F,
 236                 0x99, 0x5E, 0xC6, 0xA3, 0x71, 0x53, 0xA5, 0x78
 237         },
 238         {
 239                 // for test_msg4
 240                 0x84, 0x2A, 0x53, 0xC9, 0x9C, 0x12, 0xB0, 0xCF,
 241                 0x80, 0xCF, 0x69, 0x49, 0x1B, 0xE5, 0xE2, 0xF7,
 242                 0x51, 0x5D, 0xE8, 0x73, 0x3B, 0x6E, 0xA9, 0x42,
 243                 0x2D, 0xFD, 0x67, 0x66, 0x65, 0xB5, 0xFA, 0x42,
 244                 0xFF, 0xB3, 0xA9, 0xC4, 0x8C, 0x21, 0x77, 0x77,
 245                 0x95, 0x08, 0x48, 0xCE, 0xCD, 0xB4, 0x8F, 0x64,
 246                 0x0F, 0x81, 0xFB, 0x92, 0xBE, 0xF6, 0xF8, 0x8F,
 247                 0x7A, 0x85, 0xC1, 0xF7, 0xCD, 0x14, 0x46, 0xC9,
 248                 0x16, 0x1C, 0x0A, 0xFE, 0x8F, 0x25, 0xAE, 0x44,
 249                 0x4F, 0x40, 0xD3, 0x68, 0x00, 0x81, 0xC3, 0x5A,
 250                 0xA4, 0x3F, 0x64, 0x0F, 0xD5, 0xFA, 0x3C, 0x3C,
 251                 0x03, 0x0B, 0xCC, 0x06, 0xAB, 0xAC, 0x01, 0xD0,
 252                 0x98, 0xBC, 0xC9, 0x84, 0xEB, 0xD8, 0x32, 0x27,
 253                 0x12, 0x92, 0x1E, 0x00, 0xB1, 0xBA, 0x07, 0xD6,
 254                 0xD0, 0x1F, 0x26, 0x90, 0x70, 0x50, 0x25, 0x5E,
 255                 0xF2, 0xC8, 0xE2, 0x4F, 0x71, 0x6C, 0x52, 0xA5
 256         }
 257 };
 258 
 259 int
 260 main(int argc, char *argv[])
 261 {
 262         boolean_t       failed = B_FALSE;
 263         uint64_t        cpu_mhz = 0;
 264 
 265         if (argc == 2)
 266                 cpu_mhz = atoi(argv[1]);
 267 
 268 #define SKEIN_ALGO_TEST(_m, mode, diglen, testdigest)                   \
 269         do {                                                            \
 270                 Skein ## mode ## _Ctxt_t        ctx;                    \
 271                 uint8_t                         digest[diglen / 8];     \
 272                 Skein ## mode ## _Init(&ctx, diglen);                       \
 273                 Skein ## mode ## _Update(&ctx, _m, sizeof (_m));    \
 274                 Skein ## mode ## _Final(&ctx, digest);                      \
 275                 printf("Skein" #mode "/" #diglen "\tMessage: " #_m      \
 276                     "\tResult: ");                                      \
 277                 if (bcmp(digest, testdigest, diglen / 8) == 0) {        \
 278                         printf("OK\n");                                 \
 279                 } else {                                                \
 280                         printf("FAILED!\n");                            \
 281                         failed = B_TRUE;                                \
 282                 }                                                       \
 283         } while (0)
 284 
 285 #define SKEIN_PERF_TEST(mode, diglen)                                   \
 286         do {                                                            \
 287                 Skein ## mode ## _Ctxt_t ctx;                           \
 288                 uint8_t         digest[diglen / 8];                     \
 289                 uint8_t         block[131072];                          \
 290                 uint64_t        delta;                                  \
 291                 double          cpb = 0;                                \
 292                 int             i;                                      \
 293                 struct timeval  start, end;                             \
 294                 bzero(block, sizeof (block));                           \
 295                 gettimeofday(&start, NULL);                         \
 296                 Skein ## mode ## _Init(&ctx, diglen);                       \
 297                 for (i = 0; i < 8192; i++) {                         \
 298                         Skein ## mode ## _Update(&ctx, block,               \
 299                             sizeof (block));                            \
 300                 }                                                       \
 301                 Skein ## mode ## _Final(&ctx, digest);                      \
 302                 gettimeofday(&end, NULL);                           \
 303                 delta = (end.tv_sec * 1000000llu + end.tv_usec) -       \
 304                     (start.tv_sec * 1000000llu + start.tv_usec);        \
 305                 if (cpu_mhz != 0) {                                     \
 306                         cpb = (cpu_mhz * 1e6 * ((double)delta /         \
 307                             1000000)) / (8192 * 128 * 1024);            \
 308                 }                                                       \
 309                 printf("Skein" #mode "/" #diglen "\t%llu us "           \
 310                     "(%.02f CPB)\n", delta, cpb);                       \
 311         } while (0)
 312 
 313         printf("Running algorithm correctness tests:\n");
 314         SKEIN_ALGO_TEST(test_msg0, _256, 256, skein_256_test_digests[0]);
 315         SKEIN_ALGO_TEST(test_msg1, _256, 256, skein_256_test_digests[1]);
 316         SKEIN_ALGO_TEST(test_msg2, _256, 256, skein_256_test_digests[2]);
 317         SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]);
 318         SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]);
 319         SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]);
 320         SKEIN_ALGO_TEST(test_msg0, 1024, 1024, skein_1024_test_digests[0]);
 321         SKEIN_ALGO_TEST(test_msg3, 1024, 1024, skein_1024_test_digests[3]);
 322         SKEIN_ALGO_TEST(test_msg4, 1024, 1024, skein_1024_test_digests[4]);
 323         if (failed)
 324                 return (1);
 325 
 326         printf("Running performance tests (hashing 1024 MiB of data):\n");
 327         SKEIN_PERF_TEST(_256, 256);
 328         SKEIN_PERF_TEST(_512, 512);
 329         SKEIN_PERF_TEST(1024, 1024);
 330 
 331         return (0);
 332 }