1 /*-
2  * Copyright 2016 Vsevolod Stakhov
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /* Workaround for memset_s */
17 #ifdef __APPLE__
18 #define __STDC_WANT_LIB_EXT1__ 1
19 #include <string.h>
20 #endif
21 
22 #include "config.h"
23 #include "cryptobox.h"
24 #include "platform_config.h"
25 #include "chacha20/chacha.h"
26 #include "catena/catena.h"
27 #include "base64/base64.h"
28 #include "ottery.h"
29 #include "printf.h"
30 #define XXH_INLINE_ALL
31 #define XXH_PRIVATE_API
32 #include "xxhash.h"
33 #define MUM_TARGET_INDEPENDENT_HASH 1 /* For 32/64 bit equal hashes */
34 #include "../../contrib/mumhash/mum.h"
35 #include "../../contrib/t1ha/t1ha.h"
36 #ifdef HAVE_CPUID_H
37 #include <cpuid.h>
38 #endif
39 #ifdef HAVE_OPENSSL
40 #include <openssl/opensslv.h>
41 /* Openssl >= 1.0.1d is required for GCM verification */
42 #if OPENSSL_VERSION_NUMBER >= 0x1000104fL
43 #define HAVE_USABLE_OPENSSL 1
44 #endif
45 #endif
46 
47 #ifdef HAVE_USABLE_OPENSSL
48 #include <openssl/evp.h>
49 #include <openssl/ec.h>
50 #include <openssl/ecdh.h>
51 #include <openssl/ecdsa.h>
52 #include <openssl/rand.h>
53 #define CRYPTOBOX_CURVE_NID NID_X9_62_prime256v1
54 #endif
55 
56 #include <signal.h>
57 #include <setjmp.h>
58 #include <stdalign.h>
59 
60 #include <sodium.h>
61 
62 unsigned cpu_config = 0;
63 
64 static gboolean cryptobox_loaded = FALSE;
65 
66 static const guchar n0[16] = {0};
67 
68 #define CRYPTOBOX_ALIGNMENT   16
69 #define cryptobox_align_ptr(p, a)                                             \
70     (void *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
71 
72 static void
rspamd_cryptobox_cpuid(gint cpu[4],gint info)73 rspamd_cryptobox_cpuid (gint cpu[4], gint info)
74 {
75 	guint32 __attribute__ ((unused)) eax, __attribute__ ((unused)) ecx = 0, __attribute__ ((unused)) ebx = 0, __attribute__ ((unused)) edx = 0;
76 
77 	eax = info;
78 #if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
79 # if defined( __i386__ ) && defined ( __PIC__ )
80 
81 	/* in case of PIC under 32-bit EBX cannot be clobbered */
82 
83 	__asm__ volatile ("movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx),
84 			"+a" (eax), "+c" (ecx), "=d" (edx));
85 # else
86 	__asm__ volatile ("cpuid" : "+b" (ebx), "+a" (eax), "+c" (ecx), "=d" (edx));
87 # endif
88 
89 	cpu[0] = eax; cpu[1] = ebx; cpu[2] = ecx; cpu[3] = edx;
90 #else
91 	memset (cpu, 0, sizeof (gint) * 4);
92 #endif
93 }
94 
95 static sig_atomic_t ok = 0;
96 static jmp_buf j;
97 
98 __attribute__((noreturn))
99 static void
rspamd_cryptobox_ill_handler(int signo)100 rspamd_cryptobox_ill_handler (int signo)
101 {
102 	ok = 0;
103 	longjmp (j, -1);
104 }
105 
106 static gboolean
rspamd_cryptobox_test_instr(gint instr)107 rspamd_cryptobox_test_instr (gint instr)
108 {
109 	void (*old_handler) (int);
110 	guint32 rd;
111 
112 #if defined(__GNUC__)
113 	ok = 1;
114 	old_handler = signal (SIGILL, rspamd_cryptobox_ill_handler);
115 
116 	if (setjmp (j) != 0) {
117 		signal (SIGILL, old_handler);
118 
119 		return FALSE;
120 	}
121 
122 	switch (instr) {
123 #if defined HAVE_SSE2 && defined (__x86_64__)
124 	case CPUID_SSE2:
125 		__asm__ volatile ("psubb %xmm0, %xmm0");
126 		break;
127 	case CPUID_RDRAND:
128 		/* Use byte code here for compatibility */
129 		__asm__ volatile (".byte 0x0f,0xc7,0xf0; setc %1"
130 			: "=a" (rd), "=qm" (ok)
131 			:
132 			: "edx"
133 		);
134 		break;
135 #endif
136 #ifdef HAVE_SSE3
137 	case CPUID_SSE3:
138 		__asm__ volatile ("movshdup %xmm0, %xmm0");
139 		break;
140 #endif
141 #ifdef HAVE_SSSE3
142 	case CPUID_SSSE3:
143 		__asm__ volatile ("pshufb %xmm0, %xmm0");
144 		break;
145 #endif
146 #ifdef HAVE_SSE41
147 	case CPUID_SSE41:
148 		__asm__ volatile ("pcmpeqq %xmm0, %xmm0");
149 		break;
150 #endif
151 #if defined HAVE_SSE42 && defined(__x86_64__)
152 	case CPUID_SSE42:
153 		__asm__ volatile ("pushq %rax\n"
154 				"xorq %rax, %rax\n"
155 				"crc32 %rax, %rax\n"
156 				"popq %rax");
157 		break;
158 #endif
159 #ifdef HAVE_AVX
160 	case CPUID_AVX:
161 		__asm__ volatile ("vpaddq %xmm0, %xmm0, %xmm0");
162 		break;
163 #endif
164 #ifdef HAVE_AVX2
165 	case CPUID_AVX2:
166 		__asm__ volatile ("vpaddq %ymm0, %ymm0, %ymm0");\
167 		break;
168 #endif
169 	default:
170 		return FALSE;
171 		break;
172 	}
173 
174 	signal (SIGILL, old_handler);
175 #endif
176 
177 	(void)rd; /* Silence warning */
178 
179 	/* We actually never return here if SIGILL has been caught */
180 	return ok == 1;
181 }
182 
183 struct rspamd_cryptobox_library_ctx*
rspamd_cryptobox_init(void)184 rspamd_cryptobox_init (void)
185 {
186 	gint cpu[4], nid;
187 	const guint32 osxsave_mask = (1 << 27);
188 	const guint32 fma_movbe_osxsave_mask = ((1 << 12) | (1 << 22) | (1 << 27));
189 	const guint32 avx2_bmi12_mask = (1 << 5) | (1 << 3) | (1 << 8);
190 	gulong bit;
191 	static struct rspamd_cryptobox_library_ctx *ctx;
192 	GString *buf;
193 
194 	if (cryptobox_loaded) {
195 		/* Ignore reload attempts */
196 		return ctx;
197 	}
198 
199 	cryptobox_loaded = TRUE;
200 	ctx = g_malloc0 (sizeof (*ctx));
201 
202 	rspamd_cryptobox_cpuid (cpu, 0);
203 	nid = cpu[0];
204 	rspamd_cryptobox_cpuid (cpu, 1);
205 
206 	if (nid > 1) {
207 		if ((cpu[3] & ((guint32)1 << 26))) {
208 			if (rspamd_cryptobox_test_instr (CPUID_SSE2)) {
209 				cpu_config |= CPUID_SSE2;
210 			}
211 		}
212 		if ((cpu[2] & ((guint32)1 << 0))) {
213 			if (rspamd_cryptobox_test_instr (CPUID_SSE3)) {
214 				cpu_config |= CPUID_SSE3;
215 			}
216 		}
217 		if ((cpu[2] & ((guint32)1 << 9))) {
218 			if (rspamd_cryptobox_test_instr (CPUID_SSSE3)) {
219 				cpu_config |= CPUID_SSSE3;
220 			}
221 		}
222 		if ((cpu[2] & ((guint32)1 << 19))) {
223 			if (rspamd_cryptobox_test_instr (CPUID_SSE41)) {
224 				cpu_config |= CPUID_SSE41;
225 			}
226 		}
227 		if ((cpu[2] & ((guint32)1 << 20))) {
228 			if (rspamd_cryptobox_test_instr (CPUID_SSE42)) {
229 				cpu_config |= CPUID_SSE42;
230 			}
231 		}
232 		if ((cpu[2] & ((guint32)1 << 30))) {
233 			if (rspamd_cryptobox_test_instr (CPUID_RDRAND)) {
234 				cpu_config |= CPUID_RDRAND;
235 			}
236 		}
237 
238 		/* OSXSAVE */
239 		if ((cpu[2] & osxsave_mask) == osxsave_mask) {
240 			if ((cpu[2] & ((guint32)1 << 28))) {
241 				if (rspamd_cryptobox_test_instr (CPUID_AVX)) {
242 					cpu_config |= CPUID_AVX;
243 				}
244 			}
245 
246 			if (nid >= 7 &&
247 					(cpu[2] & fma_movbe_osxsave_mask) == fma_movbe_osxsave_mask) {
248 				rspamd_cryptobox_cpuid (cpu, 7);
249 
250 				if ((cpu[1] & avx2_bmi12_mask) == avx2_bmi12_mask) {
251 					if (rspamd_cryptobox_test_instr (CPUID_AVX2)) {
252 						cpu_config |= CPUID_AVX2;
253 					}
254 				}
255 			}
256 		}
257 	}
258 
259 	buf = g_string_new ("");
260 
261 	for (bit = 0x1; bit != 0; bit <<= 1) {
262 		if (cpu_config & bit) {
263 			switch (bit) {
264 			case CPUID_SSE2:
265 				rspamd_printf_gstring (buf, "sse2, ");
266 				break;
267 			case CPUID_SSE3:
268 				rspamd_printf_gstring (buf, "sse3, ");
269 				break;
270 			case CPUID_SSSE3:
271 				rspamd_printf_gstring (buf, "ssse3, ");
272 				break;
273 			case CPUID_SSE41:
274 				rspamd_printf_gstring (buf, "sse4.1, ");
275 				break;
276 			case CPUID_SSE42:
277 				rspamd_printf_gstring (buf, "sse4.2, ");
278 				break;
279 			case CPUID_AVX:
280 				rspamd_printf_gstring (buf, "avx, ");
281 				break;
282 			case CPUID_AVX2:
283 				rspamd_printf_gstring (buf, "avx2, ");
284 				break;
285 			case CPUID_RDRAND:
286 				rspamd_printf_gstring (buf, "rdrand, ");
287 				break;
288 			default:
289 				break; /* Silence warning */
290 			}
291 		}
292 	}
293 
294 	if (buf->len > 2) {
295 		/* Trim last chars */
296 		g_string_erase (buf, buf->len - 2, 2);
297 	}
298 
299 	ctx->cpu_extensions = buf->str;
300 	g_string_free (buf, FALSE);
301 	ctx->cpu_config = cpu_config;
302 	g_assert (sodium_init () != -1);
303 
304 	ctx->chacha20_impl = chacha_load ();
305 	ctx->base64_impl = base64_load ();
306 #if defined(HAVE_USABLE_OPENSSL) && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER))
307 	/* Needed for old openssl api, not sure about LibreSSL */
308 	ERR_load_EC_strings ();
309 	ERR_load_RAND_strings ();
310 	ERR_load_EVP_strings ();
311 #endif
312 
313 	return ctx;
314 }
315 
316 void
rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx * ctx)317 rspamd_cryptobox_deinit (struct rspamd_cryptobox_library_ctx *ctx)
318 {
319 	if (ctx) {
320 		g_free (ctx->cpu_extensions);
321 		g_free (ctx);
322 	}
323 }
324 
325 void
rspamd_cryptobox_keypair(rspamd_pk_t pk,rspamd_sk_t sk,enum rspamd_cryptobox_mode mode)326 rspamd_cryptobox_keypair (rspamd_pk_t pk, rspamd_sk_t sk,
327 		enum rspamd_cryptobox_mode mode)
328 {
329 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
330 		ottery_rand_bytes (sk, rspamd_cryptobox_MAX_SKBYTES);
331 		sk[0] &= 248;
332 		sk[31] &= 127;
333 		sk[31] |= 64;
334 
335 		crypto_scalarmult_base (pk, sk);
336 	}
337 	else {
338 #ifndef HAVE_USABLE_OPENSSL
339 		g_assert (0);
340 #else
341 		EC_KEY *ec_sec;
342 		const BIGNUM *bn_sec;
343 		BIGNUM *bn_pub;
344 		const EC_POINT *ec_pub;
345 		gint len;
346 
347 		ec_sec = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
348 		g_assert (ec_sec != NULL);
349 		g_assert (EC_KEY_generate_key (ec_sec) != 0);
350 
351 		bn_sec = EC_KEY_get0_private_key (ec_sec);
352 		g_assert (bn_sec != NULL);
353 		ec_pub = EC_KEY_get0_public_key (ec_sec);
354 		g_assert (ec_pub != NULL);
355 		bn_pub = EC_POINT_point2bn (EC_KEY_get0_group (ec_sec),
356 				ec_pub, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
357 
358 		len = BN_num_bytes (bn_sec);
359 		g_assert (len <= (gint)sizeof (rspamd_sk_t));
360 		BN_bn2bin (bn_sec, sk);
361 		len = BN_num_bytes (bn_pub);
362 		g_assert (len <= (gint)rspamd_cryptobox_pk_bytes (mode));
363 		BN_bn2bin (bn_pub, pk);
364 		BN_free (bn_pub);
365 		EC_KEY_free (ec_sec);
366 #endif
367 	}
368 }
369 
370 void
rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk,rspamd_sig_sk_t sk,enum rspamd_cryptobox_mode mode)371 rspamd_cryptobox_keypair_sig (rspamd_sig_pk_t pk, rspamd_sig_sk_t sk,
372 		enum rspamd_cryptobox_mode mode)
373 {
374 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
375 		crypto_sign_keypair (pk, sk);
376 	}
377 	else {
378 #ifndef HAVE_USABLE_OPENSSL
379 		g_assert (0);
380 #else
381 		EC_KEY *ec_sec;
382 		const BIGNUM *bn_sec;
383 		BIGNUM *bn_pub;
384 		const EC_POINT *ec_pub;
385 		gint len;
386 
387 		ec_sec = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
388 		g_assert (ec_sec != NULL);
389 		g_assert (EC_KEY_generate_key (ec_sec) != 0);
390 
391 		bn_sec = EC_KEY_get0_private_key (ec_sec);
392 		g_assert (bn_sec != NULL);
393 		ec_pub = EC_KEY_get0_public_key (ec_sec);
394 		g_assert (ec_pub != NULL);
395 		bn_pub = EC_POINT_point2bn (EC_KEY_get0_group (ec_sec),
396 				ec_pub, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
397 
398 		len = BN_num_bytes (bn_sec);
399 		g_assert (len <= (gint)sizeof (rspamd_sk_t));
400 		BN_bn2bin (bn_sec, sk);
401 		len = BN_num_bytes (bn_pub);
402 		g_assert (len <= (gint)rspamd_cryptobox_pk_bytes (mode));
403 		BN_bn2bin (bn_pub, pk);
404 		BN_free (bn_pub);
405 		EC_KEY_free (ec_sec);
406 #endif
407 	}
408 }
409 
410 void
rspamd_cryptobox_nm(rspamd_nm_t nm,const rspamd_pk_t pk,const rspamd_sk_t sk,enum rspamd_cryptobox_mode mode)411 rspamd_cryptobox_nm (rspamd_nm_t nm,
412 		const rspamd_pk_t pk, const rspamd_sk_t sk,
413 		enum rspamd_cryptobox_mode mode)
414 {
415 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
416 		guchar s[32];
417 		guchar e[32];
418 
419 		memcpy (e, sk, 32);
420 		e[0] &= 248;
421 		e[31] &= 127;
422 		e[31] |= 64;
423 
424 		if (crypto_scalarmult (s, e, pk) != -1) {
425 			hchacha (s, n0, nm, 20);
426 		}
427 
428 		rspamd_explicit_memzero (e, 32);
429 	}
430 	else {
431 #ifndef HAVE_USABLE_OPENSSL
432 		g_assert (0);
433 #else
434 		EC_KEY *lk;
435 		EC_POINT *ec_pub;
436 		BIGNUM *bn_pub, *bn_sec;
437 		gint len;
438 		guchar s[32];
439 
440 		lk = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
441 		g_assert (lk != NULL);
442 
443 		bn_pub = BN_bin2bn (pk, rspamd_cryptobox_pk_bytes (mode), NULL);
444 		g_assert (bn_pub != NULL);
445 		bn_sec = BN_bin2bn (sk, sizeof (rspamd_sk_t), NULL);
446 		g_assert (bn_sec != NULL);
447 
448 		g_assert (EC_KEY_set_private_key (lk, bn_sec) == 1);
449 		ec_pub = EC_POINT_bn2point (EC_KEY_get0_group (lk), bn_pub, NULL, NULL);
450 		g_assert (ec_pub != NULL);
451 		len = ECDH_compute_key (s, sizeof (s), ec_pub, lk, NULL);
452 		g_assert (len == sizeof (s));
453 
454 		/* Still do hchacha iteration since we are not using SHA1 KDF */
455 		hchacha (s, n0, nm, 20);
456 
457 		EC_KEY_free (lk);
458 		EC_POINT_free (ec_pub);
459 		BN_free (bn_sec);
460 		BN_free (bn_pub);
461 #endif
462 	}
463 }
464 
465 void
rspamd_cryptobox_sign(guchar * sig,unsigned long long * siglen_p,const guchar * m,gsize mlen,const rspamd_sk_t sk,enum rspamd_cryptobox_mode mode)466 rspamd_cryptobox_sign (guchar *sig, unsigned long long *siglen_p,
467 		const guchar *m, gsize mlen,
468 		const rspamd_sk_t sk,
469 		enum rspamd_cryptobox_mode mode)
470 {
471 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
472 		crypto_sign_detached (sig, siglen_p, m, mlen, sk);
473 	}
474 	else {
475 #ifndef HAVE_USABLE_OPENSSL
476 		g_assert (0);
477 #else
478 		EC_KEY *lk;
479 		BIGNUM *bn_sec, *kinv = NULL, *rp = NULL;
480 		EVP_MD_CTX *sha_ctx;
481 		unsigned char h[64];
482 		guint diglen = rspamd_cryptobox_signature_bytes (mode);
483 
484 		/* Prehash */
485 		sha_ctx = EVP_MD_CTX_create ();
486 		g_assert (EVP_DigestInit (sha_ctx, EVP_sha512()) == 1);
487 		EVP_DigestUpdate (sha_ctx, m, mlen);
488 		EVP_DigestFinal (sha_ctx, h, NULL);
489 
490 		/* Key setup */
491 		lk = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
492 		g_assert (lk != NULL);
493 		bn_sec = BN_bin2bn (sk, sizeof (rspamd_sk_t), NULL);
494 		g_assert (bn_sec != NULL);
495 		g_assert (EC_KEY_set_private_key (lk, bn_sec) == 1);
496 
497 		/* ECDSA */
498 		g_assert (ECDSA_sign_setup (lk, NULL, &kinv, &rp) == 1);
499 		g_assert (ECDSA_sign_ex (0, h, sizeof (h), sig,
500 				&diglen, kinv, rp, lk) == 1);
501 		g_assert (diglen <= sizeof (rspamd_signature_t));
502 
503 		if (siglen_p) {
504 			*siglen_p = diglen;
505 		}
506 
507 		EC_KEY_free (lk);
508 		EVP_MD_CTX_destroy (sha_ctx);
509 		BN_free (bn_sec);
510 		BN_free (kinv);
511 		BN_free (rp);
512 
513 #endif
514 	}
515 }
516 
517 bool
rspamd_cryptobox_verify(const guchar * sig,gsize siglen,const guchar * m,gsize mlen,const rspamd_pk_t pk,enum rspamd_cryptobox_mode mode)518 rspamd_cryptobox_verify (const guchar *sig,
519 		gsize siglen,
520 		const guchar *m,
521 		gsize mlen,
522 		const rspamd_pk_t pk,
523 		enum rspamd_cryptobox_mode mode)
524 {
525 	bool ret = false;
526 
527 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
528 		if (siglen == rspamd_cryptobox_signature_bytes (RSPAMD_CRYPTOBOX_MODE_25519)) {
529 			ret = (crypto_sign_verify_detached (sig, m, mlen, pk) == 0);
530 		}
531 	}
532 	else {
533 #ifndef HAVE_USABLE_OPENSSL
534 		g_assert (0);
535 #else
536 		EC_KEY *lk;
537 		EC_POINT *ec_pub;
538 		BIGNUM *bn_pub;
539 		EVP_MD_CTX *sha_ctx;
540 		unsigned char h[64];
541 
542 		/* Prehash */
543 		sha_ctx = EVP_MD_CTX_create ();
544 		g_assert (EVP_DigestInit (sha_ctx, EVP_sha512()) == 1);
545 		EVP_DigestUpdate (sha_ctx, m, mlen);
546 		EVP_DigestFinal (sha_ctx, h, NULL);
547 
548 		/* Key setup */
549 		lk = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
550 		g_assert (lk != NULL);
551 		bn_pub = BN_bin2bn (pk, rspamd_cryptobox_pk_bytes (mode), NULL);
552 		g_assert (bn_pub != NULL);
553 		ec_pub = EC_POINT_bn2point (EC_KEY_get0_group (lk), bn_pub, NULL, NULL);
554 		g_assert (ec_pub != NULL);
555 		g_assert (EC_KEY_set_public_key (lk, ec_pub) == 1);
556 
557 		/* ECDSA */
558 		ret = ECDSA_verify (0, h, sizeof (h), sig, siglen, lk) == 1;
559 
560 		EC_KEY_free (lk);
561 		EVP_MD_CTX_destroy (sha_ctx);
562 		BN_free (bn_pub);
563 		EC_POINT_free (ec_pub);
564 #endif
565 	}
566 
567 	return ret;
568 }
569 
570 static gsize
rspamd_cryptobox_encrypt_ctx_len(enum rspamd_cryptobox_mode mode)571 rspamd_cryptobox_encrypt_ctx_len (enum rspamd_cryptobox_mode mode)
572 {
573 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
574 		return sizeof (chacha_state) + CRYPTOBOX_ALIGNMENT;
575 	}
576 	else {
577 #ifndef HAVE_USABLE_OPENSSL
578 		g_assert (0);
579 #else
580 		return sizeof (EVP_CIPHER_CTX *) + CRYPTOBOX_ALIGNMENT;
581 #endif
582 	}
583 
584 	return 0;
585 }
586 
587 static gsize
rspamd_cryptobox_auth_ctx_len(enum rspamd_cryptobox_mode mode)588 rspamd_cryptobox_auth_ctx_len (enum rspamd_cryptobox_mode mode)
589 {
590 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
591 		return sizeof (crypto_onetimeauth_state) + RSPAMD_ALIGNOF(crypto_onetimeauth_state);
592 	}
593 	else {
594 #ifndef HAVE_USABLE_OPENSSL
595 		g_assert (0);
596 #else
597 		return sizeof (void *);
598 #endif
599 	}
600 
601 	return 0;
602 }
603 
604 static void *
rspamd_cryptobox_encrypt_init(void * enc_ctx,const rspamd_nonce_t nonce,const rspamd_nm_t nm,enum rspamd_cryptobox_mode mode)605 rspamd_cryptobox_encrypt_init (void *enc_ctx, const rspamd_nonce_t nonce,
606 		const rspamd_nm_t nm,
607 		enum rspamd_cryptobox_mode mode)
608 {
609 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
610 		chacha_state *s;
611 
612 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
613 		xchacha_init (s,
614 				(const chacha_key *) nm,
615 				(const chacha_iv24 *) nonce,
616 				20);
617 
618 		return s;
619 	}
620 	else {
621 #ifndef HAVE_USABLE_OPENSSL
622 		g_assert (0);
623 #else
624 		EVP_CIPHER_CTX **s;
625 
626 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
627 		memset (s, 0, sizeof (*s));
628 		*s = EVP_CIPHER_CTX_new ();
629 		g_assert (EVP_EncryptInit_ex (*s, EVP_aes_256_gcm (), NULL, NULL, NULL) == 1);
630 		g_assert (EVP_CIPHER_CTX_ctrl (*s, EVP_CTRL_GCM_SET_IVLEN,
631 				rspamd_cryptobox_nonce_bytes (mode), NULL) == 1);
632 		g_assert (EVP_EncryptInit_ex (*s, NULL, NULL, nm, nonce) == 1);
633 
634 		return s;
635 #endif
636 	}
637 
638 	return NULL;
639 }
640 
641 static void *
rspamd_cryptobox_auth_init(void * auth_ctx,void * enc_ctx,enum rspamd_cryptobox_mode mode)642 rspamd_cryptobox_auth_init (void *auth_ctx, void *enc_ctx,
643 		enum rspamd_cryptobox_mode mode)
644 {
645 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
646 		crypto_onetimeauth_state *mac_ctx;
647 		guchar RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
648 
649 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
650 		memset (subkey, 0, sizeof (subkey));
651 		chacha_update (enc_ctx, subkey, subkey, sizeof (subkey));
652 		crypto_onetimeauth_init (mac_ctx, subkey);
653 		rspamd_explicit_memzero (subkey, sizeof (subkey));
654 
655 		return mac_ctx;
656 	}
657 	else {
658 #ifndef HAVE_USABLE_OPENSSL
659 		g_assert (0);
660 #else
661 		auth_ctx = enc_ctx;
662 
663 		return auth_ctx;
664 #endif
665 	}
666 
667 	return NULL;
668 }
669 
670 static gboolean
rspamd_cryptobox_encrypt_update(void * enc_ctx,const guchar * in,gsize inlen,guchar * out,gsize * outlen,enum rspamd_cryptobox_mode mode)671 rspamd_cryptobox_encrypt_update (void *enc_ctx, const guchar *in, gsize inlen,
672 		guchar *out, gsize *outlen,
673 		enum rspamd_cryptobox_mode mode)
674 {
675 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
676 		gsize r;
677 		chacha_state *s;
678 
679 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
680 
681 		r = chacha_update (s, in, out, inlen);
682 
683 		if (outlen != NULL) {
684 			*outlen = r;
685 		}
686 
687 		return TRUE;
688 	}
689 	else {
690 #ifndef HAVE_USABLE_OPENSSL
691 		g_assert (0);
692 #else
693 		EVP_CIPHER_CTX **s = enc_ctx;
694 		gint r;
695 
696 		r = inlen;
697 		g_assert (EVP_EncryptUpdate (*s, out, &r, in, inlen) == 1);
698 
699 		if (outlen) {
700 			*outlen = r;
701 		}
702 
703 		return TRUE;
704 #endif
705 	}
706 
707 	return FALSE;
708 }
709 
710 static gboolean
rspamd_cryptobox_auth_update(void * auth_ctx,const guchar * in,gsize inlen,enum rspamd_cryptobox_mode mode)711 rspamd_cryptobox_auth_update (void *auth_ctx, const guchar *in, gsize inlen,
712 		enum rspamd_cryptobox_mode mode)
713 {
714 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
715 		crypto_onetimeauth_state *mac_ctx;
716 
717 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
718 		crypto_onetimeauth_update (mac_ctx, in, inlen);
719 
720 		return TRUE;
721 	}
722 	else {
723 #ifndef HAVE_USABLE_OPENSSL
724 		g_assert (0);
725 #else
726 		return TRUE;
727 #endif
728 	}
729 
730 	return FALSE;
731 }
732 
733 static gsize
rspamd_cryptobox_encrypt_final(void * enc_ctx,guchar * out,gsize remain,enum rspamd_cryptobox_mode mode)734 rspamd_cryptobox_encrypt_final (void *enc_ctx, guchar *out, gsize remain,
735 		enum rspamd_cryptobox_mode mode)
736 {
737 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
738 		chacha_state *s;
739 
740 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
741 		return chacha_final (s, out);
742 	}
743 	else {
744 #ifndef HAVE_USABLE_OPENSSL
745 		g_assert (0);
746 #else
747 		EVP_CIPHER_CTX **s = enc_ctx;
748 		gint r = remain;
749 
750 		g_assert (EVP_EncryptFinal_ex (*s, out, &r) == 1);
751 
752 		return r;
753 #endif
754 	}
755 
756 	return 0;
757 }
758 
759 static gboolean
rspamd_cryptobox_auth_final(void * auth_ctx,rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)760 rspamd_cryptobox_auth_final (void *auth_ctx, rspamd_mac_t sig,
761 		enum rspamd_cryptobox_mode mode)
762 {
763 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
764 		crypto_onetimeauth_state *mac_ctx;
765 
766 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
767 		crypto_onetimeauth_final (mac_ctx, sig);
768 
769 		return TRUE;
770 	}
771 	else {
772 #ifndef HAVE_USABLE_OPENSSL
773 		g_assert (0);
774 #else
775 		EVP_CIPHER_CTX **s = auth_ctx;
776 
777 		g_assert (EVP_CIPHER_CTX_ctrl (*s, EVP_CTRL_GCM_GET_TAG,
778 				sizeof (rspamd_mac_t), sig) == 1);
779 
780 		return TRUE;
781 #endif
782 	}
783 
784 	return FALSE;
785 }
786 
787 static void *
rspamd_cryptobox_decrypt_init(void * enc_ctx,const rspamd_nonce_t nonce,const rspamd_nm_t nm,enum rspamd_cryptobox_mode mode)788 rspamd_cryptobox_decrypt_init (void *enc_ctx, const rspamd_nonce_t nonce,
789 		const rspamd_nm_t nm,
790 		enum rspamd_cryptobox_mode mode)
791 {
792 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
793 
794 		chacha_state *s;
795 
796 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
797 		xchacha_init (s,
798 				(const chacha_key *) nm,
799 				(const chacha_iv24 *) nonce,
800 				20);
801 
802 		return s;
803 	}
804 	else {
805 #ifndef HAVE_USABLE_OPENSSL
806 		g_assert (0);
807 #else
808 		EVP_CIPHER_CTX **s;
809 
810 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
811 		memset (s, 0, sizeof (*s));
812 		*s = EVP_CIPHER_CTX_new ();
813 		g_assert (EVP_DecryptInit_ex(*s, EVP_aes_256_gcm (), NULL, NULL, NULL) == 1);
814 		g_assert (EVP_CIPHER_CTX_ctrl (*s, EVP_CTRL_GCM_SET_IVLEN,
815 				rspamd_cryptobox_nonce_bytes (mode), NULL) == 1);
816 		g_assert (EVP_DecryptInit_ex (*s, NULL, NULL, nm, nonce) == 1);
817 
818 		return s;
819 #endif
820 	}
821 
822 	return NULL;
823 }
824 
825 static void *
rspamd_cryptobox_auth_verify_init(void * auth_ctx,void * enc_ctx,enum rspamd_cryptobox_mode mode)826 rspamd_cryptobox_auth_verify_init (void *auth_ctx, void *enc_ctx,
827 		enum rspamd_cryptobox_mode mode)
828 {
829 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
830 		crypto_onetimeauth_state *mac_ctx;
831 		guchar RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES];
832 
833 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
834 		memset (subkey, 0, sizeof (subkey));
835 		chacha_update (enc_ctx, subkey, subkey, sizeof (subkey));
836 		crypto_onetimeauth_init (mac_ctx, subkey);
837 		rspamd_explicit_memzero (subkey, sizeof (subkey));
838 
839 		return mac_ctx;
840 	}
841 	else {
842 #ifndef HAVE_USABLE_OPENSSL
843 		g_assert (0);
844 #else
845 		auth_ctx = enc_ctx;
846 
847 		return auth_ctx;
848 #endif
849 	}
850 
851 	return NULL;
852 }
853 
854 static gboolean
rspamd_cryptobox_decrypt_update(void * enc_ctx,const guchar * in,gsize inlen,guchar * out,gsize * outlen,enum rspamd_cryptobox_mode mode)855 rspamd_cryptobox_decrypt_update (void *enc_ctx, const guchar *in, gsize inlen,
856 		guchar *out, gsize *outlen,
857 		enum rspamd_cryptobox_mode mode)
858 {
859 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
860 		gsize r;
861 		chacha_state *s;
862 
863 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
864 		r = chacha_update (s, in, out, inlen);
865 
866 		if (outlen != NULL) {
867 			*outlen = r;
868 		}
869 
870 		return TRUE;
871 	}
872 	else {
873 #ifndef HAVE_USABLE_OPENSSL
874 		g_assert (0);
875 #else
876 		EVP_CIPHER_CTX **s = enc_ctx;
877 		gint r;
878 
879 		r = outlen ? *outlen : inlen;
880 		g_assert (EVP_DecryptUpdate (*s, out, &r, in, inlen) == 1);
881 
882 		if (outlen) {
883 			*outlen = r;
884 		}
885 
886 		return TRUE;
887 #endif
888 	}
889 }
890 
891 static gboolean
rspamd_cryptobox_auth_verify_update(void * auth_ctx,const guchar * in,gsize inlen,enum rspamd_cryptobox_mode mode)892 rspamd_cryptobox_auth_verify_update (void *auth_ctx,
893 		const guchar *in, gsize inlen,
894 		enum rspamd_cryptobox_mode mode)
895 {
896 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
897 		crypto_onetimeauth_state *mac_ctx;
898 
899 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
900 		crypto_onetimeauth_update (mac_ctx, in, inlen);
901 
902 		return TRUE;
903 	}
904 	else {
905 #ifndef HAVE_USABLE_OPENSSL
906 		/* We do not need to authenticate as a separate process */
907 		return TRUE;
908 #else
909 #endif
910 	}
911 
912 	return FALSE;
913 }
914 
915 static gboolean
rspamd_cryptobox_decrypt_final(void * enc_ctx,guchar * out,gsize remain,enum rspamd_cryptobox_mode mode)916 rspamd_cryptobox_decrypt_final (void *enc_ctx, guchar *out, gsize remain,
917 		enum rspamd_cryptobox_mode mode)
918 {
919 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
920 		chacha_state *s;
921 
922 		s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT);
923 		chacha_final (s, out);
924 
925 		return TRUE;
926 	}
927 	else {
928 #ifndef HAVE_USABLE_OPENSSL
929 		g_assert (0);
930 #else
931 		EVP_CIPHER_CTX **s = enc_ctx;
932 		gint r = remain;
933 
934 		if (EVP_DecryptFinal_ex (*s, out, &r) < 0) {
935 			return FALSE;
936 		}
937 
938 		return TRUE;
939 #endif
940 	}
941 
942 	return FALSE;
943 }
944 
945 static gboolean
rspamd_cryptobox_auth_verify_final(void * auth_ctx,const rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)946 rspamd_cryptobox_auth_verify_final (void *auth_ctx, const rspamd_mac_t sig,
947 		enum rspamd_cryptobox_mode mode)
948 {
949 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
950 		rspamd_mac_t mac;
951 		crypto_onetimeauth_state *mac_ctx;
952 
953 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
954 		crypto_onetimeauth_final (mac_ctx, mac);
955 
956 		if (crypto_verify_16 (mac, sig) != 0) {
957 			return FALSE;
958 		}
959 
960 		return TRUE;
961 	}
962 	else {
963 #ifndef HAVE_USABLE_OPENSSL
964 		g_assert (0);
965 #else
966 		EVP_CIPHER_CTX **s = auth_ctx;
967 
968 		if (EVP_CIPHER_CTX_ctrl (*s, EVP_CTRL_GCM_SET_TAG, 16, (guchar *)sig) != 1) {
969 			return FALSE;
970 		}
971 
972 		return TRUE;
973 #endif
974 	}
975 
976 	return FALSE;
977 }
978 
979 
980 static void
rspamd_cryptobox_cleanup(void * enc_ctx,void * auth_ctx,enum rspamd_cryptobox_mode mode)981 rspamd_cryptobox_cleanup (void *enc_ctx, void *auth_ctx,
982 		enum rspamd_cryptobox_mode mode)
983 {
984 	if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
985 		crypto_onetimeauth_state *mac_ctx;
986 
987 		mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT);
988 		rspamd_explicit_memzero (mac_ctx, sizeof (*mac_ctx));
989 	}
990 	else {
991 #ifndef HAVE_USABLE_OPENSSL
992 		g_assert (0);
993 #else
994 		EVP_CIPHER_CTX **s = enc_ctx;
995 
996 		EVP_CIPHER_CTX_cleanup (*s);
997 		EVP_CIPHER_CTX_free (*s);
998 #endif
999 	}
1000 }
1001 
rspamd_cryptobox_encrypt_nm_inplace(guchar * data,gsize len,const rspamd_nonce_t nonce,const rspamd_nm_t nm,rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1002 void rspamd_cryptobox_encrypt_nm_inplace (guchar *data, gsize len,
1003 		const rspamd_nonce_t nonce,
1004 		const rspamd_nm_t nm,
1005 		rspamd_mac_t sig,
1006 		enum rspamd_cryptobox_mode mode)
1007 {
1008 	gsize r;
1009 	void *enc_ctx, *auth_ctx;
1010 
1011 	enc_ctx = g_alloca (rspamd_cryptobox_encrypt_ctx_len (mode));
1012 	auth_ctx = g_alloca (rspamd_cryptobox_auth_ctx_len (mode));
1013 
1014 	enc_ctx = rspamd_cryptobox_encrypt_init (enc_ctx, nonce, nm, mode);
1015 	auth_ctx = rspamd_cryptobox_auth_init (auth_ctx, enc_ctx, mode);
1016 
1017 	rspamd_cryptobox_encrypt_update (enc_ctx, data, len, data, &r, mode);
1018 	rspamd_cryptobox_encrypt_final (enc_ctx, data + r, len - r, mode);
1019 
1020 	rspamd_cryptobox_auth_update (auth_ctx, data, len, mode);
1021 	rspamd_cryptobox_auth_final (auth_ctx, sig, mode);
1022 
1023 	rspamd_cryptobox_cleanup (enc_ctx, auth_ctx, mode);
1024 }
1025 
1026 static void
rspamd_cryptobox_flush_outbuf(struct rspamd_cryptobox_segment * st,const guchar * buf,gsize len,gsize offset)1027 rspamd_cryptobox_flush_outbuf (struct rspamd_cryptobox_segment *st,
1028 		const guchar *buf, gsize len, gsize offset)
1029 {
1030 	gsize cpy_len;
1031 
1032 	while (len > 0) {
1033 		cpy_len = MIN (len, st->len - offset);
1034 		memcpy (st->data + offset, buf, cpy_len);
1035 		st ++;
1036 		buf += cpy_len;
1037 		len -= cpy_len;
1038 		offset = 0;
1039 	}
1040 }
1041 
1042 void
rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment * segments,gsize cnt,const rspamd_nonce_t nonce,const rspamd_nm_t nm,rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1043 rspamd_cryptobox_encryptv_nm_inplace (struct rspamd_cryptobox_segment *segments,
1044 		gsize cnt,
1045 		const rspamd_nonce_t nonce,
1046 		const rspamd_nm_t nm, rspamd_mac_t sig,
1047 		enum rspamd_cryptobox_mode mode)
1048 {
1049 	struct rspamd_cryptobox_segment *cur = segments, *start_seg = segments;
1050 	guchar outbuf[CHACHA_BLOCKBYTES * 16];
1051 	void *enc_ctx, *auth_ctx;
1052 	guchar *out, *in;
1053 	gsize r, remain, inremain, seg_offset;
1054 
1055 	enc_ctx = g_alloca (rspamd_cryptobox_encrypt_ctx_len (mode));
1056 	auth_ctx = g_alloca (rspamd_cryptobox_auth_ctx_len (mode));
1057 
1058 	enc_ctx = rspamd_cryptobox_encrypt_init (enc_ctx, nonce, nm, mode);
1059 	auth_ctx = rspamd_cryptobox_auth_init (auth_ctx, enc_ctx, mode);
1060 
1061 	remain = sizeof (outbuf);
1062 	out = outbuf;
1063 	inremain = cur->len;
1064 	seg_offset = 0;
1065 
1066 	for (;;) {
1067 		if (cur - segments == (gint)cnt) {
1068 			break;
1069 		}
1070 
1071 		if (cur->len <= remain) {
1072 			memcpy (out, cur->data, cur->len);
1073 			remain -= cur->len;
1074 			out += cur->len;
1075 			cur ++;
1076 
1077 			if (remain == 0) {
1078 				rspamd_cryptobox_encrypt_update (enc_ctx, outbuf, sizeof (outbuf),
1079 						outbuf, NULL, mode);
1080 				rspamd_cryptobox_auth_update (auth_ctx, outbuf, sizeof (outbuf),
1081 						mode);
1082 				rspamd_cryptobox_flush_outbuf (start_seg, outbuf,
1083 						sizeof (outbuf), seg_offset);
1084 				start_seg = cur;
1085 				seg_offset = 0;
1086 				remain = sizeof (outbuf);
1087 				out = outbuf;
1088 			}
1089 		}
1090 		else {
1091 			memcpy (out, cur->data, remain);
1092 			rspamd_cryptobox_encrypt_update (enc_ctx, outbuf, sizeof (outbuf),
1093 					outbuf, NULL, mode);
1094 			rspamd_cryptobox_auth_update (auth_ctx, outbuf, sizeof (outbuf),
1095 					mode);
1096 			rspamd_cryptobox_flush_outbuf (start_seg, outbuf, sizeof (outbuf),
1097 					seg_offset);
1098 			seg_offset = 0;
1099 
1100 			inremain = cur->len - remain;
1101 			in = cur->data + remain;
1102 			out = outbuf;
1103 			remain = 0;
1104 			start_seg = cur;
1105 
1106 			while (inremain > 0) {
1107 				if (sizeof (outbuf) <= inremain) {
1108 					memcpy (outbuf, in, sizeof (outbuf));
1109 					rspamd_cryptobox_encrypt_update (enc_ctx,
1110 							outbuf,
1111 							sizeof (outbuf),
1112 							outbuf,
1113 							NULL,
1114 							mode);
1115 					rspamd_cryptobox_auth_update (auth_ctx,
1116 							outbuf,
1117 							sizeof (outbuf),
1118 							mode);
1119 					memcpy (in, outbuf, sizeof (outbuf));
1120 					in += sizeof (outbuf);
1121 					inremain -= sizeof (outbuf);
1122 					remain = sizeof (outbuf);
1123 				}
1124 				else {
1125 					memcpy (outbuf, in, inremain);
1126 					remain = sizeof (outbuf) - inremain;
1127 					out = outbuf + inremain;
1128 					inremain = 0;
1129 				}
1130 			}
1131 
1132 			seg_offset = cur->len - (sizeof (outbuf) - remain);
1133 			cur ++;
1134 		}
1135 	}
1136 
1137 	rspamd_cryptobox_encrypt_update (enc_ctx, outbuf, sizeof (outbuf) - remain,
1138 			outbuf, &r, mode);
1139 	out = outbuf + r;
1140 	rspamd_cryptobox_encrypt_final (enc_ctx, out, sizeof (outbuf) - remain - r,
1141 			mode);
1142 
1143 	rspamd_cryptobox_auth_update (auth_ctx, outbuf, sizeof (outbuf) - remain,
1144 			mode);
1145 	rspamd_cryptobox_auth_final (auth_ctx, sig, mode);
1146 
1147 	rspamd_cryptobox_flush_outbuf (start_seg, outbuf, sizeof (outbuf) - remain,
1148 			seg_offset);
1149 	rspamd_cryptobox_cleanup (enc_ctx, auth_ctx, mode);
1150 }
1151 
1152 gboolean
rspamd_cryptobox_decrypt_nm_inplace(guchar * data,gsize len,const rspamd_nonce_t nonce,const rspamd_nm_t nm,const rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1153 rspamd_cryptobox_decrypt_nm_inplace (guchar *data, gsize len,
1154 		const rspamd_nonce_t nonce, const rspamd_nm_t nm,
1155 		const rspamd_mac_t sig, enum rspamd_cryptobox_mode mode)
1156 {
1157 	gsize r = 0;
1158 	gboolean ret = TRUE;
1159 	void *enc_ctx, *auth_ctx;
1160 
1161 	enc_ctx = g_alloca (rspamd_cryptobox_encrypt_ctx_len (mode));
1162 	auth_ctx = g_alloca (rspamd_cryptobox_auth_ctx_len (mode));
1163 
1164 	enc_ctx = rspamd_cryptobox_decrypt_init (enc_ctx, nonce, nm, mode);
1165 	auth_ctx = rspamd_cryptobox_auth_verify_init (auth_ctx, enc_ctx, mode);
1166 
1167 	rspamd_cryptobox_auth_verify_update (auth_ctx, data, len, mode);
1168 
1169 	if (!rspamd_cryptobox_auth_verify_final (auth_ctx, sig, mode)) {
1170 		ret = FALSE;
1171 	}
1172 	else {
1173 		rspamd_cryptobox_decrypt_update (enc_ctx, data, len, data, &r, mode);
1174 		ret = rspamd_cryptobox_decrypt_final (enc_ctx, data + r, len - r, mode);
1175 	}
1176 
1177 	rspamd_cryptobox_cleanup (enc_ctx, auth_ctx, mode);
1178 
1179 	return ret;
1180 }
1181 
1182 gboolean
rspamd_cryptobox_decrypt_inplace(guchar * data,gsize len,const rspamd_nonce_t nonce,const rspamd_pk_t pk,const rspamd_sk_t sk,const rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1183 rspamd_cryptobox_decrypt_inplace (guchar *data, gsize len,
1184 		const rspamd_nonce_t nonce,
1185 		const rspamd_pk_t pk, const rspamd_sk_t sk,
1186 		const rspamd_mac_t sig,
1187 		enum rspamd_cryptobox_mode mode)
1188 {
1189 	guchar nm[rspamd_cryptobox_MAX_NMBYTES];
1190 	gboolean ret;
1191 
1192 	rspamd_cryptobox_nm (nm, pk, sk, mode);
1193 	ret = rspamd_cryptobox_decrypt_nm_inplace (data, len, nonce, nm, sig, mode);
1194 
1195 	rspamd_explicit_memzero (nm, sizeof (nm));
1196 
1197 	return ret;
1198 }
1199 
1200 void
rspamd_cryptobox_encrypt_inplace(guchar * data,gsize len,const rspamd_nonce_t nonce,const rspamd_pk_t pk,const rspamd_sk_t sk,rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1201 rspamd_cryptobox_encrypt_inplace (guchar *data, gsize len,
1202 		const rspamd_nonce_t nonce,
1203 		const rspamd_pk_t pk, const rspamd_sk_t sk,
1204 		rspamd_mac_t sig,
1205 		enum rspamd_cryptobox_mode mode)
1206 {
1207 	guchar nm[rspamd_cryptobox_MAX_NMBYTES];
1208 
1209 	rspamd_cryptobox_nm (nm, pk, sk, mode);
1210 	rspamd_cryptobox_encrypt_nm_inplace (data, len, nonce, nm, sig, mode);
1211 	rspamd_explicit_memzero (nm, sizeof (nm));
1212 }
1213 
1214 void
rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment * segments,gsize cnt,const rspamd_nonce_t nonce,const rspamd_pk_t pk,const rspamd_sk_t sk,rspamd_mac_t sig,enum rspamd_cryptobox_mode mode)1215 rspamd_cryptobox_encryptv_inplace (struct rspamd_cryptobox_segment *segments,
1216 		gsize cnt,
1217 		const rspamd_nonce_t nonce,
1218 		const rspamd_pk_t pk, const rspamd_sk_t sk,
1219 		rspamd_mac_t sig,
1220 		enum rspamd_cryptobox_mode mode)
1221 {
1222 	guchar nm[rspamd_cryptobox_MAX_NMBYTES];
1223 
1224 	rspamd_cryptobox_nm (nm, pk, sk, mode);
1225 	rspamd_cryptobox_encryptv_nm_inplace (segments, cnt, nonce, nm, sig, mode);
1226 	rspamd_explicit_memzero (nm, sizeof (nm));
1227 }
1228 
1229 
1230 void
rspamd_cryptobox_siphash(unsigned char * out,const unsigned char * in,unsigned long long inlen,const rspamd_sipkey_t k)1231 rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in,
1232 		unsigned long long inlen,
1233 		const rspamd_sipkey_t k)
1234 {
1235 	crypto_shorthash_siphash24 (out, in, inlen, k);
1236 }
1237 
1238 /*
1239  * Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
1240  * Code based on IEEE Std 802.11-2007, Annex H.4.2.
1241  */
1242 static gboolean
rspamd_cryptobox_pbkdf2(const char * pass,gsize pass_len,const guint8 * salt,gsize salt_len,guint8 * key,gsize key_len,unsigned int rounds)1243 rspamd_cryptobox_pbkdf2 (const char *pass, gsize pass_len,
1244 		const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len,
1245 		unsigned int rounds)
1246 {
1247 	guint8 *asalt, obuf[crypto_generichash_blake2b_BYTES_MAX];
1248 	guint8 d1[crypto_generichash_blake2b_BYTES_MAX],
1249 			d2[crypto_generichash_blake2b_BYTES_MAX];
1250 	unsigned int i, j;
1251 	unsigned int count;
1252 	gsize r;
1253 
1254 	if (rounds < 1 || key_len == 0) {
1255 		return FALSE;
1256 	}
1257 	if (salt_len == 0 || salt_len > G_MAXSIZE - 4) {
1258 		return FALSE;
1259 	}
1260 
1261 	asalt = g_malloc (salt_len + 4);
1262 	memcpy (asalt, salt, salt_len);
1263 
1264 	for (count = 1; key_len > 0; count++) {
1265 		asalt[salt_len + 0] = (count >> 24) & 0xff;
1266 		asalt[salt_len + 1] = (count >> 16) & 0xff;
1267 		asalt[salt_len + 2] = (count >> 8) & 0xff;
1268 		asalt[salt_len + 3] = count & 0xff;
1269 
1270 		if (pass_len <= crypto_generichash_blake2b_KEYBYTES_MAX) {
1271 			crypto_generichash_blake2b (d1, sizeof (d1), asalt, salt_len + 4,
1272 					pass, pass_len);
1273 		}
1274 		else {
1275 			guint8 k[crypto_generichash_blake2b_BYTES_MAX];
1276 
1277 			/*
1278 			 * We use additional blake2 iteration to store large key
1279 			 * XXX: it is not compatible with the original implementation but safe
1280 			 */
1281 			crypto_generichash_blake2b (k, sizeof (k), pass, pass_len,
1282 					NULL, 0);
1283 			crypto_generichash_blake2b (d1, sizeof (d1), asalt, salt_len + 4,
1284 					k, sizeof (k));
1285 		}
1286 
1287 		memcpy (obuf, d1, sizeof(obuf));
1288 
1289 		for (i = 1; i < rounds; i++) {
1290 			if (pass_len <= crypto_generichash_blake2b_KEYBYTES_MAX) {
1291 				crypto_generichash_blake2b (d2, sizeof (d2), d1, sizeof (d1),
1292 						pass, pass_len);
1293 			}
1294 			else {
1295 				guint8 k[crypto_generichash_blake2b_BYTES_MAX];
1296 
1297 				/*
1298 				 * We use additional blake2 iteration to store large key
1299 				 * XXX: it is not compatible with the original implementation but safe
1300 				 */
1301 				crypto_generichash_blake2b (k, sizeof (k), pass, pass_len,
1302 						NULL, 0);
1303 				crypto_generichash_blake2b (d2, sizeof (d2), d1, sizeof (d1),
1304 						k, sizeof (k));
1305 			}
1306 
1307 			memcpy (d1, d2, sizeof(d1));
1308 
1309 			for (j = 0; j < sizeof(obuf); j++) {
1310 				obuf[j] ^= d1[j];
1311 			}
1312 		}
1313 
1314 		r = MIN(key_len, crypto_generichash_blake2b_BYTES_MAX);
1315 		memcpy (key, obuf, r);
1316 		key += r;
1317 		key_len -= r;
1318 	}
1319 
1320 	rspamd_explicit_memzero (asalt, salt_len + 4);
1321 	g_free (asalt);
1322 	rspamd_explicit_memzero (d1, sizeof (d1));
1323 	rspamd_explicit_memzero (d2, sizeof (d2));
1324 	rspamd_explicit_memzero (obuf, sizeof (obuf));
1325 
1326 	return TRUE;
1327 }
1328 
1329 gboolean
rspamd_cryptobox_pbkdf(const char * pass,gsize pass_len,const guint8 * salt,gsize salt_len,guint8 * key,gsize key_len,unsigned int complexity,enum rspamd_cryptobox_pbkdf_type type)1330 rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len,
1331 		const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len,
1332 		unsigned int complexity, enum rspamd_cryptobox_pbkdf_type type)
1333 {
1334 	gboolean ret = FALSE;
1335 
1336 	switch (type) {
1337 	case RSPAMD_CRYPTOBOX_CATENA:
1338 		if (catena (pass, pass_len, salt, salt_len, "rspamd", 6,
1339 				4, complexity, complexity, key_len, key) == 0) {
1340 			ret = TRUE;
1341 		}
1342 		break;
1343 	case RSPAMD_CRYPTOBOX_PBKDF2:
1344 	default:
1345 		ret = rspamd_cryptobox_pbkdf2 (pass, pass_len, salt, salt_len, key,
1346 				key_len, complexity);
1347 		break;
1348 	}
1349 
1350 	return ret;
1351 }
1352 
1353 guint
rspamd_cryptobox_pk_bytes(enum rspamd_cryptobox_mode mode)1354 rspamd_cryptobox_pk_bytes (enum rspamd_cryptobox_mode mode)
1355 {
1356 	if (G_UNLIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
1357 		return 32;
1358 	}
1359 	else {
1360 		return 65;
1361 	}
1362 }
1363 
1364 guint
rspamd_cryptobox_pk_sig_bytes(enum rspamd_cryptobox_mode mode)1365 rspamd_cryptobox_pk_sig_bytes (enum rspamd_cryptobox_mode mode)
1366 {
1367 	if (G_UNLIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
1368 		return 32;
1369 	}
1370 	else {
1371 		return 65;
1372 	}
1373 }
1374 
1375 guint
rspamd_cryptobox_nonce_bytes(enum rspamd_cryptobox_mode mode)1376 rspamd_cryptobox_nonce_bytes (enum rspamd_cryptobox_mode mode)
1377 {
1378 	if (G_UNLIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
1379 		return 24;
1380 	}
1381 	else {
1382 		return 16;
1383 	}
1384 }
1385 
1386 
1387 guint
rspamd_cryptobox_sk_bytes(enum rspamd_cryptobox_mode mode)1388 rspamd_cryptobox_sk_bytes (enum rspamd_cryptobox_mode mode)
1389 {
1390 	return 32;
1391 }
1392 
1393 guint
rspamd_cryptobox_sk_sig_bytes(enum rspamd_cryptobox_mode mode)1394 rspamd_cryptobox_sk_sig_bytes (enum rspamd_cryptobox_mode mode)
1395 {
1396 	if (G_UNLIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
1397 		return 64;
1398 	}
1399 	else {
1400 		return 32;
1401 	}
1402 }
1403 
1404 guint
rspamd_cryptobox_signature_bytes(enum rspamd_cryptobox_mode mode)1405 rspamd_cryptobox_signature_bytes (enum rspamd_cryptobox_mode mode)
1406 {
1407 	static guint ssl_keylen;
1408 
1409 	if (G_UNLIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) {
1410 		return 64;
1411 	}
1412 	else {
1413 #ifndef HAVE_USABLE_OPENSSL
1414 		g_assert (0);
1415 #else
1416 		if (ssl_keylen == 0) {
1417 			EC_KEY *lk;
1418 			lk = EC_KEY_new_by_curve_name (CRYPTOBOX_CURVE_NID);
1419 			ssl_keylen = ECDSA_size (lk);
1420 			EC_KEY_free (lk);
1421 		}
1422 #endif
1423 		return ssl_keylen;
1424 	}
1425 }
1426 
1427 guint
rspamd_cryptobox_nm_bytes(enum rspamd_cryptobox_mode mode)1428 rspamd_cryptobox_nm_bytes (enum rspamd_cryptobox_mode mode)
1429 {
1430 	return 32;
1431 }
1432 
1433 guint
rspamd_cryptobox_mac_bytes(enum rspamd_cryptobox_mode mode)1434 rspamd_cryptobox_mac_bytes (enum rspamd_cryptobox_mode mode)
1435 {
1436 	return 16;
1437 }
1438 
1439 void
rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t * p,const guchar * key,gsize keylen)1440 rspamd_cryptobox_hash_init (rspamd_cryptobox_hash_state_t *p, const guchar *key, gsize keylen)
1441 {
1442 	crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p,
1443 			RSPAMD_ALIGNOF(crypto_generichash_blake2b_state));
1444 	crypto_generichash_blake2b_init (st, key, keylen,
1445 			crypto_generichash_blake2b_BYTES_MAX);
1446 }
1447 
1448 /**
1449  * Update hash with data portion
1450  */
1451 void
rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t * p,const guchar * data,gsize len)1452 rspamd_cryptobox_hash_update (rspamd_cryptobox_hash_state_t *p, const guchar *data, gsize len)
1453 {
1454 	crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p,
1455 			RSPAMD_ALIGNOF(crypto_generichash_blake2b_state));
1456 	crypto_generichash_blake2b_update (st, data, len);
1457 }
1458 
1459 /**
1460  * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
1461  */
1462 void
rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t * p,guchar * out)1463 rspamd_cryptobox_hash_final (rspamd_cryptobox_hash_state_t *p, guchar *out)
1464 {
1465 	crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p,
1466 			RSPAMD_ALIGNOF(crypto_generichash_blake2b_state));
1467 	crypto_generichash_blake2b_final (st, out, crypto_generichash_blake2b_BYTES_MAX);
1468 }
1469 
1470 /**
1471  * One in all function
1472  */
rspamd_cryptobox_hash(guchar * out,const guchar * data,gsize len,const guchar * key,gsize keylen)1473 void rspamd_cryptobox_hash (guchar *out,
1474 		const guchar *data,
1475 		gsize len,
1476 		const guchar *key,
1477 		gsize keylen)
1478 {
1479 	crypto_generichash_blake2b (out, crypto_generichash_blake2b_BYTES_MAX,
1480 			data, len, key, keylen);
1481 }
1482 
1483 G_STATIC_ASSERT (sizeof (t1ha_context_t) <=
1484 		sizeof (((rspamd_cryptobox_fast_hash_state_t *)NULL)->opaque));
1485 G_STATIC_ASSERT (sizeof (struct XXH3_state_s) <=
1486 				 sizeof (((rspamd_cryptobox_fast_hash_state_t *)NULL)->opaque));
1487 
1488 
1489 struct RSPAMD_ALIGNED(16) _mum_iuf {
1490 	union {
1491 		gint64 ll;
1492 		unsigned char b[sizeof (guint64)];
1493 	} buf;
1494 	gint64 h;
1495 	unsigned rem;
1496 };
1497 
1498 rspamd_cryptobox_fast_hash_state_t*
rspamd_cryptobox_fast_hash_new(void)1499 rspamd_cryptobox_fast_hash_new(void)
1500 {
1501 	rspamd_cryptobox_fast_hash_state_t *nst;
1502 	int ret = posix_memalign ((void **)&nst, RSPAMD_ALIGNOF(rspamd_cryptobox_fast_hash_state_t),
1503 			sizeof(rspamd_cryptobox_fast_hash_state_t));
1504 
1505 	if (ret != 0) {
1506 		abort();
1507 	}
1508 
1509 	return nst;
1510 }
1511 
1512 void
rspamd_cryptobox_fast_hash_free(rspamd_cryptobox_fast_hash_state_t * st)1513 rspamd_cryptobox_fast_hash_free(rspamd_cryptobox_fast_hash_state_t *st)
1514 {
1515 	free(st);
1516 }
1517 
1518 void
rspamd_cryptobox_fast_hash_init(rspamd_cryptobox_fast_hash_state_t * st,guint64 seed)1519 rspamd_cryptobox_fast_hash_init (rspamd_cryptobox_fast_hash_state_t *st,
1520 		guint64 seed)
1521 {
1522 	XXH3_state_t *rst = (XXH3_state_t *)st->opaque;
1523 	st->type = RSPAMD_CRYPTOBOX_XXHASH3;
1524 	XXH3_64bits_reset_withSeed (rst, seed);
1525 }
1526 
1527 void
rspamd_cryptobox_fast_hash_init_specific(rspamd_cryptobox_fast_hash_state_t * st,enum rspamd_cryptobox_fast_hash_type type,guint64 seed)1528 rspamd_cryptobox_fast_hash_init_specific (rspamd_cryptobox_fast_hash_state_t *st,
1529 										  enum rspamd_cryptobox_fast_hash_type type,
1530 										  guint64 seed)
1531 {
1532 	switch (type) {
1533 	case RSPAMD_CRYPTOBOX_T1HA:
1534 	case RSPAMD_CRYPTOBOX_HASHFAST:
1535 	case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
1536 		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
1537 		st->type = RSPAMD_CRYPTOBOX_T1HA;
1538 		t1ha2_init (rst, seed, 0);
1539 		break;
1540 	}
1541 	case RSPAMD_CRYPTOBOX_XXHASH64: {
1542 		XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
1543 		st->type = RSPAMD_CRYPTOBOX_XXHASH64;
1544 		XXH64_reset (xst, seed);
1545 		break;
1546 	}
1547 	case RSPAMD_CRYPTOBOX_XXHASH32:
1548 	{
1549 		XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
1550 		st->type = RSPAMD_CRYPTOBOX_XXHASH32;
1551 		XXH32_reset (xst, seed);
1552 		break;
1553 	}
1554 	case RSPAMD_CRYPTOBOX_XXHASH3:
1555 	{
1556 		XXH3_state_t *xst = (XXH3_state_t *)  st->opaque;
1557 		st->type = RSPAMD_CRYPTOBOX_XXHASH3;
1558 		XXH3_64bits_reset_withSeed (xst, seed);
1559 		break;
1560 	}
1561 	case RSPAMD_CRYPTOBOX_MUMHASH: {
1562 		struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
1563 		st->type = RSPAMD_CRYPTOBOX_MUMHASH;
1564 		iuf->h = seed;
1565 		iuf->buf.ll = 0;
1566 		iuf->rem = 0;
1567 		break;
1568 	}
1569 	}
1570 }
1571 
1572 void
rspamd_cryptobox_fast_hash_update(rspamd_cryptobox_fast_hash_state_t * st,const void * data,gsize len)1573 rspamd_cryptobox_fast_hash_update (rspamd_cryptobox_fast_hash_state_t *st,
1574 		const void *data, gsize len)
1575 {
1576 	if (st->type == RSPAMD_CRYPTOBOX_T1HA) {
1577 		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
1578 		t1ha2_update (rst, data, len);
1579 	}
1580 	else {
1581 		switch (st->type) {
1582 		case RSPAMD_CRYPTOBOX_XXHASH64: {
1583 			XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
1584 			XXH64_update (xst, data, len);
1585 			break;
1586 		}
1587 		case RSPAMD_CRYPTOBOX_XXHASH32:
1588 		{
1589 			XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
1590 			XXH32_update (xst, data, len);
1591 			break;
1592 		}
1593 		case RSPAMD_CRYPTOBOX_XXHASH3:
1594 		{
1595 			XXH3_state_t *xst = (XXH3_state_t *)  st->opaque;
1596 			XXH3_64bits_update (xst, data, len);
1597 			break;
1598 		}
1599 		case RSPAMD_CRYPTOBOX_MUMHASH: {
1600 			struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
1601 			gsize drem = len;
1602 			const guchar *p = data;
1603 
1604 			if (iuf->rem > 0) {
1605 				/* Process remainder */
1606 				if (drem >= iuf->rem) {
1607 					memcpy (iuf->buf.b + sizeof (iuf->buf.ll) - iuf->rem,
1608 							p, iuf->rem);
1609 					drem -= iuf->rem;
1610 					p += iuf->rem;
1611 					iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
1612 					iuf->rem = 0;
1613 				}
1614 				else {
1615 					memcpy (iuf->buf.b + sizeof (iuf->buf.ll) - iuf->rem, p, drem);
1616 					iuf->rem -= drem;
1617 					drem = 0;
1618 				}
1619 			}
1620 
1621 			while (drem >= sizeof (iuf->buf.ll)) {
1622 				memcpy (iuf->buf.b, p, sizeof (iuf->buf.ll));
1623 				iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
1624 				drem -= sizeof (iuf->buf.ll);
1625 				p += sizeof (iuf->buf.ll);
1626 			}
1627 
1628 			/* Leftover */
1629 			if (drem > 0) {
1630 				iuf->rem = sizeof (guint64) - drem;
1631 				iuf->buf.ll = 0;
1632 				memcpy (iuf->buf.b, p, drem);
1633 			}
1634 			break;
1635 		}
1636 		case RSPAMD_CRYPTOBOX_T1HA:
1637 		case RSPAMD_CRYPTOBOX_HASHFAST:
1638 		case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
1639 			t1ha_context_t *rst = (t1ha_context_t *)  st->opaque;
1640 			t1ha2_update (rst, data, len);
1641 			break;
1642 		}
1643 		}
1644 	}
1645 }
1646 
1647 guint64
rspamd_cryptobox_fast_hash_final(rspamd_cryptobox_fast_hash_state_t * st)1648 rspamd_cryptobox_fast_hash_final (rspamd_cryptobox_fast_hash_state_t *st)
1649 {
1650 	guint64 ret;
1651 
1652 	if (st->type == RSPAMD_CRYPTOBOX_T1HA) {
1653 		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
1654 
1655 		return t1ha2_final (rst, NULL);
1656 	}
1657 	else {
1658 		switch (st->type) {
1659 		case RSPAMD_CRYPTOBOX_XXHASH64: {
1660 			XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
1661 			ret = XXH64_digest (xst);
1662 			break;
1663 		}
1664 		case RSPAMD_CRYPTOBOX_XXHASH32: {
1665 			XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
1666 			ret = XXH32_digest (xst);
1667 			break;
1668 		}
1669 		case RSPAMD_CRYPTOBOX_XXHASH3: {
1670 			XXH3_state_t *xst = (XXH3_state_t *)  st->opaque;
1671 			ret = XXH3_64bits_digest (xst);
1672 			break;
1673 		}
1674 		case RSPAMD_CRYPTOBOX_MUMHASH: {
1675 			struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
1676 			iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
1677 			ret = mum_hash_finish (iuf->h);
1678 			break;
1679 		}
1680 		case RSPAMD_CRYPTOBOX_T1HA:
1681 		case RSPAMD_CRYPTOBOX_HASHFAST:
1682 		case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
1683 			t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
1684 
1685 			ret = t1ha2_final (rst, NULL);
1686 			break;
1687 		}
1688 		}
1689 	}
1690 
1691 	return ret;
1692 }
1693 
1694 /**
1695  * One in all function
1696  */
1697 static inline guint64
rspamd_cryptobox_fast_hash_machdep(const void * data,gsize len,guint64 seed)1698 rspamd_cryptobox_fast_hash_machdep (const void *data,
1699 		gsize len, guint64 seed)
1700 {
1701 	return XXH3_64bits_withSeed(data, len, seed);
1702 }
1703 
1704 static inline guint64
rspamd_cryptobox_fast_hash_indep(const void * data,gsize len,guint64 seed)1705 rspamd_cryptobox_fast_hash_indep (const void *data,
1706 		gsize len, guint64 seed)
1707 {
1708 	return XXH3_64bits_withSeed(data, len, seed);
1709 }
1710 
1711 guint64
rspamd_cryptobox_fast_hash(const void * data,gsize len,guint64 seed)1712 rspamd_cryptobox_fast_hash (const void *data,
1713 		gsize len, guint64 seed)
1714 {
1715 	return rspamd_cryptobox_fast_hash_machdep (data, len, seed);
1716 }
1717 
1718 guint64
rspamd_cryptobox_fast_hash_specific(enum rspamd_cryptobox_fast_hash_type type,const void * data,gsize len,guint64 seed)1719 rspamd_cryptobox_fast_hash_specific (
1720 		enum rspamd_cryptobox_fast_hash_type type,
1721 		const void *data,
1722 		gsize len, guint64 seed)
1723 {
1724 	switch (type) {
1725 	case RSPAMD_CRYPTOBOX_XXHASH32:
1726 		return XXH32 (data, len, seed);
1727 	case RSPAMD_CRYPTOBOX_XXHASH3:
1728 		return XXH3_64bits_withSeed (data, len, seed);
1729 	case RSPAMD_CRYPTOBOX_XXHASH64:
1730 		return XXH64 (data, len, seed);
1731 	case RSPAMD_CRYPTOBOX_MUMHASH:
1732 		return mum_hash (data, len, seed);
1733 	case RSPAMD_CRYPTOBOX_T1HA:
1734 		return t1ha2_atonce (data, len, seed);
1735 	case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT:
1736 		return rspamd_cryptobox_fast_hash_indep (data, len, seed);
1737 	case RSPAMD_CRYPTOBOX_HASHFAST:
1738 	default:
1739 		return rspamd_cryptobox_fast_hash_machdep (data, len, seed);
1740 	}
1741 }
1742