1*7bc319fbSDavid du Colombier /*
2*7bc319fbSDavid du Colombier * sha2 64-bit
3*7bc319fbSDavid du Colombier */
4*7bc319fbSDavid du Colombier #include <u.h>
5*7bc319fbSDavid du Colombier #include <libc.h>
6*7bc319fbSDavid du Colombier #include <libsec.h>
7*7bc319fbSDavid du Colombier
8*7bc319fbSDavid du Colombier static void encode32(uchar*, u32int*, ulong);
9*7bc319fbSDavid du Colombier static DigestState* sha2_64(uchar *, ulong, uchar *, SHA2_256state *, int);
10*7bc319fbSDavid du Colombier
11*7bc319fbSDavid du Colombier extern void _sha2block64(uchar*, ulong, u32int*);
12*7bc319fbSDavid du Colombier
13*7bc319fbSDavid du Colombier /*
14*7bc319fbSDavid du Colombier * for sha2_224 and sha2_256, len must be multiple of 64 for all but
15*7bc319fbSDavid du Colombier * the last call. There must be room in the input buffer to pad.
16*7bc319fbSDavid du Colombier *
17*7bc319fbSDavid du Colombier * Note: sha2_224 calls sha2_256block as sha2_224, just uses different
18*7bc319fbSDavid du Colombier * initial seed and produces a 224b hash result. otherwise it's
19*7bc319fbSDavid du Colombier * the same as sha2_256.
20*7bc319fbSDavid du Colombier */
21*7bc319fbSDavid du Colombier
22*7bc319fbSDavid du Colombier SHA2_224state*
sha2_224(uchar * p,ulong len,uchar * digest,SHA2_224state * s)23*7bc319fbSDavid du Colombier sha2_224(uchar *p, ulong len, uchar *digest, SHA2_224state *s)
24*7bc319fbSDavid du Colombier {
25*7bc319fbSDavid du Colombier if(s == nil) {
26*7bc319fbSDavid du Colombier s = mallocz(sizeof(*s), 1);
27*7bc319fbSDavid du Colombier if(s == nil)
28*7bc319fbSDavid du Colombier return nil;
29*7bc319fbSDavid du Colombier s->malloced = 1;
30*7bc319fbSDavid du Colombier }
31*7bc319fbSDavid du Colombier if(s->seeded == 0){
32*7bc319fbSDavid du Colombier /*
33*7bc319fbSDavid du Colombier * seed the state with the first 32 bits of the fractional
34*7bc319fbSDavid du Colombier * parts of the square roots of the first 8 primes 2..19).
35*7bc319fbSDavid du Colombier */
36*7bc319fbSDavid du Colombier s->state[0] = 0xc1059ed8;
37*7bc319fbSDavid du Colombier s->state[1] = 0x367cd507;
38*7bc319fbSDavid du Colombier s->state[2] = 0x3070dd17;
39*7bc319fbSDavid du Colombier s->state[3] = 0xf70e5939;
40*7bc319fbSDavid du Colombier s->state[4] = 0xffc00b31;
41*7bc319fbSDavid du Colombier s->state[5] = 0x68581511;
42*7bc319fbSDavid du Colombier s->state[6] = 0x64f98fa7;
43*7bc319fbSDavid du Colombier s->state[7] = 0xbefa4fa4;
44*7bc319fbSDavid du Colombier s->seeded = 1;
45*7bc319fbSDavid du Colombier }
46*7bc319fbSDavid du Colombier return sha2_64(p, len, digest, s, SHA2_224dlen);
47*7bc319fbSDavid du Colombier }
48*7bc319fbSDavid du Colombier
49*7bc319fbSDavid du Colombier SHA2_256state*
sha2_256(uchar * p,ulong len,uchar * digest,SHA2_256state * s)50*7bc319fbSDavid du Colombier sha2_256(uchar *p, ulong len, uchar *digest, SHA2_256state *s)
51*7bc319fbSDavid du Colombier {
52*7bc319fbSDavid du Colombier if(s == nil) {
53*7bc319fbSDavid du Colombier s = mallocz(sizeof(*s), 1);
54*7bc319fbSDavid du Colombier if(s == nil)
55*7bc319fbSDavid du Colombier return nil;
56*7bc319fbSDavid du Colombier s->malloced = 1;
57*7bc319fbSDavid du Colombier }
58*7bc319fbSDavid du Colombier if(s->seeded == 0){
59*7bc319fbSDavid du Colombier /*
60*7bc319fbSDavid du Colombier * seed the state with the first 32 bits of the fractional
61*7bc319fbSDavid du Colombier * parts of the square roots of the first 8 primes 2..19).
62*7bc319fbSDavid du Colombier */
63*7bc319fbSDavid du Colombier s->state[0] = 0x6a09e667;
64*7bc319fbSDavid du Colombier s->state[1] = 0xbb67ae85;
65*7bc319fbSDavid du Colombier s->state[2] = 0x3c6ef372;
66*7bc319fbSDavid du Colombier s->state[3] = 0xa54ff53a;
67*7bc319fbSDavid du Colombier s->state[4] = 0x510e527f;
68*7bc319fbSDavid du Colombier s->state[5] = 0x9b05688c;
69*7bc319fbSDavid du Colombier s->state[6] = 0x1f83d9ab;
70*7bc319fbSDavid du Colombier s->state[7] = 0x5be0cd19;
71*7bc319fbSDavid du Colombier s->seeded = 1;
72*7bc319fbSDavid du Colombier }
73*7bc319fbSDavid du Colombier return sha2_64(p, len, digest, s, SHA2_256dlen);
74*7bc319fbSDavid du Colombier }
75*7bc319fbSDavid du Colombier
76*7bc319fbSDavid du Colombier /* common 64 byte block padding and count code for SHA2_224 and SHA2_256 */
77*7bc319fbSDavid du Colombier static DigestState*
sha2_64(uchar * p,ulong len,uchar * digest,SHA2_256state * s,int dlen)78*7bc319fbSDavid du Colombier sha2_64(uchar *p, ulong len, uchar *digest, SHA2_256state *s, int dlen)
79*7bc319fbSDavid du Colombier {
80*7bc319fbSDavid du Colombier int i;
81*7bc319fbSDavid du Colombier u32int x[16];
82*7bc319fbSDavid du Colombier uchar buf[128];
83*7bc319fbSDavid du Colombier uchar *e;
84*7bc319fbSDavid du Colombier
85*7bc319fbSDavid du Colombier /* fill out the partial 64 byte block from previous calls */
86*7bc319fbSDavid du Colombier if(s->blen){
87*7bc319fbSDavid du Colombier i = 64 - s->blen;
88*7bc319fbSDavid du Colombier if(len < i)
89*7bc319fbSDavid du Colombier i = len;
90*7bc319fbSDavid du Colombier memmove(s->buf + s->blen, p, i);
91*7bc319fbSDavid du Colombier len -= i;
92*7bc319fbSDavid du Colombier s->blen += i;
93*7bc319fbSDavid du Colombier p += i;
94*7bc319fbSDavid du Colombier if(s->blen == 64){
95*7bc319fbSDavid du Colombier _sha2block64(s->buf, s->blen, s->state);
96*7bc319fbSDavid du Colombier s->len += s->blen;
97*7bc319fbSDavid du Colombier s->blen = 0;
98*7bc319fbSDavid du Colombier }
99*7bc319fbSDavid du Colombier }
100*7bc319fbSDavid du Colombier
101*7bc319fbSDavid du Colombier /* do 64 byte blocks */
102*7bc319fbSDavid du Colombier i = len & ~(64-1);
103*7bc319fbSDavid du Colombier if(i){
104*7bc319fbSDavid du Colombier _sha2block64(p, i, s->state);
105*7bc319fbSDavid du Colombier s->len += i;
106*7bc319fbSDavid du Colombier len -= i;
107*7bc319fbSDavid du Colombier p += i;
108*7bc319fbSDavid du Colombier }
109*7bc319fbSDavid du Colombier
110*7bc319fbSDavid du Colombier /* save the left overs if not last call */
111*7bc319fbSDavid du Colombier if(digest == 0){
112*7bc319fbSDavid du Colombier if(len){
113*7bc319fbSDavid du Colombier memmove(s->buf, p, len);
114*7bc319fbSDavid du Colombier s->blen += len;
115*7bc319fbSDavid du Colombier }
116*7bc319fbSDavid du Colombier return s;
117*7bc319fbSDavid du Colombier }
118*7bc319fbSDavid du Colombier
119*7bc319fbSDavid du Colombier /*
120*7bc319fbSDavid du Colombier * this is the last time through, pad what's left with 0x80,
121*7bc319fbSDavid du Colombier * 0's, and the input count to create a multiple of 64 bytes.
122*7bc319fbSDavid du Colombier */
123*7bc319fbSDavid du Colombier if(s->blen){
124*7bc319fbSDavid du Colombier p = s->buf;
125*7bc319fbSDavid du Colombier len = s->blen;
126*7bc319fbSDavid du Colombier } else {
127*7bc319fbSDavid du Colombier memmove(buf, p, len);
128*7bc319fbSDavid du Colombier p = buf;
129*7bc319fbSDavid du Colombier }
130*7bc319fbSDavid du Colombier s->len += len;
131*7bc319fbSDavid du Colombier e = p + len;
132*7bc319fbSDavid du Colombier if(len < 56)
133*7bc319fbSDavid du Colombier i = 56 - len;
134*7bc319fbSDavid du Colombier else
135*7bc319fbSDavid du Colombier i = 120 - len;
136*7bc319fbSDavid du Colombier memset(e, 0, i);
137*7bc319fbSDavid du Colombier *e = 0x80;
138*7bc319fbSDavid du Colombier len += i;
139*7bc319fbSDavid du Colombier
140*7bc319fbSDavid du Colombier /* append the count */
141*7bc319fbSDavid du Colombier x[0] = s->len>>29;
142*7bc319fbSDavid du Colombier x[1] = s->len<<3;
143*7bc319fbSDavid du Colombier encode32(p+len, x, 8);
144*7bc319fbSDavid du Colombier
145*7bc319fbSDavid du Colombier /* digest the last part */
146*7bc319fbSDavid du Colombier _sha2block64(p, len+8, s->state);
147*7bc319fbSDavid du Colombier s->len += len+8;
148*7bc319fbSDavid du Colombier
149*7bc319fbSDavid du Colombier /* return result and free state */
150*7bc319fbSDavid du Colombier encode32(digest, s->state, dlen);
151*7bc319fbSDavid du Colombier if(s->malloced == 1)
152*7bc319fbSDavid du Colombier free(s);
153*7bc319fbSDavid du Colombier return nil;
154*7bc319fbSDavid du Colombier }
155*7bc319fbSDavid du Colombier
156*7bc319fbSDavid du Colombier /*
157*7bc319fbSDavid du Colombier * Encodes input (ulong) into output (uchar).
158*7bc319fbSDavid du Colombier * Assumes len is a multiple of 4.
159*7bc319fbSDavid du Colombier */
160*7bc319fbSDavid du Colombier static void
encode32(uchar * output,u32int * input,ulong len)161*7bc319fbSDavid du Colombier encode32(uchar *output, u32int *input, ulong len)
162*7bc319fbSDavid du Colombier {
163*7bc319fbSDavid du Colombier u32int x;
164*7bc319fbSDavid du Colombier uchar *e;
165*7bc319fbSDavid du Colombier
166*7bc319fbSDavid du Colombier for(e = output + len; output < e;) {
167*7bc319fbSDavid du Colombier x = *input++;
168*7bc319fbSDavid du Colombier *output++ = x >> 24;
169*7bc319fbSDavid du Colombier *output++ = x >> 16;
170*7bc319fbSDavid du Colombier *output++ = x >> 8;
171*7bc319fbSDavid du Colombier *output++ = x;
172*7bc319fbSDavid du Colombier }
173*7bc319fbSDavid du Colombier }
174*7bc319fbSDavid du Colombier
175*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_224(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)176*7bc319fbSDavid du Colombier hmac_sha2_224(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
177*7bc319fbSDavid du Colombier DigestState *s)
178*7bc319fbSDavid du Colombier {
179*7bc319fbSDavid du Colombier return hmac_x(p, len, key, klen, digest, s, sha2_224, SHA2_224dlen);
180*7bc319fbSDavid du Colombier }
181*7bc319fbSDavid du Colombier
182*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_256(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)183*7bc319fbSDavid du Colombier hmac_sha2_256(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
184*7bc319fbSDavid du Colombier DigestState *s)
185*7bc319fbSDavid du Colombier {
186*7bc319fbSDavid du Colombier return hmac_x(p, len, key, klen, digest, s, sha2_256, SHA2_256dlen);
187*7bc319fbSDavid du Colombier }
188