diff options
Diffstat (limited to 'src/fids/blake2b.c')
-rw-r--r-- | src/fids/blake2b.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/fids/blake2b.c b/src/fids/blake2b.c new file mode 100644 index 000000000..ec7cf8602 --- /dev/null +++ b/src/fids/blake2b.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2022 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | /* A simple unkeyed BLAKE2b Implementation based on the official reference | ||
22 | * from https://github.com/BLAKE2/BLAKE2. | ||
23 | * | ||
24 | * The original code was released under CC0 1.0 Universal license (Creative Commons), | ||
25 | * a public domain license. | ||
26 | */ | ||
27 | |||
28 | #include "fids.h" | ||
29 | |||
30 | // little-endian vs big-endian is irrelevant since the checksum is calculated and checked on the same computer. | ||
31 | static inline uint64_t load64( const void *src ) { | ||
32 | uint64_t w; | ||
33 | memcpy( &w, src, sizeof( w ) ); | ||
34 | return w; | ||
35 | } | ||
36 | |||
37 | // mixing function | ||
38 | #define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y)))) | ||
39 | #define G(a, b, c, d, x, y) { \ | ||
40 | v[a] = v[a] + v[b] + x; \ | ||
41 | v[d] = ROTR64(v[d] ^ v[a], 32); \ | ||
42 | v[c] = v[c] + v[d]; \ | ||
43 | v[b] = ROTR64(v[b] ^ v[c], 24); \ | ||
44 | v[a] = v[a] + v[b] + y; \ | ||
45 | v[d] = ROTR64(v[d] ^ v[a], 16); \ | ||
46 | v[c] = v[c] + v[d]; \ | ||
47 | v[b] = ROTR64(v[b] ^ v[c], 63); } | ||
48 | |||
49 | // init vector | ||
50 | static const uint64_t iv[8] = { | ||
51 | 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, | ||
52 | 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, | ||
53 | 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, | ||
54 | 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 | ||
55 | }; | ||
56 | |||
57 | |||
58 | const uint8_t sigma[12][16] = { | ||
59 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||
60 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | ||
61 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, | ||
62 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, | ||
63 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, | ||
64 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, | ||
65 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, | ||
66 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, | ||
67 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, | ||
68 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, | ||
69 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||
70 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } | ||
71 | }; | ||
72 | |||
73 | // blake2b context | ||
74 | typedef struct { | ||
75 | uint8_t b[128]; // input buffer | ||
76 | uint64_t h[8]; // chained state | ||
77 | uint64_t t[2]; // total number of bytes | ||
78 | size_t c; // pointer for b[] | ||
79 | size_t outlen; // digest size | ||
80 | } CTX; | ||
81 | |||
82 | // compress function | ||
83 | static void compress(CTX *ctx, int last) { | ||
84 | uint64_t m[16]; | ||
85 | uint64_t v[16]; | ||
86 | size_t i; | ||
87 | |||
88 | for (i = 0; i < 16; i++) | ||
89 | m[i] = load64(&ctx->b[8 * i]); | ||
90 | |||
91 | for (i = 0; i < 8; i++) { | ||
92 | v[i] = ctx->h[i]; | ||
93 | v[i + 8] = iv[i]; | ||
94 | } | ||
95 | |||
96 | v[12] ^= ctx->t[0]; | ||
97 | v[13] ^= ctx->t[1]; | ||
98 | if (last) | ||
99 | v[14] = ~v[14]; | ||
100 | |||
101 | for (i = 0; i < 12; i++) { | ||
102 | G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); | ||
103 | G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); | ||
104 | G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); | ||
105 | G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); | ||
106 | G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); | ||
107 | G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); | ||
108 | G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); | ||
109 | G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); | ||
110 | } | ||
111 | |||
112 | for( i = 0; i < 8; ++i ) | ||
113 | ctx->h[i] ^= v[i] ^ v[i + 8]; | ||
114 | } | ||
115 | |||
116 | static int init(CTX *ctx, size_t outlen) { // (keylen=0: no key) | ||
117 | size_t i; | ||
118 | |||
119 | if (outlen == 0 || outlen > 64) | ||
120 | return -1; | ||
121 | |||
122 | for (i = 0; i < 8; i++) | ||
123 | ctx->h[i] = iv[i]; | ||
124 | ctx->h[0] ^= 0x01010000 ^ outlen; | ||
125 | |||
126 | ctx->t[0] = 0; | ||
127 | ctx->t[1] = 0; | ||
128 | ctx->c = 0; | ||
129 | ctx->outlen = outlen; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void update(CTX *ctx, const void *in, size_t inlen) { | ||
135 | size_t i; | ||
136 | |||
137 | for (i = 0; i < inlen; i++) { | ||
138 | if (ctx->c == 128) { | ||
139 | ctx->t[0] += ctx->c; | ||
140 | if (ctx->t[0] < ctx->c) | ||
141 | ctx->t[1]++; | ||
142 | compress(ctx, 0); | ||
143 | ctx->c = 0; | ||
144 | } | ||
145 | ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | static void final(CTX *ctx, void *out) { | ||
150 | size_t i; | ||
151 | |||
152 | ctx->t[0] += ctx->c; | ||
153 | if (ctx->t[0] < ctx->c) | ||
154 | ctx->t[1]++; | ||
155 | |||
156 | while (ctx->c < 128) | ||
157 | ctx->b[ctx->c++] = 0; | ||
158 | compress(ctx, 1); | ||
159 | |||
160 | for (i = 0; i < ctx->outlen; i++) { | ||
161 | ((uint8_t *) out)[i] = | ||
162 | (ctx->h[i >> 3] >> (8 * (i & 7))) & 0xFF; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | // public function | ||
167 | int blake2b(void *out, size_t outlen, const void *in, size_t inlen) { | ||
168 | CTX ctx; | ||
169 | |||
170 | if (init(&ctx, outlen)) | ||
171 | return -1; | ||
172 | update(&ctx, in, inlen); | ||
173 | final(&ctx, out); | ||
174 | |||
175 | return 0; | ||
176 | } | ||