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