totp

Simple cli tool for storing TOTP secrets and generating tokens
git clone https://git.inz.fi/totp/
Log | Files | Refs | Submodules

sha256.c (4965B)


      1 #include <stdint.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <assert.h>
      5 
      6 #include <arpa/inet.h>
      7 
      8 #include "sha256.h"
      9 #include "util.h"
     10 
     11 static inline uint32_t _sha256_rotr32(uint32_t x, uint8_t n)
     12 {
     13 	return x >> n | x << (32 - n);
     14 }
     15 
     16 static inline void _sha256_add8(uint32_t *dest, const uint32_t *src)
     17 {
     18 	size_t i;
     19 
     20 	for (i = 0; i < 8; i++)
     21 		dest[i] += src[i];
     22 }
     23 
     24 static inline void _sha256_rotmod8(uint32_t *a, uint32_t k, uint32_t w)
     25 {
     26 	uint32_t t1 = a[7] + (_sha256_rotr32(a[4], 6) ^ _sha256_rotr32(a[4], 11) ^ _sha256_rotr32(a[4], 25)) + ((a[4] & a[5]) ^ (~a[4] & a[6])) + k + w;
     27 	uint32_t t2 = (_sha256_rotr32(a[0], 2) ^ _sha256_rotr32(a[0], 13) ^ _sha256_rotr32(a[0], 22)) + ((a[0] & a[1]) ^ (a[0] & a[2]) ^ (a[1] & a[2]));
     28 
     29 	memmove(a + 1, a, 7 * sizeof(*a));
     30 
     31 	a[4] += t1;
     32 	a[0] = t1 + t2;
     33 }
     34 
     35 static inline uint32_t _sha256_getnw(uint32_t *w, size_t i)
     36 {
     37 	return w[i & 15] +=
     38 		(_sha256_rotr32(w[(i + 1) & 15], 7) ^ _sha256_rotr32(w[(i + 1) & 15], 18) ^ (w[(i + 1) & 15] >> 3)) +
     39 		w[(i + 9) & 15] +
     40 		(_sha256_rotr32(w[(i + 14) & 15], 17) ^ _sha256_rotr32(w[(i + 14) & 15], 19) ^ (w[(i + 14) & 15] >> 10));
     41 }
     42 
     43 void sha256_init(struct sha256 *s)
     44 {
     45 	memcpy(s->h, (uint32_t[]){ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }, sizeof(s->h));
     46 	s->len = 0;
     47 }
     48 
     49 static inline void _sha256_update(uint32_t *h, const void *data)
     50 {
     51 	const uint32_t k[] = {
     52 		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
     53 		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
     54 		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
     55 		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
     56 		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
     57 		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
     58 		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
     59 		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
     60 	}; 
     61 	const uint32_t *d = data;
     62 
     63 	uint32_t w[16];
     64 	size_t i;
     65 
     66 	uint32_t wr[8];
     67 	memcpy(wr, h, sizeof(wr));
     68 
     69 	for (i = 0; i < 16; i++)
     70 		_sha256_rotmod8(wr, k[i], w[i] = ntohl(d[i]));
     71 
     72 	for (; i < 64; i++)
     73 		_sha256_rotmod8(wr, k[i], _sha256_getnw(w, i));
     74 
     75 	_sha256_add8(h, wr);
     76 }
     77 
     78 void sha256_update(struct sha256 *s, const void *data, size_t len)
     79 {
     80 	uint8_t *bw = s->buffer + (s->len & (sizeof(s->buffer) - 1));
     81 	uint8_t *bend = 1[&s->buffer];
     82 
     83 	if (data == bw) {
     84 		if (bw + len == bend)
     85 			_sha256_update(s->h, s->buffer);
     86 	} else if (bw + len > bend) {
     87 		const uint8_t *d = data;
     88 		const uint8_t *dend = d + len;
     89 
     90 		if (bw != s->buffer) {
     91 			memcpy(bw, d, bend - bw);
     92 			_sha256_update(s->h, s->buffer);
     93 			d += bend - bw;
     94 		}
     95 
     96 		while ((size_t)(dend - d) > sizeof(s->buffer)) {
     97 			_sha256_update(s->h, d);
     98 			d += sizeof(s->buffer);
     99 		}
    100 
    101 		memcpy(s->buffer, d, dend - d);
    102 	} else {
    103 		memcpy(bw, data, len);
    104 	}
    105 	s->len += len;
    106 }
    107 
    108 void sha256_finish(struct sha256 *s)
    109 {
    110 	size_t i;
    111 	uint8_t *bw = s->buffer + (s->len & (sizeof(s->buffer) - 1));
    112 	uint8_t *bend = 1[&s->buffer];
    113 
    114 	*bw++ = 0x80;
    115 	memset(bw, 0, bend - bw);
    116 
    117 	if (bw + sizeof(uint64_t) >= bend) {
    118 		_sha256_update(s->h, s->buffer);
    119 		memset(s->buffer, 0, bw - s->buffer);
    120 	}
    121 
    122 	writebeu64(bend - sizeof(uint64_t), s->len << 3);
    123 	_sha256_update(s->h, s->buffer);
    124 
    125 	for (i = 0; i < sizeof(s->h) / sizeof(*s->h); i++)
    126 		writebeu32(&s->h[i], s->h[i]);
    127 }
    128 
    129 void sha224_init(struct sha224 *s)
    130 {
    131 	struct sha256 *s256 = (struct sha256 *)s;
    132 	memcpy(s256->h, (uint32_t[]){ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 }, sizeof(s256->h));
    133 	s->len = 0;
    134 }
    135 
    136 void sha224_update(struct sha224 *s, const void *data, size_t len)
    137 {
    138 	sha256_update((struct sha256 *)s, data, len);
    139 }
    140 
    141 void sha224_finish(struct sha224 *s)
    142 {
    143 	sha256_finish((struct sha256 *)s);
    144 }
    145 
    146 void sha256_hmac(const void *key, size_t keylen,
    147 		const void *data, size_t datalen,
    148 		void *h)
    149 {
    150 	hmac(key, keylen,
    151 	     data, datalen,
    152 	     (digest_init)sha256_init,
    153 	     (digest_update)sha256_update,
    154 	     (digest_finish)sha256_finish,
    155 	     sizeof(struct sha256),
    156 	     sizeof(((struct sha256 *)0)->buffer),
    157 	     sizeof(((struct sha256 *)0)->h),
    158 	     (ptrdiff_t)&((struct sha256 *)0)->buffer,
    159 	     (ptrdiff_t)&((struct sha256 *)0)->h,
    160 	     h);
    161 }
    162 
    163 void sha224_hmac(const void *key, size_t keylen,
    164 		const void *data, size_t datalen,
    165 		void *h)
    166 {
    167 	hmac(key, keylen,
    168 	     data, datalen,
    169 	     (digest_init)sha224_init,
    170 	     (digest_update)sha224_update,
    171 	     (digest_finish)sha224_finish,
    172 	     sizeof(struct sha224),
    173 	     sizeof(((struct sha224 *)0)->buffer),
    174 	     sizeof(((struct sha224 *)0)->h),
    175 	     (ptrdiff_t)&((struct sha224 *)0)->buffer,
    176 	     (ptrdiff_t)&((struct sha224 *)0)->h,
    177 	     h);
    178 }