1 /* $NetBSD: blake2s.c,v 1.1 2020/08/20 21:21:05 riastradh 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.1 2020/08/20 21:21:05 riastradh 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 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 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 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 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 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 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 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 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 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_verbose("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