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 68 static int sha256_compress_nblocks(hash_state *md, const unsigned char *buf, 69 int blocks) 70 { 71 void *state = md->sha1.state; 72 73 COMPILE_TIME_ASSERT(sizeof(md->sha1.state[0]) == sizeof(uint32_t)); 74 75 crypto_accel_sha256_compress(state, buf, blocks); 76 return CRYPT_OK; 77 } 78 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 */ 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 */ 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 */ 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