• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
2 
3 /*
4  *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions are met:
8  *
9  *    - Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *
12  *    - Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  *    - Neither the name of Intel Corporation nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *  POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <tinycrypt/sha256.h>
34 #include <tinycrypt/constants.h>
35 #include <tinycrypt/utils.h>
36 
37 static void compress(unsigned int *iv, const uint8_t *data);
38 
tc_sha256_init(TCSha256State_t s)39 int tc_sha256_init(TCSha256State_t s)
40 {
41     /* input sanity check: */
42     if (s == (TCSha256State_t) 0) {
43         return TC_CRYPTO_FAIL;
44     }
45 
46     /*
47      * Setting the initial state values.
48      * These values correspond to the first 32 bits of the fractional parts
49      * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
50      * and 19.
51      */
52     _set((uint8_t *) s, 0x00, sizeof(*s));
53     s->iv[0] = 0x6a09e667;
54     s->iv[1] = 0xbb67ae85;
55     s->iv[2] = 0x3c6ef372; // 2:array element
56     s->iv[3] = 0xa54ff53a; // 3:array element
57     s->iv[4] = 0x510e527f; // 4:array element
58     s->iv[5] = 0x9b05688c; // 5:array element
59     s->iv[6] = 0x1f83d9ab; // 6:array element
60     s->iv[7] = 0x5be0cd19; // 7:array element
61     return TC_CRYPTO_SUCCESS;
62 }
63 
tc_sha256_update(TCSha256State_t s,const uint8_t * data,size_t datalen)64 int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
65 {
66     /* input sanity check: */
67     if (s == (TCSha256State_t) 0 ||
68             data == (void *) 0) {
69         return TC_CRYPTO_FAIL;
70     } else if (datalen == 0) {
71         return TC_CRYPTO_SUCCESS;
72     }
73 
74     while (datalen-- > 0) {
75         s->leftover[s->leftover_offset++] = *(data++);
76 
77         if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
78             compress(s->iv, s->leftover);
79             s->leftover_offset = 0;
80             s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3); // 3:byte alignment
81         }
82     }
83 
84     return TC_CRYPTO_SUCCESS;
85 }
86 
tc_sha256_final(uint8_t * digest,TCSha256State_t s)87 int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
88 {
89     unsigned int i;
90 
91     /* input sanity check: */
92     if (digest == (uint8_t *) 0 ||
93             s == (TCSha256State_t) 0) {
94         return TC_CRYPTO_FAIL;
95     }
96 
97     s->bits_hashed += (s->leftover_offset << 3); // 3:byte alignment
98     s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
99 
100     if (s->leftover_offset > (sizeof(s->leftover) - 8)) { // 8:byte alignment
101         /* there is not room for all the padding in this block */
102         _set(s->leftover + s->leftover_offset, 0x00,
103              sizeof(s->leftover) - s->leftover_offset);
104         compress(s->iv, s->leftover);
105         s->leftover_offset = 0;
106     }
107 
108     /* add the padding and the length in big-Endian format */
109     _set(s->leftover + s->leftover_offset, 0x00,
110          sizeof(s->leftover) - 8 - s->leftover_offset); // 8:byte alignment
111     s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
112     s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8); // 2:byte alignment, 8:byte alignment
113     s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16); // 3:byte alignment, 16:byte alignment
114     s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24); // 4:byte alignment, 24:byte alignment
115     s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32); // 5:byte alignment, 32:byte alignment
116     s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40); // 6:byte alignment, 40:byte alignment
117     s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48); // 7:byte alignment, 48:byte alignment
118     s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56); // 8:byte alignment, 56:byte alignment
119     /* hash the padding and length */
120     compress(s->iv, s->leftover);
121 
122     /* copy the iv out to digest */
123     for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
124         unsigned int t = *((unsigned int *) &s->iv[i]);
125         *digest++ = (uint8_t)(t >> 24); // 24:byte alignment
126         *digest++ = (uint8_t)(t >> 16); // 16:byte alignment
127         *digest++ = (uint8_t)(t >> 8); // 8:byte alignment
128         *digest++ = (uint8_t)(t);
129     }
130 
131     /* destroy the current state */
132     _set(s, 0, sizeof(*s));
133     return TC_CRYPTO_SUCCESS;
134 }
135 
136 /*
137  * Initializing SHA-256 Hash constant words K.
138  * These values correspond to the first 32 bits of the fractional parts of the
139  * cube roots of the first 64 primes between 2 and 311.
140  */
141 static const unsigned int k256[64] = { // 64:array length
142     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
143     0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
144     0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
145     0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
146     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
147     0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
148     0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
149     0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
150     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
151     0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
152     0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
153 };
154 
ROTR(unsigned int a,unsigned int n)155 static inline unsigned int ROTR(unsigned int a, unsigned int n)
156 {
157     return (((a) >> n) | ((a) << (32 - n))); // 32:byte alignment
158 }
159 
160 #define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
161 #define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
162 #define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
163 #define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
164 
165 #define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
166 #define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
167 
BigEndian(const uint8_t ** c)168 static inline unsigned int BigEndian(const uint8_t **c)
169 {
170     unsigned int n = 0;
171     n = (((unsigned int)(*((*c)++))) << 24); // 24:byte alignment
172     n |= ((unsigned int)(*((*c)++)) << 16); // 16:byte alignment
173     n |= ((unsigned int)(*((*c)++)) << 8); // 8:byte alignment
174     n |= ((unsigned int)(*((*c)++)));
175     return n;
176 }
177 
compress(unsigned int * iv,const uint8_t * data)178 static void compress(unsigned int *iv, const uint8_t *data)
179 {
180     unsigned int a, b, c, d, e, f, g, h;
181     unsigned int t1, t2;
182     unsigned int work_space[16];
183     unsigned int i;
184     a = iv[0];
185     b = iv[1];
186     c = iv[2]; // 2:array element
187     d = iv[3]; // 3:array element
188     e = iv[4]; // 4:array element
189     f = iv[5]; // 5:array element
190     g = iv[6]; // 6:array element
191     h = iv[7]; // 7:array element
192 
193     for (i = 0; i < 16; ++i) { // 16:loop cap
194         unsigned int n = BigEndian(&data);
195         t1 = work_space[i] = n;
196         t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
197         t2 = Sigma0(a) + Maj(a, b, c);
198         h = g;
199         g = f;
200         f = e;
201         e = d + t1;
202         d = c;
203         c = b;
204         b = a;
205         a = t1 + t2;
206     }
207 
208     for (; i < 64; ++i) { // 64:loop cap
209         unsigned int s0, s1;
210         s0 = work_space[(i + 1) & 0x0f];
211         s0 = sigma0(s0);
212         s1 = work_space[(i + 14) & 0x0f]; // 14:array element
213         s1 = sigma1(s1);
214         t1 = work_space[i & 0xf] += s0 + s1 + work_space[(i + 9) & 0xf]; // 9:array element
215         t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
216         t2 = Sigma0(a) + Maj(a, b, c);
217         h = g;
218         g = f;
219         f = e;
220         e = d + t1;
221         d = c;
222         c = b;
223         b = a;
224         a = t1 + t2;
225     }
226 
227     iv[0] += a;
228     iv[1] += b;
229     iv[2] += c; // 2:array element
230     iv[3] += d; // 3:array element
231     iv[4] += e; // 4:array element
232     iv[5] += f; // 5:array element
233     iv[6] += g; // 6:array element
234     iv[7] += h; // 7:array element
235 }