@@ -1994,7 +1994,7 @@ def absolute_install_dir(p):
def choose_python_exe():
exe = sys.executable

if exe[1] == ':': # Windows style paths
if options.os == 'mingw': # mingw doesn't handle the backslashes in the absolute path well
return exe.replace('\\', '/')

return exe
@@ -2137,9 +2137,9 @@ def choose_cxx_exe():

'visibility_attribute': cc.gen_visibility_attribute(options),

'lib_link_cmd': cc.so_link_command_for(osinfo.basename, options) + ' ' + external_link_cmd(),
'exe_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + ' ' + external_link_cmd(),
'post_link_cmd': '',
'lib_link_cmd': cc.so_link_command_for(osinfo.basename, options),
'exe_link_cmd': cc.binary_link_command_for(osinfo.basename, options),
'external_link_cmd': external_link_cmd(),

'ar_command': ar_command(),
'ar_options': options.ar_options or cc.ar_options or osinfo.ar_options,
@@ -304,6 +304,9 @@ channels.

Available if ``BOTAN_HAS_NOEKEON`` is defined.

.. warning::
Support for Noekeon is deprecated and will be removed in a future major release.

SEED
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@@ -154,6 +154,9 @@ Available if ``BOTAN_HAS_MD4`` is defined.
An old hash function that is now known to be trivially breakable. It is very
fast, and may still be suitable as a (non-cryptographic) checksum.

.. warning::
Support for MD4 is deprecated and will be removed in a future major release.

MD5
^^^^^^^^^

@@ -83,6 +83,9 @@ A KDF from ANSI X9.42. Sometimes used for Diffie-Hellman.

Available if ``BOTAN_HAS_X942_PRF`` is defined.

.. warning::
Support for X9.42 KDF is deprecated and will be removed in a future major release.

SP800-108
~~~~~~~~~~

@@ -59,9 +59,11 @@ Deprecated Functionality
This section lists cryptographic functionality which will be removed
in a future major release.

- Block ciphers CAST-256, GOST 28147, Kasumi, MISTY1, DESX, and XTEA.
- Block ciphers CAST-256, GOST 28147, Kasumi, MISTY1, DESX, XTEA, Noekeon

- Hash functions GOST 34.11-94 and Tiger
- Hash functions GOST 34.11-94, Tiger, MD4

- X9.42 KDF

- DLIES

@@ -1,6 +1,22 @@
Release Notes
========================================

Version 2.17.3, 2020-12-21
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* Change base64, base58, base32, and hex encoding and decoding opearations
to run in constant time (GH #2549)

* Fix a build problem on PPC64 building with Clang (GH #2547)

* Fix an install problem introduced in 2.17.2 affecting MSVC 2015

* Fix use of -L flag in linking when configured using ``--with-external-libdir``
(GH #2496)

* Fix a build problem on big-endian PowerPC related to VSX instructions
in the AES code. (GH #2515)

Version 2.17.2, 2020-11-13
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@@ -27,9 +27,9 @@ If you think you have found a security issue, see the `security page
<https://botan.randombit.net/security.html>`_ for contact information.

The latest release is
`2.17.2 <https://botan.randombit.net/releases/Botan-2.17.2.tar.xz>`_
`(sig) <https://botan.randombit.net/releases/Botan-2.17.2.tar.xz.asc>`_,
released on 2020-11-13.
`2.17.3 <https://botan.randombit.net/releases/Botan-2.17.3.tar.xz>`_
`(sig) <https://botan.randombit.net/releases/Botan-2.17.3.tar.xz.asc>`_,
released on 2020-12-21.
All releases are signed with a `PGP key <https://botan.randombit.net/pgpkey.txt>`_.
See the `release notes <https://botan.randombit.net/news.html>`_ for
what is new. Botan is also available through most
@@ -10,6 +10,7 @@ evbarm # For NetBSD

armv7
armv7l
arvm7a
armv7-a

armv8l # For AlpineLinux
@@ -58,7 +58,7 @@ rdseed -> "-mrdseed"
sha -> "-msha"
altivec -> "-maltivec"

ppc64:powercrypto -> "-mcrypto"
ppc64:powercrypto -> "-mcrypto -mvsx"
ppc64:power9 -> "-mcpu=power9"

arm64:armv8crypto -> "-march=armv8+crypto"
@@ -64,7 +64,7 @@ rdseed -> "-mrdseed"
sha -> "-msha"
altivec -> "-maltivec"

powercrypto -> "-mcrypto"
powercrypto -> "-mcrypto -mvsx"
ppc64:power9 -> "-mcpu=power9"

arm64:armv8crypto -> ""
@@ -20,7 +20,7 @@ LDFLAGS = %{ldflags}

EXE_LINK_CMD = %{exe_link_cmd}

LIB_LINKS_TO = %{link_to}
LIB_LINKS_TO = %{external_link_cmd} %{link_to}
EXE_LINKS_TO = %{link_to_botan} $(LIB_LINKS_TO)

BUILD_FLAGS = $(ABI_FLAGS) $(LANG_FLAGS) $(CXXFLAGS) $(WARN_FLAGS)
@@ -48,19 +48,19 @@ docs: %{doc_stamp_file}
%{endif}

%{doc_stamp_file}: %{doc_dir}/*.rst %{doc_dir}/api_ref/*.rst %{doc_dir}/dev_ref/*.rst
$(PYTHON_EXE) $(SCRIPTS_DIR)/build_docs.py --build-dir="%{build_dir}"
"$(PYTHON_EXE)" "$(SCRIPTS_DIR)/build_docs.py" --build-dir="%{build_dir}"

clean:
$(PYTHON_EXE) $(SCRIPTS_DIR)/cleanup.py --build-dir="%{build_dir}"
"$(PYTHON_EXE)" "$(SCRIPTS_DIR)/cleanup.py" --build-dir="%{build_dir}"

distclean:
$(PYTHON_EXE) $(SCRIPTS_DIR)/cleanup.py --build-dir="%{build_dir}" --distclean
"$(PYTHON_EXE)" "$(SCRIPTS_DIR)/cleanup.py" --build-dir="%{build_dir}" --distclean

install: %{install_targets}
$(PYTHON_EXE) $(SCRIPTS_DIR)/install.py --prefix="%{prefix}" --build-dir="%{build_dir}" --bindir=%{bindir} --libdir=%{libdir} --docdir=%{docdir} --includedir=%{includedir}
"$(PYTHON_EXE)" "$(SCRIPTS_DIR)/install.py" --prefix="%{prefix}" --build-dir="%{build_dir}" --bindir="%{bindir}" --libdir="%{libdir}" --docdir="%{docdir}" --includedir="%{includedir}"

check: tests
$(PYTHON_EXE) $(SCRIPTS_DIR)/check.py --build-dir="%{build_dir}"
"$(PYTHON_EXE)" "$(SCRIPTS_DIR)/check.py" --build-dir="%{build_dir}"

# Object Files
LIBOBJS = %{join lib_objs}
@@ -1,7 +1,7 @@

release_major = 2
release_minor = 17
release_patch = 2
release_patch = 3
release_suffix = ''
release_so_abi_rev = 17

@@ -27,7 +27,7 @@ namespace {

namespace ARIA_F {

alignas(16)
alignas(64)
const uint32_t S1[256]={
0x00636363,0x007c7c7c,0x00777777,0x007b7b7b,0x00f2f2f2,0x006b6b6b,0x006f6f6f,0x00c5c5c5,
0x00303030,0x00010101,0x00676767,0x002b2b2b,0x00fefefe,0x00d7d7d7,0x00ababab,0x00767676,
@@ -63,7 +63,7 @@ const uint32_t S1[256]={
0x00414141,0x00999999,0x002d2d2d,0x000f0f0f,0x00b0b0b0,0x00545454,0x00bbbbbb,0x00161616
};

alignas(16)
alignas(64)
const uint32_t S2[256]={
0xe200e2e2,0x4e004e4e,0x54005454,0xfc00fcfc,0x94009494,0xc200c2c2,0x4a004a4a,0xcc00cccc,
0x62006262,0x0d000d0d,0x6a006a6a,0x46004646,0x3c003c3c,0x4d004d4d,0x8b008b8b,0xd100d1d1,
@@ -99,7 +99,7 @@ const uint32_t S2[256]={
0x89008989,0xde00dede,0x71007171,0x1a001a1a,0xaf00afaf,0xba00baba,0xb500b5b5,0x81008181
};

alignas(16)
alignas(64)
const uint32_t X1[256]={
0x52520052,0x09090009,0x6a6a006a,0xd5d500d5,0x30300030,0x36360036,0xa5a500a5,0x38380038,
0xbfbf00bf,0x40400040,0xa3a300a3,0x9e9e009e,0x81810081,0xf3f300f3,0xd7d700d7,0xfbfb00fb,
@@ -135,7 +135,7 @@ const uint32_t X1[256]={
0xe1e100e1,0x69690069,0x14140014,0x63630063,0x55550055,0x21210021,0x0c0c000c,0x7d7d007d
};

alignas(16)
alignas(64)
const uint32_t X2[256]={
0x30303000,0x68686800,0x99999900,0x1b1b1b00,0x87878700,0xb9b9b900,0x21212100,0x78787800,
0x50505000,0x39393900,0xdbdbdb00,0xe1e1e100,0x72727200,0x09090900,0x62626200,0x3c3c3c00,
@@ -13,7 +13,7 @@ namespace Botan {

namespace {

const uint64_t Camellia_SBOX1[256] = {
alignas(64) const uint64_t Camellia_SBOX1[256] = {
0x7070700070000070, 0x8282820082000082, 0x2C2C2C002C00002C, 0xECECEC00EC0000EC,
0xB3B3B300B30000B3, 0x2727270027000027, 0xC0C0C000C00000C0, 0xE5E5E500E50000E5,
0xE4E4E400E40000E4, 0x8585850085000085, 0x5757570057000057, 0x3535350035000035,
@@ -79,7 +79,7 @@ const uint64_t Camellia_SBOX1[256] = {
0x1515150015000015, 0xE3E3E300E30000E3, 0xADADAD00AD0000AD, 0xF4F4F400F40000F4,
0x7777770077000077, 0xC7C7C700C70000C7, 0x8080800080000080, 0x9E9E9E009E00009E };

const uint64_t Camellia_SBOX2[256] = {
alignas(64) const uint64_t Camellia_SBOX2[256] = {
0x00E0E0E0E0E00000, 0x0005050505050000, 0x0058585858580000, 0x00D9D9D9D9D90000,
0x0067676767670000, 0x004E4E4E4E4E0000, 0x0081818181810000, 0x00CBCBCBCBCB0000,
0x00C9C9C9C9C90000, 0x000B0B0B0B0B0000, 0x00AEAEAEAEAE0000, 0x006A6A6A6A6A0000,
@@ -145,7 +145,7 @@ const uint64_t Camellia_SBOX2[256] = {
0x002A2A2A2A2A0000, 0x00C7C7C7C7C70000, 0x005B5B5B5B5B0000, 0x00E9E9E9E9E90000,
0x00EEEEEEEEEE0000, 0x008F8F8F8F8F0000, 0x0001010101010000, 0x003D3D3D3D3D0000 };

const uint64_t Camellia_SBOX3[256] = {
alignas(64) const uint64_t Camellia_SBOX3[256] = {
0x3800383800383800, 0x4100414100414100, 0x1600161600161600, 0x7600767600767600,
0xD900D9D900D9D900, 0x9300939300939300, 0x6000606000606000, 0xF200F2F200F2F200,
0x7200727200727200, 0xC200C2C200C2C200, 0xAB00ABAB00ABAB00, 0x9A009A9A009A9A00,
@@ -211,7 +211,7 @@ const uint64_t Camellia_SBOX3[256] = {
0x8A008A8A008A8A00, 0xF100F1F100F1F100, 0xD600D6D600D6D600, 0x7A007A7A007A7A00,
0xBB00BBBB00BBBB00, 0xE300E3E300E3E300, 0x4000404000404000, 0x4F004F4F004F4F00 };

const uint64_t Camellia_SBOX4[256] = {
alignas(64) const uint64_t Camellia_SBOX4[256] = {
0x7070007000007070, 0x2C2C002C00002C2C, 0xB3B300B30000B3B3, 0xC0C000C00000C0C0,
0xE4E400E40000E4E4, 0x5757005700005757, 0xEAEA00EA0000EAEA, 0xAEAE00AE0000AEAE,
0x2323002300002323, 0x6B6B006B00006B6B, 0x4545004500004545, 0xA5A500A50000A5A5,
@@ -277,7 +277,7 @@ const uint64_t Camellia_SBOX4[256] = {
0x2828002800002828, 0x7B7B007B00007B7B, 0xC9C900C90000C9C9, 0xC1C100C10000C1C1,
0xE3E300E30000E3E3, 0xF4F400F40000F4F4, 0xC7C700C70000C7C7, 0x9E9E009E00009E9E };

const uint64_t Camellia_SBOX5[256] = {
alignas(64) const uint64_t Camellia_SBOX5[256] = {
0x00E0E0E000E0E0E0, 0x0005050500050505, 0x0058585800585858, 0x00D9D9D900D9D9D9,
0x0067676700676767, 0x004E4E4E004E4E4E, 0x0081818100818181, 0x00CBCBCB00CBCBCB,
0x00C9C9C900C9C9C9, 0x000B0B0B000B0B0B, 0x00AEAEAE00AEAEAE, 0x006A6A6A006A6A6A,
@@ -343,7 +343,7 @@ const uint64_t Camellia_SBOX5[256] = {
0x002A2A2A002A2A2A, 0x00C7C7C700C7C7C7, 0x005B5B5B005B5B5B, 0x00E9E9E900E9E9E9,
0x00EEEEEE00EEEEEE, 0x008F8F8F008F8F8F, 0x0001010100010101, 0x003D3D3D003D3D3D };

const uint64_t Camellia_SBOX6[256] = {
alignas(64) const uint64_t Camellia_SBOX6[256] = {
0x3800383838003838, 0x4100414141004141, 0x1600161616001616, 0x7600767676007676,
0xD900D9D9D900D9D9, 0x9300939393009393, 0x6000606060006060, 0xF200F2F2F200F2F2,
0x7200727272007272, 0xC200C2C2C200C2C2, 0xAB00ABABAB00ABAB, 0x9A009A9A9A009A9A,
@@ -409,7 +409,7 @@ const uint64_t Camellia_SBOX6[256] = {
0x8A008A8A8A008A8A, 0xF100F1F1F100F1F1, 0xD600D6D6D600D6D6, 0x7A007A7A7A007A7A,
0xBB00BBBBBB00BBBB, 0xE300E3E3E300E3E3, 0x4000404040004040, 0x4F004F4F4F004F4F };

const uint64_t Camellia_SBOX7[256] = {
alignas(64) const uint64_t Camellia_SBOX7[256] = {
0x7070007070700070, 0x2C2C002C2C2C002C, 0xB3B300B3B3B300B3, 0xC0C000C0C0C000C0,
0xE4E400E4E4E400E4, 0x5757005757570057, 0xEAEA00EAEAEA00EA, 0xAEAE00AEAEAE00AE,
0x2323002323230023, 0x6B6B006B6B6B006B, 0x4545004545450045, 0xA5A500A5A5A500A5,
@@ -475,7 +475,7 @@ const uint64_t Camellia_SBOX7[256] = {
0x2828002828280028, 0x7B7B007B7B7B007B, 0xC9C900C9C9C900C9, 0xC1C100C1C1C100C1,
0xE3E300E3E3E300E3, 0xF4F400F4F4F400F4, 0xC7C700C7C7C700C7, 0x9E9E009E9E9E009E };

const uint64_t Camellia_SBOX8[256] = {
alignas(64) const uint64_t Camellia_SBOX8[256] = {
0x7070700070707000, 0x8282820082828200, 0x2C2C2C002C2C2C00, 0xECECEC00ECECEC00,
0xB3B3B300B3B3B300, 0x2727270027272700, 0xC0C0C000C0C0C000, 0xE5E5E500E5E5E500,
0xE4E4E400E4E4E400, 0x8585850085858500, 0x5757570057575700, 0x3535350035353500,
@@ -238,7 +238,7 @@ void CAST_128::clear()
void CAST_128::cast_ks(secure_vector<uint32_t>& K,
secure_vector<uint32_t>& X)
{
static const uint32_t S5[256] = {
alignas(64) static const uint32_t S5[256] = {
0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911, 0xB86A7FFF, 0x1DD358F5,
0x44DD9D44, 0x1731167F, 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,
0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A, 0xE6A2E77F, 0xF0C720CD,
@@ -283,7 +283,7 @@ void CAST_128::cast_ks(secure_vector<uint32_t>& K,
0x34010718, 0xBB30CAB8, 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,
0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4 };

static const uint32_t S6[256] = {
alignas(64) static const uint32_t S6[256] = {
0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C, 0x95DB08E7, 0x016843B4,
0xECED5CBC, 0x325553AC, 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138, 0x33F14961, 0xC01937BD,
@@ -328,7 +328,7 @@ void CAST_128::cast_ks(secure_vector<uint32_t>& K,
0xB0E93524, 0xBEBB8FBD, 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,
0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F };

static const uint32_t S7[256] = {
alignas(64) static const uint32_t S7[256] = {
0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693, 0x2A8D7F6F, 0xAB9BC912,
0xDE6008A1, 0x2028DA1F, 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,
0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE, 0xA05FBCF6, 0xCD4181E9,
@@ -373,7 +373,7 @@ void CAST_128::cast_ks(secure_vector<uint32_t>& K,
0xC3C0BDAE, 0x4958C24C, 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3 };

static const uint32_t S8[256] = {
alignas(64) static const uint32_t S8[256] = {
0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095, 0x7789F8B7, 0xE6C1121B,
0x0E241600, 0x052CE8B5, 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,
0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC, 0xDE9ADEB1, 0x0A0CC32C,
@@ -12,7 +12,7 @@

namespace Botan {

const uint32_t CAST_SBOX1[256] = {
alignas(64) const uint32_t CAST_SBOX1[256] = {
0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A, 0x1E213F2F, 0x9C004DD3,
0x6003E540, 0xCF9FC949, 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675,
0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E, 0x28683B6F, 0xC07FD059,
@@ -57,7 +57,7 @@ const uint32_t CAST_SBOX1[256] = {
0xB141AB08, 0x7CCA89B9, 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D,
0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF };

const uint32_t CAST_SBOX2[256] = {
alignas(64) const uint32_t CAST_SBOX2[256] = {
0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380, 0xFE61CF7A, 0xEEC5207A,
0x55889C94, 0x72FC0651, 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,
0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3, 0xA0B52F7B, 0x59E83605,
@@ -102,7 +102,7 @@ const uint32_t CAST_SBOX2[256] = {
0x5C038323, 0x3E5D3BB9, 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,
0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1 };

const uint32_t CAST_SBOX3[256] = {
alignas(64) const uint32_t CAST_SBOX3[256] = {
0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907, 0x47607FFF, 0x369FE44B,
0x8C1FC644, 0xAECECA90, 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,
0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5, 0x11107D9F, 0x07647DB9,
@@ -147,7 +147,7 @@ const uint32_t CAST_SBOX3[256] = {
0x52BCE688, 0x1B03588A, 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5,
0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783 };

const uint32_t CAST_SBOX4[256] = {
alignas(64) const uint32_t CAST_SBOX4[256] = {
0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298, 0x4A4F7BDB, 0x64AD8C57,
0x85510443, 0xFA020ED1, 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120,
0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF, 0x28147F5F, 0x4FA2B8CD,
@@ -9,7 +9,7 @@

namespace Botan {

const uint32_t DES_SPBOX1[256] = {
alignas(64) const uint32_t DES_SPBOX1[256] = {
0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404,
0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
@@ -54,7 +54,7 @@ const uint32_t DES_SPBOX1[256] = {
0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004 };

const uint32_t DES_SPBOX2[256] = {
alignas(64) const uint32_t DES_SPBOX2[256] = {
0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020,
0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
@@ -99,7 +99,7 @@ const uint32_t DES_SPBOX2[256] = {
0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000 };

const uint32_t DES_SPBOX3[256] = {
alignas(64) const uint32_t DES_SPBOX3[256] = {
0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000,
0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
@@ -144,7 +144,7 @@ const uint32_t DES_SPBOX3[256] = {
0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200 };

const uint32_t DES_SPBOX4[256] = {
alignas(64) const uint32_t DES_SPBOX4[256] = {
0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081,
0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
@@ -189,7 +189,7 @@ const uint32_t DES_SPBOX4[256] = {
0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080 };

const uint32_t DES_SPBOX5[256] = {
alignas(64) const uint32_t DES_SPBOX5[256] = {
0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100,
0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
@@ -234,7 +234,7 @@ const uint32_t DES_SPBOX5[256] = {
0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100 };

const uint32_t DES_SPBOX6[256] = {
alignas(64) const uint32_t DES_SPBOX6[256] = {
0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010,
0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
@@ -279,7 +279,7 @@ const uint32_t DES_SPBOX6[256] = {
0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010 };

const uint32_t DES_SPBOX7[256] = {
alignas(64) const uint32_t DES_SPBOX7[256] = {
0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802,
0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
@@ -324,7 +324,7 @@ const uint32_t DES_SPBOX7[256] = {
0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002 };

const uint32_t DES_SPBOX8[256] = {
alignas(64) const uint32_t DES_SPBOX8[256] = {
0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040,
0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
@@ -16,7 +16,7 @@ namespace {
/*
* KASUMI S-Boxes
*/
const uint8_t KASUMI_SBOX_S7[128] = {
alignas(64) const uint8_t KASUMI_SBOX_S7[128] = {
0x36, 0x32, 0x3E, 0x38, 0x16, 0x22, 0x5E, 0x60, 0x26, 0x06, 0x3F, 0x5D,
0x02, 0x12, 0x7B, 0x21, 0x37, 0x71, 0x27, 0x72, 0x15, 0x43, 0x41, 0x0C,
0x2F, 0x49, 0x2E, 0x1B, 0x19, 0x6F, 0x7C, 0x51, 0x35, 0x09, 0x79, 0x4F,
@@ -29,7 +29,7 @@ const uint8_t KASUMI_SBOX_S7[128] = {
0x44, 0x1D, 0x73, 0x2C, 0x40, 0x6B, 0x6C, 0x18, 0x6E, 0x53, 0x24, 0x4E,
0x2A, 0x13, 0x0F, 0x29, 0x58, 0x77, 0x3B, 0x03 };

const uint16_t KASUMI_SBOX_S9[512] = {
alignas(64) const uint16_t KASUMI_SBOX_S9[512] = {
0x00A7, 0x00EF, 0x00A1, 0x017B, 0x0187, 0x014E, 0x0009, 0x0152, 0x0026,
0x00E2, 0x0030, 0x0166, 0x01C4, 0x0181, 0x005A, 0x018D, 0x00B7, 0x00FD,
0x0093, 0x014B, 0x019F, 0x0154, 0x0033, 0x016A, 0x0132, 0x01F4, 0x0106,
@@ -12,7 +12,7 @@ namespace Botan {

namespace {

static const uint8_t MISTY1_SBOX_S7[128] = {
alignas(64) static const uint8_t MISTY1_SBOX_S7[128] = {
0x1B, 0x32, 0x33, 0x5A, 0x3B, 0x10, 0x17, 0x54, 0x5B, 0x1A, 0x72, 0x73,
0x6B, 0x2C, 0x66, 0x49, 0x1F, 0x24, 0x13, 0x6C, 0x37, 0x2E, 0x3F, 0x4A,
0x5D, 0x0F, 0x40, 0x56, 0x25, 0x51, 0x1C, 0x04, 0x0B, 0x46, 0x20, 0x0D,
@@ -25,7 +25,7 @@ static const uint8_t MISTY1_SBOX_S7[128] = {
0x2D, 0x7A, 0x7F, 0x61, 0x50, 0x22, 0x11, 0x06, 0x47, 0x16, 0x52, 0x4E,
0x71, 0x3E, 0x69, 0x43, 0x34, 0x5C, 0x58, 0x7D };

static const uint16_t MISTY1_SBOX_S9[512] = {
alignas(64) static const uint16_t MISTY1_SBOX_S9[512] = {
0x01C3, 0x00CB, 0x0153, 0x019F, 0x01E3, 0x00E9, 0x00FB, 0x0035, 0x0181,
0x00B9, 0x0117, 0x01EB, 0x0133, 0x0009, 0x002D, 0x00D3, 0x00C7, 0x014A,
0x0037, 0x007E, 0x00EB, 0x0164, 0x0193, 0x01D8, 0x00A3, 0x011E, 0x0055,
@@ -12,7 +12,7 @@ namespace Botan {

namespace {

const uint32_t SEED_S0[256] = {
alignas(64) const uint32_t SEED_S0[256] = {
0x2989A1A8, 0x05858184, 0x16C6D2D4, 0x13C3D3D0, 0x14445054, 0x1D0D111C,
0x2C8CA0AC, 0x25052124, 0x1D4D515C, 0x03434340, 0x18081018, 0x1E0E121C,
0x11415150, 0x3CCCF0FC, 0x0ACAC2C8, 0x23436360, 0x28082028, 0x04444044,
@@ -57,7 +57,7 @@ const uint32_t SEED_S0[256] = {
0x07070304, 0x33033330, 0x28C8E0E8, 0x1B0B1318, 0x05050104, 0x39497178,
0x10809090, 0x2A4A6268, 0x2A0A2228, 0x1A8A9298 };

const uint32_t SEED_S1[256] = {
alignas(64) const uint32_t SEED_S1[256] = {
0x38380830, 0xE828C8E0, 0x2C2D0D21, 0xA42686A2, 0xCC0FCFC3, 0xDC1ECED2,
0xB03383B3, 0xB83888B0, 0xAC2F8FA3, 0x60204060, 0x54154551, 0xC407C7C3,
0x44044440, 0x6C2F4F63, 0x682B4B63, 0x581B4B53, 0xC003C3C3, 0x60224262,
@@ -102,7 +102,7 @@ const uint32_t SEED_S1[256] = {
0x080A0A02, 0x84078783, 0xD819C9D1, 0x4C0C4C40, 0x80038383, 0x8C0F8F83,
0xCC0ECEC2, 0x383B0B33, 0x480A4A42, 0xB43787B3 };

const uint32_t SEED_S2[256] = {
alignas(64) const uint32_t SEED_S2[256] = {
0xA1A82989, 0x81840585, 0xD2D416C6, 0xD3D013C3, 0x50541444, 0x111C1D0D,
0xA0AC2C8C, 0x21242505, 0x515C1D4D, 0x43400343, 0x10181808, 0x121C1E0E,
0x51501141, 0xF0FC3CCC, 0xC2C80ACA, 0x63602343, 0x20282808, 0x40440444,
@@ -147,7 +147,7 @@ const uint32_t SEED_S2[256] = {
0x03040707, 0x33303303, 0xE0E828C8, 0x13181B0B, 0x01040505, 0x71783949,
0x90901080, 0x62682A4A, 0x22282A0A, 0x92981A8A };

const uint32_t SEED_S3[256] = {
alignas(64) const uint32_t SEED_S3[256] = {
0x08303838, 0xC8E0E828, 0x0D212C2D, 0x86A2A426, 0xCFC3CC0F, 0xCED2DC1E,
0x83B3B033, 0x88B0B838, 0x8FA3AC2F, 0x40606020, 0x45515415, 0xC7C3C407,
0x44404404, 0x4F636C2F, 0x4B63682B, 0x4B53581B, 0xC3C3C003, 0x42626022,
@@ -9,7 +9,7 @@

namespace Botan {

const uint8_t Twofish::Q0[256] = {
alignas(64) const uint8_t Twofish::Q0[256] = {
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
@@ -33,7 +33,7 @@ const uint8_t Twofish::Q0[256] = {
0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
0x4A, 0x5E, 0xC1, 0xE0 };

const uint8_t Twofish::Q1[256] = {
alignas(64) const uint8_t Twofish::Q1[256] = {
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
@@ -57,12 +57,12 @@ const uint8_t Twofish::Q1[256] = {
0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
0x55, 0x09, 0xBE, 0x91 };

const uint8_t Twofish::RS[32] = {
alignas(64) const uint8_t Twofish::RS[32] = {
0x01, 0xA4, 0x02, 0xA4, 0xA4, 0x56, 0xA1, 0x55, 0x55, 0x82, 0xFC, 0x87,
0x87, 0xF3, 0xC1, 0x5A, 0x5A, 0x1E, 0x47, 0x58, 0x58, 0xC6, 0xAE, 0xDB,
0xDB, 0x68, 0x3D, 0x9E, 0x9E, 0xE5, 0x19, 0x03 };

const uint8_t Twofish::EXP_TO_POLY[255] = {
alignas(64) const uint8_t Twofish::EXP_TO_POLY[255] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2,
0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6,
@@ -86,7 +86,7 @@ const uint8_t Twofish::EXP_TO_POLY[255] = {
0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1,
0x8F, 0x53, 0xA6 };

const uint8_t Twofish::POLY_TO_EXP[255] = {
alignas(64) const uint8_t Twofish::POLY_TO_EXP[255] = {
0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19,
0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A,
0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C,
@@ -110,7 +110,7 @@ const uint8_t Twofish::POLY_TO_EXP[255] = {
0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF,
0x85, 0xC8, 0xA1 };

const uint32_t Twofish::MDS0[256] = {
alignas(64) const uint32_t Twofish::MDS0[256] = {
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B,
0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B,
0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32,
@@ -155,7 +155,7 @@ const uint32_t Twofish::MDS0[256] = {
0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756,
0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 };

const uint32_t Twofish::MDS1[256] = {
alignas(64) const uint32_t Twofish::MDS1[256] = {
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252,
0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A,
0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020,
@@ -200,7 +200,7 @@ const uint32_t Twofish::MDS1[256] = {
0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7,
0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 };

const uint32_t Twofish::MDS2[256] = {
alignas(64) const uint32_t Twofish::MDS2[256] = {
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B,
0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F,
0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A,
@@ -245,7 +245,7 @@ const uint32_t Twofish::MDS2[256] = {
0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7,
0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF };

const uint32_t Twofish::MDS3[256] = {
alignas(64) const uint32_t Twofish::MDS3[256] = {
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98,
0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866,
0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643,
@@ -1,14 +1,15 @@
/*
* Base32 Encoding and Decoding
* (C) 2018 Erwan Chaussy
* (C) 2018 Jack Lloyd
* (C) 2018,2020 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/base32.h>
#include <botan/internal/codec_base.h>
#include <botan/internal/rounding.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

@@ -58,45 +59,11 @@ class Base32 final
return (round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
}

static void encode(char out[8], const uint8_t in[5]) noexcept
{
out[0] = Base32::m_bin_to_base32[(in[0] & 0xF8) >> 3];
out[1] = Base32::m_bin_to_base32[((in[0] & 0x07) << 2) | (in[1] >> 6)];
out[2] = Base32::m_bin_to_base32[((in[1] & 0x3E) >> 1)];
out[3] = Base32::m_bin_to_base32[((in[1] & 0x01) << 4) | (in[2] >> 4)];
out[4] = Base32::m_bin_to_base32[((in[2] & 0x0F) << 1) | (in[3] >> 7)];
out[5] = Base32::m_bin_to_base32[((in[3] & 0x7C) >> 2)];
out[6] = Base32::m_bin_to_base32[((in[3] & 0x03) << 3) | (in[4] >> 5)];
out[7] = Base32::m_bin_to_base32[in[4] & 0x1F];
}
static void encode(char out[8], const uint8_t in[5]) noexcept;

static inline uint8_t lookup_binary_value(char input) noexcept
{
return Base32::m_base32_to_bin[static_cast<uint8_t>(input)];
}
static uint8_t lookup_binary_value(char input) noexcept;

static inline bool check_bad_char(uint8_t bin, char input, bool ignore_ws)
{
if(bin <= 0x1F)
{
return true;
}
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
{
std::string bad_char(1, input);
if(bad_char == "\t")
{ bad_char = "\\t"; }
else if(bad_char == "\n")
{ bad_char = "\\n"; }
else if(bad_char == "\r")
{ bad_char = "\\r"; }

throw Invalid_Argument(
std::string("base32_decode: invalid base32 character '") +
bad_char + "'");
}
return false;
}
static bool check_bad_char(uint8_t bin, char input, bool ignore_ws);

static void decode(uint8_t* out_ptr, const uint8_t decode_buf[8])
{
@@ -116,55 +83,97 @@ class Base32 final
static const size_t m_encoding_bits = 5;
static const size_t m_remaining_bits_before_padding = 6;


static const size_t m_encoding_bytes_in = 5;
static const size_t m_encoding_bytes_out = 8;
};

namespace {

static const uint8_t m_bin_to_base32[32];
static const uint8_t m_base32_to_bin[256];
};
char lookup_base32_char(uint8_t x)
{
BOTAN_DEBUG_ASSERT(x < 32);

const auto in_AZ = CT::Mask<uint8_t>::is_lt(x, 26);

const char c_AZ = 'A' + x;
const char c_27 = '2' + (x - 26);

return in_AZ.select(c_AZ, c_27);
}

}

const uint8_t Base32::m_bin_to_base32[32] =
//static
void Base32::encode(char out[8], const uint8_t in[5]) noexcept
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'2', '3', '4', '5', '6', '7'
};
const uint8_t b0 = (in[0] & 0xF8) >> 3;
const uint8_t b1 = ((in[0] & 0x07) << 2) | (in[1] >> 6);
const uint8_t b2 = ((in[1] & 0x3E) >> 1);
const uint8_t b3 = ((in[1] & 0x01) << 4) | (in[2] >> 4);
const uint8_t b4 = ((in[2] & 0x0F) << 1) | (in[3] >> 7);
const uint8_t b5 = ((in[3] & 0x7C) >> 2);
const uint8_t b6 = ((in[3] & 0x03) << 3) | (in[4] >> 5);
const uint8_t b7 = in[4] & 0x1F;

out[0] = lookup_base32_char(b0);
out[1] = lookup_base32_char(b1);
out[2] = lookup_base32_char(b2);
out[3] = lookup_base32_char(b3);
out[4] = lookup_base32_char(b4);
out[5] = lookup_base32_char(b5);
out[6] = lookup_base32_char(b6);
out[7] = lookup_base32_char(b7);
}

/*
* base32 Decoder Lookup Table
* Warning: assumes ASCII encodings
*/
const uint8_t Base32::m_base32_to_bin[256] =
//static
uint8_t Base32::lookup_binary_value(char input) noexcept
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
const uint8_t c = static_cast<uint8_t>(input);

const auto is_alpha_upper = CT::Mask<uint8_t>::is_within_range(c, uint8_t('A'), uint8_t('Z'));
const auto is_decimal = CT::Mask<uint8_t>::is_within_range(c, uint8_t('2'), uint8_t('7'));

const auto is_equal = CT::Mask<uint8_t>::is_equal(c, uint8_t('='));
const auto is_whitespace = CT::Mask<uint8_t>::is_any_of(c, {
uint8_t(' '), uint8_t('\t'), uint8_t('\n'), uint8_t('\r')
});

const uint8_t c_upper = c - uint8_t('A');
const uint8_t c_decim = c - uint8_t('2') + 26;

uint8_t ret = 0xFF; // default value

ret = is_alpha_upper.select(c_upper, ret);
ret = is_decimal.select(c_decim, ret);
ret = is_equal.select(0x81, ret);
ret = is_whitespace.select(0x80, ret);

return ret;
}

//static
bool Base32::check_bad_char(uint8_t bin, char input, bool ignore_ws)
{
if(bin <= 0x1F)
{
return true;
}
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
{
std::string bad_char(1, input);
if(bad_char == "\t")
{ bad_char = "\\t"; }
else if(bad_char == "\n")
{ bad_char = "\\n"; }
else if(bad_char == "\r")
{ bad_char = "\\r"; }

throw Invalid_Argument(
std::string("base32_decode: invalid base32 character '") +
bad_char + "'");
}
return false;
}

}

@@ -1,5 +1,5 @@
/*
* (C) 2018 Jack Lloyd
* (C) 2018,2020 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -9,6 +9,7 @@
#include <botan/bigint.h>
#include <botan/divide.h>
#include <botan/loadstor.h>
#include <botan/internal/ct_utils.h>
#include <botan/hash.h>

namespace Botan {
@@ -30,73 +31,52 @@ uint32_t sha256_d_checksum(const uint8_t input[], size_t input_length)
return load_be<uint32_t>(checksum.data(), 0);
}

class Character_Table
char lookup_base58_char(uint8_t x)
{
public:
// This must be a literal constant
Character_Table(const char* alphabet) :
m_alphabet(alphabet)
{
const size_t alpha_len = std::strlen(alphabet);

// 128 or up would flow into 0x80 invalid bit
if(alpha_len == 0 || alpha_len >= 128)
throw Invalid_Argument("Bad Character_Table string");

m_alphabet_len = static_cast<uint8_t>(alpha_len);

set_mem(m_tab, 256, 0x80);

for(size_t i = 0; m_alphabet[i]; ++i)
{
const uint8_t b = static_cast<uint8_t>(m_alphabet[i]);
BOTAN_ASSERT(m_tab[b] == 0x80, "No duplicate chars");
m_tab[b] = static_cast<uint8_t>(i);
}
}

uint8_t radix() const { return m_alphabet_len; }

char operator[](size_t i) const
{
BOTAN_ASSERT(i < m_alphabet_len, "Character in range");
return m_alphabet[i];
}

uint8_t code_for(char c) const
{
return m_tab[static_cast<uint8_t>(c)];
}

private:
const char* m_alphabet;
uint8_t m_alphabet_len;
uint8_t m_tab[256];
};

static const Character_Table& BASE58_ALPHA()
{
static const Character_Table base58_alpha("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
return base58_alpha;
// "123456789 ABCDEFGH JKLMN PQRSTUVWXYZ abcdefghijk mnopqrstuvwxyz"
BOTAN_DEBUG_ASSERT(x < 58);

const auto is_dec_19 = CT::Mask<uint8_t>::is_lte(x, 8);
const auto is_alpha_AH = CT::Mask<uint8_t>::is_within_range(x, 9, 16);
const auto is_alpha_JN = CT::Mask<uint8_t>::is_within_range(x, 17, 21);
const auto is_alpha_PZ = CT::Mask<uint8_t>::is_within_range(x, 22, 32);
const auto is_alpha_ak = CT::Mask<uint8_t>::is_within_range(x, 33, 43);
// otherwise in 'm'-'z'

const char c_19 = '1' + x;
const char c_AH = 'A' + (x - 9);
const char c_JN = 'J' + (x - 17);
const char c_PZ = 'P' + (x - 22);
const char c_ak = 'a' + (x - 33);
const char c_mz = 'm' + (x - 44);

char ret = c_mz;
ret = is_dec_19.select(c_19, ret);
ret = is_alpha_AH.select(c_AH, ret);
ret = is_alpha_JN.select(c_JN, ret);
ret = is_alpha_PZ.select(c_PZ, ret);
ret = is_alpha_ak.select(c_ak, ret);

return ret;
}

std::string base58_encode(BigInt v, size_t leading_zeros)
{
const auto base58 = BASE58_ALPHA();
const uint8_t radix = 58;

std::string result;
BigInt q;
uint8_t r;

while(v.is_nonzero())
{
ct_divide_u8(v, base58.radix(), q, r);
result.push_back(base58[r]);
uint8_t r;
ct_divide_u8(v, radix, q, r);
result.push_back(lookup_base58_char(r));
v.swap(q);
}

for(size_t i = 0; i != leading_zeros; ++i)
result.push_back(base58[0]);
result.push_back('1'); // 'zero' byte

return std::string(result.rbegin(), result.rend());
}
@@ -112,6 +92,39 @@ size_t count_leading_zeros(const T input[], size_t input_length, Z zero)
return leading_zeros;
}

uint8_t base58_value_of(char input)
{
// "123456789 ABCDEFGH JKLMN PQRSTUVWXYZ abcdefghijk mnopqrstuvwxyz"

const uint8_t c = static_cast<uint8_t>(input);

const auto is_dec_19 = CT::Mask<uint8_t>::is_within_range(c, uint8_t('1'), uint8_t('9'));
const auto is_alpha_AH = CT::Mask<uint8_t>::is_within_range(c, uint8_t('A'), uint8_t('H'));
const auto is_alpha_JN = CT::Mask<uint8_t>::is_within_range(c, uint8_t('J'), uint8_t('N'));
const auto is_alpha_PZ = CT::Mask<uint8_t>::is_within_range(c, uint8_t('P'), uint8_t('Z'));

const auto is_alpha_ak = CT::Mask<uint8_t>::is_within_range(c, uint8_t('a'), uint8_t('k'));
const auto is_alpha_mz = CT::Mask<uint8_t>::is_within_range(c, uint8_t('m'), uint8_t('z'));

const uint8_t c_dec_19 = c - uint8_t('1');
const uint8_t c_AH = c - uint8_t('A') + 9;
const uint8_t c_JN = c - uint8_t('J') + 17;
const uint8_t c_PZ = c - uint8_t('P') + 22;

const uint8_t c_ak = c - uint8_t('a') + 33;
const uint8_t c_mz = c - uint8_t('m') + 44;

uint8_t ret = 0xFF; // default value

ret = is_dec_19.select(c_dec_19, ret);
ret = is_alpha_AH.select(c_AH, ret);
ret = is_alpha_JN.select(c_JN, ret);
ret = is_alpha_PZ.select(c_PZ, ret);
ret = is_alpha_ak.select(c_ak, ret);
ret = is_alpha_mz.select(c_mz, ret);
return ret;
}

}

std::string base58_encode(const uint8_t input[], size_t input_length)
@@ -130,9 +143,7 @@ std::string base58_check_encode(const uint8_t input[], size_t input_length)

std::vector<uint8_t> base58_decode(const char input[], size_t input_length)
{
const auto base58 = BASE58_ALPHA();

const size_t leading_zeros = count_leading_zeros(input, input_length, base58[0]);
const size_t leading_zeros = count_leading_zeros(input, input_length, '1');

BigInt v;

@@ -143,12 +154,12 @@ std::vector<uint8_t> base58_decode(const char input[], size_t input_length)
if(c == ' ' || c == '\n')
continue;

const size_t idx = base58.code_for(c);
const uint8_t idx = base58_value_of(c);

if(idx == 0x80)
if(idx == 0xFF)
throw Decoding_Error("Invalid base58");

v *= base58.radix();
v *= 58;
v += idx;
}

@@ -1,6 +1,6 @@
/*
* Base64 Encoding and Decoding
* (C) 2010,2015 Jack Lloyd
* (C) 2010,2015,2020 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -9,6 +9,7 @@
#include <botan/internal/codec_base.h>
#include <botan/exceptn.h>
#include <botan/internal/rounding.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

@@ -58,41 +59,11 @@ class Base64 final
return (round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
}

static void encode(char out[8], const uint8_t in[5]) noexcept
{
out[0] = Base64::m_bin_to_base64[(in[0] & 0xFC) >> 2];
out[1] = Base64::m_bin_to_base64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
out[2] = Base64::m_bin_to_base64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
out[3] = Base64::m_bin_to_base64[in[2] & 0x3F];
}
static void encode(char out[8], const uint8_t in[5]) noexcept;

static inline uint8_t lookup_binary_value(char input) noexcept
{
return Base64::m_base64_to_bin[static_cast<uint8_t>(input)];
}
static uint8_t lookup_binary_value(char input) noexcept;

static inline bool check_bad_char(uint8_t bin, char input, bool ignore_ws)
{
if(bin <= 0x3F)
{
return true;
}
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
{
std::string bad_char(1, input);
if(bad_char == "\t")
{ bad_char = "\\t"; }
else if(bad_char == "\n")
{ bad_char = "\\n"; }
else if(bad_char == "\r")
{ bad_char = "\\r"; }

throw Invalid_Argument(
std::string("base64_decode: invalid base64 character '") +
bad_char + "'");
}
return false;
}
static bool check_bad_char(uint8_t bin, char input, bool ignore_ws);

static void decode(uint8_t* out_ptr, const uint8_t decode_buf[4])
{
@@ -110,57 +81,105 @@ class Base64 final
static const size_t m_encoding_bits = 6;
static const size_t m_remaining_bits_before_padding = 8;


static const size_t m_encoding_bytes_in = 3;
static const size_t m_encoding_bytes_out = 4;
};

char lookup_base64_char(uint8_t x)
{
BOTAN_DEBUG_ASSERT(x < 64);

const auto in_az = CT::Mask<uint8_t>::is_within_range(x, 26, 51);
const auto in_09 = CT::Mask<uint8_t>::is_within_range(x, 52, 61);
const auto eq_plus = CT::Mask<uint8_t>::is_equal(x, 62);
const auto eq_slash = CT::Mask<uint8_t>::is_equal(x, 63);

const char c_AZ = 'A' + x;
const char c_az = 'a' + (x - 26);
const char c_09 = '0' + (x - 2*26);
const char c_plus = '+';
const char c_slash = '/';

char ret = c_AZ;
ret = in_az.select(c_az, ret);
ret = in_09.select(c_09, ret);
ret = eq_plus.select(c_plus, ret);
ret = eq_slash.select(c_slash, ret);

return ret;
}

static const uint8_t m_bin_to_base64[64];
static const uint8_t m_base64_to_bin[256];
};
//static
void Base64::encode(char out[8], const uint8_t in[5]) noexcept
{
const uint8_t b0 = (in[0] & 0xFC) >> 2;
const uint8_t b1 = ((in[0] & 0x03) << 4) | (in[1] >> 4);
const uint8_t b2 = ((in[1] & 0x0F) << 2) | (in[2] >> 6);
const uint8_t b3 = in[2] & 0x3F;
out[0] = lookup_base64_char(b0);
out[1] = lookup_base64_char(b1);
out[2] = lookup_base64_char(b2);
out[3] = lookup_base64_char(b3);
}

const uint8_t Base64::m_bin_to_base64[64] =
//static
uint8_t Base64::lookup_binary_value(char input) noexcept
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
const uint8_t c = static_cast<uint8_t>(input);

/*
* base64 Decoder Lookup Table
* Warning: assumes ASCII encodings
*/
const uint8_t Base64::m_base64_to_bin[256] =
const auto is_alpha_upper = CT::Mask<uint8_t>::is_within_range(c, uint8_t('A'), uint8_t('Z'));
const auto is_alpha_lower = CT::Mask<uint8_t>::is_within_range(c, uint8_t('a'), uint8_t('z'));
const auto is_decimal = CT::Mask<uint8_t>::is_within_range(c, uint8_t('0'), uint8_t('9'));

const auto is_plus = CT::Mask<uint8_t>::is_equal(c, uint8_t('+'));
const auto is_slash = CT::Mask<uint8_t>::is_equal(c, uint8_t('/'));
const auto is_equal = CT::Mask<uint8_t>::is_equal(c, uint8_t('='));

const auto is_whitespace = CT::Mask<uint8_t>::is_any_of(c, {
uint8_t(' '), uint8_t('\t'), uint8_t('\n'), uint8_t('\r')
});

const uint8_t c_upper = c - uint8_t('A');
const uint8_t c_lower = c - uint8_t('a') + 26;
const uint8_t c_decim = c - uint8_t('0') + 2*26;

uint8_t ret = 0xFF; // default value

ret = is_alpha_upper.select(c_upper, ret);
ret = is_alpha_lower.select(c_lower, ret);
ret = is_decimal.select(c_decim, ret);
ret = is_plus.select(62, ret);
ret = is_slash.select(63, ret);
ret = is_equal.select(0x81, ret);
ret = is_whitespace.select(0x80, ret);

return ret;
}

//static
bool Base64::check_bad_char(uint8_t bin, char input, bool ignore_ws)
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C,
0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
if(bin <= 0x3F)
{
return true;
}
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
{
std::string bad_char(1, input);
if(bad_char == "\t")
{ bad_char = "\\t"; }
else if(bad_char == "\n")
{ bad_char = "\\n"; }
else if(bad_char == "\r")
{ bad_char = "\\r"; }

throw Invalid_Argument(
std::string("base64_decode: invalid base64 character '") +
bad_char + "'");
}
return false;
}

}

size_t base64_encode(char out[],
@@ -1,36 +1,45 @@
/*
* Hex Encoding and Decoding
* (C) 2010 Jack Lloyd
* (C) 2010,2020 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/hex.h>
#include <botan/mem_ops.h>
#include <botan/exceptn.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

namespace {

char hex_encode_nibble(uint8_t n, bool uppercase)
{
BOTAN_DEBUG_ASSERT(n <= 15);

const auto in_09 = CT::Mask<uint8_t>::is_lt(n, 10);

const char c_09 = n + '0';
const char c_af = n + (uppercase ? 'A' : 'a') - 10;

return in_09.select(c_09, c_af);
}

}

void hex_encode(char output[],
const uint8_t input[],
size_t input_length,
bool uppercase)
{
static const uint8_t BIN_TO_HEX_UPPER[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };

static const uint8_t BIN_TO_HEX_LOWER[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };

const uint8_t* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER;

for(size_t i = 0; i != input_length; ++i)
{
uint8_t x = input[i];
output[2*i ] = tbl[(x >> 4) & 0x0F];
output[2*i+1] = tbl[(x ) & 0x0F];
const uint8_t n0 = (input[i] >> 4) & 0xF;
const uint8_t n1 = (input[i] ) & 0xF;

output[2*i ] = hex_encode_nibble(n0, uppercase);
output[2*i+1] = hex_encode_nibble(n1, uppercase);
}
}

@@ -46,57 +55,51 @@ std::string hex_encode(const uint8_t input[],
return output;
}

namespace {

uint8_t hex_char_to_bin(char input)
{
const uint8_t c = static_cast<uint8_t>(input);

const auto is_alpha_upper = CT::Mask<uint8_t>::is_within_range(c, uint8_t('A'), uint8_t('F'));
const auto is_alpha_lower = CT::Mask<uint8_t>::is_within_range(c, uint8_t('a'), uint8_t('f'));
const auto is_decimal = CT::Mask<uint8_t>::is_within_range(c, uint8_t('0'), uint8_t('9'));

const auto is_whitespace = CT::Mask<uint8_t>::is_any_of(c, {
uint8_t(' '), uint8_t('\t'), uint8_t('\n'), uint8_t('\r')
});

const uint8_t c_upper = c - uint8_t('A') + 10;
const uint8_t c_lower = c - uint8_t('a') + 10;
const uint8_t c_decim = c - uint8_t('0');

uint8_t ret = 0xFF; // default value

ret = is_alpha_upper.select(c_upper, ret);
ret = is_alpha_lower.select(c_lower, ret);
ret = is_decimal.select(c_decim, ret);
ret = is_whitespace.select(0x80, ret);

return ret;
}

}


size_t hex_decode(uint8_t output[],
const char input[],
size_t input_length,
size_t& input_consumed,
bool ignore_ws)
{
/*
* Mapping of hex characters to either their binary equivalent
* or to an error code.
* If valid hex (0-9 A-F a-f), the value.
* If whitespace, then 0x80
* Otherwise 0xFF
* Warning: this table assumes ASCII character encodings
*/

static const uint8_t HEX_TO_BIN[256] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

uint8_t* out_ptr = output;
bool top_nibble = true;

clear_mem(output, input_length / 2);

for(size_t i = 0; i != input_length; ++i)
{
const uint8_t bin = HEX_TO_BIN[static_cast<uint8_t>(input[i])];
const uint8_t bin = hex_char_to_bin(input[i]);

if(bin >= 0x10)
{
@@ -14,7 +14,7 @@ namespace Botan {

namespace {

const uint32_t CRC24_T0[256] = {
alignas(64) const uint32_t CRC24_T0[256] = {
0x00000000, 0x00FB4C86, 0x000DD58A, 0x00F6990C, 0x00E1E693, 0x001AAA15, 0x00EC3319,
0x00177F9F, 0x003981A1, 0x00C2CD27, 0x0034542B, 0x00CF18AD, 0x00D86732, 0x00232BB4,
0x00D5B2B8, 0x002EFE3E, 0x00894EC5, 0x00720243, 0x00849B4F, 0x007FD7C9, 0x0068A856,
@@ -53,7 +53,7 @@ const uint32_t CRC24_T0[256] = {
0x000CD1F6, 0x00FA48FA, 0x0001047C, 0x002FFA42, 0x00D4B6C4, 0x00222FC8, 0x00D9634E,
0x00CE1CD1, 0x00355057, 0x00C3C95B, 0x003885DD };

const uint32_t CRC24_T1[256] = {
alignas(64) const uint32_t CRC24_T1[256] = {
0x00000000, 0x00488F66, 0x00901ECD, 0x00D891AB, 0x00DB711C, 0x0093FE7A, 0x004B6FD1,
0x0003E0B7, 0x00B6E338, 0x00FE6C5E, 0x0026FDF5, 0x006E7293, 0x006D9224, 0x00251D42,
0x00FD8CE9, 0x00B5038F, 0x006CC771, 0x00244817, 0x00FCD9BC, 0x00B456DA, 0x00B7B66D,
@@ -92,7 +92,7 @@ const uint32_t CRC24_T1[256] = {
0x00FA442B, 0x0022D580, 0x006A5AE6, 0x00DF5969, 0x0097D60F, 0x004F47A4, 0x0007C8C2,
0x00042875, 0x004CA713, 0x009436B8, 0x00DCB9DE };

const uint32_t CRC24_T2[256] = {
alignas(64) const uint32_t CRC24_T2[256] = {
0x00000000, 0x00D70983, 0x00555F80, 0x00825603, 0x0051F286, 0x0086FB05, 0x0004AD06,
0x00D3A485, 0x0059A88B, 0x008EA108, 0x000CF70B, 0x00DBFE88, 0x00085A0D, 0x00DF538E,
0x005D058D, 0x008A0C0E, 0x00491C91, 0x009E1512, 0x001C4311, 0x00CB4A92, 0x0018EE17,
@@ -131,7 +131,7 @@ const uint32_t CRC24_T2[256] = {
0x002633E5, 0x00A465E6, 0x00736C65, 0x00F9606B, 0x002E69E8, 0x00AC3FEB, 0x007B3668,
0x00A892ED, 0x007F9B6E, 0x00FDCD6D, 0x002AC4EE };

const uint32_t CRC24_T3[256] = {
alignas(64) const uint32_t CRC24_T3[256] = {
0x00000000, 0x00520936, 0x00A4126C, 0x00F61B5A, 0x004825D8, 0x001A2CEE, 0x00EC37B4,
0x00BE3E82, 0x006B0636, 0x00390F00, 0x00CF145A, 0x009D1D6C, 0x002323EE, 0x00712AD8,
0x00873182, 0x00D538B4, 0x00D60C6C, 0x0084055A, 0x00721E00, 0x00201736, 0x009E29B4,
@@ -15,81 +15,85 @@ std::unique_ptr<HashFunction> CRC32::copy_state() const
return std::unique_ptr<HashFunction>(new CRC32(*this));
}

namespace {

const uint32_t CRC32_T0[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };

}

/*
* Update a CRC32 Checksum
*/
void CRC32::add_data(const uint8_t input[], size_t length)
{
const uint32_t TABLE[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };

uint32_t tmp = m_crc;
while(length >= 16)
{
tmp = TABLE[(tmp ^ input[ 0]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 1]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 2]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 3]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 4]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 5]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 6]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 7]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 8]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[ 9]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[10]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[11]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[12]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[13]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[14]) & 0xFF] ^ (tmp >> 8);
tmp = TABLE[(tmp ^ input[15]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 0]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 1]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 2]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 3]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 4]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 5]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 6]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 7]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 8]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[ 9]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[10]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[11]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[12]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[13]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[14]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[15]) & 0xFF] ^ (tmp >> 8);
input += 16;
length -= 16;
}

for(size_t i = 0; i != length; ++i)
tmp = TABLE[(tmp ^ input[i]) & 0xFF] ^ (tmp >> 8);
tmp = CRC32_T0[(tmp ^ input[i]) & 0xFF] ^ (tmp >> 8);

m_crc = tmp;
}
@@ -9,7 +9,7 @@

namespace Botan {

const uint64_t Whirlpool::C0[256] = {
alignas(64) const uint64_t Whirlpool::C0[256] = {
0x18186018C07830D8, 0x23238C2305AF4626, 0xC6C63FC67EF991B8, 0xE8E887E8136FCDFB,
0x878726874CA113CB, 0xB8B8DAB8A9626D11, 0x0101040108050209, 0x4F4F214F426E9E0D,
0x3636D836ADEE6C9B, 0xA6A6A2A6590451FF, 0xD2D26FD2DEBDB90C, 0xF5F5F3F5FB06F70E,
@@ -75,7 +75,7 @@ const uint64_t Whirlpool::C0[256] = {
0xCCCC17CC2EDB85E2, 0x424215422A578468, 0x98985A98B4C22D2C, 0xA4A4AAA4490E55ED,
0x2828A0285D885075, 0x5C5C6D5CDA31B886, 0xF8F8C7F8933FED6B, 0x8686228644A411C2 };

const uint64_t Whirlpool::C1[256] = {
alignas(64) const uint64_t Whirlpool::C1[256] = {
0xD818186018C07830, 0x2623238C2305AF46, 0xB8C6C63FC67EF991, 0xFBE8E887E8136FCD,
0xCB878726874CA113, 0x11B8B8DAB8A9626D, 0x0901010401080502, 0x0D4F4F214F426E9E,
0x9B3636D836ADEE6C, 0xFFA6A6A2A6590451, 0x0CD2D26FD2DEBDB9, 0x0EF5F5F3F5FB06F7,
@@ -141,7 +141,7 @@ const uint64_t Whirlpool::C1[256] = {
0xE2CCCC17CC2EDB85, 0x68424215422A5784, 0x2C98985A98B4C22D, 0xEDA4A4AAA4490E55,
0x752828A0285D8850, 0x865C5C6D5CDA31B8, 0x6BF8F8C7F8933FED, 0xC28686228644A411 };

const uint64_t Whirlpool::C2[256] = {
alignas(64) const uint64_t Whirlpool::C2[256] = {
0x30D818186018C078, 0x462623238C2305AF, 0x91B8C6C63FC67EF9, 0xCDFBE8E887E8136F,
0x13CB878726874CA1, 0x6D11B8B8DAB8A962, 0x0209010104010805, 0x9E0D4F4F214F426E,
0x6C9B3636D836ADEE, 0x51FFA6A6A2A65904, 0xB90CD2D26FD2DEBD, 0xF70EF5F5F3F5FB06,
@@ -207,7 +207,7 @@ const uint64_t Whirlpool::C2[256] = {
0x85E2CCCC17CC2EDB, 0x8468424215422A57, 0x2D2C98985A98B4C2, 0x55EDA4A4AAA4490E,
0x50752828A0285D88, 0xB8865C5C6D5CDA31, 0xED6BF8F8C7F8933F, 0x11C28686228644A4 };

const uint64_t Whirlpool::C3[256] = {
alignas(64) const uint64_t Whirlpool::C3[256] = {
0x7830D818186018C0, 0xAF462623238C2305, 0xF991B8C6C63FC67E, 0x6FCDFBE8E887E813,
0xA113CB878726874C, 0x626D11B8B8DAB8A9, 0x0502090101040108, 0x6E9E0D4F4F214F42,
0xEE6C9B3636D836AD, 0x0451FFA6A6A2A659, 0xBDB90CD2D26FD2DE, 0x06F70EF5F5F3F5FB,
@@ -273,7 +273,7 @@ const uint64_t Whirlpool::C3[256] = {
0xDB85E2CCCC17CC2E, 0x578468424215422A, 0xC22D2C98985A98B4, 0x0E55EDA4A4AAA449,
0x8850752828A0285D, 0x31B8865C5C6D5CDA, 0x3FED6BF8F8C7F893, 0xA411C28686228644 };

const uint64_t Whirlpool::C4[256] = {
alignas(64) const uint64_t Whirlpool::C4[256] = {
0xC07830D818186018, 0x05AF462623238C23, 0x7EF991B8C6C63FC6, 0x136FCDFBE8E887E8,
0x4CA113CB87872687, 0xA9626D11B8B8DAB8, 0x0805020901010401, 0x426E9E0D4F4F214F,
0xADEE6C9B3636D836, 0x590451FFA6A6A2A6, 0xDEBDB90CD2D26FD2, 0xFB06F70EF5F5F3F5,
@@ -339,7 +339,7 @@ const uint64_t Whirlpool::C4[256] = {
0x2EDB85E2CCCC17CC, 0x2A57846842421542, 0xB4C22D2C98985A98, 0x490E55EDA4A4AAA4,
0x5D8850752828A028, 0xDA31B8865C5C6D5C, 0x933FED6BF8F8C7F8, 0x44A411C286862286 };

const uint64_t Whirlpool::C5[256] = {
alignas(64) const uint64_t Whirlpool::C5[256] = {
0x18C07830D8181860, 0x2305AF462623238C, 0xC67EF991B8C6C63F, 0xE8136FCDFBE8E887,
0x874CA113CB878726, 0xB8A9626D11B8B8DA, 0x0108050209010104, 0x4F426E9E0D4F4F21,
0x36ADEE6C9B3636D8, 0xA6590451FFA6A6A2, 0xD2DEBDB90CD2D26F, 0xF5FB06F70EF5F5F3,
@@ -405,7 +405,7 @@ const uint64_t Whirlpool::C5[256] = {
0xCC2EDB85E2CCCC17, 0x422A578468424215, 0x98B4C22D2C98985A, 0xA4490E55EDA4A4AA,
0x285D8850752828A0, 0x5CDA31B8865C5C6D, 0xF8933FED6BF8F8C7, 0x8644A411C2868622 };

const uint64_t Whirlpool::C6[256] = {
alignas(64) const uint64_t Whirlpool::C6[256] = {
0x6018C07830D81818, 0x8C2305AF46262323, 0x3FC67EF991B8C6C6, 0x87E8136FCDFBE8E8,
0x26874CA113CB8787, 0xDAB8A9626D11B8B8, 0x0401080502090101, 0x214F426E9E0D4F4F,
0xD836ADEE6C9B3636, 0xA2A6590451FFA6A6, 0x6FD2DEBDB90CD2D2, 0xF3F5FB06F70EF5F5,
@@ -471,7 +471,7 @@ const uint64_t Whirlpool::C6[256] = {
0x17CC2EDB85E2CCCC, 0x15422A5784684242, 0x5A98B4C22D2C9898, 0xAAA4490E55EDA4A4,
0xA0285D8850752828, 0x6D5CDA31B8865C5C, 0xC7F8933FED6BF8F8, 0x228644A411C28686 };

const uint64_t Whirlpool::C7[256] = {
alignas(64) const uint64_t Whirlpool::C7[256] = {
0x186018C07830D818, 0x238C2305AF462623, 0xC63FC67EF991B8C6, 0xE887E8136FCDFBE8,
0x8726874CA113CB87, 0xB8DAB8A9626D11B8, 0x0104010805020901, 0x4F214F426E9E0D4F,
0x36D836ADEE6C9B36, 0xA6A2A6590451FFA6, 0xD26FD2DEBDB90CD2, 0xF5F3F5FB06F70EF5,
@@ -183,6 +183,30 @@ class Mask
return ~Mask<T>::is_lt(x, y);
}

static Mask<T> is_within_range(T v, T l, T u)
{
//return Mask<T>::is_gte(v, l) & Mask<T>::is_lte(v, u);

const T v_lt_l = v^((v^l) | ((v-l)^v));
const T v_gt_u = u^((u^v) | ((u-v)^u));
const T either = v_lt_l | v_gt_u;
return ~Mask<T>(expand_top_bit(either));
}

static Mask<T> is_any_of(T v, std::initializer_list<T> accepted)
{
T accept = 0;

for(auto a: accepted)
{
const T diff = a ^ v;
const T eq_zero = ~diff & (diff - 1);
accept |= eq_zero;
}

return Mask<T>(expand_top_bit(accept));
}

/**
* AND-combine two masks
*/
@@ -68,10 +68,16 @@ BOTAN_FORCE_INLINE SIMD_4x32 BOTAN_FUNC_ISA(BOTAN_CLMUL_ISA) clmul(const SIMD_4x
i2 = mask_lo.andc(i2);
}

return SIMD_4x32((__vector unsigned int)__builtin_crypto_vpmsumd(
(__vector unsigned long)i1.raw(),
(__vector unsigned long)i2.raw())
);
auto i1v = reinterpret_cast<__vector unsigned long long>(i1.raw());
auto i2v = reinterpret_cast<__vector unsigned long long>(i2.raw());

#if defined(__clang__)
auto rv = __builtin_altivec_crypto_vpmsumd(i1v, i2v);
#else
auto rv = __builtin_crypto_vpmsumd(i1v, i2v);
#endif

return SIMD_4x32(reinterpret_cast<__vector unsigned int>(rv));
#endif
}

@@ -5,27 +5,6 @@ compiler: gcc

jobs:
include:
- name: Coverage (GCC)
env:
- TARGET="coverage"
- CCACHE_MAXSIZE=2G
- PKCS11_LIB=/usr/lib/softhsm/libsofthsm2.so

- name: Fuzzers (GCC)
arch: arm64
env:
- TARGET="fuzzers"

- name: Valgrind (GCC)
env:
- TARGET="valgrind"
- CCACHE_MAXSIZE=2G

- name: Linux s390x (GCC)
arch: s390x
env:
- TARGET="shared"

- name: Linux ppc64le (GCC)
arch: ppc64le
env:
@@ -36,91 +15,12 @@ jobs:
env:
- TARGET="shared"

- name: Linux arm32 cross (GCC)
arch: arm64
env:
- TARGET="cross-arm32"

- name: Linux x86_64 (Clang)
compiler: clang
env:
- TARGET="shared"

- name: Linux ppc32 cross (GCC)
dist: xenial
env:
- TARGET="cross-ppc32"

- name: macOS x86_64 (XCode Clang)
os: osx
compiler: clang
env:
- TARGET="shared"

- name: iOS arm64 (XCode Clang)
os: osx
compiler: clang
env:
- TARGET="cross-arm64"

- name: Android arm32 cross (NDK Clang)
compiler: clang
env:
- TARGET="cross-android-arm32"
- ANDROID_NDK=android-ndk-r21d

- name: Android arm64 cross (NDK Clang)
compiler: clang
env:
- TARGET="cross-android-arm64"
- ANDROID_NDK=android-ndk-r21d

- name: MinGW x86-64 cross (GCC)
env:
- TARGET="cross-win64"

- name: Linux i386 cross (GCC)
env:
- TARGET="cross-i386"

- name: Linux GCC 4.8
dist: bionic
env:
- TARGET="gcc4.8"
- EXTRA_FLAGS="--disable-werror"

- name: Linux Clang 8
compiler: clang
env:
- TARGET="clang8"
- CXX="/usr/bin/clang++-8"

- name: Minimized
arch: arm64
env:
- TARGET="mini-shared"

- name: Baremetal (GCC)
arch: arm64
env:
- TARGET="baremetal"

- name: BSI policy
arch: arm64
env:
- TARGET="bsi"

- name: NIST policy
arch: arm64
env:
- TARGET="nist"

- name: Pylint
arch: arm64
dist: bionic
env:
- TARGET="lint"

install:
- ./src/scripts/ci/setup_travis.sh

@@ -295,7 +295,7 @@ def determine_flags(target, target_os, target_cpu, target_cc, cc_bin,
else:
run_test_command = test_prefix + test_cmd

return flags, run_test_command, make_prefix
return flags, run_test_command, make_prefix, install_prefix

def run_cmd(cmd, root_dir):
"""
@@ -501,6 +501,7 @@ def main(args=None):
'src/python/botan2.py',
'src/scripts/ci_build.py',
'src/scripts/install.py',
'src/scripts/ci_check_install.py',
'src/scripts/dist.py',
'src/scripts/cleanup.py',
'src/scripts/check.py',
@@ -522,7 +523,7 @@ def main(args=None):
cmds.append(['python3', '-m', 'pylint'] + pylint_flags + [py3_flags] + full_paths)

else:
config_flags, run_test_command, make_prefix = determine_flags(
config_flags, run_test_command, make_prefix, install_prefix = determine_flags(
target, options.os, options.cpu, options.cc,
options.cc_bin, options.compiler_cache, root_dir,
options.pkcs11_lib, options.use_gdb, options.disable_werror,
@@ -606,6 +607,7 @@ def main(args=None):

if target in ['shared', 'static', 'bsi', 'nist']:
cmds.append(make_cmd + ['install'])
cmds.append([py_interp, os.path.join(root_dir, 'src/scripts/ci_check_install.py'), install_prefix])

if target in ['sonar']:

@@ -0,0 +1,56 @@
#!/usr/bin/env python
# coding=utf8

"""
Botan CI check installation script
This script is used to validate the results of `make install`
(C) 2020 Jack Lloyd, René Meusel, Hannes Rantzsch
Botan is released under the Simplified BSD License (see license.txt)
"""

import os
import sys

def has_extension(filename, extensions):
for ext in [ext for ext in extensions]:
if filename.endswith(".%s" % ext):
return True
return False

def is_lib_file(filename):
return has_extension(filename, ["so", "a", "dll", "dylib", "lib"])

def is_header_file(filename):
return has_extension(filename, ["h", "hpp", "h++", "hxx", "hh"])

def main():
if len(sys.argv) < 2:
print("Usage: %s <install_prefix>" % sys.argv[0])
return 1
install_prefix = sys.argv[1]

if not os.path.isdir(install_prefix):
print('Error: install_prefix "%s" is not a directory' % install_prefix)
return 1

found_libs = False
found_headers = False

for (_, _, filenames) in os.walk(install_prefix):
for filename in filenames:
if is_header_file(filename):
found_headers = True
elif is_lib_file(filename):
found_libs = True
if found_libs and found_headers:
return 0

print("Error: installation incomplete. Found headers: %s. Found libs: %s. install_prefix was %s"
% (found_headers, found_libs, install_prefix))
return 1


if __name__ == '__main__':
sys.exit(main())