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