1 #include "os.h" 2 #include <libsec.h> 3 4 extern void _sha256block(SHA256state*, uchar*); 5 extern void _sha512block(SHA512state*, uchar*); 6 7 u32int sha224h0[] = { 8 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 9 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4, 10 }; 11 u32int sha256h0[] = { 12 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 13 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, 14 }; 15 16 u64int sha384h0[] = { 17 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, 18 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL, 19 }; 20 u64int sha512h0[] = { 21 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 22 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL, 23 }; 24 25 26 static SHA256state * 27 sha256init(void) 28 { 29 SHA256state *s; 30 31 s = malloc(sizeof(*s)); 32 if(s == nil) 33 return nil; 34 s->malloced = 1; 35 s->seeded = 0; 36 s->len = 0; 37 s->blen = 0; 38 39 return s; 40 } 41 42 static void 43 p32(u32int v, uchar *p) 44 { 45 p[0] = v>>24; 46 p[1] = v>>16; 47 p[2] = v>>8; 48 p[3] = v>>0; 49 } 50 51 static void 52 p64(u64int v, uchar *p) 53 { 54 p32(v>>32, p); 55 p32(v, p+4); 56 } 57 58 enum { 59 HI = 0, 60 LO = 1, 61 }; 62 static void 63 p128(u64int v[2], uchar *p) 64 { 65 p64(v[HI], p); 66 p64(v[LO], p+8); 67 } 68 69 static void 70 uvvadd(u64int v[2], int n) 71 { 72 v[LO] += n; 73 if(v[LO] < n) /* overflow */ 74 v[HI]++; 75 } 76 77 static void 78 uvvmult8(u64int v[2]) 79 { 80 v[HI] = (v[HI]<<3) | (v[LO] >> (64-3)); 81 v[LO] <<= 3; 82 } 83 84 85 static void 86 _sha256(uchar *p, ulong len, SHA256state *s) 87 { 88 u32int take; 89 90 /* complete possible partial block from last time */ 91 if(s->blen > 0 && s->blen+len >= SHA256bsize) { 92 take = SHA256bsize-s->blen; 93 memmove(s->buf+s->blen, p, take); 94 p += take; 95 len -= take; 96 _sha256block(s, s->buf); 97 s->len += SHA256bsize; 98 s->blen = 0; 99 memset(s->buf, 0, SHA256bsize); 100 } 101 /* whole blocks */ 102 while(len >= SHA256bsize) { 103 _sha256block(s, p); 104 s->len += SHA256bsize; 105 p += SHA256bsize; 106 len -= SHA256bsize; 107 } 108 /* keep possible leftover bytes */ 109 if(len > 0) { 110 memmove(s->buf+s->blen, p, len); 111 s->blen += len; 112 } 113 } 114 115 static void 116 sha256finish(SHA256state *s, uchar *digest, int smaller) 117 { 118 int i; 119 uchar end[SHA256bsize+8]; 120 u32int nzero, nb, nd; 121 122 nzero = (2*SHA256bsize - s->blen - 1 - 8) % SHA256bsize; 123 end[0] = 0x80; 124 memset(end+1, 0, nzero); 125 nb = 8*(s->len+s->blen); 126 p64(nb, end+1+nzero); 127 _sha256(end, 1+nzero+8, s); 128 129 nd = SHA256dlen/4; 130 if(smaller) 131 nd = SHA224dlen/4; 132 for(i = 0; i < nd; i++, digest += 4) 133 p32(s->h32[i], digest); 134 } 135 136 static SHA256state* 137 sha256x(uchar *p, ulong len, uchar *digest, SHA256state *s, int smaller) 138 { 139 if(s == nil) { 140 s = sha256init(); 141 if(s == nil) 142 return nil; 143 } 144 145 if(s->seeded == 0){ 146 memmove(s->h32, smaller? sha224h0: sha256h0, sizeof s->h32); 147 s->seeded = 1; 148 } 149 150 _sha256(p, len, s); 151 152 if(digest == 0) 153 return s; 154 155 sha256finish(s, digest, smaller); 156 if(s->malloced == 1) 157 free(s); 158 return nil; 159 } 160 161 SHA256state* 162 sha224(uchar *p, ulong len, uchar *digest, SHA256state *s) 163 { 164 return sha256x(p, len, digest, s, 1); 165 } 166 167 SHA256state* 168 sha256(uchar *p, ulong len, uchar *digest, SHA256state *s) 169 { 170 return sha256x(p, len, digest, s, 0); 171 } 172 173 174 static SHA512state * 175 sha512init(void) 176 { 177 SHA512state *s; 178 179 s = malloc(sizeof(*s)); 180 if(s == nil) 181 return nil; 182 s->malloced = 1; 183 s->seeded = 0; 184 s->nb128[HI] = 0; 185 s->nb128[LO] = 0; 186 s->blen = 0; 187 188 return s; 189 } 190 191 static void 192 _sha512(uchar *p, ulong len, SHA512state *s) 193 { 194 u32int take; 195 196 /* complete possible partial block from last time */ 197 if(s->blen > 0 && s->blen+len >= SHA512bsize) { 198 take = SHA512bsize-s->blen; 199 memmove(s->buf+s->blen, p, take); 200 p += take; 201 len -= take; 202 _sha512block(s, s->buf); 203 uvvadd(s->nb128, SHA512bsize); 204 s->blen = 0; 205 memset(s->buf, 0, SHA512bsize); 206 } 207 /* whole blocks */ 208 while(len >= SHA512bsize) { 209 _sha512block(s, p); 210 uvvadd(s->nb128, SHA512bsize); 211 p += SHA512bsize; 212 len -= SHA512bsize; 213 } 214 /* keep possible leftover bytes */ 215 if(len > 0) { 216 memmove(s->buf+s->blen, p, len); 217 s->blen += len; 218 } 219 } 220 221 void 222 sha512finish(SHA512state *s, uchar *digest, int smaller) 223 { 224 int i; 225 uchar end[SHA512bsize+16]; 226 u32int nzero, n; 227 u64int nb[2]; 228 229 nzero = (2*SHA512bsize - s->blen - 1 - 16) % SHA512bsize; 230 end[0] = 0x80; 231 memset(end+1, 0, nzero); 232 nb[0] = s->nb128[0]; 233 nb[1] = s->nb128[1]; 234 uvvadd(nb, s->blen); 235 uvvmult8(nb); 236 p128(nb, end+1+nzero); 237 _sha512(end, 1+nzero+16, s); 238 239 n = SHA512dlen/8; 240 if(smaller) 241 n = SHA384dlen/8; 242 for(i = 0; i < n; i++, digest += 8) 243 p64(s->h64[i], digest); 244 } 245 246 static SHA512state* 247 sha512x(uchar *p, ulong len, uchar *digest, SHA512state *s, int smaller) 248 { 249 if(s == nil) { 250 s = sha512init(); 251 if(s == nil) 252 return nil; 253 } 254 255 if(s->seeded == 0){ 256 memmove(s->h64, smaller? sha384h0: sha512h0, sizeof s->h64); 257 s->seeded = 1; 258 } 259 260 _sha512(p, len, s); 261 262 if(digest == 0) 263 return s; 264 265 sha512finish(s, digest, smaller); 266 if(s->malloced == 1) 267 free(s); 268 return nil; 269 } 270 271 SHA512state* 272 sha384(uchar *p, ulong len, uchar *digest, SHA512state *s) 273 { 274 return sha512x(p, len, digest, s, 1); 275 } 276 277 SHA512state* 278 sha512(uchar *p, ulong len, uchar *digest, SHA512state *s) 279 { 280 return sha512x(p, len, digest, s, 0); 281 } 282