Update HTML doc template.
[tmk.git] / tm_crypto.c
blob617f7733907a0bd0f1bcfec351845123eb0179be
1 /*********************************************************************
2 * Filename: sha1.c
3 * Author: Brad Conte (brad AT bradconte.com)
4 * Modified by: Andre Schalkwyk (avs.aswyk AT gmail.com) 2016-01-05
5 * Copyright:
6 * Disclaimer: This code is presented "as is" without any guarantees.
7 * Details: Implementation of the SHA1 hashing algorithm.
8 Algorithm specification can be found here:
9 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
10 This implementation uses little endian byte order.
11 *********************************************************************/
13 /*************************** HEADER FILES ***************************/
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <memory.h>
17 #include <string.h>
19 #include "tm_crypto.h"
22 /****************************** MACROS ******************************/
23 #define SHA1_BLOCK_LENGTH 64
24 #define SHA1_DIGEST_LENGTH 20
26 /**************************** DATA TYPES ****************************/
27 typedef unsigned char BYTE;
28 typedef unsigned int WORD;
30 typedef struct {
31 BYTE data[64];
32 WORD datalen;
33 unsigned long long bitlen;
34 WORD state[5];
35 WORD k[4];
36 } SHA1_CTX;
38 /*********************** FUNCTION DECLARATIONS **********************/
39 void sha1_init(SHA1_CTX *ctx);
40 void sha1_update(SHA1_CTX *ctx, const BYTE data[], size_t len);
41 void sha1_final(SHA1_CTX *ctx, BYTE hash[]);
44 /****************** HIGHER LEVEL CRYPTO FUNCTIONS *******************/
45 void tm_CryptoHashData(const unsigned char* data, unsigned char digest[CRYPTO_HASH_SIZE])
47 BYTE buff[SHA1_BLOCK_LENGTH];
48 BYTE* pBuff;
49 int bytesLeft;
50 int len;
52 /* Context to hold SHA1 hash */
53 SHA1_CTX sha_ctx;
55 if (!data) {
56 data = (BYTE *)"";
59 pBuff = (unsigned char*)&data[0];
60 len = strlen((char*)data);
62 /* Initialize SHA1 Context */
63 sha1_init(&sha_ctx);
65 while(pBuff < data + len)
67 bytesLeft = strlen((const char*)pBuff);
69 strncpy((char*)buff, (char*)pBuff, bytesLeft < SHA1_BLOCK_LENGTH ? bytesLeft : SHA1_BLOCK_LENGTH);
71 sha1_update(&sha_ctx, buff, bytesLeft < SHA1_BLOCK_LENGTH ? bytesLeft : SHA1_BLOCK_LENGTH);
73 pBuff += SHA1_BLOCK_LENGTH;
76 /* Finalize SHA1 Context */
77 sha1_final(&sha_ctx, digest);
80 void tm_CryptoHashFile(const char* file, unsigned char digest[CRYPTO_HASH_SIZE])
82 /* File Handle */
83 FILE* fp = NULL;
84 /* buffer to store unhashed datya */
85 BYTE buff[SHA1_BLOCK_LENGTH];
86 /* How many bytes we have read from */
87 int bytesRead;
88 /* Context to hold SHA1 hash */
89 SHA1_CTX sha_ctx;
91 /* Initialize SHA1 Context */
92 sha1_init(&sha_ctx);
94 if((fp = fopen(file, "r")) == NULL) {
95 printf("File %s could not be opened\n", file);
96 exit(TM_CRYPTO_FILE_ERROR);
99 while((bytesRead = fread(buff, 1, SHA1_BLOCK_LENGTH, fp)) != 0)
101 /* Update SHA1 Context with block of data that was read */
102 sha1_update(&sha_ctx, buff, bytesRead);
105 fclose(fp);
107 /* Finalize SHA1 Context */
108 sha1_final(&sha_ctx, digest);
111 void tm_CryptoHashToString(const unsigned char digest[CRYPTO_HASH_SIZE], char hash[CRYPTO_HASH_STRING_LENGTH])
113 int i;
114 char *p = hash;
116 for (i = 0; i < 20; i++) {
117 p += sprintf(p, "%02x", digest[i]);
121 /****************************** MACROS ******************************/
122 #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
124 /*********************** FUNCTION DEFINITIONS ***********************/
125 void sha1_transform(SHA1_CTX *ctx, const BYTE data[])
127 WORD a, b, c, d, e, i, j, t, m[80];
129 for (i = 0, j = 0; i < 16; ++i, j += 4)
130 m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) + (data[j + 3]);
131 for ( ; i < 80; ++i) {
132 m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
133 m[i] = (m[i] << 1) | (m[i] >> 31);
136 a = ctx->state[0];
137 b = ctx->state[1];
138 c = ctx->state[2];
139 d = ctx->state[3];
140 e = ctx->state[4];
142 for (i = 0; i < 20; ++i) {
143 t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + ctx->k[0] + m[i];
144 e = d;
145 d = c;
146 c = ROTLEFT(b, 30);
147 b = a;
148 a = t;
150 for ( ; i < 40; ++i) {
151 t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[1] + m[i];
152 e = d;
153 d = c;
154 c = ROTLEFT(b, 30);
155 b = a;
156 a = t;
158 for ( ; i < 60; ++i) {
159 t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + ctx->k[2] + m[i];
160 e = d;
161 d = c;
162 c = ROTLEFT(b, 30);
163 b = a;
164 a = t;
166 for ( ; i < 80; ++i) {
167 t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[3] + m[i];
168 e = d;
169 d = c;
170 c = ROTLEFT(b, 30);
171 b = a;
172 a = t;
175 ctx->state[0] += a;
176 ctx->state[1] += b;
177 ctx->state[2] += c;
178 ctx->state[3] += d;
179 ctx->state[4] += e;
182 void sha1_init(SHA1_CTX *ctx)
184 ctx->datalen = 0;
185 ctx->bitlen = 0;
186 ctx->state[0] = 0x67452301;
187 ctx->state[1] = 0xEFCDAB89;
188 ctx->state[2] = 0x98BADCFE;
189 ctx->state[3] = 0x10325476;
190 ctx->state[4] = 0xc3d2e1f0;
191 ctx->k[0] = 0x5a827999;
192 ctx->k[1] = 0x6ed9eba1;
193 ctx->k[2] = 0x8f1bbcdc;
194 ctx->k[3] = 0xca62c1d6;
197 void sha1_update(SHA1_CTX *ctx, const BYTE data[], size_t len)
199 size_t i;
201 for (i = 0; i < len; ++i) {
202 ctx->data[ctx->datalen] = data[i];
203 ctx->datalen++;
204 if (ctx->datalen == 64) {
205 sha1_transform(ctx, ctx->data);
206 ctx->bitlen += 512;
207 ctx->datalen = 0;
212 void sha1_final(SHA1_CTX *ctx, BYTE hash[])
214 WORD i;
216 i = ctx->datalen;
218 /* Pad whatever data is left in the buffer. */
219 if (ctx->datalen < 56) {
220 ctx->data[i++] = 0x80;
221 while (i < 56)
222 ctx->data[i++] = 0x00;
224 else {
225 ctx->data[i++] = 0x80;
226 while (i < 64)
227 ctx->data[i++] = 0x00;
228 sha1_transform(ctx, ctx->data);
229 memset(ctx->data, 0, 56);
232 /* Append to the padding the total message's length in bits and transform. */
233 ctx->bitlen += ctx->datalen * 8;
234 ctx->data[63] = ctx->bitlen;
235 ctx->data[62] = ctx->bitlen >> 8;
236 ctx->data[61] = ctx->bitlen >> 16;
237 ctx->data[60] = ctx->bitlen >> 24;
238 ctx->data[59] = ctx->bitlen >> 32;
239 ctx->data[58] = ctx->bitlen >> 40;
240 ctx->data[57] = ctx->bitlen >> 48;
241 ctx->data[56] = ctx->bitlen >> 56;
242 sha1_transform(ctx, ctx->data);
244 /* Since this implementation uses little endian byte ordering and MD uses big endian, */
245 /* reverse all the bytes when copying the final state to the output hash. */
246 for (i = 0; i < 4; ++i) {
247 hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
248 hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
249 hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
250 hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
251 hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;