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 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 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 */ 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 */ 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 */ 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