/*
 * SPDX-License-Identifier: (ISC AND BSD-3-Clause)
 * SPDX-URL: https://spdx.org/licenses/ISC.html
 * SPDX-URL: https://spdx.org/licenses/BSD-3-Clause.html
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * Copyright (C) 1997 Niels Provos <provos@umich.edu>
 * Copyright (C) 2014 Ted Unangst <tedu@openbsd.org>
 * Copyright (C) 2020 Aaron M. D. Jones <me@aaronmdjones.net>
 */

#include <atheme.h>

#define ATHEME_EKS_BF_WORDS 6U

struct atheme_eks_bf_ctx
{
	uint32_t P[18U];
	uint32_t S[4U][256U];
};

static const struct atheme_eks_bf_ctx atheme_eks_bf_initial_state = {
	.P = {
		UINT32_C(0x243F6A88), UINT32_C(0x85A308D3), UINT32_C(0x13198A2E), UINT32_C(0x03707344),
		UINT32_C(0xA4093822), UINT32_C(0x299F31D0), UINT32_C(0x082EFA98), UINT32_C(0xEC4E6C89),
		UINT32_C(0x452821E6), UINT32_C(0x38D01377), UINT32_C(0xBE5466CF), UINT32_C(0x34E90C6C),
		UINT32_C(0xC0AC29B7), UINT32_C(0xC97C50DD), UINT32_C(0x3F84D5B5), UINT32_C(0xB5470917),
		UINT32_C(0x9216D5D9), UINT32_C(0x8979FB1B),
	},
	.S = {
		{
			UINT32_C(0xD1310BA6), UINT32_C(0x98DFB5AC), UINT32_C(0x2FFD72DB), UINT32_C(0xD01ADFB7),
			UINT32_C(0xB8E1AFED), UINT32_C(0x6A267E96), UINT32_C(0xBA7C9045), UINT32_C(0xF12C7F99),
			UINT32_C(0x24A19947), UINT32_C(0xB3916CF7), UINT32_C(0x0801F2E2), UINT32_C(0x858EFC16),
			UINT32_C(0x636920D8), UINT32_C(0x71574E69), UINT32_C(0xA458FEA3), UINT32_C(0xF4933D7E),
			UINT32_C(0x0D95748F), UINT32_C(0x728EB658), UINT32_C(0x718BCD58), UINT32_C(0x82154AEE),
			UINT32_C(0x7B54A41D), UINT32_C(0xC25A59B5), UINT32_C(0x9C30D539), UINT32_C(0x2AF26013),
			UINT32_C(0xC5D1B023), UINT32_C(0x286085F0), UINT32_C(0xCA417918), UINT32_C(0xB8DB38EF),
			UINT32_C(0x8E79DCB0), UINT32_C(0x603A180E), UINT32_C(0x6C9E0E8B), UINT32_C(0xB01E8A3E),
			UINT32_C(0xD71577C1), UINT32_C(0xBD314B27), UINT32_C(0x78AF2FDA), UINT32_C(0x55605C60),
			UINT32_C(0xE65525F3), UINT32_C(0xAA55AB94), UINT32_C(0x57489862), UINT32_C(0x63E81440),
			UINT32_C(0x55CA396A), UINT32_C(0x2AAB10B6), UINT32_C(0xB4CC5C34), UINT32_C(0x1141E8CE),
			UINT32_C(0xA15486AF), UINT32_C(0x7C72E993), UINT32_C(0xB3EE1411), UINT32_C(0x636FBC2A),
			UINT32_C(0x2BA9C55D), UINT32_C(0x741831F6), UINT32_C(0xCE5C3E16), UINT32_C(0x9B87931E),
			UINT32_C(0xAFD6BA33), UINT32_C(0x6C24CF5C), UINT32_C(0x7A325381), UINT32_C(0x28958677),
			UINT32_C(0x3B8F4898), UINT32_C(0x6B4BB9AF), UINT32_C(0xC4BFE81B), UINT32_C(0x66282193),
			UINT32_C(0x61D809CC), UINT32_C(0xFB21A991), UINT32_C(0x487CAC60), UINT32_C(0x5DEC8032),
			UINT32_C(0xEF845D5D), UINT32_C(0xE98575B1), UINT32_C(0xDC262302), UINT32_C(0xEB651B88),
			UINT32_C(0x23893E81), UINT32_C(0xD396ACC5), UINT32_C(0x0F6D6FF3), UINT32_C(0x83F44239),
			UINT32_C(0x2E0B4482), UINT32_C(0xA4842004), UINT32_C(0x69C8F04A), UINT32_C(0x9E1F9B5E),
			UINT32_C(0x21C66842), UINT32_C(0xF6E96C9A), UINT32_C(0x670C9C61), UINT32_C(0xABD388F0),
			UINT32_C(0x6A51A0D2), UINT32_C(0xD8542F68), UINT32_C(0x960FA728), UINT32_C(0xAB5133A3),
			UINT32_C(0x6EEF0B6C), UINT32_C(0x137A3BE4), UINT32_C(0xBA3BF050), UINT32_C(0x7EFB2A98),
			UINT32_C(0xA1F1651D), UINT32_C(0x39AF0176), UINT32_C(0x66CA593E), UINT32_C(0x82430E88),
			UINT32_C(0x8CEE8619), UINT32_C(0x456F9FB4), UINT32_C(0x7D84A5C3), UINT32_C(0x3B8B5EBE),
			UINT32_C(0xE06F75D8), UINT32_C(0x85C12073), UINT32_C(0x401A449F), UINT32_C(0x56C16AA6),
			UINT32_C(0x4ED3AA62), UINT32_C(0x363F7706), UINT32_C(0x1BFEDF72), UINT32_C(0x429B023D),
			UINT32_C(0x37D0D724), UINT32_C(0xD00A1248), UINT32_C(0xDB0FEAD3), UINT32_C(0x49F1C09B),
			UINT32_C(0x075372C9), UINT32_C(0x80991B7B), UINT32_C(0x25D479D8), UINT32_C(0xF6E8DEF7),
			UINT32_C(0xE3FE501A), UINT32_C(0xB6794C3B), UINT32_C(0x976CE0BD), UINT32_C(0x04C006BA),
			UINT32_C(0xC1A94FB6), UINT32_C(0x409F60C4), UINT32_C(0x5E5C9EC2), UINT32_C(0x196A2463),
			UINT32_C(0x68FB6FAF), UINT32_C(0x3E6C53B5), UINT32_C(0x1339B2EB), UINT32_C(0x3B52EC6F),
			UINT32_C(0x6DFC511F), UINT32_C(0x9B30952C), UINT32_C(0xCC814544), UINT32_C(0xAF5EBD09),
			UINT32_C(0xBEE3D004), UINT32_C(0xDE334AFD), UINT32_C(0x660F2807), UINT32_C(0x192E4BB3),
			UINT32_C(0xC0CBA857), UINT32_C(0x45C8740F), UINT32_C(0xD20B5F39), UINT32_C(0xB9D3FBDB),
			UINT32_C(0x5579C0BD), UINT32_C(0x1A60320A), UINT32_C(0xD6A100C6), UINT32_C(0x402C7279),
			UINT32_C(0x679F25FE), UINT32_C(0xFB1FA3CC), UINT32_C(0x8EA5E9F8), UINT32_C(0xDB3222F8),
			UINT32_C(0x3C7516DF), UINT32_C(0xFD616B15), UINT32_C(0x2F501EC8), UINT32_C(0xAD0552AB),
			UINT32_C(0x323DB5FA), UINT32_C(0xFD238760), UINT32_C(0x53317B48), UINT32_C(0x3E00DF82),
			UINT32_C(0x9E5C57BB), UINT32_C(0xCA6F8CA0), UINT32_C(0x1A87562E), UINT32_C(0xDF1769DB),
			UINT32_C(0xD542A8F6), UINT32_C(0x287EFFC3), UINT32_C(0xAC6732C6), UINT32_C(0x8C4F5573),
			UINT32_C(0x695B27B0), UINT32_C(0xBBCA58C8), UINT32_C(0xE1FFA35D), UINT32_C(0xB8F011A0),
			UINT32_C(0x10FA3D98), UINT32_C(0xFD2183B8), UINT32_C(0x4AFCB56C), UINT32_C(0x2DD1D35B),
			UINT32_C(0x9A53E479), UINT32_C(0xB6F84565), UINT32_C(0xD28E49BC), UINT32_C(0x4BFB9790),
			UINT32_C(0xE1DDF2DA), UINT32_C(0xA4CB7E33), UINT32_C(0x62FB1341), UINT32_C(0xCEE4C6E8),
			UINT32_C(0xEF20CADA), UINT32_C(0x36774C01), UINT32_C(0xD07E9EFE), UINT32_C(0x2BF11FB4),
			UINT32_C(0x95DBDA4D), UINT32_C(0xAE909198), UINT32_C(0xEAAD8E71), UINT32_C(0x6B93D5A0),
			UINT32_C(0xD08ED1D0), UINT32_C(0xAFC725E0), UINT32_C(0x8E3C5B2F), UINT32_C(0x8E7594B7),
			UINT32_C(0x8FF6E2FB), UINT32_C(0xF2122B64), UINT32_C(0x8888B812), UINT32_C(0x900DF01C),
			UINT32_C(0x4FAD5EA0), UINT32_C(0x688FC31C), UINT32_C(0xD1CFF191), UINT32_C(0xB3A8C1AD),
			UINT32_C(0x2F2F2218), UINT32_C(0xBE0E1777), UINT32_C(0xEA752DFE), UINT32_C(0x8B021FA1),
			UINT32_C(0xE5A0CC0F), UINT32_C(0xB56F74E8), UINT32_C(0x18ACF3D6), UINT32_C(0xCE89E299),
			UINT32_C(0xB4A84FE0), UINT32_C(0xFD13E0B7), UINT32_C(0x7CC43B81), UINT32_C(0xD2ADA8D9),
			UINT32_C(0x165FA266), UINT32_C(0x80957705), UINT32_C(0x93CC7314), UINT32_C(0x211A1477),
			UINT32_C(0xE6AD2065), UINT32_C(0x77B5FA86), UINT32_C(0xC75442F5), UINT32_C(0xFB9D35CF),
			UINT32_C(0xEBCDAF0C), UINT32_C(0x7B3E89A0), UINT32_C(0xD6411BD3), UINT32_C(0xAE1E7E49),
			UINT32_C(0x00250E2D), UINT32_C(0x2071B35E), UINT32_C(0x226800BB), UINT32_C(0x57B8E0AF),
			UINT32_C(0x2464369B), UINT32_C(0xF009B91E), UINT32_C(0x5563911D), UINT32_C(0x59DFA6AA),
			UINT32_C(0x78C14389), UINT32_C(0xD95A537F), UINT32_C(0x207D5BA2), UINT32_C(0x02E5B9C5),
			UINT32_C(0x83260376), UINT32_C(0x6295CFA9), UINT32_C(0x11C81968), UINT32_C(0x4E734A41),
			UINT32_C(0xB3472DCA), UINT32_C(0x7B14A94A), UINT32_C(0x1B510052), UINT32_C(0x9A532915),
			UINT32_C(0xD60F573F), UINT32_C(0xBC9BC6E4), UINT32_C(0x2B60A476), UINT32_C(0x81E67400),
			UINT32_C(0x08BA6FB5), UINT32_C(0x571BE91F), UINT32_C(0xF296EC6B), UINT32_C(0x2A0DD915),
			UINT32_C(0xB6636521), UINT32_C(0xE7B9F9B6), UINT32_C(0xFF34052E), UINT32_C(0xC5855664),
			UINT32_C(0x53B02D5D), UINT32_C(0xA99F8FA1), UINT32_C(0x08BA4799), UINT32_C(0x6E85076A),
		},
		{
			UINT32_C(0x4B7A70E9), UINT32_C(0xB5B32944), UINT32_C(0xDB75092E), UINT32_C(0xC4192623),
			UINT32_C(0xAD6EA6B0), UINT32_C(0x49A7DF7D), UINT32_C(0x9CEE60B8), UINT32_C(0x8FEDB266),
			UINT32_C(0xECAA8C71), UINT32_C(0x699A17FF), UINT32_C(0x5664526C), UINT32_C(0xC2B19EE1),
			UINT32_C(0x193602A5), UINT32_C(0x75094C29), UINT32_C(0xA0591340), UINT32_C(0xE4183A3E),
			UINT32_C(0x3F54989A), UINT32_C(0x5B429D65), UINT32_C(0x6B8FE4D6), UINT32_C(0x99F73FD6),
			UINT32_C(0xA1D29C07), UINT32_C(0xEFE830F5), UINT32_C(0x4D2D38E6), UINT32_C(0xF0255DC1),
			UINT32_C(0x4CDD2086), UINT32_C(0x8470EB26), UINT32_C(0x6382E9C6), UINT32_C(0x021ECC5E),
			UINT32_C(0x09686B3F), UINT32_C(0x3EBAEFC9), UINT32_C(0x3C971814), UINT32_C(0x6B6A70A1),
			UINT32_C(0x687F3584), UINT32_C(0x52A0E286), UINT32_C(0xB79C5305), UINT32_C(0xAA500737),
			UINT32_C(0x3E07841C), UINT32_C(0x7FDEAE5C), UINT32_C(0x8E7D44EC), UINT32_C(0x5716F2B8),
			UINT32_C(0xB03ADA37), UINT32_C(0xF0500C0D), UINT32_C(0xF01C1F04), UINT32_C(0x0200B3FF),
			UINT32_C(0xAE0CF51A), UINT32_C(0x3CB574B2), UINT32_C(0x25837A58), UINT32_C(0xDC0921BD),
			UINT32_C(0xD19113F9), UINT32_C(0x7CA92FF6), UINT32_C(0x94324773), UINT32_C(0x22F54701),
			UINT32_C(0x3AE5E581), UINT32_C(0x37C2DADC), UINT32_C(0xC8B57634), UINT32_C(0x9AF3DDA7),
			UINT32_C(0xA9446146), UINT32_C(0x0FD0030E), UINT32_C(0xECC8C73E), UINT32_C(0xA4751E41),
			UINT32_C(0xE238CD99), UINT32_C(0x3BEA0E2F), UINT32_C(0x3280BBA1), UINT32_C(0x183EB331),
			UINT32_C(0x4E548B38), UINT32_C(0x4F6DB908), UINT32_C(0x6F420D03), UINT32_C(0xF60A04BF),
			UINT32_C(0x2CB81290), UINT32_C(0x24977C79), UINT32_C(0x5679B072), UINT32_C(0xBCAF89AF),
			UINT32_C(0xDE9A771F), UINT32_C(0xD9930810), UINT32_C(0xB38BAE12), UINT32_C(0xDCCF3F2E),
			UINT32_C(0x5512721F), UINT32_C(0x2E6B7124), UINT32_C(0x501ADDE6), UINT32_C(0x9F84CD87),
			UINT32_C(0x7A584718), UINT32_C(0x7408DA17), UINT32_C(0xBC9F9ABC), UINT32_C(0xE94B7D8C),
			UINT32_C(0xEC7AEC3A), UINT32_C(0xDB851DFA), UINT32_C(0x63094366), UINT32_C(0xC464C3D2),
			UINT32_C(0xEF1C1847), UINT32_C(0x3215D908), UINT32_C(0xDD433B37), UINT32_C(0x24C2BA16),
			UINT32_C(0x12A14D43), UINT32_C(0x2A65C451), UINT32_C(0x50940002), UINT32_C(0x133AE4DD),
			UINT32_C(0x71DFF89E), UINT32_C(0x10314E55), UINT32_C(0x81AC77D6), UINT32_C(0x5F11199B),
			UINT32_C(0x043556F1), UINT32_C(0xD7A3C76B), UINT32_C(0x3C11183B), UINT32_C(0x5924A509),
			UINT32_C(0xF28FE6ED), UINT32_C(0x97F1FBFA), UINT32_C(0x9EBABF2C), UINT32_C(0x1E153C6E),
			UINT32_C(0x86E34570), UINT32_C(0xEAE96FB1), UINT32_C(0x860E5E0A), UINT32_C(0x5A3E2AB3),
			UINT32_C(0x771FE71C), UINT32_C(0x4E3D06FA), UINT32_C(0x2965DCB9), UINT32_C(0x99E71D0F),
			UINT32_C(0x803E89D6), UINT32_C(0x5266C825), UINT32_C(0x2E4CC978), UINT32_C(0x9C10B36A),
			UINT32_C(0xC6150EBA), UINT32_C(0x94E2EA78), UINT32_C(0xA5FC3C53), UINT32_C(0x1E0A2DF4),
			UINT32_C(0xF2F74EA7), UINT32_C(0x361D2B3D), UINT32_C(0x1939260F), UINT32_C(0x19C27960),
			UINT32_C(0x5223A708), UINT32_C(0xF71312B6), UINT32_C(0xEBADFE6E), UINT32_C(0xEAC31F66),
			UINT32_C(0xE3BC4595), UINT32_C(0xA67BC883), UINT32_C(0xB17F37D1), UINT32_C(0x018CFF28),
			UINT32_C(0xC332DDEF), UINT32_C(0xBE6C5AA5), UINT32_C(0x65582185), UINT32_C(0x68AB9802),
			UINT32_C(0xEECEA50F), UINT32_C(0xDB2F953B), UINT32_C(0x2AEF7DAD), UINT32_C(0x5B6E2F84),
			UINT32_C(0x1521B628), UINT32_C(0x29076170), UINT32_C(0xECDD4775), UINT32_C(0x619F1510),
			UINT32_C(0x13CCA830), UINT32_C(0xEB61BD96), UINT32_C(0x0334FE1E), UINT32_C(0xAA0363CF),
			UINT32_C(0xB5735C90), UINT32_C(0x4C70A239), UINT32_C(0xD59E9E0B), UINT32_C(0xCBAADE14),
			UINT32_C(0xEECC86BC), UINT32_C(0x60622CA7), UINT32_C(0x9CAB5CAB), UINT32_C(0xB2F3846E),
			UINT32_C(0x648B1EAF), UINT32_C(0x19BDF0CA), UINT32_C(0xA02369B9), UINT32_C(0x655ABB50),
			UINT32_C(0x40685A32), UINT32_C(0x3C2AB4B3), UINT32_C(0x319EE9D5), UINT32_C(0xC021B8F7),
			UINT32_C(0x9B540B19), UINT32_C(0x875FA099), UINT32_C(0x95F7997E), UINT32_C(0x623D7DA8),
			UINT32_C(0xF837889A), UINT32_C(0x97E32D77), UINT32_C(0x11ED935F), UINT32_C(0x16681281),
			UINT32_C(0x0E358829), UINT32_C(0xC7E61FD6), UINT32_C(0x96DEDFA1), UINT32_C(0x7858BA99),
			UINT32_C(0x57F584A5), UINT32_C(0x1B227263), UINT32_C(0x9B83C3FF), UINT32_C(0x1AC24696),
			UINT32_C(0xCDB30AEB), UINT32_C(0x532E3054), UINT32_C(0x8FD948E4), UINT32_C(0x6DBC3128),
			UINT32_C(0x58EBF2EF), UINT32_C(0x34C6FFEA), UINT32_C(0xFE28ED61), UINT32_C(0xEE7C3C73),
			UINT32_C(0x5D4A14D9), UINT32_C(0xE864B7E3), UINT32_C(0x42105D14), UINT32_C(0x203E13E0),
			UINT32_C(0x45EEE2B6), UINT32_C(0xA3AAABEA), UINT32_C(0xDB6C4F15), UINT32_C(0xFACB4FD0),
			UINT32_C(0xC742F442), UINT32_C(0xEF6ABBB5), UINT32_C(0x654F3B1D), UINT32_C(0x41CD2105),
			UINT32_C(0xD81E799E), UINT32_C(0x86854DC7), UINT32_C(0xE44B476A), UINT32_C(0x3D816250),
			UINT32_C(0xCF62A1F2), UINT32_C(0x5B8D2646), UINT32_C(0xFC8883A0), UINT32_C(0xC1C7B6A3),
			UINT32_C(0x7F1524C3), UINT32_C(0x69CB7492), UINT32_C(0x47848A0B), UINT32_C(0x5692B285),
			UINT32_C(0x095BBF00), UINT32_C(0xAD19489D), UINT32_C(0x1462B174), UINT32_C(0x23820E00),
			UINT32_C(0x58428D2A), UINT32_C(0x0C55F5EA), UINT32_C(0x1DADF43E), UINT32_C(0x233F7061),
			UINT32_C(0x3372F092), UINT32_C(0x8D937E41), UINT32_C(0xD65FECF1), UINT32_C(0x6C223BDB),
			UINT32_C(0x7CDE3759), UINT32_C(0xCBEE7460), UINT32_C(0x4085F2A7), UINT32_C(0xCE77326E),
			UINT32_C(0xA6078084), UINT32_C(0x19F8509E), UINT32_C(0xE8EFD855), UINT32_C(0x61D99735),
			UINT32_C(0xA969A7AA), UINT32_C(0xC50C06C2), UINT32_C(0x5A04ABFC), UINT32_C(0x800BCADC),
			UINT32_C(0x9E447A2E), UINT32_C(0xC3453484), UINT32_C(0xFDD56705), UINT32_C(0x0E1E9EC9),
			UINT32_C(0xDB73DBD3), UINT32_C(0x105588CD), UINT32_C(0x675FDA79), UINT32_C(0xE3674340),
			UINT32_C(0xC5C43465), UINT32_C(0x713E38D8), UINT32_C(0x3D28F89E), UINT32_C(0xF16DFF20),
			UINT32_C(0x153E21E7), UINT32_C(0x8FB03D4A), UINT32_C(0xE6E39F2B), UINT32_C(0xDB83ADF7),
		},
		{
			UINT32_C(0xE93D5A68), UINT32_C(0x948140F7), UINT32_C(0xF64C261C), UINT32_C(0x94692934),
			UINT32_C(0x411520F7), UINT32_C(0x7602D4F7), UINT32_C(0xBCF46B2E), UINT32_C(0xD4A20068),
			UINT32_C(0xD4082471), UINT32_C(0x3320F46A), UINT32_C(0x43B7D4B7), UINT32_C(0x500061AF),
			UINT32_C(0x1E39F62E), UINT32_C(0x97244546), UINT32_C(0x14214F74), UINT32_C(0xBF8B8840),
			UINT32_C(0x4D95FC1D), UINT32_C(0x96B591AF), UINT32_C(0x70F4DDD3), UINT32_C(0x66A02F45),
			UINT32_C(0xBFBC09EC), UINT32_C(0x03BD9785), UINT32_C(0x7FAC6DD0), UINT32_C(0x31CB8504),
			UINT32_C(0x96EB27B3), UINT32_C(0x55FD3941), UINT32_C(0xDA2547E6), UINT32_C(0xABCA0A9A),
			UINT32_C(0x28507825), UINT32_C(0x530429F4), UINT32_C(0x0A2C86DA), UINT32_C(0xE9B66DFB),
			UINT32_C(0x68DC1462), UINT32_C(0xD7486900), UINT32_C(0x680EC0A4), UINT32_C(0x27A18DEE),
			UINT32_C(0x4F3FFEA2), UINT32_C(0xE887AD8C), UINT32_C(0xB58CE006), UINT32_C(0x7AF4D6B6),
			UINT32_C(0xAACE1E7C), UINT32_C(0xD3375FEC), UINT32_C(0xCE78A399), UINT32_C(0x406B2A42),
			UINT32_C(0x20FE9E35), UINT32_C(0xD9F385B9), UINT32_C(0xEE39D7AB), UINT32_C(0x3B124E8B),
			UINT32_C(0x1DC9FAF7), UINT32_C(0x4B6D1856), UINT32_C(0x26A36631), UINT32_C(0xEAE397B2),
			UINT32_C(0x3A6EFA74), UINT32_C(0xDD5B4332), UINT32_C(0x6841E7F7), UINT32_C(0xCA7820FB),
			UINT32_C(0xFB0AF54E), UINT32_C(0xD8FEB397), UINT32_C(0x454056AC), UINT32_C(0xBA489527),
			UINT32_C(0x55533A3A), UINT32_C(0x20838D87), UINT32_C(0xFE6BA9B7), UINT32_C(0xD096954B),
			UINT32_C(0x55A867BC), UINT32_C(0xA1159A58), UINT32_C(0xCCA92963), UINT32_C(0x99E1DB33),
			UINT32_C(0xA62A4A56), UINT32_C(0x3F3125F9), UINT32_C(0x5EF47E1C), UINT32_C(0x9029317C),
			UINT32_C(0xFDF8E802), UINT32_C(0x04272F70), UINT32_C(0x80BB155C), UINT32_C(0x05282CE3),
			UINT32_C(0x95C11548), UINT32_C(0xE4C66D22), UINT32_C(0x48C1133F), UINT32_C(0xC70F86DC),
			UINT32_C(0x07F9C9EE), UINT32_C(0x41041F0F), UINT32_C(0x404779A4), UINT32_C(0x5D886E17),
			UINT32_C(0x325F51EB), UINT32_C(0xD59BC0D1), UINT32_C(0xF2BCC18F), UINT32_C(0x41113564),
			UINT32_C(0x257B7834), UINT32_C(0x602A9C60), UINT32_C(0xDFF8E8A3), UINT32_C(0x1F636C1B),
			UINT32_C(0x0E12B4C2), UINT32_C(0x02E1329E), UINT32_C(0xAF664FD1), UINT32_C(0xCAD18115),
			UINT32_C(0x6B2395E0), UINT32_C(0x333E92E1), UINT32_C(0x3B240B62), UINT32_C(0xEEBEB922),
			UINT32_C(0x85B2A20E), UINT32_C(0xE6BA0D99), UINT32_C(0xDE720C8C), UINT32_C(0x2DA2F728),
			UINT32_C(0xD0127845), UINT32_C(0x95B794FD), UINT32_C(0x647D0862), UINT32_C(0xE7CCF5F0),
			UINT32_C(0x5449A36F), UINT32_C(0x877D48FA), UINT32_C(0xC39DFD27), UINT32_C(0xF33E8D1E),
			UINT32_C(0x0A476341), UINT32_C(0x992EFF74), UINT32_C(0x3A6F6EAB), UINT32_C(0xF4F8FD37),
			UINT32_C(0xA812DC60), UINT32_C(0xA1EBDDF8), UINT32_C(0x991BE14C), UINT32_C(0xDB6E6B0D),
			UINT32_C(0xC67B5510), UINT32_C(0x6D672C37), UINT32_C(0x2765D43B), UINT32_C(0xDCD0E804),
			UINT32_C(0xF1290DC7), UINT32_C(0xCC00FFA3), UINT32_C(0xB5390F92), UINT32_C(0x690FED0B),
			UINT32_C(0x667B9FFB), UINT32_C(0xCEDB7D9C), UINT32_C(0xA091CF0B), UINT32_C(0xD9155EA3),
			UINT32_C(0xBB132F88), UINT32_C(0x515BAD24), UINT32_C(0x7B9479BF), UINT32_C(0x763BD6EB),
			UINT32_C(0x37392EB3), UINT32_C(0xCC115979), UINT32_C(0x8026E297), UINT32_C(0xF42E312D),
			UINT32_C(0x6842ADA7), UINT32_C(0xC66A2B3B), UINT32_C(0x12754CCC), UINT32_C(0x782EF11C),
			UINT32_C(0x6A124237), UINT32_C(0xB79251E7), UINT32_C(0x06A1BBE6), UINT32_C(0x4BFB6350),
			UINT32_C(0x1A6B1018), UINT32_C(0x11CAEDFA), UINT32_C(0x3D25BDD8), UINT32_C(0xE2E1C3C9),
			UINT32_C(0x44421659), UINT32_C(0x0A121386), UINT32_C(0xD90CEC6E), UINT32_C(0xD5ABEA2A),
			UINT32_C(0x64AF674E), UINT32_C(0xDA86A85F), UINT32_C(0xBEBFE988), UINT32_C(0x64E4C3FE),
			UINT32_C(0x9DBC8057), UINT32_C(0xF0F7C086), UINT32_C(0x60787BF8), UINT32_C(0x6003604D),
			UINT32_C(0xD1FD8346), UINT32_C(0xF6381FB0), UINT32_C(0x7745AE04), UINT32_C(0xD736FCCC),
			UINT32_C(0x83426B33), UINT32_C(0xF01EAB71), UINT32_C(0xB0804187), UINT32_C(0x3C005E5F),
			UINT32_C(0x77A057BE), UINT32_C(0xBDE8AE24), UINT32_C(0x55464299), UINT32_C(0xBF582E61),
			UINT32_C(0x4E58F48F), UINT32_C(0xF2DDFDA2), UINT32_C(0xF474EF38), UINT32_C(0x8789BDC2),
			UINT32_C(0x5366F9C3), UINT32_C(0xC8B38E74), UINT32_C(0xB475F255), UINT32_C(0x46FCD9B9),
			UINT32_C(0x7AEB2661), UINT32_C(0x8B1DDF84), UINT32_C(0x846A0E79), UINT32_C(0x915F95E2),
			UINT32_C(0x466E598E), UINT32_C(0x20B45770), UINT32_C(0x8CD55591), UINT32_C(0xC902DE4C),
			UINT32_C(0xB90BACE1), UINT32_C(0xBB8205D0), UINT32_C(0x11A86248), UINT32_C(0x7574A99E),
			UINT32_C(0xB77F19B6), UINT32_C(0xE0A9DC09), UINT32_C(0x662D09A1), UINT32_C(0xC4324633),
			UINT32_C(0xE85A1F02), UINT32_C(0x09F0BE8C), UINT32_C(0x4A99A025), UINT32_C(0x1D6EFE10),
			UINT32_C(0x1AB93D1D), UINT32_C(0x0BA5A4DF), UINT32_C(0xA186F20F), UINT32_C(0x2868F169),
			UINT32_C(0xDCB7DA83), UINT32_C(0x573906FE), UINT32_C(0xA1E2CE9B), UINT32_C(0x4FCD7F52),
			UINT32_C(0x50115E01), UINT32_C(0xA70683FA), UINT32_C(0xA002B5C4), UINT32_C(0x0DE6D027),
			UINT32_C(0x9AF88C27), UINT32_C(0x773F8641), UINT32_C(0xC3604C06), UINT32_C(0x61A806B5),
			UINT32_C(0xF0177A28), UINT32_C(0xC0F586E0), UINT32_C(0x006058AA), UINT32_C(0x30DC7D62),
			UINT32_C(0x11E69ED7), UINT32_C(0x2338EA63), UINT32_C(0x53C2DD94), UINT32_C(0xC2C21634),
			UINT32_C(0xBBCBEE56), UINT32_C(0x90BCB6DE), UINT32_C(0xEBFC7DA1), UINT32_C(0xCE591D76),
			UINT32_C(0x6F05E409), UINT32_C(0x4B7C0188), UINT32_C(0x39720A3D), UINT32_C(0x7C927C24),
			UINT32_C(0x86E3725F), UINT32_C(0x724D9DB9), UINT32_C(0x1AC15BB4), UINT32_C(0xD39EB8FC),
			UINT32_C(0xED545578), UINT32_C(0x08FCA5B5), UINT32_C(0xD83D7CD3), UINT32_C(0x4DAD0FC4),
			UINT32_C(0x1E50EF5E), UINT32_C(0xB161E6F8), UINT32_C(0xA28514D9), UINT32_C(0x6C51133C),
			UINT32_C(0x6FD5C7E7), UINT32_C(0x56E14EC4), UINT32_C(0x362ABFCE), UINT32_C(0xDDC6C837),
			UINT32_C(0xD79A3234), UINT32_C(0x92638212), UINT32_C(0x670EFA8E), UINT32_C(0x406000E0),
		},
		{
			UINT32_C(0x3A39CE37), UINT32_C(0xD3FAF5CF), UINT32_C(0xABC27737), UINT32_C(0x5AC52D1B),
			UINT32_C(0x5CB0679E), UINT32_C(0x4FA33742), UINT32_C(0xD3822740), UINT32_C(0x99BC9BBE),
			UINT32_C(0xD5118E9D), UINT32_C(0xBF0F7315), UINT32_C(0xD62D1C7E), UINT32_C(0xC700C47B),
			UINT32_C(0xB78C1B6B), UINT32_C(0x21A19045), UINT32_C(0xB26EB1BE), UINT32_C(0x6A366EB4),
			UINT32_C(0x5748AB2F), UINT32_C(0xBC946E79), UINT32_C(0xC6A376D2), UINT32_C(0x6549C2C8),
			UINT32_C(0x530FF8EE), UINT32_C(0x468DDE7D), UINT32_C(0xD5730A1D), UINT32_C(0x4CD04DC6),
			UINT32_C(0x2939BBDB), UINT32_C(0xA9BA4650), UINT32_C(0xAC9526E8), UINT32_C(0xBE5EE304),
			UINT32_C(0xA1FAD5F0), UINT32_C(0x6A2D519A), UINT32_C(0x63EF8CE2), UINT32_C(0x9A86EE22),
			UINT32_C(0xC089C2B8), UINT32_C(0x43242EF6), UINT32_C(0xA51E03AA), UINT32_C(0x9CF2D0A4),
			UINT32_C(0x83C061BA), UINT32_C(0x9BE96A4D), UINT32_C(0x8FE51550), UINT32_C(0xBA645BD6),
			UINT32_C(0x2826A2F9), UINT32_C(0xA73A3AE1), UINT32_C(0x4BA99586), UINT32_C(0xEF5562E9),
			UINT32_C(0xC72FEFD3), UINT32_C(0xF752F7DA), UINT32_C(0x3F046F69), UINT32_C(0x77FA0A59),
			UINT32_C(0x80E4A915), UINT32_C(0x87B08601), UINT32_C(0x9B09E6AD), UINT32_C(0x3B3EE593),
			UINT32_C(0xE990FD5A), UINT32_C(0x9E34D797), UINT32_C(0x2CF0B7D9), UINT32_C(0x022B8B51),
			UINT32_C(0x96D5AC3A), UINT32_C(0x017DA67D), UINT32_C(0xD1CF3ED6), UINT32_C(0x7C7D2D28),
			UINT32_C(0x1F9F25CF), UINT32_C(0xADF2B89B), UINT32_C(0x5AD6B472), UINT32_C(0x5A88F54C),
			UINT32_C(0xE029AC71), UINT32_C(0xE019A5E6), UINT32_C(0x47B0ACFD), UINT32_C(0xED93FA9B),
			UINT32_C(0xE8D3C48D), UINT32_C(0x283B57CC), UINT32_C(0xF8D56629), UINT32_C(0x79132E28),
			UINT32_C(0x785F0191), UINT32_C(0xED756055), UINT32_C(0xF7960E44), UINT32_C(0xE3D35E8C),
			UINT32_C(0x15056DD4), UINT32_C(0x88F46DBA), UINT32_C(0x03A16125), UINT32_C(0x0564F0BD),
			UINT32_C(0xC3EB9E15), UINT32_C(0x3C9057A2), UINT32_C(0x97271AEC), UINT32_C(0xA93A072A),
			UINT32_C(0x1B3F6D9B), UINT32_C(0x1E6321F5), UINT32_C(0xF59C66FB), UINT32_C(0x26DCF319),
			UINT32_C(0x7533D928), UINT32_C(0xB155FDF5), UINT32_C(0x03563482), UINT32_C(0x8ABA3CBB),
			UINT32_C(0x28517711), UINT32_C(0xC20AD9F8), UINT32_C(0xABCC5167), UINT32_C(0xCCAD925F),
			UINT32_C(0x4DE81751), UINT32_C(0x3830DC8E), UINT32_C(0x379D5862), UINT32_C(0x9320F991),
			UINT32_C(0xEA7A90C2), UINT32_C(0xFB3E7BCE), UINT32_C(0x5121CE64), UINT32_C(0x774FBE32),
			UINT32_C(0xA8B6E37E), UINT32_C(0xC3293D46), UINT32_C(0x48DE5369), UINT32_C(0x6413E680),
			UINT32_C(0xA2AE0810), UINT32_C(0xDD6DB224), UINT32_C(0x69852DFD), UINT32_C(0x09072166),
			UINT32_C(0xB39A460A), UINT32_C(0x6445C0DD), UINT32_C(0x586CDECF), UINT32_C(0x1C20C8AE),
			UINT32_C(0x5BBEF7DD), UINT32_C(0x1B588D40), UINT32_C(0xCCD2017F), UINT32_C(0x6BB4E3BB),
			UINT32_C(0xDDA26A7E), UINT32_C(0x3A59FF45), UINT32_C(0x3E350A44), UINT32_C(0xBCB4CDD5),
			UINT32_C(0x72EACEA8), UINT32_C(0xFA6484BB), UINT32_C(0x8D6612AE), UINT32_C(0xBF3C6F47),
			UINT32_C(0xD29BE463), UINT32_C(0x542F5D9E), UINT32_C(0xAEC2771B), UINT32_C(0xF64E6370),
			UINT32_C(0x740E0D8D), UINT32_C(0xE75B1357), UINT32_C(0xF8721671), UINT32_C(0xAF537D5D),
			UINT32_C(0x4040CB08), UINT32_C(0x4EB4E2CC), UINT32_C(0x34D2466A), UINT32_C(0x0115AF84),
			UINT32_C(0xE1B00428), UINT32_C(0x95983A1D), UINT32_C(0x06B89FB4), UINT32_C(0xCE6EA048),
			UINT32_C(0x6F3F3B82), UINT32_C(0x3520AB82), UINT32_C(0x011A1D4B), UINT32_C(0x277227F8),
			UINT32_C(0x611560B1), UINT32_C(0xE7933FDC), UINT32_C(0xBB3A792B), UINT32_C(0x344525BD),
			UINT32_C(0xA08839E1), UINT32_C(0x51CE794B), UINT32_C(0x2F32C9B7), UINT32_C(0xA01FBAC9),
			UINT32_C(0xE01CC87E), UINT32_C(0xBCC7D1F6), UINT32_C(0xCF0111C3), UINT32_C(0xA1E8AAC7),
			UINT32_C(0x1A908749), UINT32_C(0xD44FBD9A), UINT32_C(0xD0DADECB), UINT32_C(0xD50ADA38),
			UINT32_C(0x0339C32A), UINT32_C(0xC6913667), UINT32_C(0x8DF9317C), UINT32_C(0xE0B12B4F),
			UINT32_C(0xF79E59B7), UINT32_C(0x43F5BB3A), UINT32_C(0xF2D519FF), UINT32_C(0x27D9459C),
			UINT32_C(0xBF97222C), UINT32_C(0x15E6FC2A), UINT32_C(0x0F91FC71), UINT32_C(0x9B941525),
			UINT32_C(0xFAE59361), UINT32_C(0xCEB69CEB), UINT32_C(0xC2A86459), UINT32_C(0x12BAA8D1),
			UINT32_C(0xB6C1075E), UINT32_C(0xE3056A0C), UINT32_C(0x10D25065), UINT32_C(0xCB03A442),
			UINT32_C(0xE0EC6E0E), UINT32_C(0x1698DB3B), UINT32_C(0x4C98A0BE), UINT32_C(0x3278E964),
			UINT32_C(0x9F1F9532), UINT32_C(0xE0D392DF), UINT32_C(0xD3A0342B), UINT32_C(0x8971F21E),
			UINT32_C(0x1B0A7441), UINT32_C(0x4BA3348C), UINT32_C(0xC5BE7120), UINT32_C(0xC37632D8),
			UINT32_C(0xDF359F8D), UINT32_C(0x9B992F2E), UINT32_C(0xE60B6F47), UINT32_C(0x0FE3F11D),
			UINT32_C(0xE54CDA54), UINT32_C(0x1EDAD891), UINT32_C(0xCE6279CF), UINT32_C(0xCD3E7E6F),
			UINT32_C(0x1618B166), UINT32_C(0xFD2C1D05), UINT32_C(0x848FD2C5), UINT32_C(0xF6FB2299),
			UINT32_C(0xF523F357), UINT32_C(0xA6327623), UINT32_C(0x93A83531), UINT32_C(0x56CCCD02),
			UINT32_C(0xACF08162), UINT32_C(0x5A75EBB5), UINT32_C(0x6E163697), UINT32_C(0x88D273CC),
			UINT32_C(0xDE966292), UINT32_C(0x81B949D0), UINT32_C(0x4C50901B), UINT32_C(0x71C65614),
			UINT32_C(0xE6C6C7BD), UINT32_C(0x327A140A), UINT32_C(0x45E1D006), UINT32_C(0xC3F27B9A),
			UINT32_C(0xC9AA53FD), UINT32_C(0x62A80F00), UINT32_C(0xBB25BFE2), UINT32_C(0x35BDD2F6),
			UINT32_C(0x71126905), UINT32_C(0xB2040222), UINT32_C(0xB6CBCF7C), UINT32_C(0xCD769C2B),
			UINT32_C(0x53113EC0), UINT32_C(0x1640E3D3), UINT32_C(0x38ABBD60), UINT32_C(0x2547ADF0),
			UINT32_C(0xBA38209C), UINT32_C(0xF746CE76), UINT32_C(0x77AFA1C5), UINT32_C(0x20756060),
			UINT32_C(0x85CBFE4E), UINT32_C(0x8AE88DD8), UINT32_C(0x7AAAF9B0), UINT32_C(0x4CF9AA7E),
			UINT32_C(0x1948C25C), UINT32_C(0x02FB8A8C), UINT32_C(0x01C36AE4), UINT32_C(0xD6EBE1F9),
			UINT32_C(0x90D4F869), UINT32_C(0xA65CDEA0), UINT32_C(0x3F09252D), UINT32_C(0xC208E69F),
			UINT32_C(0xB74E6132), UINT32_C(0xCE77E25B), UINT32_C(0x578FDFE3), UINT32_C(0x3AC372E6),
		},
	},
};

static void
atheme_eks_bf_ctx_init(struct atheme_eks_bf_ctx *const restrict ctx)
{
	(void) memcpy(ctx, &atheme_eks_bf_initial_state, sizeof atheme_eks_bf_initial_state);
}

static uint32_t
atheme_eks_bf_word(const unsigned char *const restrict data, const size_t data_len, size_t *const restrict pos)
{
	uint32_t temp = 0U;
	size_t idx = *pos;

	for (unsigned int i = 0U; i < 4U; i++)
	{
		if (idx >= data_len)
			idx = 0U;

		temp = ((temp << 8U) | data[idx++]);
	}

	*pos = idx;
	return temp;
}

static inline uint32_t
atheme_eks_bf_f(const struct atheme_eks_bf_ctx *const restrict ctx, const uint32_t T)
{
	return ((((ctx->S[0x00U][((T >> 0x18U) & 0xFFU)]) + ctx->S[0x01U][((T >> 0x10U) & 0xFFU)])
	         ^ ctx->S[0x02U][((T >> 0x08U) & 0xFFU)]) + ctx->S[0x03U][((T >> 0x00U) & 0xFFU)]);
}

static void
atheme_eks_bf_encipher(struct atheme_eks_bf_ctx *const restrict ctx,
                       uint32_t *const restrict Lo, uint32_t *const restrict Ro)
{
	uint32_t Li = *Lo;
	uint32_t Ri = *Ro;
	size_t N = 0U;

	Li ^= ctx->P[N++];

	for (unsigned int i = 0U; i < 8U; i++)
	{
		Ri ^= (atheme_eks_bf_f(ctx, Li) ^ ctx->P[N++]);
		Li ^= (atheme_eks_bf_f(ctx, Ri) ^ ctx->P[N++]);
	}

	Ri ^= ctx->P[N++];

	*Lo = Ri;
	*Ro = Li;

	(void) smemzero(&Li, sizeof Li);
	(void) smemzero(&Ri, sizeof Ri);
}

static void
atheme_eks_bf_expand_state(struct atheme_eks_bf_ctx *const restrict ctx, const unsigned char *const restrict data,
                           const size_t data_len, const unsigned char *const restrict key, const size_t key_len)
{
	size_t data_pos = 0U;
	size_t key_pos = 0U;
	uint32_t L = 0U;
	uint32_t R = 0U;

	for (unsigned int i = 0U; i < 18U; i++)
		ctx->P[i] ^= atheme_eks_bf_word(key, key_len, &key_pos);

	for (unsigned int i = 0U; i < 18U; i += 2U)
	{
		if (data && data_len)
		{
			L ^= atheme_eks_bf_word(data, data_len, &data_pos);
			R ^= atheme_eks_bf_word(data, data_len, &data_pos);
		}

		(void) atheme_eks_bf_encipher(ctx, &L, &R);

		ctx->P[i + 0U] = L;
		ctx->P[i + 1U] = R;
	}

	for (unsigned int i = 0U; i < 4U; i++)
	{
		for (unsigned int k = 0U; k < 256U; k += 2U)
		{
			if (data && data_len)
			{
				L ^= atheme_eks_bf_word(data, data_len, &data_pos);
				R ^= atheme_eks_bf_word(data, data_len, &data_pos);
			}

			(void) atheme_eks_bf_encipher(ctx, &L, &R);

			ctx->S[i][k + 0U] = L;
			ctx->S[i][k + 1U] = R;
		}
	}

	(void) smemzero(&L, sizeof L);
	(void) smemzero(&R, sizeof R);
}

bool ATHEME_FATTR_WUR
atheme_eks_bf_compute(const char *const restrict password, const unsigned int minor, const unsigned int cost,
                      const unsigned char salt[const restrict static ATHEME_BCRYPT_SALTLEN],
                      unsigned char hash[const restrict static ATHEME_BCRYPT_HASHLEN])
{
	unsigned char ciphertext[ATHEME_BCRYPT_HASHLEN] = "OrpheanBeholderScryDoubt";
	uint32_t cdata[ATHEME_EKS_BF_WORDS];
	struct atheme_eks_bf_ctx ctx;
	size_t pass_len;

	if (cost > ATHEME_BCRYPT_ROUNDS_MAX)
		return false;

	switch (minor)
	{
		case 'a':
			pass_len = ((strlen(password) + 1U) % 256U);
			break;

		case 'b':
			pass_len = strlen(password);
			if (pass_len > 72U)
				pass_len = 72U;

			pass_len++;
			break;

		default:
			return false;
	}

	(void) atheme_eks_bf_ctx_init(&ctx);
	(void) atheme_eks_bf_expand_state(&ctx, salt, ATHEME_BCRYPT_SALTLEN, (const void *) password, pass_len);

	for (unsigned int i = 0U; i < (1U << cost); i++)
	{
		(void) atheme_eks_bf_expand_state(&ctx, NULL, 0U, (const void *) password, pass_len);
		(void) atheme_eks_bf_expand_state(&ctx, NULL, 0U, salt, ATHEME_BCRYPT_SALTLEN);
	}

	{
		// This could be precomputed ...
		size_t ciphertextpos = 0U;
		for (unsigned int i = 0U; i < ATHEME_EKS_BF_WORDS; i++)
			cdata[i] = atheme_eks_bf_word(ciphertext, sizeof ciphertext, &ciphertextpos);
	}

	for (unsigned int i = 0U; i < 64U; i++)
	{
		uint32_t *cdataptr = cdata;

		for (unsigned int j = 0U; j < 3U; j++)
		{
			(void) atheme_eks_bf_encipher(&ctx, cdataptr + 0U, cdataptr + 1U);

			cdataptr += 2U;
		}
	}

	for (unsigned int i = 0U; i < ATHEME_EKS_BF_WORDS; i++)
	{
		ciphertext[(i * 4U) + 3U] = cdata[i] & 0xFFU; cdata[i] = cdata[i] >> 8U;
		ciphertext[(i * 4U) + 2U] = cdata[i] & 0xFFU; cdata[i] = cdata[i] >> 8U;
		ciphertext[(i * 4U) + 1U] = cdata[i] & 0xFFU; cdata[i] = cdata[i] >> 8U;
		ciphertext[(i * 4U) + 0U] = cdata[i] & 0xFFU; cdata[i] = cdata[i] >> 8U;
	}

	(void) memcpy(hash, ciphertext, ATHEME_BCRYPT_HASHLEN);

	(void) smemzero(cdata, sizeof cdata);
	(void) smemzero(ciphertext, sizeof ciphertext);
	(void) smemzero(&ctx, sizeof ctx);

	return true;
}

bool ATHEME_FATTR_WUR
atheme_eks_bf_testsuite_run(void)
{
	/* Vectors cover both versions of the algorithm ($2a$, $2b$) with password lengths of 16, 72, 80, 255, and 288
	 * The 288-character test is for PASSLEN, & also uses a different cost parameter, to ensure that's working too
	 * This tests proper password truncation across both versions and excercises the integer overflow bug in $2a$
	 * Generated using OpenBSD 6.6 crypt(3). Also included are the vectors from Openwall.   -- amdj
	 */

	static const struct {
		unsigned int    minor;
		unsigned int    cost;
		const char *    pass;
		const char *    salt;
		const char *    hash;
	} bcrypt_test_vectors[] = {
		{
			.minor  = 'a',
			.cost   = 6U,
			.pass   = "CBeUJzTele9heJUJ",
			.salt   = "ohenGeFSDABnUHh5SeDd6.",
			.hash   = "ag71YUUK2lOIXs5ixAvAJ34tmmodOwy",
		}, {
			.minor  = 'a',
			.cost   = 6U,
			.pass   = "EgXXVII2yoB9B8J84W0da06r1Re6qctv145uncvrwWc2qdFml6aGcbq3Kb1ZBLBKxzT8mUuf",
			.salt   = "NTDvUCJaRdg3jQ9oKipNY.",
			.hash   = "LGN0dmI925eGyg0QdECEKzyTRmnHKBW",
		}, {
			.minor  = 'a',
			.cost   = 6U,
			.pass   = "5CTTpzdE2lfamlvySgJm12Tqxz2nx7m6n3UNEgphhBE4tml2hZYL9FiVeWXzAoy95f5IF0Zr1F6CwYZH",
			.salt   = "CFVz6yjKeTCPK7FPmiPdS.",
			.hash   = "WSbzIlrqiONTkd0oT5Agt0ooju1RFwC",
		}, {
			.minor  = 'a',
			.cost   = 6U,
			.pass   = "KFRo2WhHkgRrbFPrs5ExAbpKMcbyoY85Dbajg5e7GFeL2eLwX2H6wOgERB9ii8FLZJddowWfeSddyV26"
			          "R21kgUnLzlcoARLVKFZXonpjJKmCfDUnNJU5NqoWyJuNcKCHHPlaKuuzRfPQvB0rbUTEqrYhHXw5WaOb"
			          "mW0BuUMtgIPxxgispnmqhVq5Qx6eEWQHPKPWSR6Ok3Dje5GodoxUuORcSr5zoEvDQ0fxitiU36JjrQuV"
			          "XWbz2g2gW1L8hui",
			.salt   = "6sO2ANIReq82hjEpTp9UX.",
			.hash   = "MCUbT2Np9CaWqL6IiRIpgJgprWj/ADC",
		}, {
			.minor  = 'a',
			.cost   = 7U,
			.pass   = "9CGRpgwoaOVeN3aRknQNy694JwCJ8JZQS9LQD5y0faeDcqe5d3MbTgubWEezJSVeuOnLtO7nCUjgJLcY"
			          "RwrKfStA21rCwVnxvGToI9FHdv1PiG6pKEA6zODUY2db5tu778sWqeplzlLaEFkiHP8p1pddfRD1SO4k"
			          "VNgpIVu1XJY266LkCYP0N813nU91gD4GDLHqZHJMgwHcL4bE8AAw8Mxj6fWIdeqUHMIFEelydDrv3Xg8"
			          "5YEda8GlmgNuDUtp3Xhnx4V6kBvUnOyse4yhnzAA4vV6a4zM",
			.salt   = "8LatJY1B0xLgOqjJgnw8n.",
			.hash   = "hAxiWPSgcU3FO.Zv1xLpuabK57TpshG",
		}, {
			.minor  = 'b',
			.cost   = 6U,
			.pass   = "HxRuFQ6NQQ6qUGyl",
			.salt   = "2A6mT9C8DmTFh4COUmVUv.",
			.hash   = "wkgqGlOmWAA9idF6/6Lgh6HV5tKzKJy",
		}, {
			.minor  = 'b',
			.cost   = 6U,
			.pass   = "DGk1phfKLIiDICtomAcWKmoWSTQRuhlKnlg7W2SFKYds7LiYDSiYTdRP62fqVhWc7V8rBGxB",
			.salt   = "hQBwoEjLAKchHTV1aUAwH.",
			.hash   = "Nz9vouAKZJyRhxis9jH1Gme1WpPS7rK",
		}, {
			.minor  = 'b',
			.cost   = 6U,
			.pass   = "9VbzUUUjP4IJ4J6bnVHQATV0lUUcaTUz2Wrthm7M6dhXe6Mia2eDAL04DdvLtcLWMBKP67T79ZPeXMcc",
			.salt   = "nRUAtHMvRN2V9TwWQ0pAH.",
			.hash   = "95eFAsnMyu9AucGbQvAzK/2jxOSxS2e",
		}, {
			.minor  = 'b',
			.cost   = 6U,
			.pass   = "snAWwjATOEY9GC4RvBxMR0sfHAwMqa5MiCAuHFZkE08g8oU256osYjxkaRSmwFrgLMpxyDcvsGvVi6KC"
			          "sAF7sF2UDcY3LNZ3kpFjsIYF7ZlJkjiXtmqkl0YFI6HFp3AWBLsROoVPe1WJRSTmPka2hCox8KBMWLdA"
			          "NnqOekKtEkZHrSQYH2UzBFWmDrxeeLDnUo03JBswmkswkXMrwun7tKg7SD0W1YzvMndj4d1NnA6gbL2y"
			          "pSmMnqm0c60Ge9J",
			.salt   = "jraRNxLBFSUeFzyJJy1ZB.",
			.hash   = "DmeFiqUoWseb6fGWI4e8YZzgl52w37a",
		}, {
			.minor  = 'b',
			.cost   = 7U,
			.pass   = "O3mnkoiEiCSwgeWsgfiYqQy4PvGFE4xMCDcwBgfBVT0HmlE9ZaVhSftoSR4N4VaJfQPF0GJJqGLsCSMP"
			          "WHAhD5299LKl2sxEyiiVchCJCN4sSplQbzLXdqpPU6Z2aXtlTde82sa0mvrmt3eIeW0j9bHSlo49FT02"
			          "hRgjX75qOXkvArJAKzYENt0LFHB83JaoFXrwKajfMBqOP7nLZoIGkMRG3DYWArTf3ns351fIeLlLpAy0"
			          "PQDk9BZ6nL1kuM3gAhjOK7UqjPR5u6y3EkWiClgnQoAmTOrJ",
			.salt   = "x1vqpIY72Ve8jGCBX0tYQ.",
			.hash   = "v2T7to51OKHvwRCVIBvw5VZoPhCKgJ6",
		}, {
			.minor  = 'a',
			.cost   = 0U,
			.pass   = "8b \xd0\xc1\xd2\xcf\xcc\xd8",
			.salt   = "abcdefghijklmnopqrstuu",
			.hash   = "i1D709vfamulimlGcq0qq3UvuUasvEa",
		}, {
			.minor  = 'b',
			.cost   = 0U,
			.pass   = "8b \xd0\xc1\xd2\xcf\xcc\xd8",
			.salt   = "abcdefghijklmnopqrstuu",
			.hash   = "i1D709vfamulimlGcq0qq3UvuUasvEa",
		},
	};

	(void) slog(LG_DEBUG, "%s: running self-test", MOWGLI_FUNC_NAME);

	for (size_t vecnum = 0U; vecnum < ((sizeof bcrypt_test_vectors) / (sizeof bcrypt_test_vectors[0])); vecnum++)
	{
		unsigned char saltbuf[ATHEME_BCRYPT_SALTLEN];
		unsigned char hashbuf[ATHEME_BCRYPT_HASHLEN];
		unsigned char compbuf[ATHEME_BCRYPT_HASHLEN];

		if (base64_decode_table(bcrypt_test_vectors[vecnum].salt, saltbuf, sizeof saltbuf,
		      BASE64_ALPHABET_CRYPT3_BLOWFISH) != sizeof saltbuf)
		{
			(void) slog(LG_ERROR, "%s: vector %zu: base64_decode_table(salt) failed (BUG)",
			                      MOWGLI_FUNC_NAME, vecnum);
			return false;
		}

		const size_t hashlen = base64_decode_table(bcrypt_test_vectors[vecnum].hash, hashbuf,
		                                           sizeof hashbuf, BASE64_ALPHABET_CRYPT3_BLOWFISH);

		if (hashlen == BASE64_FAIL)
		{
			(void) slog(LG_ERROR, "%s: vector %zu: base64_decode_table(hash) failed (BUG)",
			                      MOWGLI_FUNC_NAME, vecnum);
			return false;
		}

		if (! atheme_eks_bf_compute(bcrypt_test_vectors[vecnum].pass, bcrypt_test_vectors[vecnum].minor,
		                            bcrypt_test_vectors[vecnum].cost, saltbuf, compbuf))
			// This function logs messages on failure
			return false;

		if (memcmp(hashbuf, compbuf, hashlen) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector %zu: memcmp(3) mismatch; algorithm is not functioning "
			                      "correctly (BUG)", MOWGLI_FUNC_NAME, vecnum);
			return false;
		}
	}

	return true;
}
