/* * sha256.c - Implementation of the Secure Hash Algorithm-256 (SHA-256). * * Implemented from the description on the NIST Web site: * http://csrc.nist.gov/cryptval/shs.html * * * Copyright (C) 2012 Rafal Kupiec (customized for sessmgr) * Copyright (C) 2009 Eric Bishop (adapted as standalone utility) * Copyright (C) 2002 Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "sha256.h" static void ProcessBlock(SHA256Context *sha, const unsigned char *block) { u_int32_t W[64]; u_int32_t a, b, c, d, e, f, g, h; u_int32_t temp, temp2; int t; for(t = 0; t < 16; ++t) { W[t] = (((u_int32_t) (block[t * 4 + 0])) << 24) | (((u_int32_t) (block[t * 4 + 1])) << 16) | (((u_int32_t) (block[t * 4 + 2])) << 8) | ((u_int32_t) (block[t * 4 + 3])); } for(t = 16; t < 64; ++t) { W[t] = TRUNCLONG(RHO1(W[t - 2]) + W[t - 7] + RHO0(W[t - 15]) + W[t - 16]); } a = sha->A; b = sha->B; c = sha->C; d = sha->D; e = sha->E; f = sha->F; g = sha->G; h = sha->H; for(t = 0; t < 64; ++t) { temp = TRUNCLONG(h + SUM1(e) + CH(e, f, g) + K[t] + W[t]); temp2 = TRUNCLONG(SUM0(a) + MAJ(a, b, c)); h = g; g = f; f = e; e = TRUNCLONG(d + temp); d = c; c = b; b = a; a = TRUNCLONG(temp + temp2); } sha->A = TRUNCLONG(sha->A + a); sha->B = TRUNCLONG(sha->B + b); sha->C = TRUNCLONG(sha->C + c); sha->D = TRUNCLONG(sha->D + d); sha->E = TRUNCLONG(sha->E + e); sha->F = TRUNCLONG(sha->F + f); sha->G = TRUNCLONG(sha->G + g); sha->H = TRUNCLONG(sha->H + h); DoMemZero(W, sizeof(u_int32_t) * 64); a = b = c = d = e = f = g = h = temp = temp2 = 0; } void SHA256Data(SHA256Context *sha, const void *buffer, unsigned long len) { unsigned long templen; sha->totalLen += (u_int64_t)len; while(len > 0) { if(!(sha->inputLen) && len >= 64) { ProcessBlock(sha, (const unsigned char *) buffer); buffer = (const void *) (((const unsigned char *) buffer) + 64); len -= 64; } else { templen = len; if(templen > (64 - sha->inputLen)) { templen = 64 - sha->inputLen; } memcpy(sha->input + sha->inputLen, buffer, templen); if((sha->inputLen += templen) >= 64) { ProcessBlock(sha, sha->input); sha->inputLen = 0; } buffer = (const void *) (((const unsigned char *) buffer) + templen); len -= templen; } } } void SHA256Finalize(SHA256Context *sha, unsigned char hash[SHA256_HASH_SIZE]) { u_int64_t totalBits; if(hash) { if(sha->inputLen >= 56) { sha->input[(sha->inputLen)++] = (unsigned char) 0x80; while(sha->inputLen < 64) { sha->input[(sha->inputLen)++] = (unsigned char) 0x00; } ProcessBlock(sha, sha->input); sha->inputLen = 0; } else { sha->input[(sha->inputLen)++] = (unsigned char) 0x80; } while(sha->inputLen < 56) { sha->input[(sha->inputLen)++] = (unsigned char) 0x00; } totalBits = (sha->totalLen << 3); WriteLong(sha->input + 56, (u_int32_t) (totalBits >> 32)); WriteLong(sha->input + 60, (u_int32_t) totalBits); ProcessBlock(sha, sha->input); WriteLong(hash, sha->A); WriteLong(hash + 4, sha->B); WriteLong(hash + 8, sha->C); WriteLong(hash + 12, sha->D); WriteLong(hash + 16, sha->E); WriteLong(hash + 20, sha->F); WriteLong(hash + 24, sha->G); WriteLong(hash + 28, sha->H); } DoMemZero(sha, sizeof(SHA256Context)); } void SHA256Init(SHA256Context *sha) { sha->inputLen = 0; sha->A = 0x6a09e667; sha->B = 0xbb67ae85; sha->C = 0x3c6ef372; sha->D = 0xa54ff53a; sha->E = 0x510e527f; sha->F = 0x9b05688c; sha->G = 0x1f83d9ab; sha->H = 0x5be0cd19; sha->totalLen = 0; } static void WriteLong(unsigned char *buf, u_int32_t value) { buf[0] = (unsigned char)(value >> 24); buf[1] = (unsigned char)(value >> 16); buf[2] = (unsigned char)(value >> 8); buf[3] = (unsigned char)value; } unsigned char* get_sha256_hash(const char* unhashed) { SHA256Context sha; unsigned char* hash = (unsigned char*) malloc(32); SHA256Init(&sha); SHA256Data(&sha, unhashed, strlen(unhashed)); SHA256Finalize(&sha, hash); return hash; } char* get_sha256_hash_hex_str(const char* unhashed) { unsigned char* hashed = get_sha256_hash(unhashed); char* hashed_hex = (char*) malloc(65); char next_hex[3]; int index =0; hashed_hex[0] = '\0'; for(index=0; index < 32; index++) { sprintf(next_hex, "%02X", hashed[index]); strcat(hashed_hex, next_hex); } free(hashed); return hashed_hex; }