1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  * Copyright (c) 2001-2007, Tom St Denis
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
32  *
33  * LibTomCrypt is a library that provides various cryptographic
34  * algorithms in a highly modular and flexible manner.
35  *
36  * The library is free for all purposes without any express
37  * guarantee it works.
38  *
39  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
40  */
41 #include <crypto/crypto_accel.h>
42 #include <tomcrypt_private.h>
43 
44 #ifdef LTC_SHA256
45 
46 const struct ltc_hash_descriptor sha256_desc =
47 {
48     "sha256",
49     0,
50     32,
51     64,
52 
53     /* OID */
54    { 2, 16, 840, 1, 101, 3, 4, 2, 1,  },
55    9,
56 
57     &sha256_init,
58     &sha256_process,
59     &sha256_done,
60     &sha256_test,
61     NULL
62 };
63 
64 
65 /* Implemented in assembly */
66 int sha256_ce_transform(ulong32 *state, const unsigned char *buf, int blocks);
67 
sha256_compress_nblocks(hash_state * md,const unsigned char * buf,int blocks)68 static int sha256_compress_nblocks(hash_state *md, const unsigned char *buf,
69 				   int blocks)
70 {
71    void *state = md->sha256.state;
72 
73    COMPILE_TIME_ASSERT(sizeof(md->sha256.state[0]) == sizeof(uint32_t));
74 
75     crypto_accel_sha256_compress(state, buf, blocks);
76     return CRYPT_OK;
77 }
78 
sha256_compress(hash_state * md,const unsigned char * buf)79 static int sha256_compress(hash_state *md, const unsigned char *buf)
80 {
81    return sha256_compress_nblocks(md, buf, 1);
82 }
83 
84 /**
85    Initialize the hash state
86    @param md   The hash state you wish to initialize
87    @return CRYPT_OK if successful
88 */
sha256_init(hash_state * md)89 int sha256_init(hash_state * md)
90 {
91     LTC_ARGCHK(md != NULL);
92 
93     md->sha256.curlen = 0;
94     md->sha256.length = 0;
95     md->sha256.state[0] = 0x6A09E667UL;
96     md->sha256.state[1] = 0xBB67AE85UL;
97     md->sha256.state[2] = 0x3C6EF372UL;
98     md->sha256.state[3] = 0xA54FF53AUL;
99     md->sha256.state[4] = 0x510E527FUL;
100     md->sha256.state[5] = 0x9B05688CUL;
101     md->sha256.state[6] = 0x1F83D9ABUL;
102     md->sha256.state[7] = 0x5BE0CD19UL;
103     return CRYPT_OK;
104 }
105 
106 /**
107    Process a block of memory though the hash
108    @param md     The hash state
109    @param in     The data to hash
110    @param inlen  The length of the data (octets)
111    @return CRYPT_OK if successful
112 */
113 HASH_PROCESS_NBLOCKS(sha256_process, sha256_compress_nblocks, sha256, 64)
114 
115 /**
116    Terminate the hash to get the digest
117    @param md  The hash state
118    @param out [out] The destination of the hash (32 bytes)
119    @return CRYPT_OK if successful
120 */
sha256_done(hash_state * md,unsigned char * out)121 int sha256_done(hash_state * md, unsigned char *out)
122 {
123     int i;
124 
125     LTC_ARGCHK(md  != NULL);
126     LTC_ARGCHK(out != NULL);
127 
128     if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
129        return CRYPT_INVALID_ARG;
130     }
131 
132 
133     /* increase the length of the message */
134     md->sha256.length += md->sha256.curlen * 8;
135 
136     /* append the '1' bit */
137     md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
138 
139     /* if the length is currently above 56 bytes we append zeros
140      * then compress.  Then we can fall back to padding zeros and length
141      * encoding like normal.
142      */
143     if (md->sha256.curlen > 56) {
144         while (md->sha256.curlen < 64) {
145             md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
146         }
147         sha256_compress(md, md->sha256.buf);
148         md->sha256.curlen = 0;
149     }
150 
151     /* pad upto 56 bytes of zeroes */
152     while (md->sha256.curlen < 56) {
153         md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
154     }
155 
156     /* store length */
157     STORE64H(md->sha256.length, md->sha256.buf+56);
158     sha256_compress(md, md->sha256.buf);
159 
160     /* copy output */
161     for (i = 0; i < 8; i++) {
162         STORE32H(md->sha256.state[i], out+(4*i));
163     }
164 #ifdef LTC_CLEAN_STACK
165     zeromem(md, sizeof(hash_state));
166 #endif
167     return CRYPT_OK;
168 }
169 
170 /**
171   Self-test the hash
172   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
173 */
sha256_test(void)174 int  sha256_test(void)
175 {
176  #ifndef LTC_TEST
177     return CRYPT_NOP;
178  #else
179   static const struct {
180       const char *msg;
181       unsigned char hash[32];
182   } tests[] = {
183     { "abc",
184       { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
185         0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
186         0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
187         0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
188     },
189     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
190       { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
191         0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
192         0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
193         0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
194     },
195   };
196 
197   int i;
198   unsigned char tmp[32];
199   hash_state md;
200 
201   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
202       sha256_init(&md);
203       sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
204       sha256_done(&md, tmp);
205       if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {
206          return CRYPT_FAIL_TESTVECTOR;
207       }
208   }
209   return CRYPT_OK;
210  #endif
211 }
212 
213 #endif /*LTC_SHA256*/
214