File indexing completed on 2024-04-28 16:59:49
0001 /* This code is public-domain - it is based on libcrypt 0002 * placed in the public domain by Wei Dai and other contributors. 0003 */ 0004 // gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test 0005 0006 #include <stdint.h> 0007 #include <string.h> 0008 0009 /* This is the only section changed for dferry - apparently our endianness macro is exotic */ 0010 #ifdef BIGENDIAN 0011 #define SHA_BIG_ENDIAN 0012 #endif 0013 0014 /* header */ 0015 0016 #define HASH_LENGTH 20 0017 #define BLOCK_LENGTH 64 0018 0019 typedef struct sha1nfo { 0020 uint32_t buffer[BLOCK_LENGTH/4]; 0021 uint32_t state[HASH_LENGTH/4]; 0022 uint32_t byteCount; 0023 uint8_t bufferOffset; 0024 uint8_t keyBuffer[BLOCK_LENGTH]; 0025 uint8_t innerHash[HASH_LENGTH]; 0026 } sha1nfo; 0027 0028 /* public API - prototypes - TODO: doxygen*/ 0029 0030 /** 0031 */ 0032 void sha1_init(sha1nfo *s); 0033 /** 0034 */ 0035 void sha1_writebyte(sha1nfo *s, uint8_t data); 0036 /** 0037 */ 0038 void sha1_write(sha1nfo *s, const char *data, size_t len); 0039 /** 0040 */ 0041 uint8_t* sha1_result(sha1nfo *s); 0042 /** 0043 */ 0044 void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength); 0045 /** 0046 */ 0047 uint8_t* sha1_resultHmac(sha1nfo *s); 0048 0049 0050 /* code */ 0051 #define SHA1_K0 0x5a827999 0052 #define SHA1_K20 0x6ed9eba1 0053 #define SHA1_K40 0x8f1bbcdc 0054 #define SHA1_K60 0xca62c1d6 0055 0056 void sha1_init(sha1nfo *s) { 0057 s->state[0] = 0x67452301; 0058 s->state[1] = 0xefcdab89; 0059 s->state[2] = 0x98badcfe; 0060 s->state[3] = 0x10325476; 0061 s->state[4] = 0xc3d2e1f0; 0062 s->byteCount = 0; 0063 s->bufferOffset = 0; 0064 } 0065 0066 uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 0067 return ((number << bits) | (number >> (32-bits))); 0068 } 0069 0070 void sha1_hashBlock(sha1nfo *s) { 0071 uint8_t i; 0072 uint32_t a,b,c,d,e,t; 0073 0074 a=s->state[0]; 0075 b=s->state[1]; 0076 c=s->state[2]; 0077 d=s->state[3]; 0078 e=s->state[4]; 0079 for (i=0; i<80; i++) { 0080 if (i>=16) { 0081 t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 0082 s->buffer[i&15] = sha1_rol32(t,1); 0083 } 0084 if (i<20) { 0085 t = (d ^ (b & (c ^ d))) + SHA1_K0; 0086 } else if (i<40) { 0087 t = (b ^ c ^ d) + SHA1_K20; 0088 } else if (i<60) { 0089 t = ((b & c) | (d & (b | c))) + SHA1_K40; 0090 } else { 0091 t = (b ^ c ^ d) + SHA1_K60; 0092 } 0093 t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 0094 e=d; 0095 d=c; 0096 c=sha1_rol32(b,30); 0097 b=a; 0098 a=t; 0099 } 0100 s->state[0] += a; 0101 s->state[1] += b; 0102 s->state[2] += c; 0103 s->state[3] += d; 0104 s->state[4] += e; 0105 } 0106 0107 void sha1_addUncounted(sha1nfo *s, uint8_t data) { 0108 uint8_t * const b = (uint8_t*) s->buffer; 0109 #ifdef SHA_BIG_ENDIAN 0110 b[s->bufferOffset] = data; 0111 #else 0112 b[s->bufferOffset ^ 3] = data; 0113 #endif 0114 s->bufferOffset++; 0115 if (s->bufferOffset == BLOCK_LENGTH) { 0116 sha1_hashBlock(s); 0117 s->bufferOffset = 0; 0118 } 0119 } 0120 0121 void sha1_writebyte(sha1nfo *s, uint8_t data) { 0122 ++s->byteCount; 0123 sha1_addUncounted(s, data); 0124 } 0125 0126 void sha1_write(sha1nfo *s, const char *data, size_t len) { 0127 for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 0128 } 0129 0130 void sha1_pad(sha1nfo *s) { 0131 // Implement SHA-1 padding (fips180-2 ยง5.1.1) 0132 0133 // Pad with 0x80 followed by 0x00 until the end of the block 0134 sha1_addUncounted(s, 0x80); 0135 while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 0136 0137 // Append length in the last 8 bytes 0138 sha1_addUncounted(s, 0); // We're only using 32 bit lengths 0139 sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 0140 sha1_addUncounted(s, 0); // So zero pad the top bits 0141 sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 0142 sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 0143 sha1_addUncounted(s, s->byteCount >> 13); // byte. 0144 sha1_addUncounted(s, s->byteCount >> 5); 0145 sha1_addUncounted(s, s->byteCount << 3); 0146 } 0147 0148 uint8_t* sha1_result(sha1nfo *s) { 0149 // Pad to complete the last block 0150 sha1_pad(s); 0151 0152 #ifndef SHA_BIG_ENDIAN 0153 // Swap byte order back 0154 int i; 0155 for (i=0; i<5; i++) { 0156 s->state[i]= 0157 (((s->state[i])<<24)& 0xff000000) 0158 | (((s->state[i])<<8) & 0x00ff0000) 0159 | (((s->state[i])>>8) & 0x0000ff00) 0160 | (((s->state[i])>>24)& 0x000000ff); 0161 } 0162 #endif 0163 0164 // Return pointer to hash (20 characters) 0165 return (uint8_t*) s->state; 0166 } 0167 0168 #define HMAC_IPAD 0x36 0169 #define HMAC_OPAD 0x5c 0170 0171 void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) { 0172 uint8_t i; 0173 memset(s->keyBuffer, 0, BLOCK_LENGTH); 0174 if (keyLength > BLOCK_LENGTH) { 0175 // Hash long keys 0176 sha1_init(s); 0177 for (;keyLength--;) sha1_writebyte(s, *key++); 0178 memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); 0179 } else { 0180 // Block length keys are used as is 0181 memcpy(s->keyBuffer, key, keyLength); 0182 } 0183 // Start inner hash 0184 sha1_init(s); 0185 for (i=0; i<BLOCK_LENGTH; i++) { 0186 sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD); 0187 } 0188 } 0189 0190 uint8_t* sha1_resultHmac(sha1nfo *s) { 0191 uint8_t i; 0192 // Complete inner hash 0193 memcpy(s->innerHash,sha1_result(s),HASH_LENGTH); 0194 // Calculate outer hash 0195 sha1_init(s); 0196 for (i=0; i<BLOCK_LENGTH; i++) sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD); 0197 for (i=0; i<HASH_LENGTH; i++) sha1_writebyte(s, s->innerHash[i]); 0198 return sha1_result(s); 0199 } 0200 0201 /* self-test */ 0202 0203 #ifdef SHA1TEST 0204 #include <stdio.h> 0205 0206 uint8_t hmacKey1[]={ 0207 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0208 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0209 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0210 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f 0211 }; 0212 uint8_t hmacKey2[]={ 0213 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0214 0x40,0x41,0x42,0x43 0215 }; 0216 uint8_t hmacKey3[]={ 0217 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0218 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0219 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0220 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0221 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0222 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0223 0xb0,0xb1,0xb2,0xb3 0224 }; 0225 uint8_t hmacKey4[]={ 0226 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0227 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0228 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0229 0xa0 0230 }; 0231 0232 void printHash(uint8_t* hash) { 0233 int i; 0234 for (i=0; i<20; i++) { 0235 printf("%02x", hash[i]); 0236 } 0237 printf("\n"); 0238 } 0239 0240 0241 int main (int argc, char **argv) { 0242 uint32_t a; 0243 sha1nfo s; 0244 0245 // SHA tests 0246 printf("Test: FIPS 180-2 C.1 and RFC3174 7.3 TEST1\n"); 0247 printf("Expect:a9993e364706816aba3e25717850c26c9cd0d89d\n"); 0248 printf("Result:"); 0249 sha1_init(&s); 0250 sha1_write(&s, "abc", 3); 0251 printHash(sha1_result(&s)); 0252 printf("\n\n"); 0253 0254 printf("Test: FIPS 180-2 C.2 and RFC3174 7.3 TEST2\n"); 0255 printf("Expect:84983e441c3bd26ebaae4aa1f95129e5e54670f1\n"); 0256 printf("Result:"); 0257 sha1_init(&s); 0258 sha1_write(&s, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); 0259 printHash(sha1_result(&s)); 0260 printf("\n\n"); 0261 0262 printf("Test: RFC3174 7.3 TEST4\n"); 0263 printf("Expect:dea356a2cddd90c7a7ecedc5ebb563934f460452\n"); 0264 printf("Result:"); 0265 sha1_init(&s); 0266 for (a=0; a<80; a++) sha1_write(&s, "01234567", 8); 0267 printHash(sha1_result(&s)); 0268 printf("\n\n"); 0269 0270 // HMAC tests 0271 printf("Test: FIPS 198a A.1\n"); 0272 printf("Expect:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a\n"); 0273 printf("Result:"); 0274 sha1_initHmac(&s, hmacKey1, 64); 0275 sha1_write(&s, "Sample #1",9); 0276 printHash(sha1_resultHmac(&s)); 0277 printf("\n\n"); 0278 0279 printf("Test: FIPS 198a A.2\n"); 0280 printf("Expect:0922d3405faa3d194f82a45830737d5cc6c75d24\n"); 0281 printf("Result:"); 0282 sha1_initHmac(&s, hmacKey2, 20); 0283 sha1_write(&s, "Sample #2", 9); 0284 printHash(sha1_resultHmac(&s)); 0285 printf("\n\n"); 0286 0287 printf("Test: FIPS 198a A.3\n"); 0288 printf("Expect:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa\n"); 0289 printf("Result:"); 0290 sha1_initHmac(&s, hmacKey3,100); 0291 sha1_write(&s, "Sample #3", 9); 0292 printHash(sha1_resultHmac(&s)); 0293 printf("\n\n"); 0294 0295 printf("Test: FIPS 198a A.4\n"); 0296 printf("Expect:9ea886efe268dbecce420c7524df32e0751a2a26\n"); 0297 printf("Result:"); 0298 sha1_initHmac(&s, hmacKey4,49); 0299 sha1_write(&s, "Sample #4", 9); 0300 printHash(sha1_resultHmac(&s)); 0301 printf("\n\n"); 0302 0303 // Long tests 0304 printf("Test: FIPS 180-2 C.3 and RFC3174 7.3 TEST3\n"); 0305 printf("Expect:34aa973cd4c4daa4f61eeb2bdbad27316534016f\n"); 0306 printf("Result:"); 0307 sha1_init(&s); 0308 for (a=0; a<1000000; a++) sha1_writebyte(&s, 'a'); 0309 printHash(sha1_result(&s)); 0310 0311 return 0; 0312 } 0313 #endif /* self-test */