You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cryptobox.c 42KB

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