aboutsummaryrefslogtreecommitdiffstats
path: root/libblake_internal_blakes_update.c
blob: 525600aed3fed29a500fbcace7e5d939fad39d01 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* See LICENSE file for copyright and license details. */
#include "common.h"

#define A 10
#define B 11
#define C 12
#define D 13
#define E 14
#define F 15

#define CS0 UINT_LEAST32_C(0x243F6A88)
#define CS1 UINT_LEAST32_C(0x85A308D3)
#define CS2 UINT_LEAST32_C(0x13198A2E)
#define CS3 UINT_LEAST32_C(0x03707344)
#define CS4 UINT_LEAST32_C(0xA4093822)
#define CS5 UINT_LEAST32_C(0x299F31D0)
#define CS6 UINT_LEAST32_C(0x082EFA98)
#define CS7 UINT_LEAST32_C(0xEC4E6C89)
#define CS8 UINT_LEAST32_C(0x452821E6)
#define CS9 UINT_LEAST32_C(0x38D01377)
#define CSA UINT_LEAST32_C(0xBE5466CF)
#define CSB UINT_LEAST32_C(0x34E90C6C)
#define CSC UINT_LEAST32_C(0xC0AC29B7)
#define CSD UINT_LEAST32_C(0xC97C50DD)
#define CSE UINT_LEAST32_C(0x3F84D5B5)
#define CSF UINT_LEAST32_C(0xB5470917)

static uint_least32_t
decode_uint32_be(const unsigned char *data)
{
	return (((uint_least32_t)(data[0] & 255)) << 24) |
	       (((uint_least32_t)(data[1] & 255)) << 16) |
	       (((uint_least32_t)(data[2] & 255)) <<  8) |
	       (((uint_least32_t)(data[3] & 255)) <<  0);
}

static uint_least32_t
rotate_right(uint_least32_t x, int n)
{
	return ((x >> n) | (x << (32 - n))) & UINT_LEAST32_C(0xFFFFffff);
}

size_t
libblake_internal_blakes_update(struct libblake_blakes_state *state, const unsigned char *data, size_t len)
{
	size_t off = 0;
	struct libblake_blakes_state s;
	uint_least32_t v[16], m[16];

	memcpy(&s, state, sizeof(s));

	for (; len - off >= 64; off += 64, data = &data[64]) {
		s.t[0] = (s.t[0] + 512) & UINT_LEAST32_C(0xFFFFffff);
		if (s.t[0] < 512)
			s.t[1] = (s.t[1] + 1) & UINT_LEAST32_C(0xFFFFffff);

		memcpy(v, s.h, sizeof(s.h));
		v[8] = s.s[0] ^ CS0;
		v[9] = s.s[1] ^ CS1;
		v[A] = s.s[2] ^ CS2;
		v[B] = s.s[3] ^ CS3;
		v[C] = s.t[0] ^ CS4;
		v[D] = s.t[0] ^ CS5;
		v[E] = s.t[1] ^ CS6;
		v[F] = s.t[1] ^ CS7;

		m[0] = decode_uint32_be(&data[0 * 4]);
		m[1] = decode_uint32_be(&data[1 * 4]);
		m[2] = decode_uint32_be(&data[2 * 4]);
		m[3] = decode_uint32_be(&data[3 * 4]);
		m[4] = decode_uint32_be(&data[4 * 4]);
		m[5] = decode_uint32_be(&data[5 * 4]);
		m[6] = decode_uint32_be(&data[6 * 4]);
		m[7] = decode_uint32_be(&data[7 * 4]);
		m[8] = decode_uint32_be(&data[8 * 4]);
		m[9] = decode_uint32_be(&data[9 * 4]);
		m[A] = decode_uint32_be(&data[A * 4]);
		m[B] = decode_uint32_be(&data[B * 4]);
		m[C] = decode_uint32_be(&data[C * 4]);
		m[D] = decode_uint32_be(&data[D * 4]);
		m[E] = decode_uint32_be(&data[E * 4]);
		m[F] = decode_uint32_be(&data[F * 4]);

#define GS(mj, mk, nj, nk, a, b, c, d)\
		a = (a + b + (mj ^ nk)) & UINT_LEAST32_C(0xFFFFffff);\
		d = rotate_right(d ^ a, 16);\
		c = (c + d) & UINT_LEAST32_C(0xFFFFffff);\
		b = rotate_right(b ^ c, 12);\
		a = (a + b + (mk ^ nj)) & UINT_LEAST32_C(0xFFFFffff);\
		d = rotate_right(d ^ a, 8);\
		c = (c + d) & UINT_LEAST32_C(0xFFFFffff);\
		b = rotate_right(b ^ c, 7)

#define ROUNDS(S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, SA, SB, SC, SD, SE, SF)\
		GS(m[S0], m[S1], CS##S0, CS##S1, v[0], v[4], v[8], v[C]);\
		GS(m[S2], m[S3], CS##S2, CS##S3, v[1], v[5], v[9], v[D]);\
		GS(m[S4], m[S5], CS##S4, CS##S5, v[2], v[6], v[A], v[E]);\
		GS(m[S6], m[S7], CS##S6, CS##S7, v[3], v[7], v[B], v[F]);\
		GS(m[S8], m[S9], CS##S8, CS##S9, v[0], v[5], v[A], v[F]);\
		GS(m[SA], m[SB], CS##SA, CS##SB, v[1], v[6], v[B], v[C]);\
		GS(m[SC], m[SD], CS##SC, CS##SD, v[2], v[7], v[8], v[D]);\
		GS(m[SE], m[SF], CS##SE, CS##SF, v[3], v[4], v[9], v[E])

		ROUNDS(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F);
		ROUNDS(E, A, 4, 8, 9, F, D, 6, 1, C, 0, 2, B, 7, 5, 3);
		ROUNDS(B, 8, C, 0, 5, 2, F, D, A, E, 3, 6, 7, 1, 9, 4);
		ROUNDS(7, 9, 3, 1, D, C, B, E, 2, 6, 5, A, 4, 0, F, 8);
		ROUNDS(9, 0, 5, 7, 2, 4, A, F, E, 1, B, C, 6, 8, 3, D);
		ROUNDS(2, C, 6, A, 0, B, 8, 3, 4, D, 7, 5, F, E, 1, 9);
		ROUNDS(C, 5, 1, F, E, D, 4, A, 0, 7, 6, 3, 9, 2, 8, B);
		ROUNDS(D, B, 7, E, C, 1, 3, 9, 5, 0, F, 4, 8, 6, 2, A);
		ROUNDS(6, F, E, 9, B, 3, 0, 8, C, 2, D, 7, 1, 4, A, 5);
		ROUNDS(A, 2, 8, 4, 7, 6, 1, 5, F, B, 9, E, 3, C, D, 0);
		ROUNDS(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F);
		ROUNDS(E, A, 4, 8, 9, F, D, 6, 1, C, 0, 2, B, 7, 5, 3);
		ROUNDS(B, 8, C, 0, 5, 2, F, D, A, E, 3, 6, 7, 1, 9, 4);
		ROUNDS(7, 9, 3, 1, D, C, B, E, 2, 6, 5, A, 4, 0, F, 8);

		s.h[0] ^= s.s[0] ^ v[0] ^ v[8];
		s.h[1] ^= s.s[1] ^ v[1] ^ v[9];
		s.h[2] ^= s.s[2] ^ v[2] ^ v[A];
		s.h[3] ^= s.s[3] ^ v[3] ^ v[B];
		s.h[4] ^= s.s[0] ^ v[4] ^ v[C];
		s.h[5] ^= s.s[1] ^ v[5] ^ v[D];
		s.h[6] ^= s.s[2] ^ v[6] ^ v[E];
		s.h[7] ^= s.s[3] ^ v[7] ^ v[F];
	}

	memcpy(state, &s, sizeof(s));

	return off;
}