xref: /netbsd-src/sys/crypto/blake2/blake2s.c (revision 129a3690a1cfe72cb6f1e9597c867c8e7ed09a18)
1 /*	$NetBSD: blake2s.c,v 1.2 2021/10/17 14:45:45 jmcneill Exp $	*/
2 
3 /*-
4  * Copyright (c) 2015 Taylor R. Campbell
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #ifdef _KERNEL
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: blake2s.c,v 1.2 2021/10/17 14:45:45 jmcneill Exp $");
33 
34 #include <sys/types.h>
35 #include <sys/module.h>
36 
37 #include <lib/libkern/libkern.h>
38 
39 #else
40 
41 #define	_POSIX_C_SOURCE	200809L
42 
43 #include <assert.h>
44 #include <stdint.h>
45 #include <string.h>
46 
47 #endif
48 
49 #include "blake2s.h"
50 
51 #include <sys/endian.h>
52 
53 static inline uint32_t
rotr32(uint32_t x,unsigned c)54 rotr32(uint32_t x, unsigned c)
55 {
56 
57 	return ((x >> c) | (x << (32 - c)));
58 }
59 
60 #define	BLAKE2S_G(VA, VB, VC, VD, X, Y)	do				      \
61 {									      \
62 	(VA) = (VA) + (VB) + (X);					      \
63 	(VD) = rotr32((VD) ^ (VA), 16);					      \
64 	(VC) = (VC) + (VD);						      \
65 	(VB) = rotr32((VB) ^ (VC), 12);					      \
66 	(VA) = (VA) + (VB) + (Y);					      \
67 	(VD) = rotr32((VD) ^ (VA), 8);					      \
68 	(VC) = (VC) + (VD);						      \
69 	(VB) = rotr32((VB) ^ (VC), 7);					      \
70 } while (0)
71 
72 static const uint32_t blake2s_iv[8] = {
73 	0x6a09e667U, 0xbb67ae85U, 0x3c6ef372U, 0xa54ff53aU,
74 	0x510e527fU, 0x9b05688cU, 0x1f83d9abU, 0x5be0cd19U,
75 };
76 
77 static const uint8_t blake2s_sigma[10][16] = {
78 	{  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },
79 	{ 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 },
80 	{ 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 },
81 	{  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 },
82 	{  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 },
83 	{  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 },
84 	{ 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 },
85 	{ 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 },
86 	{  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 },
87 	{ 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0 },
88 };
89 
90 static void
blake2s_compress(uint32_t h[8],uint64_t c,uint32_t last,const uint8_t in[64])91 blake2s_compress(uint32_t h[8], uint64_t c, uint32_t last,
92     const uint8_t in[64])
93 {
94 	uint32_t v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15;
95 	uint32_t m[16];
96 	unsigned i;
97 
98 	/* Load the variables: first 8 from state, next 8 from IV.  */
99 	v0 = h[0];
100 	v1 = h[1];
101 	v2 = h[2];
102 	v3 = h[3];
103 	v4 = h[4];
104 	v5 = h[5];
105 	v6 = h[6];
106 	v7 = h[7];
107 	v8 = blake2s_iv[0];
108 	v9 = blake2s_iv[1];
109 	v10 = blake2s_iv[2];
110 	v11 = blake2s_iv[3];
111 	v12 = blake2s_iv[4];
112 	v13 = blake2s_iv[5];
113 	v14 = blake2s_iv[6];
114 	v15 = blake2s_iv[7];
115 
116 	/* Incorporate the block counter and whether this is last.  */
117 	v12 ^= c & 0xffffffffU;
118 	v13 ^= c >> 32;
119 	v14 ^= last;
120 
121 	/* Load the message block.  */
122 	for (i = 0; i < 16; i++)
123 		m[i] = le32dec(in + 4*i);
124 
125 	/* Transform the variables.  */
126 	for (i = 0; i < 10; i++) {
127 		const uint8_t *sigma = blake2s_sigma[i];
128 
129 		BLAKE2S_G(v0, v4,  v8, v12, m[sigma[ 0]], m[sigma[ 1]]);
130 		BLAKE2S_G(v1, v5,  v9, v13, m[sigma[ 2]], m[sigma[ 3]]);
131 		BLAKE2S_G(v2, v6, v10, v14, m[sigma[ 4]], m[sigma[ 5]]);
132 		BLAKE2S_G(v3, v7, v11, v15, m[sigma[ 6]], m[sigma[ 7]]);
133 		BLAKE2S_G(v0, v5, v10, v15, m[sigma[ 8]], m[sigma[ 9]]);
134 		BLAKE2S_G(v1, v6, v11, v12, m[sigma[10]], m[sigma[11]]);
135 		BLAKE2S_G(v2, v7,  v8, v13, m[sigma[12]], m[sigma[13]]);
136 		BLAKE2S_G(v3, v4,  v9, v14, m[sigma[14]], m[sigma[15]]);
137 	}
138 
139 	/* Update the state.  */
140 	h[0] ^= v0 ^ v8;
141 	h[1] ^= v1 ^ v9;
142 	h[2] ^= v2 ^ v10;
143 	h[3] ^= v3 ^ v11;
144 	h[4] ^= v4 ^ v12;
145 	h[5] ^= v5 ^ v13;
146 	h[6] ^= v6 ^ v14;
147 	h[7] ^= v7 ^ v15;
148 
149 	(void)explicit_memset(m, 0, sizeof m);
150 }
151 
152 void
blake2s_init(struct blake2s * B,size_t dlen,const void * key,size_t keylen)153 blake2s_init(struct blake2s *B, size_t dlen, const void *key, size_t keylen)
154 {
155 	uint32_t param0;
156 	unsigned i;
157 
158 	assert(0 < dlen);
159 	assert(dlen <= 32);
160 	assert(keylen <= 32);
161 
162 	/* Record the digest length.  */
163 	B->dlen = dlen;
164 
165 	/* Initialize the buffer.  */
166 	B->nb = 0;
167 
168 	/* Initialize the state.  */
169 	B->c = 0;
170 	for (i = 0; i < 8; i++)
171 		B->h[i] = blake2s_iv[i];
172 
173 	/*
174 	 * Set the parameters.  We support only variable digest and key
175 	 * lengths: no tree hashing, no salt, no personalization.
176 	 */
177 	param0 = 0;
178 	param0 |= (uint32_t)dlen << 0;
179 	param0 |= (uint32_t)keylen << 8;
180 	param0 |= (uint32_t)1 << 16; /* tree fanout = 1 */
181 	param0 |= (uint32_t)1 << 24; /* tree depth = 1 */
182 	B->h[0] ^= param0;
183 
184 	/* If there's a key, compress it as the first message block.  */
185 	if (keylen) {
186 		static const uint8_t zero_block[64];
187 
188 		blake2s_update(B, key, keylen);
189 		blake2s_update(B, zero_block, 64 - keylen);
190 	}
191 }
192 
193 void
blake2s_update(struct blake2s * B,const void * buf,size_t len)194 blake2s_update(struct blake2s *B, const void *buf, size_t len)
195 {
196 	const uint8_t *p = buf;
197 	size_t n = len;
198 
199 	/* Check the current state of the buffer.  */
200 	if (n <= 64u - B->nb) {
201 		/* Can at most exactly fill the buffer.  */
202 		(void)memcpy(&B->b[B->nb], p, n);
203 		B->nb += n;
204 		return;
205 	} else if (0 < B->nb) {
206 		/* Can fill the buffer and go on.  */
207 		(void)memcpy(&B->b[B->nb], p, 64 - B->nb);
208 		B->c += 64;
209 		blake2s_compress(B->h, B->c, 0, B->b);
210 		p += 64 - B->nb;
211 		n -= 64 - B->nb;
212 	}
213 
214 	/* At a block boundary.  Compress straight from the input.  */
215 	while (64 < n) {
216 		B->c += 64;
217 		blake2s_compress(B->h, B->c, 0, p);
218 		p += 64;
219 		n -= 64;
220 	}
221 
222 	/*
223 	 * Put whatever's left in the buffer.  We may fill the buffer,
224 	 * but we can't compress in that case until we know whether we
225 	 * are compressing the last block or not.
226 	 */
227 	(void)memcpy(B->b, p, n);
228 	B->nb = n;
229 }
230 
231 void
blake2s_final(struct blake2s * B,void * digest)232 blake2s_final(struct blake2s *B, void *digest)
233 {
234 	uint8_t *d = digest;
235 	unsigned dlen = B->dlen;
236 	unsigned i;
237 
238 	/* Pad with zeros, and do the last compression.  */
239 	B->c += B->nb;
240 	for (i = B->nb; i < 64; i++)
241 		B->b[i] = 0;
242 	blake2s_compress(B->h, B->c, ~(uint32_t)0, B->b);
243 
244 	/* Reveal the first dlen/4 words of the state.  */
245 	for (i = 0; i < dlen/4; i++)
246 		le32enc(d + 4*i, B->h[i]);
247 	d += 4*i;
248 	dlen -= 4*i;
249 
250 	/* If the caller wants a partial word, reveal that too.  */
251 	if (dlen) {
252 		uint32_t hi = B->h[i];
253 
254 		do {
255 			*d++ = hi;
256 			hi >>= 8;
257 		} while (--dlen);
258 	}
259 
260 	/* Erase the state.  */
261 	(void)explicit_memset(B, 0, sizeof B);
262 }
263 
264 void
blake2s(void * digest,size_t dlen,const void * key,size_t keylen,const void * in,size_t inlen)265 blake2s(void *digest, size_t dlen, const void *key, size_t keylen,
266     const void *in, size_t inlen)
267 {
268 	struct blake2s ctx;
269 
270 	blake2s_init(&ctx, dlen, key, keylen);
271 	blake2s_update(&ctx, in, inlen);
272 	blake2s_final(&ctx, digest);
273 }
274 
275 static void
blake2_selftest_prng(void * buf,size_t len,uint32_t seed)276 blake2_selftest_prng(void *buf, size_t len, uint32_t seed)
277 {
278 	uint8_t *p = buf;
279 	size_t n = len;
280 	uint32_t t, a, b;
281 
282 	a = 0xdead4bad * seed;
283 	b = 1;
284 
285 	while (n--) {
286 		t = a + b;
287 		*p++ = t >> 24;
288 		a = b;
289 		b = t;
290 	}
291 }
292 
293 int
blake2s_selftest(void)294 blake2s_selftest(void)
295 {
296 	const uint8_t d0[32] = {
297 		0x6a,0x41,0x1f,0x08,0xce,0x25,0xad,0xcd,
298 		0xfb,0x02,0xab,0xa6,0x41,0x45,0x1c,0xec,
299 		0x53,0xc5,0x98,0xb2,0x4f,0x4f,0xc7,0x87,
300 		0xfb,0xdc,0x88,0x79,0x7f,0x4c,0x1d,0xfe,
301 	};
302 	const unsigned dlen[4] = { 16, 20, 28, 32 };
303 	const unsigned mlen[6] = { 0, 3, 64, 65, 255, 1024 };
304 	uint8_t m[1024], d[32], k[32];
305 	struct blake2s ctx;
306 	unsigned di, mi, i;
307 
308 	blake2s_init(&ctx, 32, NULL, 0);
309 	for (di = 0; di < 4; di++) {
310 		for (mi = 0; mi < 6; mi++) {
311 			blake2_selftest_prng(m, mlen[mi], mlen[mi]);
312 			blake2s(d, dlen[di], NULL, 0, m, mlen[mi]);
313 			blake2s_update(&ctx, d, dlen[di]);
314 
315 			blake2_selftest_prng(k, dlen[di], dlen[di]);
316 			blake2s(d, dlen[di], k, dlen[di], m, mlen[mi]);
317 			blake2s_update(&ctx, d, dlen[di]);
318 		}
319 	}
320 	blake2s_final(&ctx, d);
321 	for (i = 0; i < 32; i++) {
322 		if (d[i] != d0[i])
323 			return -1;
324 	}
325 
326 	return 0;
327 }
328 
329 #ifdef _KERNEL
330 
331 MODULE(MODULE_CLASS_MISC, blake2s, NULL);
332 
333 static int
blake2s_modcmd(modcmd_t cmd,void * opaque)334 blake2s_modcmd(modcmd_t cmd, void *opaque)
335 {
336 
337 	switch (cmd) {
338 	case MODULE_CMD_INIT:
339 		if (blake2s_selftest())
340 			panic("blake2s: self-test failed");
341 		aprint_debug("blake2s: self-test passed\n");
342 		return 0;
343 	case MODULE_CMD_FINI:
344 		return 0;
345 	default:
346 		return ENOTTY;
347 	}
348 }
349 
350 #endif
351