1 /*********************************************************************
3 * Author: Brad Conte (brad AT bradconte.com)
4 * Modified by: Andre Schalkwyk (avs.aswyk AT gmail.com) 2016-01-05
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 ***************************/
19 #include "tm_crypto.h"
20 #include "config.h" /* for WORD */
23 /****************************** MACROS ******************************/
24 #define SHA1_BLOCK_LENGTH 64
25 #define SHA1_DIGEST_LENGTH 20
27 /**************************** DATA TYPES ****************************/
28 typedef unsigned char BYTE
;
33 unsigned long long bitlen
;
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
];
52 /* Context to hold SHA1 hash */
59 pBuff
= (unsigned char*)&data
[0];
60 len
= strlen((char*)data
);
62 /* Initialize SHA1 Context */
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
])
84 /* buffer to store unhashed datya */
85 BYTE buff
[SHA1_BLOCK_LENGTH
];
86 /* How many bytes we have read from */
88 /* Context to hold SHA1 hash */
91 /* Initialize SHA1 Context */
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
);
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
])
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);
142 for (i
= 0; i
< 20; ++i
) {
143 t
= ROTLEFT(a
, 5) + ((b
& c
) ^ (~b
& d
)) + e
+ ctx
->k
[0] + m
[i
];
150 for ( ; i
< 40; ++i
) {
151 t
= ROTLEFT(a
, 5) + (b
^ c
^ d
) + e
+ ctx
->k
[1] + m
[i
];
158 for ( ; i
< 60; ++i
) {
159 t
= ROTLEFT(a
, 5) + ((b
& c
) ^ (b
& d
) ^ (c
& d
)) + e
+ ctx
->k
[2] + m
[i
];
166 for ( ; i
< 80; ++i
) {
167 t
= ROTLEFT(a
, 5) + (b
^ c
^ d
) + e
+ ctx
->k
[3] + m
[i
];
182 void sha1_init(SHA1_CTX
*ctx
)
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
)
201 for (i
= 0; i
< len
; ++i
) {
202 ctx
->data
[ctx
->datalen
] = data
[i
];
204 if (ctx
->datalen
== 64) {
205 sha1_transform(ctx
, ctx
->data
);
212 void sha1_final(SHA1_CTX
*ctx
, BYTE hash
[])
218 /* Pad whatever data is left in the buffer. */
219 if (ctx
->datalen
< 56) {
220 ctx
->data
[i
++] = 0x80;
222 ctx
->data
[i
++] = 0x00;
225 ctx
->data
[i
++] = 0x80;
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;