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