1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2015, 2020, Linaro Limited
4 * Copyright (c) 2001-2007, Tom St Denis
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
31 *
32 * LibTomCrypt is a library that provides various cryptographic
33 * algorithms in a highly modular and flexible manner.
34 *
35 * The library is free for all purposes without any express
36 * guarantee it works.
37 *
38 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
39 */
40 #include <crypto/crypto_accel.h>
41 #include <tomcrypt_private.h>
42 /**
43 @file sha1.c
44 LTC_SHA1 code by Tom St Denis
45 */
46
47
48 const struct ltc_hash_descriptor sha1_desc =
49 {
50 "sha1",
51 2,
52 20,
53 64,
54
55 /* OID */
56 { 1, 3, 14, 3, 2, 26, },
57 6,
58
59 &sha1_init,
60 &sha1_process,
61 &sha1_done,
62 &sha1_test,
63 NULL
64 };
65
sha1_compress_nblocks(hash_state * md,const unsigned char * buf,int blocks)66 static int sha1_compress_nblocks(hash_state *md, const unsigned char *buf,
67 int blocks)
68 {
69 void *state = md->sha1.state;
70
71 COMPILE_TIME_ASSERT(sizeof(md->sha1.state[0]) == sizeof(uint32_t));
72
73 crypto_accel_sha1_compress(state, buf, blocks);
74 return CRYPT_OK;
75 }
76
sha1_compress(hash_state * md,const unsigned char * buf)77 static int sha1_compress(hash_state *md, const unsigned char *buf)
78 {
79 return sha1_compress_nblocks(md, buf, 1);
80 }
81
82 /**
83 Process a block of memory though the hash
84 @param md The hash state
85 @param in The data to hash
86 @param inlen The length of the data (octets)
87 @return CRYPT_OK if successful
88 */
89 HASH_PROCESS_NBLOCKS(sha1_process, sha1_compress_nblocks, sha1, 64)
90
91 /**
92 Initialize the hash state
93 @param md The hash state you wish to initialize
94 @return CRYPT_OK if successful
95 */
sha1_init(hash_state * md)96 int sha1_init(hash_state * md)
97 {
98 LTC_ARGCHK(md != NULL);
99 md->sha1.state[0] = 0x67452301UL;
100 md->sha1.state[1] = 0xefcdab89UL;
101 md->sha1.state[2] = 0x98badcfeUL;
102 md->sha1.state[3] = 0x10325476UL;
103 md->sha1.state[4] = 0xc3d2e1f0UL;
104 md->sha1.curlen = 0;
105 md->sha1.length = 0;
106 return CRYPT_OK;
107 }
108
109 /**
110 Terminate the hash to get the digest
111 @param md The hash state
112 @param out [out] The destination of the hash (20 bytes)
113 @return CRYPT_OK if successful
114 */
sha1_done(hash_state * md,unsigned char * out)115 int sha1_done(hash_state * md, unsigned char *out)
116 {
117 int i;
118
119 LTC_ARGCHK(md != NULL);
120 LTC_ARGCHK(out != NULL);
121
122 if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
123 return CRYPT_INVALID_ARG;
124 }
125
126 /* increase the length of the message */
127 md->sha1.length += md->sha1.curlen * 8;
128
129 /* append the '1' bit */
130 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
131
132 /* if the length is currently above 56 bytes we append zeros
133 * then compress. Then we can fall back to padding zeros and length
134 * encoding like normal.
135 */
136 if (md->sha1.curlen > 56) {
137 while (md->sha1.curlen < 64) {
138 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
139 }
140 sha1_compress(md, md->sha1.buf);
141 md->sha1.curlen = 0;
142 }
143
144 /* pad upto 56 bytes of zeroes */
145 while (md->sha1.curlen < 56) {
146 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
147 }
148
149 /* store length */
150 STORE64H(md->sha1.length, md->sha1.buf+56);
151 sha1_compress(md, md->sha1.buf);
152
153 /* copy output */
154 for (i = 0; i < 5; i++) {
155 STORE32H(md->sha1.state[i], out+(4*i));
156 }
157 #ifdef LTC_CLEAN_STACK
158 zeromem(md, sizeof(hash_state));
159 #endif
160 return CRYPT_OK;
161 }
162
163 /**
164 Self-test the hash
165 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
166 */
sha1_test(void)167 int sha1_test(void)
168 {
169 #ifndef LTC_TEST
170 return CRYPT_NOP;
171 #else
172 static const struct {
173 const char *msg;
174 unsigned char hash[20];
175 } tests[] = {
176 { "abc",
177 { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
178 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
179 0x9c, 0xd0, 0xd8, 0x9d }
180 },
181 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
182 { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
183 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
184 0xE5, 0x46, 0x70, 0xF1 }
185 }
186 };
187
188 int i;
189 unsigned char tmp[20];
190 hash_state md;
191
192 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
193 sha1_init(&md);
194 sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
195 sha1_done(&md, tmp);
196 if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
197 return CRYPT_FAIL_TESTVECTOR;
198 }
199 }
200 return CRYPT_OK;
201 #endif
202 }
203