181 lines
5.0 KiB
C
181 lines
5.0 KiB
C
|
/*
|
||
|
* 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 <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#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;
|
||
|
}
|