166458Sdfr/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
266458Sdfr
366458Sdfr/*
4139790Simp * Public Domain, Author: Daniel J. Bernstein
566458Sdfr * Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c
666458Sdfr */
766458Sdfr
866458Sdfr#include "includes.h"
966458Sdfr
1066458Sdfr#include "crypto_api.h"
1166458Sdfr
1266458Sdfrtypedef unsigned long long uint64;
1366458Sdfr
1466458Sdfrstatic uint64 load_bigendian(const unsigned char *x)
1566458Sdfr{
1666458Sdfr  return
1766458Sdfr      (uint64) (x[7]) \
1866458Sdfr  | (((uint64) (x[6])) << 8) \
1966458Sdfr  | (((uint64) (x[5])) << 16) \
2066458Sdfr  | (((uint64) (x[4])) << 24) \
2166458Sdfr  | (((uint64) (x[3])) << 32) \
2266458Sdfr  | (((uint64) (x[2])) << 40) \
2366458Sdfr  | (((uint64) (x[1])) << 48) \
2466458Sdfr  | (((uint64) (x[0])) << 56)
2566458Sdfr  ;
2666458Sdfr}
2766458Sdfr
2866458Sdfrstatic void store_bigendian(unsigned char *x,uint64 u)
2966458Sdfr{
3066458Sdfr  x[7] = u; u >>= 8;
3166458Sdfr  x[6] = u; u >>= 8;
3266458Sdfr  x[5] = u; u >>= 8;
3366458Sdfr  x[4] = u; u >>= 8;
3466458Sdfr  x[3] = u; u >>= 8;
3566458Sdfr  x[2] = u; u >>= 8;
3666458Sdfr  x[1] = u; u >>= 8;
3766458Sdfr  x[0] = u;
3866458Sdfr}
3966458Sdfr
4066458Sdfr#define SHR(x,c) ((x) >> (c))
4166458Sdfr#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
42196994Sphk
43196994Sphk#define Ch(x,y,z) ((x & y) ^ (~x & z))
44196994Sphk#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
4566458Sdfr#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
4666458Sdfr#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
4766458Sdfr#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
4870508Sdfr#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
49196994Sphk
5096912Smarcel#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
51154128Simp
52154128Simp#define EXPAND \
53154128Simp  M(w0 ,w14,w9 ,w1 ) \
5466458Sdfr  M(w1 ,w15,w10,w2 ) \
5566458Sdfr  M(w2 ,w0 ,w11,w3 ) \
5666458Sdfr  M(w3 ,w1 ,w12,w4 ) \
5766458Sdfr  M(w4 ,w2 ,w13,w5 ) \
5866458Sdfr  M(w5 ,w3 ,w14,w6 ) \
5966458Sdfr  M(w6 ,w4 ,w15,w7 ) \
60210369Skib  M(w7 ,w5 ,w0 ,w8 ) \
61210369Skib  M(w8 ,w6 ,w1 ,w9 ) \
62210369Skib  M(w9 ,w7 ,w2 ,w10) \
6366458Sdfr  M(w10,w8 ,w3 ,w11) \
64177661Sjb  M(w11,w9 ,w4 ,w12) \
65224207Sattilio  M(w12,w10,w5 ,w13) \
66224217Sattilio  M(w13,w11,w6 ,w14) \
67224207Sattilio  M(w14,w12,w7 ,w15) \
6874733Sjhb  M(w15,w13,w8 ,w0 )
6974733Sjhb
7074733Sjhb#define F(w,k) \
7166458Sdfr  T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
72250338Sattilio  T2 = Sigma0(a) + Maj(a,b,c); \
73250338Sattilio  h = g; \
74250338Sattilio  g = f; \
75250338Sattilio  f = e; \
76195376Ssam  e = d + T1; \
77195376Ssam  d = c; \
7866458Sdfr  c = b; \
7966458Sdfr  b = a; \
8066458Sdfr  a = T1 + T2;
8166458Sdfr
8266458Sdfrint crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
8366458Sdfr{
84195376Ssam  uint64 state[8];
8566458Sdfr  uint64 a;
86191278Srwatson  uint64 b;
87191278Srwatson  uint64 c;
88191278Srwatson  uint64 d;
89191278Srwatson  uint64 e;
90191309Srwatson  uint64 f;
91191276Srwatson  uint64 g;
92191276Srwatson  uint64 h;
93119347Smarcel  uint64 T1;
94119347Smarcel  uint64 T2;
9583198Sdfr
96119347Smarcel  a = load_bigendian(statebytes +  0); state[0] = a;
97119347Smarcel  b = load_bigendian(statebytes +  8); state[1] = b;
9866458Sdfr  c = load_bigendian(statebytes + 16); state[2] = c;
9966458Sdfr  d = load_bigendian(statebytes + 24); state[3] = d;
10066458Sdfr  e = load_bigendian(statebytes + 32); state[4] = e;
101197316Salc  f = load_bigendian(statebytes + 40); state[5] = f;
102197316Salc  g = load_bigendian(statebytes + 48); state[6] = g;
103118239Speter  h = load_bigendian(statebytes + 56); state[7] = h;
104199719Smarcel
105118239Speter  while (inlen >= 128) {
106116355Salc    uint64 w0  = load_bigendian(in +   0);
10766458Sdfr    uint64 w1  = load_bigendian(in +   8);
108261985Smarcel    uint64 w2  = load_bigendian(in +  16);
109261985Smarcel    uint64 w3  = load_bigendian(in +  24);
110261985Smarcel    uint64 w4  = load_bigendian(in +  32);
111261985Smarcel    uint64 w5  = load_bigendian(in +  40);
112261985Smarcel    uint64 w6  = load_bigendian(in +  48);
11366458Sdfr    uint64 w7  = load_bigendian(in +  56);
11466458Sdfr    uint64 w8  = load_bigendian(in +  64);
11566458Sdfr    uint64 w9  = load_bigendian(in +  72);
11666458Sdfr    uint64 w10 = load_bigendian(in +  80);
11766458Sdfr    uint64 w11 = load_bigendian(in +  88);
11866458Sdfr    uint64 w12 = load_bigendian(in +  96);
11966458Sdfr    uint64 w13 = load_bigendian(in + 104);
12066458Sdfr    uint64 w14 = load_bigendian(in + 112);
12166458Sdfr    uint64 w15 = load_bigendian(in + 120);
12266458Sdfr
12396912Smarcel    F(w0 ,0x428a2f98d728ae22ULL)
124274648Skib    F(w1 ,0x7137449123ef65cdULL)
125274648Skib    F(w2 ,0xb5c0fbcfec4d3b2fULL)
126274648Skib    F(w3 ,0xe9b5dba58189dbbcULL)
127274648Skib    F(w4 ,0x3956c25bf348b538ULL)
128196994Sphk    F(w5 ,0x59f111f1b605d019ULL)
129    F(w6 ,0x923f82a4af194f9bULL)
130    F(w7 ,0xab1c5ed5da6d8118ULL)
131    F(w8 ,0xd807aa98a3030242ULL)
132    F(w9 ,0x12835b0145706fbeULL)
133    F(w10,0x243185be4ee4b28cULL)
134    F(w11,0x550c7dc3d5ffb4e2ULL)
135    F(w12,0x72be5d74f27b896fULL)
136    F(w13,0x80deb1fe3b1696b1ULL)
137    F(w14,0x9bdc06a725c71235ULL)
138    F(w15,0xc19bf174cf692694ULL)
139
140    EXPAND
141
142    F(w0 ,0xe49b69c19ef14ad2ULL)
143    F(w1 ,0xefbe4786384f25e3ULL)
144    F(w2 ,0x0fc19dc68b8cd5b5ULL)
145    F(w3 ,0x240ca1cc77ac9c65ULL)
146    F(w4 ,0x2de92c6f592b0275ULL)
147    F(w5 ,0x4a7484aa6ea6e483ULL)
148    F(w6 ,0x5cb0a9dcbd41fbd4ULL)
149    F(w7 ,0x76f988da831153b5ULL)
150    F(w8 ,0x983e5152ee66dfabULL)
151    F(w9 ,0xa831c66d2db43210ULL)
152    F(w10,0xb00327c898fb213fULL)
153    F(w11,0xbf597fc7beef0ee4ULL)
154    F(w12,0xc6e00bf33da88fc2ULL)
155    F(w13,0xd5a79147930aa725ULL)
156    F(w14,0x06ca6351e003826fULL)
157    F(w15,0x142929670a0e6e70ULL)
158
159    EXPAND
160
161    F(w0 ,0x27b70a8546d22ffcULL)
162    F(w1 ,0x2e1b21385c26c926ULL)
163    F(w2 ,0x4d2c6dfc5ac42aedULL)
164    F(w3 ,0x53380d139d95b3dfULL)
165    F(w4 ,0x650a73548baf63deULL)
166    F(w5 ,0x766a0abb3c77b2a8ULL)
167    F(w6 ,0x81c2c92e47edaee6ULL)
168    F(w7 ,0x92722c851482353bULL)
169    F(w8 ,0xa2bfe8a14cf10364ULL)
170    F(w9 ,0xa81a664bbc423001ULL)
171    F(w10,0xc24b8b70d0f89791ULL)
172    F(w11,0xc76c51a30654be30ULL)
173    F(w12,0xd192e819d6ef5218ULL)
174    F(w13,0xd69906245565a910ULL)
175    F(w14,0xf40e35855771202aULL)
176    F(w15,0x106aa07032bbd1b8ULL)
177
178    EXPAND
179
180    F(w0 ,0x19a4c116b8d2d0c8ULL)
181    F(w1 ,0x1e376c085141ab53ULL)
182    F(w2 ,0x2748774cdf8eeb99ULL)
183    F(w3 ,0x34b0bcb5e19b48a8ULL)
184    F(w4 ,0x391c0cb3c5c95a63ULL)
185    F(w5 ,0x4ed8aa4ae3418acbULL)
186    F(w6 ,0x5b9cca4f7763e373ULL)
187    F(w7 ,0x682e6ff3d6b2b8a3ULL)
188    F(w8 ,0x748f82ee5defb2fcULL)
189    F(w9 ,0x78a5636f43172f60ULL)
190    F(w10,0x84c87814a1f0ab72ULL)
191    F(w11,0x8cc702081a6439ecULL)
192    F(w12,0x90befffa23631e28ULL)
193    F(w13,0xa4506cebde82bde9ULL)
194    F(w14,0xbef9a3f7b2c67915ULL)
195    F(w15,0xc67178f2e372532bULL)
196
197    EXPAND
198
199    F(w0 ,0xca273eceea26619cULL)
200    F(w1 ,0xd186b8c721c0c207ULL)
201    F(w2 ,0xeada7dd6cde0eb1eULL)
202    F(w3 ,0xf57d4f7fee6ed178ULL)
203    F(w4 ,0x06f067aa72176fbaULL)
204    F(w5 ,0x0a637dc5a2c898a6ULL)
205    F(w6 ,0x113f9804bef90daeULL)
206    F(w7 ,0x1b710b35131c471bULL)
207    F(w8 ,0x28db77f523047d84ULL)
208    F(w9 ,0x32caab7b40c72493ULL)
209    F(w10,0x3c9ebe0a15c9bebcULL)
210    F(w11,0x431d67c49c100d4cULL)
211    F(w12,0x4cc5d4becb3e42b6ULL)
212    F(w13,0x597f299cfc657e2aULL)
213    F(w14,0x5fcb6fab3ad6faecULL)
214    F(w15,0x6c44198c4a475817ULL)
215
216    a += state[0];
217    b += state[1];
218    c += state[2];
219    d += state[3];
220    e += state[4];
221    f += state[5];
222    g += state[6];
223    h += state[7];
224
225    state[0] = a;
226    state[1] = b;
227    state[2] = c;
228    state[3] = d;
229    state[4] = e;
230    state[5] = f;
231    state[6] = g;
232    state[7] = h;
233
234    in += 128;
235    inlen -= 128;
236  }
237
238  store_bigendian(statebytes +  0,state[0]);
239  store_bigendian(statebytes +  8,state[1]);
240  store_bigendian(statebytes + 16,state[2]);
241  store_bigendian(statebytes + 24,state[3]);
242  store_bigendian(statebytes + 32,state[4]);
243  store_bigendian(statebytes + 40,state[5]);
244  store_bigendian(statebytes + 48,state[6]);
245  store_bigendian(statebytes + 56,state[7]);
246
247  return inlen;
248}
249