1 /*############################################################################
2 # Copyright 2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16 /// A SHA-512 implementation.
17 /*! \file */
18
19 #include "epid/member/tiny/math/sha512.h"
20
21 #include <stdint.h>
22 #include "epid/member/tiny/stdlib/tiny_stdlib.h"
23
24 static void sha512_compress(uint64_t* iv, void const* in);
25
tinysha512_init(sha512_state * s)26 void tinysha512_init(sha512_state* s) {
27 s->iv[0] = 0x6a09e667f3bcc908ULL;
28 s->iv[1] = 0xbb67ae8584caa73bULL;
29 s->iv[2] = 0x3c6ef372fe94f82bULL;
30 s->iv[3] = 0xa54ff53a5f1d36f1ULL;
31 s->iv[4] = 0x510e527fade682d1ULL;
32 s->iv[5] = 0x9b05688c2b3e6c1fULL;
33 s->iv[6] = 0x1f83d9abfb41bd6bULL;
34 s->iv[7] = 0x5be0cd19137e2179ULL;
35
36 s->bits_hashed_high = s->bits_hashed_low = (uint64_t)0;
37 s->leftover_offset = 0;
38 }
39
tinysha512_update(sha512_state * s,void const * data,size_t data_length)40 void tinysha512_update(sha512_state* s, void const* data, size_t data_length) {
41 unsigned char const* tmp_data = (unsigned char const*)data;
42
43 while (data_length-- > 0) {
44 s->leftover[s->leftover_offset++] = *(tmp_data++);
45 if (s->leftover_offset >= SHA512_BLOCK_SIZE) {
46 sha512_compress(s->iv, s->leftover);
47 s->leftover_offset = 0;
48 s->bits_hashed_low += (SHA512_BLOCK_SIZE << 3);
49 }
50 }
51 }
52
tinysha512_final(unsigned char * digest,sha512_state * s)53 void tinysha512_final(unsigned char* digest, sha512_state* s) {
54 size_t i, j;
55
56 s->bits_hashed_low += (s->leftover_offset << 3);
57
58 s->leftover[s->leftover_offset++] = 0x80;
59 /* there is always room for one byte */
60 if (s->leftover_offset > (sizeof(s->leftover) - 16)) {
61 /* the data's bit length cannot be encoded in the last block */
62 (void)memset(s->leftover + s->leftover_offset, 0x00,
63 sizeof(s->leftover) - s->leftover_offset);
64 sha512_compress(s->iv, s->leftover);
65 s->leftover_offset = 0;
66 }
67
68 (void)memset(s->leftover + s->leftover_offset, 0x00,
69 sizeof(s->leftover) - 16 - s->leftover_offset);
70 for (i = 0; i < 8; i++) {
71 s->leftover[sizeof(s->leftover) - (i + 1)] =
72 (unsigned char)(s->bits_hashed_low >> (8 * i));
73 s->leftover[sizeof(s->leftover) - (i + 1) - 8] =
74 (unsigned char)(s->bits_hashed_high >> (8 * i));
75 }
76 sha512_compress(s->iv, s->leftover);
77
78 for (i = 0; i < SHA512_DIGEST_WORDS; ++i) {
79 uint64_t w = s->iv[i];
80 for (j = 0; j < 8; j++) {
81 digest[j] = (unsigned char)(w >> (8 * (7 - j)));
82 }
83 digest += 8;
84 }
85 }
86
87 #define B(x, j) \
88 (((uint64_t)(*(((unsigned char const*)(&x)) + j))) << ((7 - j) * 8))
89
pull64(const uint64_t x)90 static uint64_t pull64(const uint64_t x) {
91 int16_t i;
92 uint64_t result = 0;
93 for (i = 0; i < 8; i++) result |= B(x, i);
94 return result;
95 }
ROTR(const uint64_t x,unsigned char s)96 static uint64_t ROTR(const uint64_t x, unsigned char s) {
97 return (x >> s) | (x << (64 - s));
98 }
99
100 #define Sigma0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39))
101
102 #define Sigma1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41))
103 #define sigma0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x) >> 7))
104 #define sigma1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ ((x) >> 6))
105
106 #define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
107 #define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
108
109 static const uint64_t k512[80] = {
110 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
111 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
112 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
113 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
114 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
115 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
116 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
117 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
118 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
119 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
120 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
121 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
122 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
123 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
124 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
125 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
126 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
127 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
128 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
129 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
130 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
131 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
132 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
133 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
134 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
135 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
136 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
137
sha512_compress(uint64_t * iv,void const * in)138 static void sha512_compress(uint64_t* iv, void const* in) {
139 const uint64_t* w = (const uint64_t*)in;
140 uint64_t a, e, t;
141 uint64_t work_space[80 + 9];
142 uint64_t* work_ptr;
143 int i;
144 volatile int j;
145
146 work_ptr = work_space + 80;
147 // j is declared volatile to prevent the optimizer from replacing the for loop
148 // with a memcpy
149 for (j = 0; j < 8; j++) work_ptr[j] = iv[j];
150
151 for (i = 0; i < 80; i++, work_ptr--) {
152 if (i < 16) {
153 t = pull64(w[i]);
154 } else {
155 t = sigma0(work_ptr[8 + 16 - 1]);
156 t += sigma1(work_ptr[8 + 16 - 14]);
157 t += work_ptr[8 + 16] + work_ptr[8 + 16 - 9];
158 }
159 work_ptr[8] = t;
160 t += work_ptr[7] + Sigma1(work_ptr[4]) +
161 Ch(work_ptr[4], work_ptr[5], work_ptr[6]) + k512[i];
162 e = work_ptr[3] + t;
163 a = t + Sigma0(work_ptr[0]) + Maj(work_ptr[0], work_ptr[1], work_ptr[2]);
164 work_ptr[-1] = a;
165 work_ptr[3] = e;
166 }
167
168 for (i = 0; i < 8; i++) iv[i] += work_ptr[i];
169 }
170