xref: /freebsd/sys/contrib/libsodium/src/libsodium/crypto_hash/sha512/cp/hash_sha512_cp.c (revision 3611ec604864a7d4dcc9a3ea898c80eb35eef8a0)
1 
2 /*-
3  * Copyright 2005,2007,2009 Colin Percival
4  * 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
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 #include <limits.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <sys/types.h>
35 
36 #include "crypto_hash_sha512.h"
37 #include "private/common.h"
38 #include "utils.h"
39 
40 static void
be64enc_vect(unsigned char * dst,const uint64_t * src,size_t len)41 be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
42 {
43     size_t i;
44 
45     for (i = 0; i < len / 8; i++) {
46         STORE64_BE(dst + i * 8, src[i]);
47     }
48 }
49 
50 static void
be64dec_vect(uint64_t * dst,const unsigned char * src,size_t len)51 be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
52 {
53     size_t i;
54 
55     for (i = 0; i < len / 8; i++) {
56         dst[i] = LOAD64_BE(src + i * 8);
57     }
58 }
59 
60 static const uint64_t Krnd[80] = {
61     0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
62     0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
63     0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
64     0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
65     0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
66     0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
67     0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
68     0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
69     0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
70     0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
71     0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
72     0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
73     0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
74     0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
75     0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
76     0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
77     0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
78     0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
79     0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
80     0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
81     0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
82     0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
83     0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
84     0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
85     0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
86     0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
87     0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
88 };
89 
90 #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
91 #define Maj(x, y, z) ((x & (y | z)) | (y & z))
92 #define SHR(x, n) (x >> n)
93 #define ROTR(x, n) ROTR64(x, n)
94 #define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
95 #define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
96 #define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
97 #define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
98 
99 #define RND(a, b, c, d, e, f, g, h, k) \
100     h += S1(e) + Ch(e, f, g) + k;      \
101     d += h;                            \
102     h += S0(a) + Maj(a, b, c);
103 
104 #define RNDr(S, W, i, ii)                                                   \
105     RND(S[(80 - i) % 8], S[(81 - i) % 8], S[(82 - i) % 8], S[(83 - i) % 8], \
106         S[(84 - i) % 8], S[(85 - i) % 8], S[(86 - i) % 8], S[(87 - i) % 8], \
107         W[i + ii] + Krnd[i + ii])
108 
109 #define MSCH(W, ii, i) \
110     W[i + ii + 16] =   \
111         s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
112 
113 static void
SHA512_Transform(uint64_t * state,const uint8_t block[128],uint64_t W[80],uint64_t S[8])114 SHA512_Transform(uint64_t *state, const uint8_t block[128], uint64_t W[80],
115                  uint64_t S[8])
116 {
117     int i;
118 
119     be64dec_vect(W, block, 128);
120     memcpy(S, state, 64);
121     for (i = 0; i < 80; i += 16) {
122         RNDr(S, W, 0, i);
123         RNDr(S, W, 1, i);
124         RNDr(S, W, 2, i);
125         RNDr(S, W, 3, i);
126         RNDr(S, W, 4, i);
127         RNDr(S, W, 5, i);
128         RNDr(S, W, 6, i);
129         RNDr(S, W, 7, i);
130         RNDr(S, W, 8, i);
131         RNDr(S, W, 9, i);
132         RNDr(S, W, 10, i);
133         RNDr(S, W, 11, i);
134         RNDr(S, W, 12, i);
135         RNDr(S, W, 13, i);
136         RNDr(S, W, 14, i);
137         RNDr(S, W, 15, i);
138         if (i == 64) {
139             break;
140         }
141         MSCH(W, 0, i);
142         MSCH(W, 1, i);
143         MSCH(W, 2, i);
144         MSCH(W, 3, i);
145         MSCH(W, 4, i);
146         MSCH(W, 5, i);
147         MSCH(W, 6, i);
148         MSCH(W, 7, i);
149         MSCH(W, 8, i);
150         MSCH(W, 9, i);
151         MSCH(W, 10, i);
152         MSCH(W, 11, i);
153         MSCH(W, 12, i);
154         MSCH(W, 13, i);
155         MSCH(W, 14, i);
156         MSCH(W, 15, i);
157     }
158     for (i = 0; i < 8; i++) {
159         state[i] += S[i];
160     }
161 }
162 
163 static const uint8_t PAD[128] = {
164     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165     0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166     0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167     0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168     0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169     0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
170 };
171 
172 static void
SHA512_Pad(crypto_hash_sha512_state * state,uint64_t tmp64[80+8])173 SHA512_Pad(crypto_hash_sha512_state *state, uint64_t tmp64[80 + 8])
174 {
175     unsigned int r;
176     unsigned int i;
177 
178     r = (unsigned int) ((state->count[1] >> 3) & 0x7f);
179     if (r < 112) {
180         for (i = 0; i < 112 - r; i++) {
181             state->buf[r + i] = PAD[i];
182         }
183     } else {
184         for (i = 0; i < 128 - r; i++) {
185             state->buf[r + i] = PAD[i];
186         }
187         SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
188         memset(&state->buf[0], 0, 112);
189     }
190     be64enc_vect(&state->buf[112], state->count, 16);
191     SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
192 }
193 
194 int
crypto_hash_sha512_init(crypto_hash_sha512_state * state)195 crypto_hash_sha512_init(crypto_hash_sha512_state *state)
196 {
197     static const uint64_t sha512_initial_state[8] = {
198         0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
199         0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
200         0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
201     };
202 
203     state->count[0] = state->count[1] = (uint64_t) 0U;
204     memcpy(state->state, sha512_initial_state, sizeof sha512_initial_state);
205 
206     return 0;
207 }
208 
209 int
crypto_hash_sha512_update(crypto_hash_sha512_state * state,const unsigned char * in,unsigned long long inlen)210 crypto_hash_sha512_update(crypto_hash_sha512_state *state,
211                           const unsigned char *in, unsigned long long inlen)
212 {
213     uint64_t           tmp64[80 + 8];
214     uint64_t           bitlen[2];
215     unsigned long long i;
216     unsigned long long r;
217 
218     if (inlen <= 0U) {
219         return 0;
220     }
221     r = (unsigned long long) ((state->count[1] >> 3) & 0x7f);
222 
223     bitlen[1] = ((uint64_t) inlen) << 3;
224     bitlen[0] = ((uint64_t) inlen) >> 61;
225     /* LCOV_EXCL_START */
226     if ((state->count[1] += bitlen[1]) < bitlen[1]) {
227         state->count[0]++;
228     }
229     /* LCOV_EXCL_STOP */
230     state->count[0] += bitlen[0];
231     if (inlen < 128 - r) {
232         for (i = 0; i < inlen; i++) {
233             state->buf[r + i] = in[i];
234         }
235         return 0;
236     }
237     for (i = 0; i < 128 - r; i++) {
238         state->buf[r + i] = in[i];
239     }
240     SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
241     in += 128 - r;
242     inlen -= 128 - r;
243 
244     while (inlen >= 128) {
245         SHA512_Transform(state->state, in, &tmp64[0], &tmp64[80]);
246         in += 128;
247         inlen -= 128;
248     }
249     inlen &= 127;
250     for (i = 0; i < inlen; i++) {
251         state->buf[i] = in[i];
252     }
253     sodium_memzero((void *) tmp64, sizeof tmp64);
254 
255     return 0;
256 }
257 
258 int
crypto_hash_sha512_final(crypto_hash_sha512_state * state,unsigned char * out)259 crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out)
260 {
261     uint64_t tmp64[80 + 8];
262 
263     SHA512_Pad(state, tmp64);
264     be64enc_vect(out, state->state, 64);
265     sodium_memzero((void *) tmp64, sizeof tmp64);
266     sodium_memzero((void *) state, sizeof *state);
267 
268     return 0;
269 }
270 
271 int
crypto_hash_sha512(unsigned char * out,const unsigned char * in,unsigned long long inlen)272 crypto_hash_sha512(unsigned char *out, const unsigned char *in,
273                    unsigned long long inlen)
274 {
275     crypto_hash_sha512_state state;
276 
277     crypto_hash_sha512_init(&state);
278     crypto_hash_sha512_update(&state, in, inlen);
279     crypto_hash_sha512_final(&state, out);
280 
281     return 0;
282 }
283