1220497Smarkm/* 2220497Smarkm * Copyright (c) 2011 The FreeBSD Project. All rights reserved. 3220497Smarkm * 4220497Smarkm * Redistribution and use in source and binary forms, with or without 5220497Smarkm * modification, are permitted provided that the following conditions 6220497Smarkm * are met: 7220497Smarkm * 1. Redistributions of source code must retain the above copyright 8220497Smarkm * notice, this list of conditions and the following disclaimer. 9220497Smarkm * 2. Redistributions in binary form must reproduce the above copyright 10220497Smarkm * notice, this list of conditions and the following disclaimer in the 11220497Smarkm * documentation and/or other materials provided with the distribution. 12220497Smarkm * 13220497Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14220497Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15220497Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16220497Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17220497Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18220497Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19220497Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20220497Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21220497Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22220497Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23220497Smarkm * SUCH DAMAGE. 24220497Smarkm */ 25220497Smarkm 26220497Smarkm/* Based on: 27220497Smarkm * SHA256-based Unix crypt implementation. Released into the Public Domain by 28220497Smarkm * Ulrich Drepper <drepper@redhat.com>. */ 29220497Smarkm 30220497Smarkm#include <sys/cdefs.h> 31220497Smarkm__FBSDID("$FreeBSD: releng/11.0/lib/libcrypt/crypt-sha256.c 221471 2011-05-05 01:09:42Z obrien $"); 32220497Smarkm 33220497Smarkm#include <sys/endian.h> 34220497Smarkm#include <sys/param.h> 35220497Smarkm 36220497Smarkm#include <errno.h> 37220497Smarkm#include <limits.h> 38220497Smarkm#include <sha256.h> 39220497Smarkm#include <stdbool.h> 40220497Smarkm#include <stdint.h> 41220497Smarkm#include <stdio.h> 42220497Smarkm#include <stdlib.h> 43220497Smarkm#include <string.h> 44220497Smarkm 45220497Smarkm#include "crypt.h" 46220497Smarkm 47220497Smarkm/* Define our magic string to mark salt for SHA256 "encryption" replacement. */ 48220497Smarkmstatic const char sha256_salt_prefix[] = "$5$"; 49220497Smarkm 50220497Smarkm/* Prefix for optional rounds specification. */ 51220497Smarkmstatic const char sha256_rounds_prefix[] = "rounds="; 52220497Smarkm 53220497Smarkm/* Maximum salt string length. */ 54220497Smarkm#define SALT_LEN_MAX 16 55220497Smarkm/* Default number of rounds if not explicitly specified. */ 56220497Smarkm#define ROUNDS_DEFAULT 5000 57220497Smarkm/* Minimum number of rounds. */ 58220497Smarkm#define ROUNDS_MIN 1000 59220497Smarkm/* Maximum number of rounds. */ 60220497Smarkm#define ROUNDS_MAX 999999999 61220497Smarkm 62220497Smarkmstatic char * 63221471Sobriencrypt_sha256_r(const char *key, const char *salt, char *buffer, int buflen) 64220497Smarkm{ 65220497Smarkm u_long srounds; 66220497Smarkm int n; 67220497Smarkm uint8_t alt_result[32], temp_result[32]; 68220497Smarkm SHA256_CTX ctx, alt_ctx; 69220497Smarkm size_t salt_len, key_len, cnt, rounds; 70220497Smarkm char *cp, *copied_key, *copied_salt, *p_bytes, *s_bytes, *endp; 71220497Smarkm const char *num; 72220497Smarkm bool rounds_custom; 73220497Smarkm 74220497Smarkm copied_key = NULL; 75220497Smarkm copied_salt = NULL; 76220497Smarkm 77220497Smarkm /* Default number of rounds. */ 78220497Smarkm rounds = ROUNDS_DEFAULT; 79220497Smarkm rounds_custom = false; 80220497Smarkm 81220497Smarkm /* Find beginning of salt string. The prefix should normally always 82220497Smarkm * be present. Just in case it is not. */ 83220497Smarkm if (strncmp(sha256_salt_prefix, salt, sizeof(sha256_salt_prefix) - 1) == 0) 84220497Smarkm /* Skip salt prefix. */ 85220497Smarkm salt += sizeof(sha256_salt_prefix) - 1; 86220497Smarkm 87220497Smarkm if (strncmp(salt, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1) 88220497Smarkm == 0) { 89220497Smarkm num = salt + sizeof(sha256_rounds_prefix) - 1; 90220497Smarkm srounds = strtoul(num, &endp, 10); 91220497Smarkm 92220497Smarkm if (*endp == '$') { 93220497Smarkm salt = endp + 1; 94220497Smarkm rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); 95220497Smarkm rounds_custom = true; 96220497Smarkm } 97220497Smarkm } 98220497Smarkm 99220497Smarkm salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX); 100220497Smarkm key_len = strlen(key); 101220497Smarkm 102220497Smarkm /* Prepare for the real work. */ 103220497Smarkm SHA256_Init(&ctx); 104220497Smarkm 105220497Smarkm /* Add the key string. */ 106220497Smarkm SHA256_Update(&ctx, key, key_len); 107220497Smarkm 108220497Smarkm /* The last part is the salt string. This must be at most 8 109220497Smarkm * characters and it ends at the first `$' character (for 110220497Smarkm * compatibility with existing implementations). */ 111220497Smarkm SHA256_Update(&ctx, salt, salt_len); 112220497Smarkm 113220497Smarkm /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The 114220497Smarkm * final result will be added to the first context. */ 115220497Smarkm SHA256_Init(&alt_ctx); 116220497Smarkm 117220497Smarkm /* Add key. */ 118220497Smarkm SHA256_Update(&alt_ctx, key, key_len); 119220497Smarkm 120220497Smarkm /* Add salt. */ 121220497Smarkm SHA256_Update(&alt_ctx, salt, salt_len); 122220497Smarkm 123220497Smarkm /* Add key again. */ 124220497Smarkm SHA256_Update(&alt_ctx, key, key_len); 125220497Smarkm 126220497Smarkm /* Now get result of this (32 bytes) and add it to the other context. */ 127220497Smarkm SHA256_Final(alt_result, &alt_ctx); 128220497Smarkm 129220497Smarkm /* Add for any character in the key one byte of the alternate sum. */ 130220497Smarkm for (cnt = key_len; cnt > 32; cnt -= 32) 131220497Smarkm SHA256_Update(&ctx, alt_result, 32); 132220497Smarkm SHA256_Update(&ctx, alt_result, cnt); 133220497Smarkm 134220497Smarkm /* Take the binary representation of the length of the key and for 135220497Smarkm * every 1 add the alternate sum, for every 0 the key. */ 136220497Smarkm for (cnt = key_len; cnt > 0; cnt >>= 1) 137220497Smarkm if ((cnt & 1) != 0) 138220497Smarkm SHA256_Update(&ctx, alt_result, 32); 139220497Smarkm else 140220497Smarkm SHA256_Update(&ctx, key, key_len); 141220497Smarkm 142220497Smarkm /* Create intermediate result. */ 143220497Smarkm SHA256_Final(alt_result, &ctx); 144220497Smarkm 145220497Smarkm /* Start computation of P byte sequence. */ 146220497Smarkm SHA256_Init(&alt_ctx); 147220497Smarkm 148220497Smarkm /* For every character in the password add the entire password. */ 149220497Smarkm for (cnt = 0; cnt < key_len; ++cnt) 150220497Smarkm SHA256_Update(&alt_ctx, key, key_len); 151220497Smarkm 152220497Smarkm /* Finish the digest. */ 153220497Smarkm SHA256_Final(temp_result, &alt_ctx); 154220497Smarkm 155220497Smarkm /* Create byte sequence P. */ 156220497Smarkm cp = p_bytes = alloca(key_len); 157220497Smarkm for (cnt = key_len; cnt >= 32; cnt -= 32) { 158220497Smarkm memcpy(cp, temp_result, 32); 159220497Smarkm cp += 32; 160220497Smarkm } 161220497Smarkm memcpy(cp, temp_result, cnt); 162220497Smarkm 163220497Smarkm /* Start computation of S byte sequence. */ 164220497Smarkm SHA256_Init(&alt_ctx); 165220497Smarkm 166220497Smarkm /* For every character in the password add the entire password. */ 167220497Smarkm for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) 168220497Smarkm SHA256_Update(&alt_ctx, salt, salt_len); 169220497Smarkm 170220497Smarkm /* Finish the digest. */ 171220497Smarkm SHA256_Final(temp_result, &alt_ctx); 172220497Smarkm 173220497Smarkm /* Create byte sequence S. */ 174220497Smarkm cp = s_bytes = alloca(salt_len); 175220497Smarkm for (cnt = salt_len; cnt >= 32; cnt -= 32) { 176220497Smarkm memcpy(cp, temp_result, 32); 177220497Smarkm cp += 32; 178220497Smarkm } 179220497Smarkm memcpy(cp, temp_result, cnt); 180220497Smarkm 181220497Smarkm /* Repeatedly run the collected hash value through SHA256 to burn CPU 182220497Smarkm * cycles. */ 183220497Smarkm for (cnt = 0; cnt < rounds; ++cnt) { 184220497Smarkm /* New context. */ 185220497Smarkm SHA256_Init(&ctx); 186220497Smarkm 187220497Smarkm /* Add key or last result. */ 188220497Smarkm if ((cnt & 1) != 0) 189220497Smarkm SHA256_Update(&ctx, p_bytes, key_len); 190220497Smarkm else 191220497Smarkm SHA256_Update(&ctx, alt_result, 32); 192220497Smarkm 193220497Smarkm /* Add salt for numbers not divisible by 3. */ 194220497Smarkm if (cnt % 3 != 0) 195220497Smarkm SHA256_Update(&ctx, s_bytes, salt_len); 196220497Smarkm 197220497Smarkm /* Add key for numbers not divisible by 7. */ 198220497Smarkm if (cnt % 7 != 0) 199220497Smarkm SHA256_Update(&ctx, p_bytes, key_len); 200220497Smarkm 201220497Smarkm /* Add key or last result. */ 202220497Smarkm if ((cnt & 1) != 0) 203220497Smarkm SHA256_Update(&ctx, alt_result, 32); 204220497Smarkm else 205220497Smarkm SHA256_Update(&ctx, p_bytes, key_len); 206220497Smarkm 207220497Smarkm /* Create intermediate result. */ 208220497Smarkm SHA256_Final(alt_result, &ctx); 209220497Smarkm } 210220497Smarkm 211220497Smarkm /* Now we can construct the result string. It consists of three 212220497Smarkm * parts. */ 213220497Smarkm cp = stpncpy(buffer, sha256_salt_prefix, MAX(0, buflen)); 214220497Smarkm buflen -= sizeof(sha256_salt_prefix) - 1; 215220497Smarkm 216220497Smarkm if (rounds_custom) { 217220497Smarkm n = snprintf(cp, MAX(0, buflen), "%s%zu$", 218220497Smarkm sha256_rounds_prefix, rounds); 219220497Smarkm 220220497Smarkm cp += n; 221220497Smarkm buflen -= n; 222220497Smarkm } 223220497Smarkm 224220497Smarkm cp = stpncpy(cp, salt, MIN((size_t)MAX(0, buflen), salt_len)); 225220497Smarkm buflen -= MIN((size_t)MAX(0, buflen), salt_len); 226220497Smarkm 227220497Smarkm if (buflen > 0) { 228220497Smarkm *cp++ = '$'; 229220497Smarkm --buflen; 230220497Smarkm } 231220497Smarkm 232220497Smarkm b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4, &buflen, &cp); 233220497Smarkm b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, &buflen, &cp); 234220497Smarkm b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, &buflen, &cp); 235220497Smarkm b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, &buflen, &cp); 236220497Smarkm b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, &buflen, &cp); 237220497Smarkm b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, &buflen, &cp); 238220497Smarkm b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, &buflen, &cp); 239220497Smarkm b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, &buflen, &cp); 240220497Smarkm b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, &buflen, &cp); 241220497Smarkm b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, &buflen, &cp); 242220497Smarkm b64_from_24bit(0, alt_result[31], alt_result[30], 3, &buflen, &cp); 243220497Smarkm if (buflen <= 0) { 244220497Smarkm errno = ERANGE; 245220497Smarkm buffer = NULL; 246220497Smarkm } 247220497Smarkm else 248220497Smarkm *cp = '\0'; /* Terminate the string. */ 249220497Smarkm 250220497Smarkm /* Clear the buffer for the intermediate result so that people 251220497Smarkm * attaching to processes or reading core dumps cannot get any 252220497Smarkm * information. We do it in this way to clear correct_words[] inside 253220497Smarkm * the SHA256 implementation as well. */ 254220497Smarkm SHA256_Init(&ctx); 255220497Smarkm SHA256_Final(alt_result, &ctx); 256220497Smarkm memset(temp_result, '\0', sizeof(temp_result)); 257220497Smarkm memset(p_bytes, '\0', key_len); 258220497Smarkm memset(s_bytes, '\0', salt_len); 259220497Smarkm memset(&ctx, '\0', sizeof(ctx)); 260220497Smarkm memset(&alt_ctx, '\0', sizeof(alt_ctx)); 261220497Smarkm if (copied_key != NULL) 262220497Smarkm memset(copied_key, '\0', key_len); 263220497Smarkm if (copied_salt != NULL) 264220497Smarkm memset(copied_salt, '\0', salt_len); 265220497Smarkm 266220497Smarkm return buffer; 267220497Smarkm} 268220497Smarkm 269220497Smarkm/* This entry point is equivalent to crypt(3). */ 270220497Smarkmchar * 271221471Sobriencrypt_sha256(const char *key, const char *salt) 272220497Smarkm{ 273220497Smarkm /* We don't want to have an arbitrary limit in the size of the 274220497Smarkm * password. We can compute an upper bound for the size of the 275220497Smarkm * result in advance and so we can prepare the buffer we pass to 276221471Sobrien * `crypt_sha256_r'. */ 277220497Smarkm static char *buffer; 278220497Smarkm static int buflen; 279220497Smarkm int needed; 280220497Smarkm char *new_buffer; 281220497Smarkm 282220497Smarkm needed = (sizeof(sha256_salt_prefix) - 1 283220497Smarkm + sizeof(sha256_rounds_prefix) + 9 + 1 284220497Smarkm + strlen(salt) + 1 + 43 + 1); 285220497Smarkm 286220497Smarkm if (buflen < needed) { 287220497Smarkm new_buffer = (char *)realloc(buffer, needed); 288220497Smarkm 289220497Smarkm if (new_buffer == NULL) 290220497Smarkm return NULL; 291220497Smarkm 292220497Smarkm buffer = new_buffer; 293220497Smarkm buflen = needed; 294220497Smarkm } 295220497Smarkm 296221471Sobrien return crypt_sha256_r(key, salt, buffer, buflen); 297220497Smarkm} 298220497Smarkm 299220497Smarkm#ifdef TEST 300220497Smarkm 301220497Smarkmstatic const struct { 302220497Smarkm const char *input; 303220497Smarkm const char result[32]; 304220497Smarkm} tests[] = 305220497Smarkm{ 306220497Smarkm /* Test vectors from FIPS 180-2: appendix B.1. */ 307220497Smarkm { 308220497Smarkm "abc", 309220497Smarkm "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" 310220497Smarkm "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" 311220497Smarkm }, 312220497Smarkm /* Test vectors from FIPS 180-2: appendix B.2. */ 313220497Smarkm { 314220497Smarkm "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 315220497Smarkm "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" 316220497Smarkm "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" 317220497Smarkm }, 318220497Smarkm /* Test vectors from the NESSIE project. */ 319220497Smarkm { 320220497Smarkm "", 321220497Smarkm "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24" 322220497Smarkm "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" 323220497Smarkm }, 324220497Smarkm { 325220497Smarkm "a", 326220497Smarkm "\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d" 327220497Smarkm "\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb" 328220497Smarkm }, 329220497Smarkm { 330220497Smarkm "message digest", 331220497Smarkm "\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad" 332220497Smarkm "\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50" 333220497Smarkm }, 334220497Smarkm { 335220497Smarkm "abcdefghijklmnopqrstuvwxyz", 336220497Smarkm "\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52" 337220497Smarkm "\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73" 338220497Smarkm }, 339220497Smarkm { 340220497Smarkm "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 341220497Smarkm "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" 342220497Smarkm "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" 343220497Smarkm }, 344220497Smarkm { 345220497Smarkm "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 346220497Smarkm "\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80" 347220497Smarkm "\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0" 348220497Smarkm }, 349220497Smarkm { 350220497Smarkm "123456789012345678901234567890123456789012345678901234567890" 351220497Smarkm "12345678901234567890", 352220497Smarkm "\xf3\x71\xbc\x4a\x31\x1f\x2b\x00\x9e\xef\x95\x2d\xd8\x3c\xa8\x0e" 353220497Smarkm "\x2b\x60\x02\x6c\x8e\x93\x55\x92\xd0\xf9\xc3\x08\x45\x3c\x81\x3e" 354220497Smarkm } 355220497Smarkm}; 356220497Smarkm 357220497Smarkm#define ntests (sizeof (tests) / sizeof (tests[0])) 358220497Smarkm 359220497Smarkmstatic const struct { 360220497Smarkm const char *salt; 361220497Smarkm const char *input; 362220497Smarkm const char *expected; 363220497Smarkm} tests2[] = 364220497Smarkm{ 365220497Smarkm { 366220497Smarkm "$5$saltstring", "Hello world!", 367220497Smarkm "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5" 368220497Smarkm }, 369220497Smarkm { 370220497Smarkm "$5$rounds=10000$saltstringsaltstring", "Hello world!", 371220497Smarkm "$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2." 372220497Smarkm "opqey6IcA" 373220497Smarkm }, 374220497Smarkm { 375220497Smarkm "$5$rounds=5000$toolongsaltstring", "This is just a test", 376220497Smarkm "$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8" 377220497Smarkm "mGRcvxa5" 378220497Smarkm }, 379220497Smarkm { 380220497Smarkm "$5$rounds=1400$anotherlongsaltstring", 381220497Smarkm "a very much longer text to encrypt. This one even stretches over more" 382220497Smarkm "than one line.", 383220497Smarkm "$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12" 384220497Smarkm "oP84Bnq1" 385220497Smarkm }, 386220497Smarkm { 387220497Smarkm "$5$rounds=77777$short", 388220497Smarkm "we have a short salt string but not a short password", 389220497Smarkm "$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/" 390220497Smarkm }, 391220497Smarkm { 392220497Smarkm "$5$rounds=123456$asaltof16chars..", "a short string", 393220497Smarkm "$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/" 394220497Smarkm "cZKmF/wJvD" 395220497Smarkm }, 396220497Smarkm { 397220497Smarkm "$5$rounds=10$roundstoolow", "the minimum number is still observed", 398220497Smarkm "$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97" 399220497Smarkm "2bIC" 400220497Smarkm }, 401220497Smarkm}; 402220497Smarkm 403220497Smarkm#define ntests2 (sizeof (tests2) / sizeof (tests2[0])) 404220497Smarkm 405220497Smarkmint 406220497Smarkmmain(void) 407220497Smarkm{ 408220497Smarkm SHA256_CTX ctx; 409220497Smarkm uint8_t sum[32]; 410220497Smarkm int result = 0; 411220497Smarkm int i, cnt; 412220497Smarkm 413220497Smarkm for (cnt = 0; cnt < (int)ntests; ++cnt) { 414220497Smarkm SHA256_Init(&ctx); 415220497Smarkm SHA256_Update(&ctx, tests[cnt].input, strlen(tests[cnt].input)); 416220497Smarkm SHA256_Final(sum, &ctx); 417220497Smarkm if (memcmp(tests[cnt].result, sum, 32) != 0) { 418220497Smarkm for (i = 0; i < 32; i++) 419220497Smarkm printf("%02X", tests[cnt].result[i]); 420220497Smarkm printf("\n"); 421220497Smarkm for (i = 0; i < 32; i++) 422220497Smarkm printf("%02X", sum[i]); 423220497Smarkm printf("\n"); 424220497Smarkm printf("test %d run %d failed\n", cnt, 1); 425220497Smarkm result = 1; 426220497Smarkm } 427220497Smarkm 428220497Smarkm SHA256_Init(&ctx); 429220497Smarkm for (i = 0; tests[cnt].input[i] != '\0'; ++i) 430220497Smarkm SHA256_Update(&ctx, &tests[cnt].input[i], 1); 431220497Smarkm SHA256_Final(sum, &ctx); 432220497Smarkm if (memcmp(tests[cnt].result, sum, 32) != 0) { 433220497Smarkm for (i = 0; i < 32; i++) 434220497Smarkm printf("%02X", tests[cnt].result[i]); 435220497Smarkm printf("\n"); 436220497Smarkm for (i = 0; i < 32; i++) 437220497Smarkm printf("%02X", sum[i]); 438220497Smarkm printf("\n"); 439220497Smarkm printf("test %d run %d failed\n", cnt, 2); 440220497Smarkm result = 1; 441220497Smarkm } 442220497Smarkm } 443220497Smarkm 444220497Smarkm /* Test vector from FIPS 180-2: appendix B.3. */ 445220497Smarkm char buf[1000]; 446220497Smarkm 447220497Smarkm memset(buf, 'a', sizeof(buf)); 448220497Smarkm SHA256_Init(&ctx); 449220497Smarkm for (i = 0; i < 1000; ++i) 450220497Smarkm SHA256_Update(&ctx, buf, sizeof(buf)); 451220497Smarkm SHA256_Final(sum, &ctx); 452220497Smarkm static const char expected[32] = 453220497Smarkm "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" 454220497Smarkm "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0"; 455220497Smarkm 456220497Smarkm if (memcmp(expected, sum, 32) != 0) { 457220497Smarkm printf("test %d failed\n", cnt); 458220497Smarkm result = 1; 459220497Smarkm } 460220497Smarkm 461220497Smarkm for (cnt = 0; cnt < ntests2; ++cnt) { 462221471Sobrien char *cp = crypt_sha256(tests2[cnt].input, tests2[cnt].salt); 463220497Smarkm 464220497Smarkm if (strcmp(cp, tests2[cnt].expected) != 0) { 465220497Smarkm printf("test %d: expected \"%s\", got \"%s\"\n", 466220497Smarkm cnt, tests2[cnt].expected, cp); 467220497Smarkm result = 1; 468220497Smarkm } 469220497Smarkm } 470220497Smarkm 471220497Smarkm if (result == 0) 472220497Smarkm puts("all tests OK"); 473220497Smarkm 474220497Smarkm return result; 475220497Smarkm} 476220497Smarkm 477220497Smarkm#endif /* TEST */ 478