908
|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
|
2 * |
|
3 * LibTomCrypt is a library that provides various cryptographic |
|
4 * algorithms in a highly modular and flexible manner. |
|
5 * |
|
6 * The library is free for all purposes without any express |
|
7 * guarantee it works. |
|
8 * |
|
9 * Tom St Denis, [email protected], http://libtomcrypt.com |
|
10 */ |
|
11 #include "tomcrypt.h" |
|
12 |
|
13 /** |
|
14 @file sha1.c |
|
15 SHA1 code by Tom St Denis |
|
16 */ |
|
17 |
|
18 |
|
19 #ifdef DROPBEAR_SHA1_ASM |
|
20 |
|
21 const struct ltc_hash_descriptor sha1_asm_desc = |
|
22 { |
|
23 "sha1_asm", |
|
24 102, |
|
25 20, |
|
26 64, |
|
27 |
|
28 /* OID */ |
|
29 { 1, 3, 14, 3, 2, 26, }, |
|
30 6, |
|
31 |
|
32 &sha1_init, |
|
33 &sha1_process, |
|
34 &sha1_done, |
|
35 &sha1_test, |
|
36 NULL |
|
37 }; |
|
38 |
|
39 /** |
|
40 Initialize the hash state |
|
41 @param md The hash state you wish to initialize |
|
42 @return CRYPT_OK if successful |
|
43 */ |
|
44 int sha1_init(hash_state * md) |
|
45 { |
|
46 LTC_ARGCHK(md != NULL); |
|
47 md->sha1.state[0] = 0x67452301UL; |
|
48 md->sha1.state[1] = 0xefcdab89UL; |
|
49 md->sha1.state[2] = 0x98badcfeUL; |
|
50 md->sha1.state[3] = 0x10325476UL; |
|
51 md->sha1.state[4] = 0xc3d2e1f0UL; |
|
52 md->sha1.curlen = 0; |
|
53 md->sha1.length = 0; |
|
54 return CRYPT_OK; |
|
55 } |
|
56 |
|
57 void sha1_block_data_order(void* state_vars, const unsigned char *buf, size_t num); |
|
58 |
|
59 static int sha1_asm_compress(hash_state *md, unsigned char *buf) |
|
60 { |
|
61 sha1_block_data_order(&md->sha1.state, buf, 1); |
|
62 return CRYPT_OK; |
|
63 } |
|
64 |
|
65 /** |
|
66 Process a block of memory though the hash |
|
67 @param md The hash state |
|
68 @param in The data to hash |
|
69 @param inlen The length of the data (octets) |
|
70 @return CRYPT_OK if successful |
|
71 */ |
|
72 HASH_PROCESS(sha1_process, sha1_asm_compress, sha1, 64) |
|
73 |
|
74 /** |
|
75 Terminate the hash to get the digest |
|
76 @param md The hash state |
|
77 @param out [out] The destination of the hash (20 bytes) |
|
78 @return CRYPT_OK if successful |
|
79 */ |
|
80 int sha1_done(hash_state * md, unsigned char *out) |
|
81 { |
|
82 int i; |
|
83 |
|
84 LTC_ARGCHK(md != NULL); |
|
85 LTC_ARGCHK(out != NULL); |
|
86 |
|
87 if (md->sha1.curlen >= sizeof(md->sha1.buf)) { |
|
88 return CRYPT_INVALID_ARG; |
|
89 } |
|
90 |
|
91 /* increase the length of the message */ |
|
92 md->sha1.length += md->sha1.curlen * 8; |
|
93 |
|
94 /* append the '1' bit */ |
|
95 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; |
|
96 |
|
97 /* if the length is currently above 56 bytes we append zeros |
|
98 * then compress. Then we can fall back to padding zeros and length |
|
99 * encoding like normal. |
|
100 */ |
|
101 if (md->sha1.curlen > 56) { |
|
102 while (md->sha1.curlen < 64) { |
|
103 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; |
|
104 } |
|
105 sha1_asm_compress(md, md->sha1.buf); |
|
106 md->sha1.curlen = 0; |
|
107 } |
|
108 |
|
109 /* pad upto 56 bytes of zeroes */ |
|
110 while (md->sha1.curlen < 56) { |
|
111 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; |
|
112 } |
|
113 |
|
114 /* store length */ |
|
115 STORE64H(md->sha1.length, md->sha1.buf+56); |
|
116 sha1_asm_compress(md, md->sha1.buf); |
|
117 |
|
118 /* copy output */ |
|
119 for (i = 0; i < 5; i++) { |
|
120 STORE32H(md->sha1.state[i], out+(4*i)); |
|
121 } |
|
122 #ifdef LTC_CLEAN_STACK |
|
123 zeromem(md, sizeof(hash_state)); |
|
124 #endif |
|
125 return CRYPT_OK; |
|
126 } |
|
127 |
|
128 /** |
|
129 Self-test the hash |
|
130 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled |
|
131 */ |
|
132 int sha1_test(void) |
|
133 { |
|
134 #ifndef LTC_TEST |
|
135 return CRYPT_NOP; |
|
136 #else |
|
137 static const struct { |
|
138 char *msg; |
|
139 unsigned char hash[20]; |
|
140 } tests[] = { |
|
141 { "abc", |
|
142 { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, |
|
143 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, |
|
144 0x9c, 0xd0, 0xd8, 0x9d } |
|
145 }, |
|
146 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", |
|
147 { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, |
|
148 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, |
|
149 0xE5, 0x46, 0x70, 0xF1 } |
|
150 } |
|
151 }; |
|
152 |
|
153 int i; |
|
154 unsigned char tmp[20]; |
|
155 hash_state md; |
|
156 |
|
157 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { |
|
158 sha1_init(&md); |
|
159 sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); |
|
160 sha1_done(&md, tmp); |
|
161 if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { |
|
162 return CRYPT_FAIL_TESTVECTOR; |
|
163 } |
|
164 } |
|
165 return CRYPT_OK; |
|
166 #endif |
|
167 } |
|
168 |
|
169 #endif |
|
170 |
|
171 |
|
172 |
|
173 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */ |
|
174 /* $Revision: 1.8 $ */ |
|
175 /* $Date: 2006/11/01 09:28:17 $ */ |