totp

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

sha512.c (6034B)


      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 "sha512.h"
      9 #include "util.h"
     10 
     11 static inline uint64_t _sha512_rotr64(uint64_t x, uint8_t n)
     12 {
     13 	return x >> n | x << (64 - n);
     14 }
     15 
     16 static inline void _sha512_add8(uint64_t *dest, const uint64_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 _sha512_rotmod8(uint64_t *a, uint64_t k, uint64_t w)
     25 {
     26 	uint64_t t1 = a[7] + (_sha512_rotr64(a[4], 14) ^ _sha512_rotr64(a[4], 18) ^ _sha512_rotr64(a[4], 41)) + ((a[4] & a[5]) ^ (~a[4] & a[6])) + k + w;
     27 	uint64_t t2 = (_sha512_rotr64(a[0], 28) ^ _sha512_rotr64(a[0], 34) ^ _sha512_rotr64(a[0], 39)) + ((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 uint64_t _sha512_getnw(uint64_t *w, size_t i)
     36 {
     37 	return w[i & 15] +=
     38 		(_sha512_rotr64(w[(i + 1) & 15], 1) ^ _sha512_rotr64(w[(i + 1) & 15], 8) ^ (w[(i + 1) & 15] >> 7)) +
     39 		w[(i + 9) & 15] +
     40 		(_sha512_rotr64(w[(i + 14) & 15], 19) ^ _sha512_rotr64(w[(i + 14) & 15], 61) ^ (w[(i + 14) & 15] >> 6));
     41 }
     42 
     43 void sha512_init(struct sha512 *s)
     44 {
     45 	memcpy(s->h, (uint64_t[]){
     46 			0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 
     47 			0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 
     48 			}, sizeof(s->h));
     49 	s->len = 0;
     50 }
     51 
     52 static inline void _sha512_update(uint64_t *h, const void *data)
     53 {
     54 	const uint64_t k[] = {
     55 		0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
     56 		0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
     57 		0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
     58 		0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
     59 		0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
     60 		0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
     61 		0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
     62 		0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
     63 		0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
     64 		0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
     65 		0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
     66 		0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
     67 		0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
     68 		0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
     69 		0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
     70 		0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
     71 	}; 
     72 	const uint8_t *d = data;
     73 
     74 	uint64_t w[16];
     75 	size_t i;
     76 
     77 	uint64_t wr[8];
     78 	memcpy(wr, h, sizeof(wr));
     79 
     80 	for (i = 0; i < sizeof(w) / sizeof(*w); i++) {
     81 		w[i] = readbeu64(&d[i * sizeof(uint64_t)]);
     82 		_sha512_rotmod8(wr, k[i], w[i]);
     83 	}
     84 
     85 	for (; i < sizeof(k) / sizeof(*k); i++)
     86 		_sha512_rotmod8(wr, k[i], _sha512_getnw(w, i));
     87 
     88 	_sha512_add8(h, wr);
     89 }
     90 
     91 void sha512_update(struct sha512 *s, const void *data, size_t len)
     92 {
     93 	uint8_t *bw = s->buffer + (s->len & (sizeof(s->buffer) - 1));
     94 	uint8_t *bend = 1[&s->buffer];
     95 
     96 	if (data == bw) {
     97 		if (bw + len == bend)
     98 			_sha512_update(s->h, s->buffer);
     99 	} else if (bw + len > bend) {
    100 		const uint8_t *d = data;
    101 		const uint8_t *dend = d + len;
    102 
    103 		if (bw != s->buffer) {
    104 			memcpy(bw, d, bend - bw);
    105 			_sha512_update(s->h, s->buffer);
    106 			d += bend - bw;
    107 		}
    108 
    109 		while ((size_t)(dend - d) > sizeof(s->buffer)) {
    110 			_sha512_update(s->h, d);
    111 			d += sizeof(s->buffer);
    112 		}
    113 
    114 		memcpy(s->buffer, d, dend - d);
    115 	} else {
    116 		memcpy(bw, data, len);
    117 	}
    118 	s->len += len;
    119 }
    120 
    121 void sha512_finish(struct sha512 *s)
    122 {
    123 	size_t i;
    124 	uint8_t *bw = s->buffer + (s->len & (sizeof(s->buffer) - 1));
    125 	uint8_t *bend = 1[&s->buffer];
    126 
    127 	*bw++ = 0x80;
    128 	memset(bw, 0, bend - bw);
    129 
    130 	if (bw + 2 * sizeof(uint64_t) >= bend) {
    131 		_sha512_update(s->h, s->buffer);
    132 		memset(s->buffer, 0, bw - s->buffer);
    133 	}
    134 
    135 	writebeu64(&s->buffer[120], s->len << 3);
    136 	_sha512_update(s->h, s->buffer);
    137 
    138 	for (i = 0; i < sizeof(s->h) / sizeof(*s->h); i++)
    139 		writebeu64(&s->h[i], s->h[i]);
    140 }
    141 
    142 void sha384_init(struct sha384 *s)
    143 {
    144 	struct sha512 *s5 = (struct sha512 *)s;
    145 	memcpy(s5->h, (uint64_t[]){
    146 			0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 
    147 			0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4
    148 	       }, sizeof(s5->h));
    149 	s5->len = 0;
    150 }
    151 
    152 void sha384_update(struct sha384 *s, const void *data, size_t len)
    153 {
    154 	sha512_update((struct sha512 *)s, data, len);
    155 }
    156 
    157 void sha384_finish(struct sha384 *s)
    158 {
    159 	sha512_finish((struct sha512 *)s);
    160 }
    161 
    162 void sha512_hmac(const void *key, size_t keylen,
    163 		const void *data, size_t datalen,
    164 		void *h)
    165 {
    166 	hmac(key, keylen,
    167 	     data, datalen,
    168 	     (digest_init)sha512_init,
    169 	     (digest_update)sha512_update,
    170 	     (digest_finish)sha512_finish,
    171 	     sizeof(struct sha512),
    172 	     sizeof(((struct sha512 *)0)->buffer),
    173 	     sizeof(((struct sha512 *)0)->h),
    174 	     (ptrdiff_t)&((struct sha512 *)0)->buffer,
    175 	     (ptrdiff_t)&((struct sha512 *)0)->h,
    176 	     h);
    177 }
    178 
    179 void sha384_hmac(const void *key, size_t keylen,
    180 		const void *data, size_t datalen,
    181 		void *h)
    182 {
    183 	hmac(key, keylen,
    184 	     data, datalen,
    185 	     (digest_init)sha384_init,
    186 	     (digest_update)sha384_update,
    187 	     (digest_finish)sha384_finish,
    188 	     sizeof(struct sha384),
    189 	     sizeof(((struct sha384 *)0)->buffer),
    190 	     sizeof(((struct sha384 *)0)->h),
    191 	     (ptrdiff_t)&((struct sha384 *)0)->buffer,
    192 	     (ptrdiff_t)&((struct sha384 *)0)->h,
    193 	     h);
    194 }