| 1 | /********************************************************************* |
| 2 | * Filename: sha1.c |
| 3 | * Author: Brad Conte (brad AT bradconte.com) |
| 4 | * Copyright: |
| 5 | * Disclaimer: This code is presented "as is" without any guarantees. |
| 6 | * Details: Implementation of the SHA1 hashing algorithm. |
| 7 | Algorithm specification can be found here: |
| 8 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf |
| 9 | This implementation uses little endian byte order. |
| 10 | *********************************************************************/ |
| 11 | |
| 12 | /*************************** HEADER FILES ***************************/ |
| 13 | #include <stdlib.h> |
| 14 | #include <string.h> |
| 15 | #include "sha1.h" |
| 16 | |
| 17 | /****************************** MACROS ******************************/ |
| 18 | #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b))) |
| 19 | |
| 20 | /*********************** FUNCTION DEFINITIONS ***********************/ |
| 21 | void sha1_transform(SHA1_CTX *ctx, const BYTE data[]) |
| 22 | { |
| 23 | WORD a, b, c, d, e, i, j, t, m[80]; |
| 24 | |
| 25 | for (i = 0, j = 0; i < 16; ++i, j += 4) |
| 26 | m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) + (data[j + 3]); |
| 27 | for ( ; i < 80; ++i) { |
| 28 | m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]); |
| 29 | m[i] = (m[i] << 1) | (m[i] >> 31); |
| 30 | } |
| 31 | |
| 32 | a = ctx->state[0]; |
| 33 | b = ctx->state[1]; |
| 34 | c = ctx->state[2]; |
| 35 | d = ctx->state[3]; |
| 36 | e = ctx->state[4]; |
| 37 | |
| 38 | for (i = 0; i < 20; ++i) { |
| 39 | t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + ctx->k[0] + m[i]; |
| 40 | e = d; |
| 41 | d = c; |
| 42 | c = ROTLEFT(b, 30); |
| 43 | b = a; |
| 44 | a = t; |
| 45 | } |
| 46 | for ( ; i < 40; ++i) { |
| 47 | t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[1] + m[i]; |
| 48 | e = d; |
| 49 | d = c; |
| 50 | c = ROTLEFT(b, 30); |
| 51 | b = a; |
| 52 | a = t; |
| 53 | } |
| 54 | for ( ; i < 60; ++i) { |
| 55 | t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + ctx->k[2] + m[i]; |
| 56 | e = d; |
| 57 | d = c; |
| 58 | c = ROTLEFT(b, 30); |
| 59 | b = a; |
| 60 | a = t; |
| 61 | } |
| 62 | for ( ; i < 80; ++i) { |
| 63 | t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + ctx->k[3] + m[i]; |
| 64 | e = d; |
| 65 | d = c; |
| 66 | c = ROTLEFT(b, 30); |
| 67 | b = a; |
| 68 | a = t; |
| 69 | } |
| 70 | |
| 71 | ctx->state[0] += a; |
| 72 | ctx->state[1] += b; |
| 73 | ctx->state[2] += c; |
| 74 | ctx->state[3] += d; |
| 75 | ctx->state[4] += e; |
| 76 | } |
| 77 | |
| 78 | void sha1_init(SHA1_CTX *ctx) |
| 79 | { |
| 80 | ctx->datalen = 0; |
| 81 | ctx->bitlen = 0; |
| 82 | ctx->state[0] = 0x67452301; |
| 83 | ctx->state[1] = 0xEFCDAB89; |
| 84 | ctx->state[2] = 0x98BADCFE; |
| 85 | ctx->state[3] = 0x10325476; |
| 86 | ctx->state[4] = 0xc3d2e1f0; |
| 87 | ctx->k[0] = 0x5a827999; |
| 88 | ctx->k[1] = 0x6ed9eba1; |
| 89 | ctx->k[2] = 0x8f1bbcdc; |
| 90 | ctx->k[3] = 0xca62c1d6; |
| 91 | } |
| 92 | |
| 93 | void sha1_update(SHA1_CTX *ctx, const BYTE data[], size_t len) |
| 94 | { |
| 95 | size_t i; |
| 96 | |
| 97 | for (i = 0; i < len; ++i) { |
| 98 | ctx->data[ctx->datalen] = data[i]; |
| 99 | ctx->datalen++; |
| 100 | if (ctx->datalen == 64) { |
| 101 | sha1_transform(ctx, ctx->data); |
| 102 | ctx->bitlen += 512; |
| 103 | ctx->datalen = 0; |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | void sha1_final(SHA1_CTX *ctx, BYTE hash[]) |
| 109 | { |
| 110 | WORD i; |
| 111 | |
| 112 | i = ctx->datalen; |
| 113 | |
| 114 | // Pad whatever data is left in the buffer. |
| 115 | if (ctx->datalen < 56) { |
| 116 | ctx->data[i++] = 0x80; |
| 117 | while (i < 56) |
| 118 | ctx->data[i++] = 0x00; |
| 119 | } |
| 120 | else { |
| 121 | ctx->data[i++] = 0x80; |
| 122 | while (i < 64) |
| 123 | ctx->data[i++] = 0x00; |
| 124 | sha1_transform(ctx, ctx->data); |
| 125 | memset(ctx->data, 0, 56); |
| 126 | } |
| 127 | |
| 128 | // Append to the padding the total message's length in bits and transform. |
| 129 | ctx->bitlen += ctx->datalen * 8; |
| 130 | ctx->data[63] = ctx->bitlen; |
| 131 | ctx->data[62] = ctx->bitlen >> 8; |
| 132 | ctx->data[61] = ctx->bitlen >> 16; |
| 133 | ctx->data[60] = ctx->bitlen >> 24; |
| 134 | ctx->data[59] = ctx->bitlen >> 32; |
| 135 | ctx->data[58] = ctx->bitlen >> 40; |
| 136 | ctx->data[57] = ctx->bitlen >> 48; |
| 137 | ctx->data[56] = ctx->bitlen >> 56; |
| 138 | sha1_transform(ctx, ctx->data); |
| 139 | |
| 140 | // Since this implementation uses little endian byte ordering and MD uses big endian, |
| 141 | // reverse all the bytes when copying the final state to the output hash. |
| 142 | for (i = 0; i < 4; ++i) { |
| 143 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; |
| 144 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; |
| 145 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; |
| 146 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; |
| 147 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; |
| 148 | } |
| 149 | } |