1*7bc319fbSDavid du Colombier /*
2*7bc319fbSDavid du Colombier * sha2 128-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 encode64(uchar*, u64int*, ulong);
9*7bc319fbSDavid du Colombier static DigestState* sha2_128(uchar *, ulong, uchar *, SHA2_256state *, int);
10*7bc319fbSDavid du Colombier
11*7bc319fbSDavid du Colombier extern void _sha2block128(uchar*, ulong, u64int*);
12*7bc319fbSDavid du Colombier
13*7bc319fbSDavid du Colombier /*
14*7bc319fbSDavid du Colombier * for sha2_384 and sha2_512, len must be multiple of 128 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_384 calls sha2_512block as sha2_384; it just uses a different
18*7bc319fbSDavid du Colombier * initial seed to produce a truncated 384b hash result. otherwise
19*7bc319fbSDavid du Colombier * it's the same as sha2_512.
20*7bc319fbSDavid du Colombier */
21*7bc319fbSDavid du Colombier SHA2_384state*
sha2_384(uchar * p,ulong len,uchar * digest,SHA2_384state * s)22*7bc319fbSDavid du Colombier sha2_384(uchar *p, ulong len, uchar *digest, SHA2_384state *s)
23*7bc319fbSDavid du Colombier {
24*7bc319fbSDavid du Colombier if(s == nil) {
25*7bc319fbSDavid du Colombier s = mallocz(sizeof(*s), 1);
26*7bc319fbSDavid du Colombier if(s == nil)
27*7bc319fbSDavid du Colombier return nil;
28*7bc319fbSDavid du Colombier s->malloced = 1;
29*7bc319fbSDavid du Colombier }
30*7bc319fbSDavid du Colombier if(s->seeded == 0){
31*7bc319fbSDavid du Colombier /*
32*7bc319fbSDavid du Colombier * seed the state with the first 64 bits of the fractional
33*7bc319fbSDavid du Colombier * parts of the square roots of the 9th thru 16th primes.
34*7bc319fbSDavid du Colombier */
35*7bc319fbSDavid du Colombier s->bstate[0] = 0xcbbb9d5dc1059ed8LL;
36*7bc319fbSDavid du Colombier s->bstate[1] = 0x629a292a367cd507LL;
37*7bc319fbSDavid du Colombier s->bstate[2] = 0x9159015a3070dd17LL;
38*7bc319fbSDavid du Colombier s->bstate[3] = 0x152fecd8f70e5939LL;
39*7bc319fbSDavid du Colombier s->bstate[4] = 0x67332667ffc00b31LL;
40*7bc319fbSDavid du Colombier s->bstate[5] = 0x8eb44a8768581511LL;
41*7bc319fbSDavid du Colombier s->bstate[6] = 0xdb0c2e0d64f98fa7LL;
42*7bc319fbSDavid du Colombier s->bstate[7] = 0x47b5481dbefa4fa4LL;
43*7bc319fbSDavid du Colombier s->seeded = 1;
44*7bc319fbSDavid du Colombier }
45*7bc319fbSDavid du Colombier return sha2_128(p, len, digest, s, SHA2_384dlen);
46*7bc319fbSDavid du Colombier }
47*7bc319fbSDavid du Colombier
48*7bc319fbSDavid du Colombier SHA2_512state*
sha2_512(uchar * p,ulong len,uchar * digest,SHA2_512state * s)49*7bc319fbSDavid du Colombier sha2_512(uchar *p, ulong len, uchar *digest, SHA2_512state *s)
50*7bc319fbSDavid du Colombier {
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 64 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->bstate[0] = 0x6a09e667f3bcc908LL;
64*7bc319fbSDavid du Colombier s->bstate[1] = 0xbb67ae8584caa73bLL;
65*7bc319fbSDavid du Colombier s->bstate[2] = 0x3c6ef372fe94f82bLL;
66*7bc319fbSDavid du Colombier s->bstate[3] = 0xa54ff53a5f1d36f1LL;
67*7bc319fbSDavid du Colombier s->bstate[4] = 0x510e527fade682d1LL;
68*7bc319fbSDavid du Colombier s->bstate[5] = 0x9b05688c2b3e6c1fLL;
69*7bc319fbSDavid du Colombier s->bstate[6] = 0x1f83d9abfb41bd6bLL;
70*7bc319fbSDavid du Colombier s->bstate[7] = 0x5be0cd19137e2179LL;
71*7bc319fbSDavid du Colombier s->seeded = 1;
72*7bc319fbSDavid du Colombier }
73*7bc319fbSDavid du Colombier return sha2_128(p, len, digest, s, SHA2_512dlen);
74*7bc319fbSDavid du Colombier }
75*7bc319fbSDavid du Colombier
76*7bc319fbSDavid du Colombier /* common 128 byte block padding and count code for SHA2_384 and SHA2_512 */
77*7bc319fbSDavid du Colombier static DigestState*
sha2_128(uchar * p,ulong len,uchar * digest,SHA2_512state * s,int dlen)78*7bc319fbSDavid du Colombier sha2_128(uchar *p, ulong len, uchar *digest, SHA2_512state *s, int dlen)
79*7bc319fbSDavid du Colombier {
80*7bc319fbSDavid du Colombier int i;
81*7bc319fbSDavid du Colombier u64int x[16];
82*7bc319fbSDavid du Colombier uchar buf[256];
83*7bc319fbSDavid du Colombier uchar *e;
84*7bc319fbSDavid du Colombier
85*7bc319fbSDavid du Colombier /* fill out the partial 128 byte block from previous calls */
86*7bc319fbSDavid du Colombier if(s->blen){
87*7bc319fbSDavid du Colombier i = 128 - 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 == 128){
95*7bc319fbSDavid du Colombier _sha2block128(s->buf, s->blen, s->bstate);
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 128 byte blocks */
102*7bc319fbSDavid du Colombier i = len & ~(128-1);
103*7bc319fbSDavid du Colombier if(i){
104*7bc319fbSDavid du Colombier _sha2block128(p, i, s->bstate);
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 128 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 < 112)
133*7bc319fbSDavid du Colombier i = 112 - len;
134*7bc319fbSDavid du Colombier else
135*7bc319fbSDavid du Colombier i = 240 - 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] = 0; /* assume 32b length, i.e. < 4GB */
142*7bc319fbSDavid du Colombier x[1] = s->len<<3;
143*7bc319fbSDavid du Colombier encode64(p+len, x, 16);
144*7bc319fbSDavid du Colombier
145*7bc319fbSDavid du Colombier /* digest the last part */
146*7bc319fbSDavid du Colombier _sha2block128(p, len+16, s->bstate);
147*7bc319fbSDavid du Colombier s->len += len+16;
148*7bc319fbSDavid du Colombier
149*7bc319fbSDavid du Colombier /* return result and free state */
150*7bc319fbSDavid du Colombier encode64(digest, s->bstate, 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 long) into output (uchar).
158*7bc319fbSDavid du Colombier * Assumes len is a multiple of 8.
159*7bc319fbSDavid du Colombier */
160*7bc319fbSDavid du Colombier static void
encode64(uchar * output,u64int * input,ulong len)161*7bc319fbSDavid du Colombier encode64(uchar *output, u64int *input, ulong len)
162*7bc319fbSDavid du Colombier {
163*7bc319fbSDavid du Colombier u64int 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 >> 56;
169*7bc319fbSDavid du Colombier *output++ = x >> 48;
170*7bc319fbSDavid du Colombier *output++ = x >> 40;
171*7bc319fbSDavid du Colombier *output++ = x >> 32;
172*7bc319fbSDavid du Colombier *output++ = x >> 24;
173*7bc319fbSDavid du Colombier *output++ = x >> 16;
174*7bc319fbSDavid du Colombier *output++ = x >> 8;
175*7bc319fbSDavid du Colombier *output++ = x;
176*7bc319fbSDavid du Colombier }
177*7bc319fbSDavid du Colombier }
178*7bc319fbSDavid du Colombier
179*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_384(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)180*7bc319fbSDavid du Colombier hmac_sha2_384(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
181*7bc319fbSDavid du Colombier DigestState *s)
182*7bc319fbSDavid du Colombier {
183*7bc319fbSDavid du Colombier return hmac_x(p, len, key, klen, digest, s, sha2_384, SHA2_384dlen);
184*7bc319fbSDavid du Colombier }
185*7bc319fbSDavid du Colombier
186*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_512(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)187*7bc319fbSDavid du Colombier hmac_sha2_512(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
188*7bc319fbSDavid du Colombier DigestState *s)
189*7bc319fbSDavid du Colombier {
190*7bc319fbSDavid du Colombier return hmac_x(p, len, key, klen, digest, s, sha2_512, SHA2_512dlen);
191*7bc319fbSDavid du Colombier }
192