1 // SPDX-License-Identifier: Unlicense AND BSD-2-Clause 2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ 3 /* Copyright (c) 2023 Linaro Limited */ 4 #include <crypto/crypto_accel.h> 5 #include <tomcrypt_private.h> 6 7 /** 8 @param sha512.c 9 LTC_SHA512 by Tom St Denis 10 */ 11 12 #ifdef LTC_SHA512 13 14 const struct ltc_hash_descriptor sha512_desc = 15 { 16 "sha512", 17 5, 18 64, 19 128, 20 21 /* OID */ 22 { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, 23 9, 24 25 &sha512_init, 26 &sha512_process, 27 &sha512_done, 28 &sha512_test, 29 NULL 30 }; 31 32 33 /* Implemented in assembly */ 34 int sha512_ce_transform(ulong64 *state, const unsigned char *buf, int blocks); 35 36 static int sha512_compress_nblocks(hash_state *md, const unsigned char *buf, 37 int blocks) 38 { 39 void *state = md->sha512.state; 40 41 COMPILE_TIME_ASSERT(sizeof(md->sha512.state[0]) == sizeof(uint64_t)); 42 43 crypto_accel_sha512_compress(state, buf, blocks); 44 45 return CRYPT_OK; 46 } 47 48 static int sha512_compress(hash_state *md, const unsigned char *buf) 49 { 50 return sha512_compress_nblocks(md, buf, 1); 51 } 52 53 /** 54 Initialize the hash state 55 @param md The hash state you wish to initialize 56 @return CRYPT_OK if successful 57 */ 58 int sha512_init(hash_state * md) 59 { 60 LTC_ARGCHK(md != NULL); 61 md->sha512.curlen = 0; 62 md->sha512.length = 0; 63 md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); 64 md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); 65 md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); 66 md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); 67 md->sha512.state[4] = CONST64(0x510e527fade682d1); 68 md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); 69 md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); 70 md->sha512.state[7] = CONST64(0x5be0cd19137e2179); 71 return CRYPT_OK; 72 } 73 74 HASH_PROCESS_NBLOCKS(sha512_process, sha512_compress_nblocks, sha512, 128) 75 76 /** 77 Terminate the hash to get the digest 78 @param md The hash state 79 @param out [out] The destination of the hash (64 bytes) 80 @return CRYPT_OK if successful 81 */ 82 int sha512_done(hash_state * md, unsigned char *out) 83 { 84 int i; 85 86 LTC_ARGCHK(md != NULL); 87 LTC_ARGCHK(out != NULL); 88 89 if (md->sha512.curlen >= sizeof(md->sha512.buf)) { 90 return CRYPT_INVALID_ARG; 91 } 92 93 /* increase the length of the message */ 94 md->sha512.length += md->sha512.curlen * CONST64(8); 95 96 /* append the '1' bit */ 97 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; 98 99 /* if the length is currently above 112 bytes we append zeros 100 * then compress. Then we can fall back to padding zeros and length 101 * encoding like normal. 102 */ 103 if (md->sha512.curlen > 112) { 104 while (md->sha512.curlen < 128) { 105 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; 106 } 107 sha512_compress(md, md->sha512.buf); 108 md->sha512.curlen = 0; 109 } 110 111 /* pad upto 120 bytes of zeroes 112 * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash 113 * > 2^64 bits of data... :-) 114 */ 115 while (md->sha512.curlen < 120) { 116 md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; 117 } 118 119 /* store length */ 120 STORE64H(md->sha512.length, md->sha512.buf+120); 121 sha512_compress(md, md->sha512.buf); 122 123 /* copy output */ 124 for (i = 0; i < 8; i++) { 125 STORE64H(md->sha512.state[i], out+(8*i)); 126 } 127 #ifdef LTC_CLEAN_STACK 128 zeromem(md, sizeof(hash_state)); 129 #endif 130 return CRYPT_OK; 131 } 132 133 /** 134 Self-test the hash 135 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 136 */ 137 int sha512_test(void) 138 { 139 #ifndef LTC_TEST 140 return CRYPT_NOP; 141 #else 142 static const struct { 143 const char *msg; 144 unsigned char hash[64]; 145 } tests[] = { 146 { "abc", 147 { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 148 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 149 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 150 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 151 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 152 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 153 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 154 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } 155 }, 156 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 157 { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 158 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 159 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 160 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 161 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 162 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 163 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 164 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } 165 }, 166 }; 167 168 int i; 169 unsigned char tmp[64]; 170 hash_state md; 171 172 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { 173 sha512_init(&md); 174 sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); 175 sha512_done(&md, tmp); 176 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { 177 return CRYPT_FAIL_TESTVECTOR; 178 } 179 } 180 return CRYPT_OK; 181 #endif 182 } 183 184 #endif /*LTC_SHA512*/ 185