Просмотр исходного кода

port to work with flipper and fbt

Struan Clark 2 лет назад
Родитель
Сommit
f889441cd8
43 измененных файлов с 40 добавлено и 17970 удалено
  1. 19 19
      crypto/aes/aestst.c
  2. 1 1
      crypto/ed25519-donna/ed25519-donna-impl-base.c
  3. 2 2
      crypto/ed25519-donna/ed25519-donna-impl-base.h
  4. 1 1
      crypto/ed25519-donna/ed25519-hash-custom-keccak.h
  5. 1 1
      crypto/ed25519-donna/ed25519-hash-custom-sha3.h
  6. 1 1
      crypto/ed25519-donna/ed25519-hash-custom.h
  7. 2 2
      crypto/ed25519-donna/ed25519.c
  8. 1 1
      crypto/ed25519-donna/ed25519.h
  9. 0 105
      crypto/fuzzer/README.md
  10. 0 399
      crypto/fuzzer/extract_fuzzer_dictionary.py
  11. 0 49
      crypto/fuzzer/extract_fuzzer_dictionary.sh
  12. 0 1616
      crypto/fuzzer/fuzzer.c
  13. 0 21
      crypto/fuzzer/sanitizer_ignorelist.txt
  14. 1 1
      crypto/hmac_drbg.h
  15. 2 2
      crypto/memzero.c
  16. 1 1
      crypto/monero/base58.c
  17. 2 2
      crypto/monero/base58.h
  18. 1 1
      crypto/monero/xmr.c
  19. 2 2
      crypto/monero/xmr.h
  20. 0 1039
      crypto/tests/test_bignum.py
  21. 0 9815
      crypto/tests/test_check.c
  22. 0 571
      crypto/tests/test_check_cardano.h
  23. 0 76
      crypto/tests/test_check_cashaddr.h
  24. 0 1132
      crypto/tests/test_check_monero.h
  25. 0 254
      crypto/tests/test_check_segwit.h
  26. 0 381
      crypto/tests/test_curves.py
  27. 0 150
      crypto/tests/test_openssl.c
  28. 0 231
      crypto/tests/test_speed.c
  29. 0 748
      crypto/tests/test_wycheproof.py
  30. 0 3
      crypto/tools/.gitignore
  31. 0 54
      crypto/tools/README.md
  32. 0 100
      crypto/tools/bip39bruteforce.c
  33. 0 73
      crypto/tools/mktable.c
  34. 0 18
      crypto/tools/nem_test_vectors.erb
  35. 0 126
      crypto/tools/nem_test_vectors.rb
  36. 0 48
      crypto/tools/xpubaddrgen.c
  37. 0 359
      crypto/zkp_bip340.c
  38. 0 22
      crypto/zkp_bip340.h
  39. 0 112
      crypto/zkp_context.c
  40. 0 16
      crypto/zkp_context.h
  41. 0 382
      crypto/zkp_ecdsa.c
  42. 0 30
      crypto/zkp_ecdsa.h
  43. 3 3
      views/flipbip39_scene_1.c

+ 19 - 19
crypto/aes/aestst.c

@@ -96,25 +96,25 @@ unsigned char res[3][32] =
     }
 };
 
-void cycles(volatile uint64_t *rtn)
-{
-#if defined( _MSCVER )
-    __asm   // read the Pentium Time Stamp Counter
-    {   cpuid
-        rdtsc
-        mov     ecx,rtn
-        mov     [ecx],eax
-        mov     [ecx+4],edx
-        cpuid
-    }
-#elif defined( __GNUC__ )
-#if defined(__aarch64__)
-    __asm__ __volatile__("mrs %0, cntvct_el0": "=r" (*rtn));
-#else
-    __asm__ __volatile__("rdtsc": "=A" (*rtn));
-#endif
-#endif
-}
+// void cycles(volatile uint64_t *rtn)
+// {
+// #if defined( _MSCVER )
+//     __asm   // read the Pentium Time Stamp Counter
+//     {   cpuid
+//         rdtsc
+//         mov     ecx,rtn
+//         mov     [ecx],eax
+//         mov     [ecx+4],edx
+//         cpuid
+//     }
+// #elif defined( __GNUC__ )
+// #if defined(__aarch64__)
+//     __asm__ __volatile__("mrs %0, cntvct_el0": "=r" (*rtn));
+// #else
+//     __asm__ __volatile__("rdtsc": "=A" (*rtn));
+// #endif
+// #endif
+// }
 
 int main(void)
 {   unsigned char   out[32], ret[32], err = 0;

+ 1 - 1
crypto/ed25519-donna/ed25519-donna-impl-base.c

@@ -1,6 +1,6 @@
 #include <assert.h>
 #include "ed25519-donna.h"
-#include "memzero.h"
+#include "../memzero.h"
 
 /* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
 /* d = -121665 / 121666 */

+ 2 - 2
crypto/ed25519-donna/ed25519-donna-impl-base.h

@@ -24,9 +24,9 @@ void ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_nie
 #endif
 
 /* computes [s1]p1 + [s2]p2 */
-#if USE_MONERO
+//#if USE_MONERO
 void ge25519_double_scalarmult_vartime2(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const ge25519 *p2, const bignum256modm s2);
-#endif
+//#endif
 
 void ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit);
 

+ 1 - 1
crypto/ed25519-donna/ed25519-hash-custom-keccak.h

@@ -12,7 +12,7 @@
 #ifndef ED25519_HASH_CUSTOM
 #define ED25519_HASH_CUSTOM
 
-#include "sha3.h"
+#include "../sha3.h"
 
 #define ed25519_hash_context SHA3_CTX
 #define ed25519_hash_init(ctx) keccak_512_Init(ctx)

+ 1 - 1
crypto/ed25519-donna/ed25519-hash-custom-sha3.h

@@ -12,7 +12,7 @@
 #ifndef ED25519_HASH_CUSTOM
 #define ED25519_HASH_CUSTOM
 
-#include "sha3.h"
+#include "../sha3.h"
 
 #define ed25519_hash_context SHA3_CTX
 #define ed25519_hash_init(ctx) sha3_512_Init(ctx)

+ 1 - 1
crypto/ed25519-donna/ed25519-hash-custom.h

@@ -12,7 +12,7 @@
 #ifndef ED25519_HASH_CUSTOM
 #define ED25519_HASH_CUSTOM
 
-#include "sha2.h"
+#include "../sha2.h"
 
 #define ed25519_hash_context SHA512_CTX
 #define ed25519_hash_init(ctx) sha512_Init(ctx)

+ 2 - 2
crypto/ed25519-donna/ed25519.c

@@ -18,8 +18,8 @@
 #include "ed25519.h"
 
 #include "ed25519-hash-custom.h"
-#include "rand.h"
-#include "memzero.h"
+#include "../rand.h"
+#include "../memzero.h"
 
 /*
 	Generates a (extsk[0..31]) and aExt (extsk[32..63])

+ 1 - 1
crypto/ed25519-donna/ed25519.h

@@ -1,7 +1,7 @@
 #ifndef ED25519_H
 #define ED25519_H
 
-#include "options.h"
+#include "../options.h"
 
 #if defined(__cplusplus)
 extern "C" {

+ 0 - 105
crypto/fuzzer/README.md

@@ -1,105 +0,0 @@
-# Fuzz Testing trezor-crypto
-Selected functions can be fuzzed via specific libFuzzer harnesses for increased test coverage and issue detection.
-
-Note: the following commands are relative to the trezor-crypto main directory.
-
-## Build
-
-A modern C compiler with built-in libFuzzer support is required. The build process will use `clang` by default.
-Set the `CC=` environment variable if you want to use a special compiler variant.
-
-```bash
-make clean
-FUZZER=1 make fuzzer -j$(nproc)
-```
-
-### Sanitizers
-Recommended: ASAN / UBSAN / MSAN flags for error detection can be specified via the special `SANFLAGS`.
-
-Examples:
-
-* `SANFLAGS="-fsanitize=address,undefined"`
-* `SANFLAGS="-fsanitize=memory -fsanitize-memory-track-origins"`
-
-### Optimizations
-
-Override `OPTFLAGS` to test the library at different optimization levels or simplify the debugging of detected issues.
-
-Examples:
-
-* `OPTFLAGS="-O0 -ggdb3"`
-* `OPTFLAGS="-O3 -march=native -fno-omit-frame-pointer -gline-tables-only"`
-
-To be determined:
-
-* semi-automatic use of `-fsanitize-ignorelist` to reduce sanitizer overhead on hot functions
-* `-flto` and `-flto=thin` link time optimization
-
-Advanced usage:
-* [Profile guided optimization](https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization)
-
-### Fuzzer-specific Configuration Flags
-
-* `-DFUZZ_ALLOW_SLOW` to enable optional fuzzing targets of slow functions
-* select a specific fuzz testing harness with `-DFUZZER_EXCLUSIVE_TARGET=` to disable the use of all other targets
-
-### Other Flags
-
-To be determined:
-
-* `-DNDEBUG`
-* `-DUSE_BIP39_CACHE=0 -DUSE_BIP32_CACHE=0` to explicitly disable the cache, a workaround for automatic cache clearing is used otherwise
-* `-D_FORTIFY_SOURCE=2` together with optimization flag -O2 or above
-* `-fstack-protector-strong` or `-fstack-protector-all`
-* `-m32` to closer emulate the 32-bit environment present on microcontroller platforms
-    * manually adjust Makefile `DSECP256K1_CONTEXT_SIZE=` for 32-bit values, see `legacy/firmware/Makefile`
-    * this flag requires 32-bit build support for gcc-multilib, libc and others
-    * switching from 64-bit to 32-bit has some effects on sanitizer internals such as Address Sanitizer
-* `-DSHA2_UNROLL_TRANSFORM` SHA2 optimization flags
-* `-fsanitize-coverage=edge,trace-cmp,trace-div,indirect-calls,trace-gep,no-prune` to add program counter granularity
-* starting with clang-15, the additional `trace-loads` and `trace-stores` sanitizer coverage options are also available
-
-## Operation
-
-See the [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html#options) for valid options and usage. Detailed fuzzer usage and relevant considerations are out of scope of this document.
-
-**Warning**: fuzzing is resource-intensive and can have a negative impact on your system stability.
-
-Basic fuzzer call:
-```bash
-./fuzzer/fuzzer
-```
-
-Here is a more sophisticated multithreading example with a persistent input corpus and other optimizations:
-```bash
-mkdir fuzzer/fuzzer_corpus
-./fuzzer/fuzzer -max_len=2048 -use_value_profile=1 -workers=16 -jobs=16 -timeout=1 -reload=5 -print_pcs=1 -print_funcs=42  fuzzer/fuzzer_corpus
-```
-
-Hint: for more permanent setups, consider invoking the fuzzer from outside of the source directory to avoid cluttering it with logfiles and crash inputs. Similarly, it is recommended to store the fuzzer corpus in another location.
-
-## Automated Fuzzer Dictionary Generation
-
-[Dictionaries](https://llvm.org/docs/LibFuzzer.html#dictionaries) are a useful mechanism to augment the capabilities of the fuzzer. Specify them via the `-dict=` flag.
-
-### Collect Interesting Strings From Unit Tests
-
-```bash
-cd fuzzer
-./extract_fuzzer_dictionary.sh fuzzer_crypto_tests_strings_dictionary1.txt
-```
-The resulting file can be used as a fuzzer dictionary.
-
-## Evaluate Source Coverage
-
-  1. build the fuzzer binary with `CFLAGS="-fprofile-instr-generate -fcoverage-mapping"`
-  1. run with suitable `-runs=` or `-max_total_time=` limits
-  1. convert the recorded data `llvm-profdata merge -output=default.profdata -instr default.profraw`
-  1. render the data `llvm-cov show fuzzer/fuzzer -instr-profile=default.profdata -format=html -output-dir=coverage-report`
-  1. analyze report at `coverage-report/index.html`
-  1. (optional) remove artifacts with `rm default.profraw default.profdata && rm -r coverage-report`
-
-## Using Honggfuzz Fuzzer
-
-Although this code is designed primarily for libFuzzer, it can also be used with [Honggfuzz](https://honggfuzz.dev).
-However, the usage details are out of scope of this document.

+ 0 - 399
crypto/fuzzer/extract_fuzzer_dictionary.py

@@ -1,399 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-This experimental program is designed to extract a subset of interesting test
-case snippets from the trezor-crypto test directory and output them as a
-standard fuzzer dictionary file.
-
-The program is built on quick-and-dirty regex matching that is known to be
-incorrect for parsing code files, but is considered "good enough" for this
-specific purpose.
-Note that there are target-specific configurations and internal filter settings.
-"""
-
-import argparse
-import binascii
-import glob
-import re
-
-# re2 is considered for future use
-# it requires a system installation and the google-re2 python package
-# import re2
-
-
-# Expected target format for strings in code:
-# Most strings are defined in the general form "example"
-# There are a few test vectors in crypto/tests/wycheproof/javascript/EcUtil.js
-# with 'example' style string definitions, these are ignored for now
-
-TARGET_DIR = "../tests"
-
-# intentionally excluded file types that currently do not provide enough value:
-# *.js, *.md, *.sh, *.html and others from the wycheproof subdirectory
-
-targeted_filetypes_multiline_classA = ("*.c", "*.h", "*.py")
-# Java files have different multiline strings that are handled differently
-targeted_filetypes_multiline_classB = ("*.java",)
-targeted_filetypes_multiline = (
-    targeted_filetypes_multiline_classA + targeted_filetypes_multiline_classB
-)
-
-# files without multiline string content
-# Note: consider switching to actual JSON parsing?
-# Note: the wycheproof repository has a number of test cases for other
-# cryptography such as DSA and RSA which are currently less interesting for the
-# fuzzer dictionary and therefore excluded
-targeted_filetypes_singleline = (
-    "aes*.json",
-    "ecdh*.json",
-    "ecdsa*.json",
-    "x25519*.json",
-    "chacha20*.json",
-    "kw*.json",
-)
-
-verbose = False
-
-# patterns to extract
-# singleline:
-# "4a1e76f133afb"
-# 0xAF8BBDFE8CDD5 and 0x0488b21e
-# m/0'/2147483647'/1'/2147483646'/2' in test_check.c via m/[\d'/]+
-#
-# multiline:
-# "fffc" \n "99"
-# "dpubZ9169K" \n "bTYbcY"
-# "\x65\xf9" \\n  "\xa0\x6a"
-# { 0x086d8bd5, 0x1018f82f, \n 0xc55ece} , see rg "0x([a-zA-Z0-9])+"
-
-# patterns to ignore
-# lines with print statements
-# lines with exceptions
-# comments and other metadata in the testvector JSON files
-# filenames
-# import statements and other package names
-
-# patterns to investigate further
-# public keys with the form BEGIN PUBLIC KEY
-# TODO "abc" + "def" string concatenation on the same line without newline
-# strings in comments
-
-# dictionary text export file format
-# general description:
-# https://github.com/AFLplusplus/AFLplusplus/blob/stable/dictionaries/README.md
-#
-# the exported file is primarly designed for use with a recent libFuzzer version
-# and is known to be partially incompatible with other fuzzers that impose
-# other limitations
-#
-# known incompatibilities:
-# * honggfuzz only reads a limited number of dictionary entries (8192 with version 2.5)
-# * afl++ only reads line content with up to 128 byte
-
-# match everything in quotes that doesn't have an internal quote character and
-# at least one internal character
-regex_string_general_definition = r"\"[^\"]+\""
-regex_string_general = re.compile(regex_string_general_definition)
-# the capturing group ignores prefix and suffix outside of the quotes
-# Note that this is prone to matching the last line of a C-style multiline string,
-# which is addressed via extra state handling during the file processing
-regex_oneline_string = re.compile(
-    r"(" + regex_string_general_definition + r")\s*[\,\)]+"
-)
-# ignore lines that have a "+" character preceding a string
-regex_oneline_string_java_ignore1 = re.compile(r"^\s*\+\s*\"")
-
-regex_hex_character_segment_inner_definition = "[0-9a-fA-F]+"
-regex_hex_character_input_complete = re.compile(
-    '^"' + regex_hex_character_segment_inner_definition + '"$'
-)
-regex_hex_character_input_inner = re.compile(
-    regex_hex_character_segment_inner_definition
-)
-# most constants are preceded by a space, but some have a "(" "[" or "{" before them
-regex_hex_constant_singleline = re.compile(r"(?<=\(|\[|\{| )0x[a-fA-F0-9]+")
-
-regex_c_style_multiline = re.compile(r"(?:\".+\"\s*\n\s*)+(?:\".+\")", re.MULTILINE)
-regex_c_intermediary_content = re.compile(r"\"\s*\n\s*\"", re.MULTILINE)
-# TODO how to prevent matching in the middle of a multi-line string concatenation?
-# negative lookbehind for "+" is not possible generically and
-# (?<!\+ ) and similar patterns are too static
-
-regex_java_style_multiline = re.compile(
-    r"(?:\".+\"\s*\n\s*\+\s*)+(?:\".+\")", re.MULTILINE
-)
-regex_java_intermediary_content = re.compile(r"\"\s*\n\s*\+\s*\"", re.MULTILINE)
-
-regex_text_newline = re.compile(r"\\n")
-
-# primitive regex that catches most filenames in the data set
-regex_filename_heuristic = re.compile(r"\.[a-zA-Z]+")
-
-counter_hex_content = 0
-counter_wycheproof_hex_reconstruction = 0
-
-# TODO add '"curve"' to capture algorithm names?
-allowlist_keywords_json = (
-    '"uncompressed"',
-    '"wx"',
-    '"wy"',
-    '"msg"',
-    '"sig"',
-    '"key"',
-    '"iv"',
-    '"ct"',
-    '"aad"',
-    '"tag"',
-    '"public"',
-    '"private"',
-    '"shared"',
-    '"padding"',
-    '"x"',
-    '"d"',
-)
-
-# TODO the "keyPem" entry is only a workaround for an encoding issue
-ignore_keywords_java = (
-    "println(",
-    "Exception(",
-    '"keyPem"',
-)
-ignore_keywords_c = ("printf(",)
-
-
-def ignore_single_line_json(data):
-    """return True if the input should be ignored"""
-    # ignore everything that is not matched by the allowlist
-    for keyword in allowlist_keywords_json:
-        if data.find(keyword) > -1:
-            return False
-    return True
-
-
-def ignore_single_line_java(data):
-    """return True if the input should be ignored"""
-    for keyword in ignore_keywords_java:
-        if data.find(keyword) > -1:
-            return True
-    return False
-
-
-def ignore_single_line_c(data):
-    """return True if the input should be ignored"""
-    for keyword in ignore_keywords_c:
-        if data.find(keyword) > -1:
-            return True
-    return False
-
-
-def ignore_general(data):
-    """return True if the input should be ignored"""
-    if regex_filename_heuristic.search(data):
-        return True
-    return False
-
-
-def encode_strings_for_dictionary(data):
-    """
-    Assumes that inputs are already in string quotes
-
-    Handles dictionary-specific encoding steps
-    """
-    # libfuzzer does not like "\n" string patterns in dictionary files, replace
-    # it with an encoded newline
-    data = regex_text_newline.sub("\\\\x0a", data)
-    return data
-
-
-def detect_and_convert_hex(data):
-    """
-    Convert hex strings
-
-    Directly pass through non-hex content
-    """
-    global counter_hex_content
-    global counter_wycheproof_hex_reconstruction
-    match_result1 = regex_hex_character_input_complete.search(data)
-    if match_result1:
-
-        match_result2 = regex_hex_character_input_inner.search(match_result1.string)
-        isolated_substring = match_result2.group(0)
-        if len(isolated_substring) % 2 == 1:
-            # Note: the test cases in the wycheproof testvector JSON files have
-            # a custom binary hex format to represent keys
-            # among other things, this results in hex strings with an uneven
-            # number of characters
-            # see tests/wycheproof/java/com/google/security/wycheproof/JsonUtil.java
-            # specifically the asBigInteger() function for more information
-            if isolated_substring[0] >= "0" and isolated_substring[0] <= "7":
-                isolated_substring = "0" + isolated_substring
-            else:
-                isolated_substring = "f" + isolated_substring
-            counter_wycheproof_hex_reconstruction += 1
-
-        converted_result = ""
-        try:
-            # test error-free conversion to binary
-            binascii.unhexlify(isolated_substring)
-            hex_with_c_style_formatting = ""
-            pos = 0
-            while pos < len(isolated_substring) - 1:
-                hex_with_c_style_formatting += "\\x" + isolated_substring[pos : pos + 2]
-                pos += 2
-
-            converted_result = '"%s"' % hex_with_c_style_formatting
-        # TODO binascii.Incomplete exception also relevant?
-        except binascii.Error:
-            # default to the original input
-            return data
-        counter_hex_content += 1
-        return converted_result
-    return data
-
-
-def search_files_recursively(directory, filetype_glob):
-    """returns glob search results"""
-    target_files = []
-    print_verbose("searching in %s" % directory)
-    for filetype in filetype_glob:
-        print_verbose("searching for %s" % filetype)
-        target_files.extend(glob.glob(f"{directory}/**/{filetype}", recursive=True))
-    return target_files
-
-
-def print_verbose(text):
-    """print wrapper"""
-    if verbose:
-        print(text)
-
-
-def recursive_dictionary_extraction(directory):
-    """handle the central extraction logic"""
-    # TODO split this function up into subfunctions
-    global counter_hex_content
-    # handle as a set structure to de-duplicate results automatically
-    candidate_lines = set()
-
-    target_files = search_files_recursively(directory, targeted_filetypes_singleline)
-    for filepath in target_files:
-        per_file_result_counter = 0
-        with open(filepath) as _file:
-            print_verbose("processing %s" % filepath)
-            for _, line in enumerate(_file.readlines()):
-                if ignore_single_line_json(line):
-                    continue
-                results = regex_oneline_string.findall(line)
-                for result in results:
-                    candidate_lines.add(result)
-                    per_file_result_counter += 1
-            if per_file_result_counter > 0:
-                print_verbose("results: %d" % per_file_result_counter)
-
-    print_verbose("number of candidate entries: %d" % len(candidate_lines))
-
-    target_files = search_files_recursively(directory, targeted_filetypes_multiline)
-    for filepath in target_files:
-        per_file_result_counter = 0
-        with open(filepath) as _file:
-            last_line_was_multiline_string = False
-            print_verbose("processing %s for single-line strings" % filepath)
-            for _, line in enumerate(_file.readlines()):
-                if ignore_single_line_java(line):
-                    last_line_was_multiline_string = False
-                    continue
-                if ignore_single_line_c(line):
-                    last_line_was_multiline_string = False
-                    continue
-                if regex_oneline_string_java_ignore1.search(line):
-                    last_line_was_multiline_string = True
-                    if regex_oneline_string.search(line):
-                        # the Java multiline string apparently ends on this line
-                        last_line_was_multiline_string = False
-                    continue
-
-                result_general_string = regex_string_general.search(line)
-                if result_general_string:
-                    # at least one general string is matched, see if it is
-                    # a single-line string
-                    results = regex_oneline_string.findall(line)
-                    for result in results:
-                        if not last_line_was_multiline_string:
-                            candidate_lines.add(result)
-                            per_file_result_counter += 1
-                        last_line_was_multiline_string = False
-                    if len(results) == 0:
-                        last_line_was_multiline_string = True
-                else:
-                    last_line_was_multiline_string = False
-
-                # TODO split this into a separate loop?
-                results = regex_hex_constant_singleline.findall(line)
-                for result in results:
-                    # remove the "0x" prefix, add quotes
-                    candidate_lines.add('"%s"' % result[2:])
-                    per_file_result_counter += 1
-
-            if per_file_result_counter > 0:
-                print_verbose("results: %d" % per_file_result_counter)
-
-    target_files = search_files_recursively(
-        directory, targeted_filetypes_multiline_classA
-    )
-
-    for filepath in target_files:
-        with open(filepath) as _file:
-            print_verbose("processing %s for C-style multi-line strings" % filepath)
-            filecontent = _file.read()
-            multiline_results = regex_c_style_multiline.findall(filecontent)
-            if len(multiline_results) > 0:
-                print_verbose("results: %d" % len(multiline_results))
-            for result in multiline_results:
-                cleanup = regex_c_intermediary_content.sub("", result)
-                candidate_lines.add(cleanup)
-
-    target_files = search_files_recursively(
-        directory, targeted_filetypes_multiline_classB
-    )
-
-    for filepath in target_files:
-        with open(filepath) as _file:
-            print_verbose("processing %s for Java-style multi-line strings" % filepath)
-            filecontent = _file.read()
-            multiline_results = regex_java_style_multiline.findall(filecontent)
-            if len(multiline_results) > 0:
-                print_verbose("results: %d" % len(multiline_results))
-            for result in multiline_results:
-                cleanup = regex_java_intermediary_content.sub("", result)
-                candidate_lines.add(cleanup)
-
-    return candidate_lines
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser()
-    parser.add_argument("dictionary_output_file", help="output file", type=str)
-    parser.add_argument("--verbose", action="store_true", help="verbose stdout output")
-
-    args = parser.parse_args()
-    verbose = args.verbose
-
-    collected_candidate_lines = recursive_dictionary_extraction(TARGET_DIR)
-    sorted_candidate_lines = sorted(collected_candidate_lines)
-    result_lines = []
-    for candidate_line in sorted_candidate_lines:
-        if ignore_general(candidate_line):
-            continue
-        result_lines.append(
-            encode_strings_for_dictionary(detect_and_convert_hex(candidate_line))
-        )
-
-    print_verbose("counter_hex_content: %d" % counter_hex_content)
-    print_verbose(
-        "counter_wycheproof_hex_reconstruction: %d"
-        % counter_wycheproof_hex_reconstruction
-    )
-    print_verbose("overall deduplicated entries: %d" % len(sorted_candidate_lines))
-
-    with open(args.dictionary_output_file, "w") as _file:
-        for result_line in result_lines:
-            _file.write("%s\n" % result_line)

+ 0 - 49
crypto/fuzzer/extract_fuzzer_dictionary.sh

@@ -1,49 +0,0 @@
-#!/usr/bin/env bash
-
-# usage: script.sh target-dictionary-filename
-
-# This script searches for interesting strings in the source code and converts
-# them into a standard fuzzer dictionary file.
-#
-# Note that this script is phased out in favor of the more sophisticated
-# extract_fuzzer_dictionary.py program
-
-# TODO known issues: the end result has some duplicates in it
-
-TARGET_DIR=../tests
-OUTPUT_FILE=${1:-fuzzer_crypto_tests_strings_dictionary1.txt}
-
-multiline_string_search() {
-  # TODO the `find` regex behavior is Linux-specific
-  find $TARGET_DIR -type f -regextype posix-extended -regex '.*\.(c|h|py|json|java|js)' | xargs cat | perl -p0e 's/"\s*\n\s*\"//smg'
-}
-
-# ensure empty file
-echo -n "" > $OUTPUT_FILE
-
-# strip multiline strings and extract them
-# exclude some hex strings, but allow hex strings with mixed capitalization (Ethereum, rskip60)
-multiline_string_search | grep -P -o  "\"[\w ]+\"" | grep -v -P "\"(([0-9a-f][0-9a-f])+|([0-9A-F][0-9A-F])+)\"" | sort | uniq | while read -r line ; do
-  echo "$line" >> $OUTPUT_FILE
-done
-
-# extract individual BIP39 and SLIP39 words
-# TODO are those actually valuable as fuzzer dictionary input?
-# grep -r -P -o -h "\"\w+\""  ../slip39_wordlist.h ../bip39_english.h | sort | uniq >> fuzzer_crypto_tests_strings_dictionary1.txt
-
-# extract and convert binary input data from the unit tests
-# find each file, cat it, concatenate multiline strings, look for hex strings in quotes
-# note that this returns multiple megabyte of result strings due to the large amount
-# of test cases in the wycheproof project subfolder
-multiline_string_search | grep -P -o "\"([0-9a-fA-F][0-9a-fA-F])+\"" | grep -P -o "([0-9a-fA-F][0-9a-fA-F])+" | sort | uniq | while read -r line ; do
-  # turn ascii hex strings AA into \xaa for the fuzzer format and add quotes
-  # extra backslash escape due to the bash nesting
-  escaped_hex=`echo $line | sed -e 's/../\\\\x&/g'`
-  echo "\"$escaped_hex\"" >> $OUTPUT_FILE
-done
-
-# search and reassemble BIP39 test seeds that span multiple lines
-# find each file, cat it, concatenate multiline strings, look for BIP39 seed combinations with reasonable length
-multiline_string_search | grep -Po "(\w{3,10} ){11,23}(\w{3,10})" | sort | uniq | while read -r line ; do
-  echo "\"$line\"" >> $OUTPUT_FILE
-done

+ 0 - 1616
crypto/fuzzer/fuzzer.c

@@ -1,1616 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Christian Reitter
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-// includes for potential target functions
-// based on test_check.c
-#include "address.h"
-#include "aes/aes.h"
-#include "base32.h"
-#include "base58.h"
-#include "bignum.h"
-#include "bip32.h"
-#include "bip39.h"
-#include "blake256.h"
-#include "blake2b.h"
-#include "blake2s.h"
-#include "chacha_drbg.h"
-#include "curves.h"
-#include "ecdsa.h"
-#include "ed25519-donna/ed25519-donna.h"
-#include "ed25519-donna/ed25519-keccak.h"
-#include "ed25519-donna/ed25519.h"
-#include "hasher.h"
-#include "hmac_drbg.h"
-#include "memzero.h"
-#include "monero/monero.h"
-#include "nem.h"
-#include "nist256p1.h"
-#include "pbkdf2.h"
-#include "rand.h"
-#include "rc4.h"
-#include "rfc6979.h"
-#include "script.h"
-#include "secp256k1.h"
-#include "segwit_addr.h"
-#include "sha2.h"
-#include "sha3.h"
-#include "shamir.h"
-#include "slip39.h"
-#include "slip39_wordlist.h"
-#include "zkp_bip340.h"
-#include "zkp_context.h"
-#include "zkp_ecdsa.h"
-
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#include <sanitizer/msan_interface.h>
-#endif
-#endif
-
-/* code design notes
- *
- * TODO note down design tradeoffs for this fuzzer style
- */
-
-/* code performance notes
- *
- * use #define over runtime checks for performance reasons
- * avoid VLA arrays for performance reasons
- * potential performance drawbacks of heap usage are accepted for better out of
- * bounds error detection some expensive functions are hidden with compile-time
- * switches fuzzer harnesses are meant to exit early if the preconditions are
- * not met
- */
-
-/* fuzzer input data handling */
-const uint8_t *fuzzer_ptr;
-size_t fuzzer_length;
-
-const uint8_t *fuzzer_input(size_t len) {
-  if (fuzzer_length < len) {
-    fuzzer_length = 0;
-    return NULL;
-  }
-  const uint8_t *result = fuzzer_ptr;
-  fuzzer_length -= len;
-  fuzzer_ptr += len;
-  return result;
-}
-
-/* fuzzer state handling */
-void fuzzer_reset_state(void) {
-  // reset the PRNGs to make individual fuzzer runs deterministic
-  srand(0);
-  random_reseed(0);
-
-  // clear internal caches
-  // note: this is not strictly required for all fuzzer targets
-#if USE_BIP32_CACHE
-  bip32_cache_clear();
-#endif
-#if USE_BIP39_CACHE
-  bip39_cache_clear();
-#endif
-}
-
-void crash(void) {
-  // intentionally exit the program
-  // the fuzzer framework treats this as a crash
-  exit(1);
-}
-
-// IDEA are there advantages to turning this into a macro?
-//
-// check the memory area for memory information leaks if MSAN is available,
-// crash if problems are detected
-void check_msan(void *pointer, size_t length) {
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-  // check `address` for memory info leakage
-  __msan_check_mem_is_initialized(pointer, length);
-#else
-  // ignore if MSan is not enabled
-  (void)pointer;
-  (void)length;
-#endif
-#else
-  // ignore if the compiler does not know __has_feature()
-  (void)pointer;
-  (void)length;
-#endif
-}
-
-// simplify the pointer check after a var_pointer = malloc()
-// return -1 to mark fuzz input as uninteresting for the fuzz engine
-// warning: use only if no manual memory cleanup is needed
-#define RETURN_IF_NULL(var_pointer) \
-  if (var_pointer == NULL) {        \
-    return -1;                      \
-  }
-
-void zkp_initialize_context_or_crash(void) {
-  // The current context usage has persistent side effects
-  // TODO switch to frequent re-initialization where necessary
-  if (!zkp_context_is_initialized()) {
-    if (zkp_context_init() != 0) {
-      crash();
-    }
-  }
-}
-
-/* individual fuzzer harness functions */
-
-int fuzz_bn_format(void) {
-  bignum256 target_bignum;
-  // we need some amount of initial data
-  if (fuzzer_length < sizeof(target_bignum) + 1 + 1) {
-    return -1;
-  }
-
-#define FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE 512
-  char buf[FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE] = {0};
-  int ret = 0;
-
-  // mutate the struct contents
-  memcpy(&target_bignum, fuzzer_input(sizeof(target_bignum)),
-         sizeof(target_bignum));
-
-  uint8_t prefixlen = 0;
-  uint8_t suffixlen = 0;
-  uint32_t decimals = 0;
-  int32_t exponent = 0;
-  bool trailing = false;
-  // range 1 to 128
-  prefixlen = (fuzzer_input(1)[0] & 127) + 1;
-  suffixlen = (fuzzer_input(1)[0] & 127) + 1;
-
-  // check for the second half of the data
-  if (fuzzer_length < (size_t)(prefixlen + suffixlen + 4 + 4 + 1 - 2)) {
-    return -1;
-  }
-  memcpy(&decimals, fuzzer_input(4), 4);
-  memcpy(&exponent, fuzzer_input(4), 4);
-  trailing = (fuzzer_input(1)[0] & 1);
-
-  // IDEA allow prefix == NULL
-  char *prefix = malloc(prefixlen);
-  RETURN_IF_NULL(prefix);
-  // IDEA allow suffix == NULL
-  char *suffix = malloc(suffixlen);
-  if (suffix == NULL) {
-    free(prefix);
-    return -1;
-  }
-
-  memset(prefix, 0, prefixlen);
-  memset(suffix, 0, suffixlen);
-  // only fetch up to (length - 1) to ensure null termination together with the
-  // memset
-  memcpy(prefix, fuzzer_input(prefixlen - 1), prefixlen - 1);
-  memcpy(suffix, fuzzer_input(suffixlen - 1), suffixlen - 1);
-
-  ret = bn_format(&target_bignum, prefix, suffix, decimals, exponent, trailing,
-                  0, buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE);
-
-  // basic sanity checks for the return values
-  if (ret > FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE) {
-    crash();
-  }
-
-  check_msan(&buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE);
-
-  free(prefix);
-  free(suffix);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define BASE32_DECODE_MAX_INPUT_LEN 512
-
-int fuzz_base32_decode(void) {
-  if (fuzzer_length < 2 || fuzzer_length > BASE32_DECODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  char *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  // basic heuristic: the decoded output will always fit in less or equal space
-  uint8_t *out_buffer = malloc(fuzzer_length);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  size_t outlen = fuzzer_length;
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  // null-terminate input buffer to prevent issues with strlen()
-  in_buffer[raw_inlen - 1] = 0;
-
-  uint8_t *ret = base32_decode(in_buffer, raw_inlen, out_buffer, outlen,
-                               BASE32_ALPHABET_RFC4648);
-
-  if (ret != NULL) {
-    check_msan(out_buffer, outlen);
-  }
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define BASE32_ENCODE_MAX_INPUT_LEN 512
-
-int fuzz_base32_encode(void) {
-  if (fuzzer_length > BASE32_ENCODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  uint8_t *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  // TODO: find a better heuristic for output buffer size
-  size_t outlen = 2 * fuzzer_length;
-  char *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_ptr, raw_inlen);
-  fuzzer_input(raw_inlen);
-
-  char *ret = base32_encode(in_buffer, raw_inlen, out_buffer, outlen,
-                            BASE32_ALPHABET_RFC4648);
-
-  if (ret != NULL) {
-    // the return value is a pointer to the end of the written buffer,
-    // use it to calculate the used buffer area
-    check_msan(out_buffer, ret - out_buffer);
-  }
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// internal limit is 128, try some extra bytes
-#define BASE58_ENCODE_MAX_INPUT_LEN 140
-
-int fuzz_base58_encode_check(void) {
-  if (fuzzer_length > BASE58_ENCODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  uint8_t *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  // TODO: find a better heuristic for output buffer size
-  size_t outlen = 2 * fuzzer_length;
-  char *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  int ret = 0;
-  // run multiple hasher variants for the same input
-  base58_encode_check(in_buffer, raw_inlen, HASHER_SHA2D, out_buffer, outlen);
-  base58_encode_check(in_buffer, raw_inlen, HASHER_BLAKED, out_buffer, outlen);
-  base58_encode_check(in_buffer, raw_inlen, HASHER_GROESTLD_TRUNC, out_buffer,
-                      outlen);
-  ret = base58_encode_check(in_buffer, raw_inlen, HASHER_SHA3K, out_buffer,
-                            outlen);
-
-  // check one of the encode results
-  if (ret != 0) {
-    // the return value describes how many characters are written
-    check_msan(out_buffer, ret);
-  }
-
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// internal limit is 128, try some extra bytes
-#define BASE58_DECODE_MAX_INPUT_LEN 140
-
-int fuzz_base58_decode_check(void) {
-  if (fuzzer_length > BASE58_DECODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  uint8_t *in_buffer = malloc(fuzzer_length + 1);
-  RETURN_IF_NULL(in_buffer);
-
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-  uint8_t out_buffer[MAX_ADDR_RAW_SIZE] = {0};
-  // force null-termination
-  in_buffer[raw_inlen] = 0;
-  const char *in_char = (const char *)in_buffer;
-
-  // run multiple hasher variants for the same input
-  base58_decode_check(in_char, HASHER_SHA2D, out_buffer, MAX_ADDR_RAW_SIZE);
-  base58_decode_check(in_char, HASHER_BLAKED, out_buffer, MAX_ADDR_RAW_SIZE);
-  base58_decode_check(in_char, HASHER_GROESTLD_TRUNC, out_buffer,
-                      MAX_ADDR_RAW_SIZE);
-  base58_decode_check(in_char, HASHER_SHA3K, out_buffer, MAX_ADDR_RAW_SIZE);
-
-  check_msan(out_buffer, MAX_ADDR_RAW_SIZE);
-
-  free(in_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size meant to limit input complexity
-// there is no input size limit for the target function
-#define XMR_BASE58_ADDR_DECODE_MAX_INPUT_LEN 512
-
-int fuzz_xmr_base58_addr_decode_check(void) {
-  if (fuzzer_length > XMR_BASE58_ADDR_DECODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  // TODO no null termination used !?
-  // TODO use better size heuristic
-  size_t outlen = fuzzer_length;
-  char *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  uint8_t *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  // tag is only written to
-  uint64_t tag = 0;
-  size_t raw_inlen = fuzzer_length;
-  // mutate in_buffer
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  int ret = xmr_base58_addr_decode_check(in_buffer, raw_inlen, &tag, out_buffer,
-                                         outlen);
-
-  // IDEA check tag for expected values?
-  // IDEA re-encode valid decoding results to check function consistency?
-
-  if (ret != 0) {
-    check_msan(out_buffer, outlen);
-  }
-
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define XMR_BASE58_DECODE_MAX_INPUT_LEN 512
-// a more focused variant of the xmr_base58_addr_decode_check() harness
-int fuzz_xmr_base58_decode(void) {
-  if (fuzzer_length > XMR_BASE58_DECODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  // TODO better size heuristic
-  size_t outlen = fuzzer_length;
-  char *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  uint8_t *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  memset(out_buffer, 0, outlen);
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  xmr_base58_decode(in_buffer, raw_inlen, out_buffer, &outlen);
-
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN 140
-
-int fuzz_xmr_base58_addr_encode_check(void) {
-  // tag_in is internally limited
-  uint8_t tag_in;
-  int ret1 = 0;
-  size_t tag_size = sizeof(tag_in);
-  if (fuzzer_length < tag_size + 1 ||
-      fuzzer_length > XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  // mutate tag_in
-  memcpy(&tag_in, fuzzer_input(tag_size), tag_size);
-
-  // TODO better size heuristic
-  size_t outlen = fuzzer_length * 2;
-  uint8_t *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  char *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  memset(out_buffer, 0, outlen);
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  ret1 = xmr_base58_addr_encode_check(tag_in, in_buffer, raw_inlen, out_buffer,
-                                      outlen);
-
-  if (ret1 != 0) {
-    // encoding successful
-    uint64_t second_tag = 0;
-    // TODO improve length
-    uint8_t dummy_buffer[XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN] = {0};
-    int ret2 = 0;
-    // ret1 represents the actual length of the encoded string
-    // this is important for the decode function to succeed
-    ret2 = xmr_base58_addr_decode_check(out_buffer, ret1, &second_tag,
-                                        dummy_buffer, sizeof(dummy_buffer));
-    // the tag comparison is between unequal types, but this is acceptable here
-    if (ret2 == 0 || tag_in != second_tag) {
-      crash();
-    }
-  }
-
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define XMR_BASE58_ENCODE_MAX_INPUT_LEN 512
-// a more focused variant of the xmr_base58_addr_encode_check() harness
-int fuzz_xmr_base58_encode(void) {
-  if (fuzzer_length > XMR_BASE58_ENCODE_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  // TODO better size heuristic
-  size_t outlen = fuzzer_length * 2;
-  uint8_t *in_buffer = malloc(fuzzer_length);
-  RETURN_IF_NULL(in_buffer);
-  char *out_buffer = malloc(outlen);
-  if (out_buffer == NULL) {
-    free(in_buffer);
-    return -1;
-  }
-
-  memset(out_buffer, 0, outlen);
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  xmr_base58_encode(out_buffer, &outlen, in_buffer, raw_inlen);
-
-  free(in_buffer);
-  free(out_buffer);
-  return 0;
-}
-
-int fuzz_xmr_serialize_varint(void) {
-// arbitrarily chosen maximum size
-#define XMR_SERIALIZE_VARINT_MAX_INPUT_LEN 128
-
-  uint64_t varint_in;
-  size_t varint_in_size = sizeof(varint_in);
-  if (fuzzer_length <= varint_in_size ||
-      fuzzer_length > XMR_SERIALIZE_VARINT_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  uint8_t out_buffer[XMR_SERIALIZE_VARINT_MAX_INPUT_LEN] = {0};
-  size_t outlen = sizeof(out_buffer);
-  uint64_t varint_out = 0;
-
-  // mutate varint_in
-  memcpy(&varint_in, fuzzer_input(varint_in_size), varint_in_size);
-
-  // mutate in_buffer
-  size_t raw_inlen = fuzzer_length;
-  uint8_t *in_buffer = malloc(raw_inlen);
-  RETURN_IF_NULL(in_buffer);
-  memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
-
-  // use the varint
-  xmr_size_varint(varint_in);
-  xmr_write_varint(out_buffer, outlen, varint_in);
-
-  // use the input buffer
-  xmr_read_varint(in_buffer, raw_inlen, &varint_out);
-
-  // IDEA cross-check write/read results
-
-  free(in_buffer);
-  return 0;
-}
-
-// arbitrarily chosen maximum size
-#define NEM_VALIDATE_ADDRESS_MAX_INPUT_LEN 128
-
-int fuzz_nem_validate_address(void) {
-  if (fuzzer_length < 1 || fuzzer_length > NEM_VALIDATE_ADDRESS_MAX_INPUT_LEN) {
-    return -1;
-  }
-
-  uint8_t network = fuzzer_input(1)[0];
-  size_t raw_inlen = fuzzer_length + 1;
-  char *in_buffer = malloc(raw_inlen);
-  RETURN_IF_NULL(in_buffer);
-
-  // mutate the buffer
-  memcpy(in_buffer, fuzzer_input(raw_inlen - 1), raw_inlen - 1);
-  // force null-termination
-  in_buffer[raw_inlen - 1] = 0;
-
-  nem_validate_address(in_buffer, network);
-
-  free(in_buffer);
-  return 0;
-}
-
-int fuzz_nem_get_address(void) {
-  unsigned char ed25519_public_key_fuzz[32] = {0};
-  uint8_t version = 0;
-
-  // TODO switch to < comparison?
-  if (fuzzer_length != (sizeof(ed25519_public_key_fuzz) + sizeof(version))) {
-    return -1;
-  }
-
-  char address[NEM_ADDRESS_SIZE + 1] = {0};
-
-  memcpy(ed25519_public_key_fuzz, fuzzer_input(sizeof(ed25519_public_key_fuzz)),
-         sizeof(ed25519_public_key_fuzz));
-  memcpy(&version, fuzzer_input(sizeof(version)), sizeof(version));
-
-  nem_get_address(ed25519_public_key_fuzz, version, address);
-
-  check_msan(&address, sizeof(address));
-  return 0;
-}
-
-int fuzz_xmr_get_subaddress_secret_key(void) {
-  bignum256modm m = {0};
-  uint32_t major = 0;
-  uint32_t minor = 0;
-  if (fuzzer_length != (sizeof(bignum256modm) + 2 * sizeof(uint32_t))) {
-    return -1;
-  }
-
-  bignum256modm output = {0};
-
-  memcpy(m, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
-  memcpy(&major, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
-  memcpy(&minor, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
-
-  xmr_get_subaddress_secret_key(output, major, minor, m);
-
-  check_msan(&output, sizeof(output));
-  return 0;
-}
-
-int fuzz_xmr_derive_private_key(void) {
-  bignum256modm base = {0};
-  ge25519 deriv = {0};
-  uint32_t idx = 0;
-
-  if (fuzzer_length !=
-      (sizeof(bignum256modm) + sizeof(ge25519) + sizeof(uint32_t))) {
-    return -1;
-  }
-
-  memcpy(base, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
-  memcpy(&deriv, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
-  memcpy(&idx, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
-
-  bignum256modm output = {0};
-
-  xmr_derive_private_key(output, &deriv, idx, base);
-  check_msan(&output, sizeof(output));
-  return 0;
-}
-
-int fuzz_xmr_derive_public_key(void) {
-  ge25519 base = {0};
-  ge25519 deriv = {0};
-  uint32_t idx = 0;
-
-  if (fuzzer_length != (2 * sizeof(ge25519) + sizeof(uint32_t))) {
-    return -1;
-  }
-
-  memcpy(&base, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
-  memcpy(&deriv, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
-  memcpy(&idx, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
-
-  ge25519 output = {0};
-
-  xmr_derive_public_key(&output, &deriv, idx, &base);
-  check_msan(&output, sizeof(output));
-  return 0;
-}
-
-#define SHAMIR_MAX_SHARE_COUNT 16
-#define SHAMIR_MAX_DATA_LEN (SHAMIR_MAX_SHARE_COUNT * SHAMIR_MAX_LEN)
-int fuzz_shamir_interpolate(void) {
-  if (fuzzer_length != (2 * sizeof(uint8_t) + SHAMIR_MAX_SHARE_COUNT +
-                        SHAMIR_MAX_DATA_LEN + sizeof(size_t))) {
-    return -1;
-  }
-
-  uint8_t result[SHAMIR_MAX_LEN] = {0};
-  uint8_t result_index = 0;
-  uint8_t share_indices[SHAMIR_MAX_SHARE_COUNT] = {0};
-  uint8_t share_values_content[SHAMIR_MAX_SHARE_COUNT][SHAMIR_MAX_LEN] = {0};
-  const uint8_t *share_values[SHAMIR_MAX_SHARE_COUNT] = {0};
-  uint8_t share_count = 0;
-  size_t len = 0;
-
-  for (size_t i = 0; i < SHAMIR_MAX_SHARE_COUNT; i++) {
-    share_values[i] = share_values_content[i];
-  }
-
-  memcpy(&result_index, fuzzer_input(sizeof(uint8_t)), sizeof(uint8_t));
-  memcpy(&share_indices, fuzzer_input(SHAMIR_MAX_SHARE_COUNT),
-         SHAMIR_MAX_SHARE_COUNT);
-  memcpy(&share_values_content, fuzzer_input(SHAMIR_MAX_DATA_LEN),
-         SHAMIR_MAX_DATA_LEN);
-  memcpy(&share_count, fuzzer_input(sizeof(uint8_t)), sizeof(uint8_t));
-  // note: this is platform specific via byte length of size_t
-  memcpy(&len, fuzzer_input(sizeof(size_t)), sizeof(size_t));
-
-  // mirror a check that the real code does
-  if (share_count < 1 || share_count > SHAMIR_MAX_SHARE_COUNT) {
-    return 0;
-  }
-  // (len > SHAMIR_MAX_LEN) is handled in the target function
-
-  shamir_interpolate(result, result_index, share_indices, share_values,
-                     share_count, len);
-  check_msan(&result, sizeof(result));
-  return 0;
-}
-
-int fuzz_ecdsa_sign_digest_functions(void) {
-  // bug result reference: https://github.com/trezor/trezor-firmware/pull/1697
-
-  uint8_t curve_decider = 0;
-  uint8_t priv_key[32] = {0};
-  uint8_t digest[32] = {0};
-
-  uint8_t sig1[64] = {0};
-  uint8_t sig2[64] = {0};
-  uint8_t pby1, pby2 = 0;
-  if (fuzzer_length < 1 + sizeof(priv_key) + sizeof(digest)) {
-    return -1;
-  }
-  const ecdsa_curve *curve;
-
-  memcpy(&curve_decider, fuzzer_input(1), 1);
-  memcpy(&priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
-  memcpy(&digest, fuzzer_input(sizeof(digest)), sizeof(digest));
-
-  // pick one of the standard curves
-  if ((curve_decider & 0x1) == 1) {
-    curve = &secp256k1;
-  } else {
-    curve = &nist256p1;
-  }
-
-  int res = 0;
-
-  // IDEA optionally set a function for is_canonical() callback
-  int res1 = ecdsa_sign_digest(curve, priv_key, digest, sig1, &pby1, NULL);
-
-  // the zkp function variant is only defined for a specific curve
-  if (curve == &secp256k1) {
-    int res2 =
-        zkp_ecdsa_sign_digest(curve, priv_key, digest, sig2, &pby2, NULL);
-    if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
-      // one variant succeeded where the other did not
-      crash();
-    }
-    if (res1 == 0 && res2 == 0) {
-      if ((pby1 != pby2) || memcmp(&sig1, &sig2, sizeof(sig1)) != 0) {
-        // result values are different
-        crash();
-      }
-    }
-  }
-
-  // successful signing
-  if (res1 == 0) {
-    uint8_t pub_key[33] = {0};
-    res = ecdsa_get_public_key33(curve, priv_key, pub_key);
-    if (res != 0) {
-      // pubkey derivation did not succeed
-      crash();
-    }
-
-    res = ecdsa_verify_digest(curve, pub_key, sig1, digest);
-    if (res != 0) {
-      // verification did not succeed
-      crash();
-    }
-  }
-  return 0;
-}
-
-int fuzz_ecdsa_verify_digest_functions(void) {
-  uint8_t curve_decider = 0;
-  uint8_t hash[32] = {0};
-  uint8_t sig[64] = {0};
-  uint8_t pub_key[65] = {0};
-
-  if (fuzzer_length < 1 + sizeof(hash) + sizeof(sig) + sizeof(pub_key)) {
-    return -1;
-  }
-
-  memcpy(&curve_decider, fuzzer_input(1), 1);
-  memcpy(&hash, fuzzer_input(sizeof(hash)), sizeof(hash));
-  memcpy(&sig, fuzzer_input(sizeof(sig)), sizeof(sig));
-  memcpy(&pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
-
-  const ecdsa_curve *curve;
-  // pick one of the standard curves
-  if ((curve_decider & 0x1) == 1) {
-    curve = &secp256k1;
-  } else {
-    curve = &nist256p1;
-  }
-
-  int res1 = ecdsa_verify_digest(curve, (const uint8_t *)&pub_key,
-                                 (const uint8_t *)&sig, (const uint8_t *)&hash);
-  if (res1 == 0) {
-    // See if the fuzzer ever manages to get find a correct verification
-    // intentionally trigger a crash to make this case observable
-    // TODO this is not an actual problem, remove in the future
-    crash();
-  }
-
-  // the zkp_ecdsa* function only accepts the secp256k1 curve
-  if (curve == &secp256k1) {
-    int res2 =
-        zkp_ecdsa_verify_digest(curve, (const uint8_t *)&pub_key,
-                                (const uint8_t *)&sig, (const uint8_t *)&hash);
-
-    // the error code behavior is different between both functions, compare only
-    // verification state
-    if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
-      // results differ, this is a problem
-      crash();
-    }
-  }
-
-  return 0;
-}
-
-int fuzz_word_index(void) {
-#define MAX_WORD_LENGTH 12
-
-  if (fuzzer_length < MAX_WORD_LENGTH) {
-    return -1;
-  }
-
-  char word[MAX_WORD_LENGTH + 1] = {0};
-  memcpy(&word, fuzzer_ptr, MAX_WORD_LENGTH);
-  size_t word_length = strlen(word);
-  uint16_t index = 0;
-
-  word_index(&index, (const char *)&word, word_length);
-
-  return 0;
-}
-
-int fuzz_slip39_word_completion_mask(void) {
-  if (fuzzer_length != 2) {
-    return -1;
-  }
-  uint16_t sequence = (fuzzer_ptr[0] << 8) + fuzzer_ptr[1];
-  fuzzer_input(2);
-
-  slip39_word_completion_mask(sequence);
-
-  return 0;
-}
-
-// regular MAX_MNEMONIC_LEN is 240, try some extra bytes
-#define MAX_MNEMONIC_FUZZ_LENGTH 256
-int fuzz_mnemonic_check(void) {
-  if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH) {
-    return -1;
-  }
-
-  char mnemonic[MAX_MNEMONIC_FUZZ_LENGTH + 1] = {0};
-  memcpy(&mnemonic, fuzzer_ptr, MAX_MNEMONIC_FUZZ_LENGTH);
-
-  // at the time of creation of this fuzzer harness, mnemonic_check()
-  // internally calls mnemonic_to_bits() while checking the result
-  int ret = mnemonic_check(mnemonic);
-
-  (void)ret;
-  /*
-  if(ret == 1) {
-    // correct result
-  }
-  */
-
-  return 0;
-}
-
-int fuzz_mnemonic_from_data(void) {
-  if (fuzzer_length < 16 || fuzzer_length > 32) {
-    return -1;
-  }
-
-  const char *mnemo_result = mnemonic_from_data(fuzzer_ptr, fuzzer_length);
-  if (mnemo_result != NULL) {
-    int res = mnemonic_check(mnemo_result);
-    if (res == 0) {
-      // TODO the mnemonic_check() function is currently incorrectly rejecting
-      // valid 15 and 21 word seeds
-      // remove this workaround limitation later
-      if (fuzzer_length != 20 && fuzzer_length != 28) {
-        // the generated mnemonic has an invalid format
-        crash();
-      }
-    }
-  }
-  // scrub the internal buffer to rule out persistent side effects
-  mnemonic_clear();
-  return 0;
-}
-
-// passphrase normally has a 64 or 256 byte length maximum
-#define MAX_PASSPHRASE_FUZZ_LENGTH 257
-int fuzz_mnemonic_to_seed(void) {
-  if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH + MAX_PASSPHRASE_FUZZ_LENGTH) {
-    return -1;
-  }
-
-  char mnemonic[MAX_PASSPHRASE_FUZZ_LENGTH + 1] = {0};
-  char passphrase[MAX_MNEMONIC_FUZZ_LENGTH + 1] = {0};
-  uint8_t seed[512 / 8] = {0};
-
-  memcpy(&mnemonic, fuzzer_input(MAX_MNEMONIC_FUZZ_LENGTH),
-         MAX_MNEMONIC_FUZZ_LENGTH);
-  memcpy(&passphrase, fuzzer_input(MAX_PASSPHRASE_FUZZ_LENGTH),
-         MAX_PASSPHRASE_FUZZ_LENGTH);
-
-  mnemonic_to_seed(mnemonic, passphrase, seed, NULL);
-
-  return 0;
-}
-
-int fuzz_ethereum_address_checksum(void) {
-  uint8_t addr[20] = {0};
-  char address[43] = {0};
-  uint64_t chain_id = 0;
-  bool rskip60 = false;
-
-  if (fuzzer_length < sizeof(addr) + sizeof(address) + sizeof(chain_id) + 1) {
-    return -1;
-  }
-
-  memcpy(addr, fuzzer_input(sizeof(addr)), sizeof(addr));
-  memcpy(address, fuzzer_input(sizeof(address)), sizeof(address));
-  memcpy(&chain_id, fuzzer_input(sizeof(chain_id)), sizeof(chain_id));
-  // usually dependent on chain_id, but determined separately here
-  rskip60 = (*fuzzer_input(1)) & 0x1;
-
-  ethereum_address_checksum(addr, address, rskip60, chain_id);
-
-  return 0;
-}
-
-int fuzz_aes(void) {
-  if (fuzzer_length < 1 + 16 + 16 + 32) {
-    return -1;
-  }
-
-  aes_encrypt_ctx ctxe;
-  aes_decrypt_ctx ctxd;
-  uint8_t ibuf[16] = {0};
-  uint8_t obuf[16] = {0};
-  uint8_t iv[16] = {0};
-  uint8_t cbuf[16] = {0};
-
-  const uint8_t *keylength_decider = fuzzer_input(1);
-
-  // note: the unit test uses the fixed 32 byte key
-  // 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
-  uint8_t keybuf[32] = {0};
-  memcpy(&keybuf, fuzzer_input(32), 32);
-
-#ifdef AES_VAR
-  // try 128, 192, 256 bit key lengths
-
-  size_t keylength = 32;
-  switch (keylength_decider[0] & 0x3) {
-    case 0:
-      // invalid length
-      keylength = 1;
-      break;
-    case 1:
-      keylength = 16;
-      break;
-    case 2:
-      keylength = 24;
-      break;
-    case 3:
-      keylength = 32;
-      break;
-  }
-
-  if (aes_encrypt_key((const unsigned char *)&keybuf, keylength, &ctxe) ||
-      aes_decrypt_key((const unsigned char *)&keybuf, keylength, &ctxd)) {
-    // initialization problems, stop processing
-    // we expect this to happen with the invalid key length
-    return 0;
-  }
-#else
-  // use a 256 bit key length
-  (void)keylength_decider;
-  aes_encrypt_key256((const unsigned char *)&keybuf, &ctxe);
-  aes_decrypt_key256((const unsigned char *)&keybuf, &ctxd);
-#endif
-
-  memcpy(ibuf, fuzzer_input(16), 16);
-  memcpy(iv, fuzzer_input(16), 16);
-
-  aes_ecb_encrypt(ibuf, obuf, 16, &ctxe);
-  aes_ecb_decrypt(ibuf, obuf, 16, &ctxd);
-
-  aes_cbc_encrypt(ibuf, obuf, 16, iv, &ctxe);
-  aes_cbc_decrypt(ibuf, obuf, 16, iv, &ctxd);
-
-  aes_cfb_encrypt(ibuf, obuf, 16, iv, &ctxe);
-  aes_cfb_decrypt(ibuf, obuf, 16, iv, &ctxe);
-
-  aes_ofb_encrypt(ibuf, obuf, 16, iv, &ctxe);
-  aes_ofb_decrypt(ibuf, obuf, 16, iv, &ctxe);
-
-  aes_ctr_encrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
-  aes_ctr_decrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
-  return 0;
-}
-
-int fuzz_chacha_drbg(void) {
-#define CHACHA_DRBG_ENTROPY_LENGTH 32
-#define CHACHA_DRBG_RESEED_LENGTH 32
-#define CHACHA_DRBG_NONCE_LENGTH 16
-#define CHACHA_DRBG_RESULT_LENGTH 16
-
-  if (fuzzer_length < CHACHA_DRBG_ENTROPY_LENGTH + CHACHA_DRBG_RESEED_LENGTH +
-                          CHACHA_DRBG_NONCE_LENGTH) {
-    return -1;
-  }
-
-  uint8_t entropy[CHACHA_DRBG_ENTROPY_LENGTH] = {0};
-  uint8_t reseed[CHACHA_DRBG_RESEED_LENGTH] = {0};
-  uint8_t nonce_bytes[CHACHA_DRBG_NONCE_LENGTH] = {0};
-  uint8_t result[CHACHA_DRBG_RESULT_LENGTH] = {0};
-  CHACHA_DRBG_CTX ctx;
-
-  // IDEA switch to variable input sizes
-  memcpy(&entropy, fuzzer_input(CHACHA_DRBG_ENTROPY_LENGTH),
-         CHACHA_DRBG_ENTROPY_LENGTH);
-  memcpy(&reseed, fuzzer_input(CHACHA_DRBG_RESEED_LENGTH),
-         CHACHA_DRBG_RESEED_LENGTH);
-  memcpy(&nonce_bytes, fuzzer_input(CHACHA_DRBG_NONCE_LENGTH),
-         CHACHA_DRBG_NONCE_LENGTH);
-
-  chacha_drbg_init(&ctx, entropy, sizeof(entropy), nonce_bytes,
-                   sizeof(nonce_bytes));
-  chacha_drbg_reseed(&ctx, reseed, sizeof(reseed), NULL, 0);
-  chacha_drbg_generate(&ctx, result, sizeof(result));
-
-  return 0;
-}
-
-int fuzz_ed25519_sign_verify(void) {
-  ed25519_secret_key secret_key;
-  ed25519_signature signature;
-  ed25519_public_key public_key;
-  // length chosen arbitrarily
-  uint8_t message[32] = {0};
-  int ret = 0;
-
-  if (fuzzer_length <
-      sizeof(secret_key) + sizeof(signature) + sizeof(message)) {
-    return -1;
-  }
-
-  memcpy(&secret_key, fuzzer_input(sizeof(secret_key)), sizeof(secret_key));
-  memcpy(&signature, fuzzer_input(sizeof(signature)), sizeof(signature));
-  memcpy(&message, fuzzer_input(sizeof(message)), sizeof(message));
-
-  ed25519_publickey(secret_key, public_key);
-  // sign message, this should always succeed
-  ed25519_sign(message, sizeof(message), secret_key, signature);
-
-  // verify message, we expect this to work
-  ret = ed25519_sign_open(message, sizeof(message), public_key, signature);
-
-  if (ret != 0) {
-    // verification did not succeed
-    crash();
-  }
-
-  return 0;
-}
-
-int fuzz_zkp_bip340_sign_digest(void) {
-  uint8_t priv_key[32] = {0};
-  uint8_t aux_input[32] = {0};
-  uint8_t digest[32] = {0};
-  uint8_t pub_key[32] = {0};
-  uint8_t sig[64] = {0};
-
-  if (fuzzer_length <
-      sizeof(priv_key) + sizeof(aux_input) + sizeof(digest) + sizeof(sig)) {
-    return -1;
-  }
-  memcpy(priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
-  memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
-  // TODO leave initialized to 0x0?
-  memcpy(aux_input, fuzzer_input(sizeof(aux_input)), sizeof(aux_input));
-  // TODO leave initialized to 0x0?
-  memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
-
-  zkp_bip340_get_public_key(priv_key, pub_key);
-  check_msan(&pub_key, sizeof(pub_key));
-  zkp_bip340_sign_digest(priv_key, digest, sig, aux_input);
-  check_msan(&sig, sizeof(sig));
-  check_msan(&aux_input, sizeof(aux_input));
-
-  // IDEA test sign result?
-
-  return 0;
-}
-
-int fuzz_zkp_bip340_verify_digest(void) {
-  int res = 0;
-  uint8_t pub_key[32] = {0};
-  uint8_t digest[32] = {0};
-  uint8_t sig[64] = {0};
-
-  if (fuzzer_length < sizeof(digest) + sizeof(pub_key) + sizeof(sig)) {
-    return -1;
-  }
-  memcpy(pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
-  memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
-  memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
-
-  res = zkp_bip340_verify_digest(pub_key, sig, digest);
-
-  // res == 0 is valid, but crash to make successful passes visible
-  // TODO remove this later
-  if (res == 0) {
-    crash();
-  }
-
-  return 0;
-}
-
-int fuzz_zkp_bip340_tweak_keys(void) {
-  uint8_t internal_priv[32] = {0};
-  uint8_t root_hash[32] = {0};
-  uint8_t internal_pub[32] = {0};
-  uint8_t result[32] = {0};
-
-  if (fuzzer_length <
-      sizeof(internal_priv) + sizeof(root_hash) + sizeof(internal_pub)) {
-    return -1;
-  }
-  memcpy(internal_priv, fuzzer_input(sizeof(internal_priv)),
-         sizeof(internal_priv));
-  memcpy(root_hash, fuzzer_input(sizeof(root_hash)), sizeof(root_hash));
-  memcpy(internal_pub, fuzzer_input(sizeof(internal_pub)),
-         sizeof(internal_pub));
-
-  // IDEA act on return values
-  zkp_bip340_tweak_private_key(internal_priv, root_hash, result);
-  zkp_bip340_tweak_public_key(internal_pub, root_hash, result);
-
-  return 0;
-}
-
-int fuzz_ecdsa_get_public_key_functions(void) {
-  uint8_t privkey[32] = {0};
-  uint8_t pubkey33_1[33] = {0};
-  uint8_t pubkey33_2[33] = {0};
-  uint8_t pubkey65_1[65] = {0};
-  uint8_t pubkey65_2[65] = {0};
-
-  // note: the zkp_ecdsa_* variants require this specific curve
-  const ecdsa_curve *curve = &secp256k1;
-
-  if (fuzzer_length < sizeof(privkey)) {
-    return -1;
-  }
-  memcpy(privkey, fuzzer_input(sizeof(privkey)), sizeof(privkey));
-
-  int res_33_1 = ecdsa_get_public_key33(curve, privkey, pubkey33_1);
-  int res_33_2 = zkp_ecdsa_get_public_key33(curve, privkey, pubkey33_2);
-  int res_65_1 = ecdsa_get_public_key65(curve, privkey, pubkey65_1);
-  int res_65_2 = zkp_ecdsa_get_public_key65(curve, privkey, pubkey65_2);
-
-  // the function pairs have different return error codes for the same input
-  // so only fail if the one succeeds where the other does not
-  if ((res_33_1 == 0 && res_33_2 != 0) || (res_33_1 != 0 && res_33_2 == 0)) {
-    // function result mismatch
-    crash();
-  }
-  if ((res_65_1 == 0 && res_65_2 != 0) || (res_65_1 != 0 && res_65_2 == 0)) {
-    // function result mismatch
-    crash();
-  }
-
-  if (res_33_1 == 0 && res_33_2 == 0 &&
-      memcmp(&pubkey33_1, &pubkey33_2, sizeof(pubkey33_1)) != 0) {
-    // function result data mismatch
-    crash();
-  }
-
-  if (res_65_1 == 0 && res_65_2 == 0 &&
-      memcmp(&pubkey65_1, &pubkey65_2, sizeof(pubkey65_1)) != 0) {
-    // function result data mismatch
-    crash();
-  }
-
-  return 0;
-}
-
-int fuzz_ecdsa_recover_pub_from_sig_functions(void) {
-  uint8_t digest[32] = {0};
-  uint8_t sig[64] = {0};
-  const ecdsa_curve *curve = &secp256k1;
-  uint8_t recid = 0;
-  uint8_t pubkey1[65] = {0};
-  uint8_t pubkey2[65] = {0};
-
-  if (fuzzer_length < sizeof(digest) + sizeof(sig) + sizeof(recid)) {
-    return -1;
-  }
-  memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
-  memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
-  memcpy(&recid, fuzzer_input(sizeof(recid)), sizeof(recid));
-  // conform to parameter requirements
-  recid = recid & 0x03;
-
-  int res1 = zkp_ecdsa_recover_pub_from_sig(curve, pubkey1, sig, digest, recid);
-  int res2 = ecdsa_recover_pub_from_sig(curve, pubkey2, sig, digest, recid);
-
-  if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
-    // result mismatch
-    // bug result reference: https://github.com/trezor/trezor-firmware/pull/2050
-    crash();
-  }
-
-  if (res1 == 0 && res2 == 0 &&
-      memcmp(&pubkey1, &pubkey2, sizeof(pubkey1)) != 0) {
-    // pubkey result mismatch
-    crash();
-  }
-
-  return 0;
-}
-
-int fuzz_ecdsa_sig_from_der(void) {
-  // bug result reference: https://github.com/trezor/trezor-firmware/pull/2058
-  uint8_t der[72] = {0};
-  uint8_t out[72] = {0};
-
-  if (fuzzer_length < sizeof(der)) {
-    return -1;
-  }
-  memcpy(der, fuzzer_input(sizeof(der)), sizeof(der));
-  // null-terminate
-  der[sizeof(der) - 1] = 0;
-  size_t der_len = strlen((const char *)der);
-
-  // IDEA use different fuzzer-controlled der_len such as 1 to 73
-  int ret = ecdsa_sig_from_der(der, der_len, out);
-  (void)ret;
-  // IDEA check if back conversion works
-
-  return 0;
-}
-
-int fuzz_ecdsa_sig_to_der(void) {
-  uint8_t sig[64] = {0};
-  uint8_t der[72] = {0};
-
-  if (fuzzer_length < sizeof(sig)) {
-    return -1;
-  }
-  memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
-
-  int ret = ecdsa_sig_to_der((const uint8_t *)&sig, der);
-  (void)ret;
-  // IDEA check if back conversion works
-
-  return 0;
-}
-
-int fuzz_button_sequence_to_word(void) {
-  uint16_t input = 0;
-  if (fuzzer_length < sizeof(input)) {
-    return -1;
-  }
-  memcpy(&input, fuzzer_input(sizeof(input)), sizeof(input));
-
-  button_sequence_to_word(input);
-  return 0;
-}
-
-int fuzz_xmr_add_keys(void) {
-  bignum256modm a, b;
-  ge25519 A, B;
-
-  if (fuzzer_length < sizeof(bignum256modm) * 2 + sizeof(ge25519) * 2) {
-    return -1;
-  }
-  memcpy(&a, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
-  memcpy(&b, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
-  memcpy(&A, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
-  memcpy(&B, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
-
-  ge25519 r;
-
-  xmr_add_keys2(&r, a, b, &B);
-  check_msan(&r, sizeof(r));
-
-  xmr_add_keys2_vartime(&r, a, b, &B);
-  check_msan(&r, sizeof(r));
-
-  xmr_add_keys3(&r, a, &A, b, &B);
-  check_msan(&r, sizeof(r));
-
-  xmr_add_keys3_vartime(&r, a, &A, b, &B);
-  check_msan(&r, sizeof(r));
-
-  return 0;
-}
-
-int fuzz_ecdh_multiply(void) {
-  uint8_t priv_key[32];
-  // 33 or 65 bytes content
-  uint8_t pub_key[65];
-  uint8_t decider;
-  if (fuzzer_length < sizeof(priv_key) + sizeof(pub_key) + sizeof(decider)) {
-    return -1;
-  }
-  memcpy(&priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
-  memcpy(&pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
-  memcpy(&decider, fuzzer_input(sizeof(decider)), sizeof(decider));
-
-  uint8_t session_key[65] = {0};
-  int res1 = 0;
-
-  // TODO evaluate crash with &curve == NULL, documentation / convention issue?
-
-  const ecdsa_curve *curve2;
-  // ecdh_multiply() is only called with secp256k1 and nist256p1 curve from
-  // modtrezorcrypto code theoretically other curve parameters are also possible
-  if ((decider & 1) == 0) {
-    curve2 = &nist256p1;
-  } else {
-    curve2 = &secp256k1;
-  }
-
-  res1 = ecdh_multiply(curve2, (uint8_t *)&priv_key, (uint8_t *)&pub_key,
-                       (uint8_t *)&session_key);
-  check_msan(&session_key, sizeof(session_key));
-
-  if (res1 != 0) {
-    // failure case
-  }
-
-  return 0;
-}
-
-int fuzz_segwit_addr_encode(void) {
-  // the current firmware code only uses witver = 0 and witver = 1
-  // we give more flexibility, but do not allow the full int range
-  uint8_t chosen_witver = 0;
-  // restrict fuzzer variations to lengths of 0 to 255
-  uint8_t chosen_witprog_len = 0;
-
-  // in typical use, hrp is a bech32 prefix of 2 to 4 chars
-  // TODO make this dynamic, investigate lowercase requirements
-  // see also https://github.com/sipa/bech32/issues/38
-  char *hrp = "bc";
-
-  if (fuzzer_length < sizeof(chosen_witver) + sizeof(chosen_witprog_len)) {
-    return -1;
-  }
-  memcpy(&chosen_witver, fuzzer_input(sizeof(chosen_witver)),
-         sizeof(chosen_witver));
-  memcpy(&chosen_witprog_len, fuzzer_input(sizeof(chosen_witprog_len)),
-         sizeof(chosen_witprog_len));
-
-  if (chosen_witprog_len > fuzzer_length) {
-    return -1;
-  }
-
-  char output_address[MAX_ADDR_SIZE] = {0};
-  uint8_t *witprog = malloc(chosen_witprog_len);
-  RETURN_IF_NULL(witprog);
-  memcpy(witprog, fuzzer_input(chosen_witprog_len), chosen_witprog_len);
-
-  int ret = segwit_addr_encode(output_address, hrp, chosen_witver, witprog,
-                               chosen_witprog_len);
-
-  // IDEA act depending on ret
-  (void)ret;
-
-  free(witprog);
-  return 0;
-}
-
-// int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len,
-// const char* hrp, const char* addr) {
-int fuzz_segwit_addr_decode(void) {
-  int decoded_witver = 0;
-  size_t decoded_witprog_len = 0;
-  // TODO
-  uint8_t addr_raw[MAX_ADDR_RAW_SIZE] = {0};
-  uint8_t chosen_addr_len = 0;
-
-  if (fuzzer_length < sizeof(chosen_addr_len)) {
-    return -1;
-  }
-
-  memcpy(&chosen_addr_len, fuzzer_input(sizeof(chosen_addr_len)),
-         sizeof(chosen_addr_len));
-
-  if (chosen_addr_len > fuzzer_length) {
-    return -1;
-  }
-
-  char *addr = malloc(chosen_addr_len + 1);
-  RETURN_IF_NULL(addr);
-  memcpy(addr, fuzzer_input(chosen_addr_len), chosen_addr_len);
-  // null termination
-  addr[chosen_addr_len] = 0;
-
-  // TODO see comments in fuzz_segwit_addr_encode()
-  char *hrp = "bc";
-
-  int ret = segwit_addr_decode(&decoded_witver, addr_raw, &decoded_witprog_len,
-                               hrp, addr);
-  // IDEA act depending on ret
-  (void)ret;
-
-  free(addr);
-  return 0;
-}
-
-/* fuzzer main function */
-
-#define META_HEADER_SIZE 3
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  // reject input that is too short
-  if (size < META_HEADER_SIZE) {
-    return -1;
-  }
-
-  fuzzer_reset_state();
-
-  // this controls up to 256 different test cases
-  uint8_t target_decision = data[0];
-
-  // data[1] is reserved for explicit sub decisions
-  // uint8_t target_sub_decision = data[1];
-
-  // data[2] is reserved for future use
-
-  // assign the fuzzer payload data for the target functions
-  fuzzer_ptr = data + META_HEADER_SIZE;
-  fuzzer_length = size - META_HEADER_SIZE;
-
-  // if active: reject all other inputs that are not the selected target
-  // this is helpful for directing the fuzzing focus on a specific case
-#ifdef FUZZER_EXCLUSIVE_TARGET
-  if (target_decision != FUZZER_EXCLUSIVE_TARGET) {
-    return -1;
-  }
-#endif
-
-  // recent libFuzzer implementations support marking inputs as non-interesting
-  // via return -1; instead of the regular return 0;
-  // see
-  // https://github.com/llvm/llvm-project/commit/92fb310151d2b1e349695fc0f1c5d5d50afb3b52
-  int target_result = 0;
-
-  // TODO reorder and regroup target functions
-  switch (target_decision) {
-    case 0:
-      target_result = fuzz_bn_format();
-      break;
-    case 1:
-      target_result = fuzz_base32_decode();
-      break;
-    case 2:
-      target_result = fuzz_base32_encode();
-      break;
-    case 3:
-      target_result = fuzz_base58_encode_check();
-      break;
-    case 4:
-      target_result = fuzz_base58_decode_check();
-      break;
-    case 5:
-      target_result = fuzz_xmr_base58_addr_decode_check();
-      break;
-    case 6:
-      target_result = fuzz_xmr_base58_addr_encode_check();
-      break;
-    case 7:
-      target_result = fuzz_xmr_serialize_varint();
-      break;
-    case 8:
-      target_result = fuzz_nem_validate_address();
-      break;
-    case 9:
-      target_result = fuzz_nem_get_address();
-      break;
-    case 10:
-      target_result = fuzz_xmr_get_subaddress_secret_key();
-      break;
-    case 11:
-      target_result = fuzz_xmr_derive_private_key();
-      break;
-    case 12:
-      target_result = fuzz_xmr_derive_public_key();
-      break;
-    case 13:
-      target_result = fuzz_shamir_interpolate();
-      break;
-    case 14:
-#ifdef FUZZ_ALLOW_SLOW
-      zkp_initialize_context_or_crash();
-      // slow through expensive bignum operations
-      target_result = fuzz_ecdsa_verify_digest_functions();
-#endif
-      break;
-    case 15:
-      target_result = fuzz_word_index();
-      break;
-    case 16:
-      target_result = fuzz_slip39_word_completion_mask();
-      break;
-    case 17:
-      target_result = fuzz_mnemonic_check();
-      break;
-    case 18:
-#ifdef FUZZ_ALLOW_SLOW
-      target_result = fuzz_aes();
-#endif
-      break;
-    case 22:
-      target_result = fuzz_chacha_drbg();
-      break;
-    case 23:
-#ifdef FUZZ_ALLOW_SLOW
-      zkp_initialize_context_or_crash();
-      // slow through expensive bignum operations
-      target_result = fuzz_ecdsa_sign_digest_functions();
-#endif
-      break;
-    case 24:
-      target_result = fuzz_ed25519_sign_verify();
-      break;
-    case 25:
-      target_result = fuzz_mnemonic_from_data();
-      break;
-    case 26:
-      target_result = fuzz_mnemonic_to_seed();
-      break;
-    case 27:
-      target_result = fuzz_button_sequence_to_word();
-      break;
-    case 28:
-      target_result = fuzz_segwit_addr_encode();
-      break;
-    case 29:
-      target_result = fuzz_segwit_addr_decode();
-      break;
-    case 30:
-      target_result = fuzz_ethereum_address_checksum();
-      break;
-
-    case 41:
-      zkp_initialize_context_or_crash();
-      target_result = fuzz_zkp_bip340_sign_digest();
-      break;
-    case 42:
-      zkp_initialize_context_or_crash();
-      target_result = fuzz_zkp_bip340_verify_digest();
-      break;
-    case 43:
-      zkp_initialize_context_or_crash();
-      target_result = fuzz_zkp_bip340_tweak_keys();
-      break;
-    case 50:
-      zkp_initialize_context_or_crash();
-      target_result = fuzz_ecdsa_get_public_key_functions();
-      break;
-    case 51:
-      zkp_initialize_context_or_crash();
-      target_result = fuzz_ecdsa_recover_pub_from_sig_functions();
-      break;
-    case 52:
-      target_result = fuzz_ecdsa_sig_from_der();
-      break;
-    case 53:
-      target_result = fuzz_ecdsa_sig_to_der();
-      break;
-    case 60:
-      target_result = fuzz_xmr_base58_encode();
-      break;
-    case 61:
-      target_result = fuzz_xmr_base58_decode();
-      break;
-    case 63:
-      target_result = fuzz_xmr_add_keys();
-      break;
-    case 64:
-      target_result = fuzz_ecdh_multiply();
-      break;
-
-    default:
-      // mark as uninteresting input
-      return -1;
-      break;
-  }
-  return target_result;
-}

+ 0 - 21
crypto/fuzzer/sanitizer_ignorelist.txt

@@ -1,21 +0,0 @@
-# ignore bignum math operations and other hot crypto primitives
-
-fun:*sha256_Update*
-fun:*sha256_Raw*
-fun:*sha256_Transform*
-fun:*sha512_Transform*
-fun:*pbkdf2_hmac_sha512_Update*
-fun:*pbkdf2_*
-fun:*hmac_*
-fun:*sha256_*
-# TODO this is very broad
-fun:*bn_*
-fun:*bn_inverse*
-fun:*bn_multiply*
-fun:*bn_multiply_long*
-fun:*bn_multiply_reduce_step*
-fun:*bn_multiply_step*
-fun:*curve25519_mul*
-fun:*point_multiply*
-fun:*point_jacobian_add*
-fun:*scalar_multiply*

+ 1 - 1
crypto/hmac_drbg.h

@@ -23,7 +23,7 @@
 #ifndef __HMAC_DRBG_H__
 #define __HMAC_DRBG_H__
 
-#include <sha2.h>
+#include "sha2.h"
 #include <stdint.h>
 
 // HMAC based Deterministic Random Bit Generator with SHA-256

+ 2 - 2
crypto/memzero.c

@@ -51,8 +51,8 @@ void memzero(void *const pnt, const size_t len) {
   SecureZeroMemory(pnt, len);
 #elif defined(HAVE_MEMSET_S)
   memset_s(pnt, (rsize_t)len, 0, (rsize_t)len);
-#elif defined(HAVE_EXPLICIT_BZERO)
-  explicit_bzero(pnt, len);
+// #elif defined(HAVE_EXPLICIT_BZERO)
+//   explicit_bzero(pnt, len);
 #elif defined(HAVE_EXPLICIT_MEMSET)
   explicit_memset(pnt, 0, len);
 #else

+ 1 - 1
crypto/monero/base58.c

@@ -39,7 +39,7 @@
 #include "../base58.h"
 #include "../byte_order.h"
 #include "int-util.h"
-#include "sha2.h"
+#include "../sha2.h"
 
 const size_t alphabet_size = 58;  // sizeof(b58digits_ordered) - 1;
 const size_t full_encoded_block_size = 11;

+ 2 - 2
crypto/monero/base58.h

@@ -35,8 +35,8 @@
 #define __XMR_BASE58_H__
 
 #include <stdbool.h>
-#include "hasher.h"
-#include "options.h"
+#include "../hasher.h"
+#include "../options.h"
 
 int xmr_base58_addr_encode_check(uint64_t tag, const uint8_t *data,
                                  size_t binsz, char *b58, size_t b58sz);

+ 1 - 1
crypto/monero/xmr.c

@@ -5,7 +5,7 @@
 #include "xmr.h"
 #include "../byte_order.h"
 #include "int-util.h"
-#include "rand.h"
+#include "../rand.h"
 #include "serialize.h"
 
 const ge25519 ALIGN(16) xmr_h = {

+ 2 - 2
crypto/monero/xmr.h

@@ -5,8 +5,8 @@
 #ifndef TREZOR_CRYPTO_XMR_H
 #define TREZOR_CRYPTO_XMR_H
 
-#include "ed25519-donna/ed25519-donna.h"
-#include "hasher.h"
+#include "../ed25519-donna/ed25519-donna.h"
+#include "../hasher.h"
 
 extern const ge25519 ALIGN(16) xmr_h;
 

+ 0 - 1039
crypto/tests/test_bignum.py

@@ -1,1039 +0,0 @@
-#!/usr/bin/python
-import ctypes
-import itertools
-import os
-import random
-from ctypes import (
-    c_bool,
-    c_char,
-    c_int,
-    c_size_t,
-    c_uint,
-    c_uint8,
-    c_uint16,
-    c_uint32,
-    c_uint64,
-)
-from math import floor, log, sqrt
-
-import pytest
-
-dir = os.path.abspath(os.path.dirname(__file__))
-lib = ctypes.cdll.LoadLibrary(os.path.join(dir, "libtrezor-crypto.so"))
-
-limbs_number = 9
-bits_per_limb = 29
-
-
-@pytest.fixture()
-def prime(request):
-    return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
-
-
-@pytest.fixture(params=range(limbs_number * bits_per_limb))
-def bignum_bit_index(request):
-    return request.param
-
-
-max_decimal_digits = floor(limbs_number * bits_per_limb * log(2, 10))
-
-
-@pytest.fixture(params=range(max_decimal_digits))
-def bignum_decimal_digit_index(request):
-    return request.param
-
-
-iterations = int(os.environ.get("ITERS", 1000))
-
-
-@pytest.fixture(params=range(iterations))
-def r(request):
-    return Random(request.param)
-
-
-def implication(p, c):
-    return not p or c
-
-
-def uint32_p_to_int(pointer):
-    return pointer.contents.value
-
-
-def uint32_p():
-    return ctypes.POINTER(c_int)(c_int())
-
-
-limb_type = c_uint32
-
-
-def bignum(limbs_number=limbs_number):
-    return (limbs_number * limb_type)()
-
-
-def limbs_to_bignum(limbs):
-    return (limbs_number * limb_type)(*limbs)
-
-
-def int_to_bignum(number, limbs_number=limbs_number):
-    assert number >= 0
-    assert number.bit_length() <= limbs_number * bits_per_limb
-
-    bn = (limbs_number * limb_type)()
-    for i in range(limbs_number):
-        bn[i] = number % 2**bits_per_limb
-        number //= 2**bits_per_limb
-
-    return bn
-
-
-def bignum_to_int(bignum, limbs_number=limbs_number):
-    number = 0
-
-    for i in reversed(range(limbs_number)):
-        number *= 2**bits_per_limb
-        number += bignum[i]
-
-    return number
-
-
-def raw_number():
-    return (32 * c_uint8)()
-
-
-def raw_number_to_integer(raw_number, endianess):
-    return int.from_bytes(raw_number, endianess)
-
-
-def integer_to_raw_number(number, endianess):
-    return (32 * c_uint8)(*number.to_bytes(32, endianess))
-
-
-def bignum_is_normalised(bignum):
-    for limb in bignum:
-        if limb > 2**bits_per_limb:
-            return False
-    return True
-
-
-def number_is_partly_reduced(number, prime):
-    return number < 2 * prime
-
-
-def number_is_fully_reduced(number, prime):
-    return number < prime
-
-
-class Random(random.Random):
-    def rand_int_normalized(self):
-        return self.randrange(0, 2 ** (limbs_number * bits_per_limb))
-
-    def rand_int_256(self):
-        return self.randrange(0, 2**256)
-
-    def rand_int_reduced(self, p):
-        return self.randrange(0, 2 * p)
-
-    def rand_int_bitsize(self, bitsize):
-        return self.randrange(0, 2**bitsize)
-
-    def rand_bit_index(self):
-        return self.randrange(0, limbs_number * bits_per_limb)
-
-    def rand_bignum(self, limbs_number=limbs_number):
-        return (limb_type * limbs_number)(
-            *[self.randrange(0, 256**4) for _ in range(limbs_number)]
-        )
-
-
-def assert_bn_read_be(in_number):
-    raw_in_number = integer_to_raw_number(in_number, "big")
-    bn_out_number = bignum()
-    lib.bn_read_be(raw_in_number, bn_out_number)
-    out_number = bignum_to_int(bn_out_number)
-
-    assert bignum_is_normalised(bn_out_number)
-    assert out_number == in_number
-
-
-def assert_bn_read_le(in_number):
-    raw_in_number = integer_to_raw_number(in_number, "little")
-    bn_out_number = bignum()
-    lib.bn_read_le(raw_in_number, bn_out_number)
-    out_number = bignum_to_int(bn_out_number)
-
-    assert bignum_is_normalised(bn_out_number)
-    assert out_number == in_number
-
-
-def assert_bn_write_be(in_number):
-    bn_in_number = int_to_bignum(in_number)
-    raw_out_number = raw_number()
-    lib.bn_write_be(bn_in_number, raw_out_number)
-    out_number = raw_number_to_integer(raw_out_number, "big")
-
-    assert out_number == in_number
-
-
-def assert_bn_write_le(in_number):
-    bn_in_number = int_to_bignum(in_number)
-    raw_out_number = raw_number()
-    lib.bn_write_le(bn_in_number, raw_out_number)
-    out_number = raw_number_to_integer(raw_out_number, "little")
-
-    assert out_number == in_number
-
-
-def assert_bn_read_uint32(x):
-    bn_out_number = bignum()
-    lib.bn_read_uint32(c_uint32(x), bn_out_number)
-    out_number = bignum_to_int(bn_out_number)
-
-    assert bignum_is_normalised(bn_out_number)
-    assert out_number == x
-
-
-def assert_bn_read_uint64(x):
-    bn_out_number = bignum()
-    lib.bn_read_uint64(c_uint64(x), bn_out_number)
-    out_number = bignum_to_int(bn_out_number)
-
-    assert bignum_is_normalised(bn_out_number)
-    assert out_number == x
-
-
-def assert_bn_bitcount(x):
-    bn_x = int_to_bignum(x)
-    return_value = lib.bn_bitcount(bn_x)
-
-    assert return_value == x.bit_length()
-
-
-def assert_bn_digitcount(x):
-    bn_x = int_to_bignum(x)
-    return_value = lib.bn_digitcount(bn_x)
-
-    assert return_value == len(str(x))
-
-
-def assert_bn_zero():
-    bn_x = bignum()
-    lib.bn_zero(bn_x)
-    x = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x == 0
-
-
-def assert_bn_one():
-    bn_x = bignum()
-    lib.bn_one(bn_x)
-    x = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x == 1
-
-
-def assert_bn_is_zero(x):
-    bn_x = int_to_bignum(x)
-    return_value = lib.bn_is_zero(bn_x)
-
-    assert return_value == (x == 0)
-
-
-def assert_bn_is_one(x):
-    bn_x = int_to_bignum(x)
-    return_value = lib.bn_is_one(bn_x)
-
-    assert return_value == (x == 1)
-
-
-def assert_bn_is_less(x, y):
-    bn_x = int_to_bignum(x)
-    bn_y = int_to_bignum(y)
-    return_value = lib.bn_is_less(bn_x, bn_y)
-
-    assert return_value == (x < y)
-
-
-def assert_bn_is_equal(x, y):
-    bn_x = int_to_bignum(x)
-    bn_y = int_to_bignum(y)
-    return_value = lib.bn_is_equal(bn_x, bn_y)
-
-    assert return_value == (x == y)
-
-
-def assert_bn_cmov(cond, truecase, falsecase):
-    bn_res = bignum()
-    bn_truecase = int_to_bignum(truecase)
-    bn_falsecase = int_to_bignum(falsecase)
-    lib.bn_cmov(bn_res, c_uint32(cond), bn_truecase, bn_falsecase)
-    res = bignum_to_int(bn_res)
-
-    assert res == truecase if cond else falsecase
-
-
-def assert_bn_cnegate(cond, x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_cnegate(c_uint32(cond), bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new % prime == -x_old % prime if cond else x_old % prime
-
-
-def assert_bn_lshift(x_old):
-    bn_x = int_to_bignum(x_old)
-    lib.bn_lshift(bn_x)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == (x_old << 1)
-
-
-def assert_bn_rshift(x_old):
-    bn_x = int_to_bignum(x_old)
-    lib.bn_rshift(bn_x)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == (x_old >> 1)
-
-
-def assert_bn_setbit(x_old, i):
-    bn_x = int_to_bignum(x_old)
-    lib.bn_setbit(bn_x, c_uint16(i))
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old | (1 << i)
-
-
-def assert_bn_clearbit(x_old, i):
-    bn_x = int_to_bignum(x_old)
-    lib.bn_clearbit(bn_x, c_uint16(i))
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old & ~(1 << i)
-
-
-def assert_bn_testbit(x_old, i):
-    bn_x = int_to_bignum(x_old)
-    return_value = lib.bn_testbit(bn_x, c_uint16(i))
-
-    assert return_value == x_old >> i & 1
-
-
-def assert_bn_xor(x, y):
-    bn_res = bignum()
-    bn_x = int_to_bignum(x)
-    bn_y = int_to_bignum(y)
-    lib.bn_xor(bn_res, bn_x, bn_y)
-    res = bignum_to_int(bn_res)
-
-    assert res == x ^ y
-
-
-def assert_bn_mult_half(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_mult_half(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert implication(
-        number_is_partly_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
-    )
-    assert x_new == (x_old + prime) >> 1 if x_old & 1 else x_old >> 1
-
-
-def assert_bn_mult_k(x_old, k, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_mult_k(bn_x, c_uint8(k), bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new == (x_old * k) % prime
-
-
-def assert_bn_mod(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_mod(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_fully_reduced(x_new, prime)
-    assert x_new == x_old % prime
-
-
-def assert_bn_multiply_long(k_old, x_old):
-    bn_k = int_to_bignum(k_old)
-    bn_x = int_to_bignum(x_old)
-    bn_res = bignum(2 * limbs_number)
-    lib.bn_multiply_long(bn_k, bn_x, bn_res)
-    res = bignum_to_int(bn_res, 2 * limbs_number)
-
-    assert res == k_old * x_old
-
-
-def assert_bn_multiply_reduce_step(res_old, prime, d):
-    bn_res = int_to_bignum(res_old, 2 * limbs_number)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_multiply_reduce_step(bn_res, bn_prime, d)
-    res_new = bignum_to_int(bn_res, 2 * limbs_number)
-
-    assert bignum_is_normalised(bn_res)
-    assert res_new < 2 * prime * 2 ** (d * bits_per_limb)
-
-
-def assert_bn_multiply(k, x_old, prime):
-    bn_k = int_to_bignum(k)
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_multiply(bn_k, bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new == (k * x_old) % prime
-
-
-def assert_bn_fast_mod(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_fast_mod(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new % prime == x_old % prime
-
-
-def assert_bn_fast_mod_bn(bn_x, prime):
-    bn_x
-    x_old = bignum_to_int(bn_x)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_fast_mod(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new % prime == x_old % prime
-
-
-def assert_bn_power_mod(x, e, prime):
-    bn_x = int_to_bignum(x)
-    bn_e = int_to_bignum(e)
-    bn_prime = int_to_bignum(prime)
-    bn_res_new = bignum()
-    lib.bn_power_mod(bn_x, bn_e, bn_prime, bn_res_new)
-    res_new = bignum_to_int(bn_res_new)
-
-    assert bignum_is_normalised(bn_res_new)
-    assert number_is_partly_reduced(res_new, prime)
-    assert res_new % prime == pow(x, e, prime)
-
-
-def assert_bn_sqrt(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_sqrt(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_fully_reduced(x_new, prime)
-    assert x_new**2 % prime == x_old % prime
-
-
-def assert_inverse_mod_power_two(x, m):
-    return_value = lib.inverse_mod_power_two(c_uint32(x), c_uint32(m))
-
-    assert return_value * x % 2**m == 1
-
-
-def assert_bn_divide_base(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_divide_base(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert implication(
-        number_is_fully_reduced(x_old, prime), number_is_fully_reduced(x_new, prime)
-    )
-    assert implication(
-        number_is_partly_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
-    )
-    assert x_new * 2**bits_per_limb % prime == x_old % prime
-
-
-def assert_bn_inverse(x_old, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_inverse(bn_x, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_fully_reduced(x_new, prime)
-    assert (x_old == 0 and x_new == 0) or (x_old != 0 and (x_old * x_new) % prime == 1)
-
-
-def assert_bn_normalize(bn_x):
-    x_old = bignum_to_int(bn_x)
-    lib.bn_normalize(bn_x)
-    x_new = bignum_to_int(bn_x)
-
-    assert x_new == x_old % 2 ** (bits_per_limb * limbs_number)
-    assert bignum_is_normalised(bn_x)
-
-
-def assert_bn_add(x_old, y):
-    bn_x = int_to_bignum(x_old)
-    bn_y = int_to_bignum(y)
-    lib.bn_add(bn_x, bn_y)
-    x_new = bignum_to_int(bn_x)
-    y = bignum_to_int(bn_y)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old + y
-
-
-def assert_bn_addmod(x_old, y, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_y = int_to_bignum(y)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_addmod(bn_x, bn_y, bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert number_is_partly_reduced(x_new, prime)
-    assert x_new % prime == (x_old + y) % prime
-
-
-def assert_bn_addi(x_old, y):
-    bn_x = int_to_bignum(x_old)
-    lib.bn_addi(bn_x, c_uint32(y))
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old + y
-
-
-def assert_bn_subi(x_old, y, prime):
-    bn_x = int_to_bignum(x_old)
-    bn_prime = int_to_bignum(prime)
-    lib.bn_subi(bn_x, c_uint32(y), bn_prime)
-    x_new = bignum_to_int(bn_x)
-
-    assert bignum_is_normalised(bn_x)
-    assert implication(
-        number_is_fully_reduced(x_old, prime), number_is_partly_reduced(x_new, prime)
-    )
-    assert x_new % prime == (x_old - y) % prime
-
-
-def assert_bn_subtractmod(x, y, prime):
-    bn_x = int_to_bignum(x)
-    bn_y = int_to_bignum(y)
-    bn_prime = int_to_bignum(prime)
-    bn_res = bignum()
-    lib.bn_subtractmod(bn_x, bn_y, bn_res, bn_prime)
-    res = bignum_to_int(bn_res)
-
-    assert bignum_is_normalised(bn_x)
-    assert res % prime == (x - y) % prime
-
-
-def assert_bn_subtract(x, y):
-    bn_x = int_to_bignum(x)
-    bn_y = int_to_bignum(y)
-    bn_res = bignum()
-    lib.bn_subtract(bn_x, bn_y, bn_res)
-    res = bignum_to_int(bn_res)
-
-    assert bignum_is_normalised(bn_x)
-    assert res == x - y
-
-
-def assert_bn_long_division(x, d):
-    bn_x = int_to_bignum(x)
-    bn_q = bignum()
-    uint32_p_r = uint32_p()
-    lib.bn_long_division(bn_x, d, bn_q, uint32_p_r)
-    r = uint32_p_to_int(uint32_p_r)
-    q = bignum_to_int(bn_q)
-
-    assert bignum_is_normalised(bn_q)
-    assert q == x // d
-    assert r == x % d
-
-
-def assert_bn_divmod58(x_old):
-    bn_x = int_to_bignum(x_old)
-    uint32_p_r = uint32_p()
-    lib.bn_divmod58(bn_x, uint32_p_r)
-    x_new = bignum_to_int(bn_x)
-    r = uint32_p_to_int(uint32_p_r)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old // 58
-    assert r == x_old % 58
-
-
-def assert_bn_divmod1000(x_old):
-    bn_x = int_to_bignum(x_old)
-    uint32_p_r = uint32_p()
-    lib.bn_divmod1000(bn_x, uint32_p_r)
-    x_new = bignum_to_int(bn_x)
-    r = uint32_p_to_int(uint32_p_r)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old // 1000
-    assert r == x_old % 1000
-
-
-def assert_bn_divmod10(x_old):
-    bn_x = int_to_bignum(x_old)
-    uint32_p_r = uint32_p()
-    lib.bn_divmod10(bn_x, uint32_p_r)
-    x_new = bignum_to_int(bn_x)
-    r = uint32_p_to_int(uint32_p_r)
-
-    assert bignum_is_normalised(bn_x)
-    assert x_new == x_old // 10
-    assert r == x_old % 10
-
-
-def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing, thousands):
-    def format(amount, prefix, suffix, decimals, exponent, trailing, thousands):
-        if exponent >= 0:
-            amount *= 10**exponent
-        else:
-            amount //= 10 ** (-exponent)
-
-        d = pow(10, decimals)
-
-        integer_part = amount // d
-        integer_str = f"{integer_part:,}".replace(",", thousands or "")
-
-        if decimals:
-            decimal_part = amount % d
-            decimal_str = f".{decimal_part:0{decimals}d}"
-            if not trailing:
-                decimal_str = decimal_str.rstrip("0").rstrip(".")
-        else:
-            decimal_str = ""
-
-        return prefix + integer_str + decimal_str + suffix
-
-    def string_to_char_p(string):
-        return ctypes.create_string_buffer(string.encode("ascii"))
-
-    def char_p_to_string(pointer):
-        return str(pointer.value, "ascii")
-
-    bn_x = int_to_bignum(x)
-    output_length = 100
-    output = string_to_char_p("?" * output_length)
-    return_value = lib.bn_format(
-        bn_x,
-        string_to_char_p(prefix),
-        string_to_char_p(suffix),
-        c_uint(decimals),
-        c_int(exponent),
-        c_bool(trailing),
-        c_char(0),
-        output,
-        c_size_t(output_length),
-    )
-
-    correct_output = format(x, prefix, suffix, decimals, exponent, trailing, "")
-    correct_return_value = len(correct_output)
-    if len(correct_output) >= output_length:
-        correct_output = ""
-        correct_return_value = 0
-
-    assert char_p_to_string(output) == correct_output
-    assert return_value == correct_return_value
-
-
-def test_bn_read_be(r):
-    assert_bn_read_be(r.rand_int_256())
-
-
-def test_bn_read_le(r):
-    assert_bn_read_le(r.rand_int_256())
-
-
-def test_bn_write_be(r):
-    assert_bn_write_be(r.rand_int_256())
-
-
-def test_bn_write_le(r):
-    assert_bn_write_le(r.rand_int_256())
-
-
-def test_bn_read_uint32(r):
-    assert_bn_read_uint32(r.rand_int_bitsize(32))
-
-
-def test_bn_read_uint64(r):
-    assert_bn_read_uint64(r.rand_int_bitsize(64))
-
-
-def test_bn_bitcount_1(r):
-    assert_bn_bitcount(r.rand_int_normalized())
-
-
-def test_bn_bitcount_2(bignum_bit_index):
-    assert_bn_bitcount(2**bignum_bit_index - 1)
-    assert_bn_bitcount(2**bignum_bit_index)
-
-
-def test_bn_digitcount_1(r):
-    assert_bn_digitcount(r.rand_int_normalized())
-
-
-def test_bn_digitcount_2(bignum_decimal_digit_index):
-    assert_bn_digitcount(10**bignum_decimal_digit_index - 1)
-    assert_bn_digitcount(10**bignum_decimal_digit_index)
-
-
-def test_bn_zero():
-    assert_bn_zero()
-
-
-def test_bn_one():
-    assert_bn_one()
-
-
-def test_bn_is_zero_1():
-    assert_bn_is_zero(0)
-    assert_bn_is_zero(1)
-
-
-def test_bn_is_zero_2(bignum_bit_index):
-    assert_bn_is_zero(2**bignum_bit_index)
-
-
-def test_bn_is_one_1():
-    assert_bn_is_one(0)
-    assert_bn_is_one(1)
-
-
-def test_bn_is_one_2(bignum_bit_index):
-    assert_bn_is_one(2**bignum_bit_index)
-
-
-def test_bn_is_less_1(r):
-    a = r.rand_int_normalized()
-    b = r.rand_int_normalized()
-    assert_bn_is_less(a, a)
-    assert_bn_is_less(a, b)
-    assert_bn_is_less(b, a)
-
-
-def test_bn_is_less_2(r):
-    a = r.rand_int_normalized()
-    i = r.rand_bit_index()
-    b = a ^ 2**i
-    assert_bn_is_less(a, b)
-
-
-def test_bn_is_less_3():
-    assert_bn_is_less(0, 0)
-    assert_bn_is_less(1, 0)
-    assert_bn_is_less(0, 1)
-    assert_bn_is_less(1, 1)
-
-
-def test_bn_is_equal_1(r):
-    a = r.rand_int_normalized()
-    b = r.rand_int_normalized()
-    assert_bn_is_equal(a, a)
-    assert_bn_is_equal(a, b)
-
-
-def test_bn_is_equal_2():
-    assert_bn_is_equal(0, 0)
-    assert_bn_is_equal(1, 0)
-    assert_bn_is_equal(0, 1)
-    assert_bn_is_equal(1, 1)
-
-
-def test_bn_cmov(r):
-    a = r.rand_int_normalized()
-    b = r.rand_int_normalized()
-    assert_bn_cmov(0, a, b)
-    assert_bn_cmov(1, a, b)
-
-
-def test_bn_cnegate(r, prime):
-    a = r.rand_int_reduced(prime)
-    assert_bn_cnegate(0, a, prime)
-    assert_bn_cnegate(1, a, prime)
-
-
-def test_bn_lshift(r):
-    assert_bn_lshift(r.rand_int_normalized() // 2)
-
-
-def test_bn_rshift(r):
-    assert_bn_rshift(r.rand_int_normalized())
-
-
-def test_bn_testbit(r):
-    assert_bn_testbit(r.rand_int_normalized(), r.rand_bit_index())
-
-
-def test_bn_setbit(r):
-    assert_bn_setbit(r.rand_int_normalized(), r.rand_bit_index())
-
-
-def test_bn_clearbit(r):
-    assert_bn_clearbit(r.rand_int_normalized(), r.rand_bit_index())
-
-
-def test_bn_xor(r):
-    assert_bn_xor(r.rand_int_normalized(), r.rand_int_normalized())
-
-
-def test_bn_mult_half_1(r, prime):
-    assert_bn_mult_half(r.rand_int_reduced(prime), prime)
-
-
-def test_bn_mult_half_2(r, prime):
-    assert_bn_mult_half(r.rand_int_normalized(), prime)
-
-
-def test_bn_mult_k(r, prime):
-    assert_bn_mult_k(r.rand_int_normalized(), r.randrange(9), prime)
-
-
-def test_bn_mod_1(r, prime):
-    assert_bn_mod(r.rand_int_reduced(prime), prime)
-
-
-def test_bn_mod_2(r, prime):
-    for x in [
-        0,
-        1,
-        2,
-        prime - 2,
-        prime - 1,
-        prime,
-        prime + 1,
-        prime + 2,
-        2 * prime - 2,
-        2 * prime - 1,
-    ]:
-        assert_bn_mod(x, prime)
-
-
-def test_bn_multiply_long(r, prime):
-    x = r.randrange(floor(sqrt(2**519)))
-    k = r.randrange(floor(sqrt(2**519)))
-    assert_bn_multiply_long(k, x)
-
-
-def test_bn_multiply_reduce_step(r, prime):
-    k = r.randrange(0, limbs_number)
-    res = r.randrange(2 ** (256 + 29 * k + 31))
-    assert_bn_multiply_reduce_step(res, prime, k)
-
-
-def test_bn_multiply(r, prime):
-    x = r.randrange(floor(sqrt(2**519)))
-    k = r.randrange(floor(sqrt(2**519)))
-    assert_bn_multiply(k, x, prime)
-
-
-def test_bn_fast_mod_1(r, prime):
-    assert_bn_fast_mod(r.rand_int_normalized(), prime)
-
-
-def test_bn_fast_mod_2(r, prime):
-    bn_x = r.rand_bignum()
-    assert_bn_fast_mod_bn(bn_x, prime)
-
-
-def test_bn_power_mod(r, prime):
-    x = r.rand_int_bitsize(259)
-    e = r.rand_int_normalized()
-    assert_bn_power_mod(x, e, prime)
-
-
-def test_bn_sqrt_1(prime):
-    assert_bn_sqrt(0, prime)
-    assert_bn_sqrt(1, prime)
-
-
-def test_bn_sqrt_2(r, prime):
-    def is_quadratic_residuum(x, p):
-        return pow(x, (p - 1) // 2, p) == 1
-
-    while True:
-        x = r.rand_int_bitsize(259)
-        if is_quadratic_residuum(x, prime):
-            break
-
-    assert_bn_sqrt(x, prime)
-
-
-def test_inverse_mod_power_two(r):
-    m = r.randrange(1, 33)
-    i = r.randrange(1, 2**29, 2)
-    assert_inverse_mod_power_two(i, m)
-
-
-def test_bn_divide_base(r, prime):
-    assert_bn_divide_base(r.rand_int_256(), prime)
-
-
-def test_bn_inverse_1(prime):
-    assert_bn_inverse(0, prime)
-    assert_bn_inverse(1, prime)
-
-
-def test_bn_inverse_2(r, prime):
-    from math import gcd
-
-    while True:
-        n = r.randrange(0, prime)
-        if gcd(n, prime) == 1:
-            break
-
-    assert_bn_inverse(n, prime)
-
-
-def test_bn_normalize(r):
-    assert_bn_normalize(r.rand_bignum())
-
-
-def test_bn_add_1(r):
-    assert_bn_add(r.rand_int_256(), r.rand_int_256())
-
-
-def test_bn_add_2(r):
-    while True:
-        a = r.rand_int_normalized()
-        b = r.rand_int_normalized()
-        if a + b < 2 ** (limbs_number * bits_per_limb):
-            break
-    assert_bn_add(a, b)
-
-
-def test_bn_add_3():
-    a = Random().rand_int_normalized()
-    b = 2 ** (limbs_number * bits_per_limb) - 1 - a
-    assert_bn_add(a, b)
-
-
-def test_bn_addmod(r, prime):
-    assert_bn_addmod(r.rand_int_normalized(), r.rand_int_normalized(), prime)
-
-
-def test_bn_addi_1(r):
-    while True:
-        a = r.rand_int_normalized()
-        b = r.randrange(2**32 - 2**bits_per_limb + 1)
-        if a + b < 2 ** (limbs_number * bits_per_limb):
-            break
-    assert_bn_addi(a, b)
-
-
-def test_bn_addi_2():
-    b = 2**32 - 2**bits_per_limb
-    a = 2 ** (limbs_number * bits_per_limb) - 1 - b
-    assert_bn_addi(a, b)
-
-
-def test_bn_subi_1(r, prime):
-    while True:
-        a = r.rand_int_normalized()
-        b = r.randrange(prime % 2**bits_per_limb)
-        if a + prime - b < 2 ** (limbs_number * bits_per_limb):
-            break
-    assert_bn_subi(a, b, prime)
-
-
-def test_bn_subi_2(prime):
-    b = (prime % 2**bits_per_limb) - 1
-    a = 2 ** (limbs_number * bits_per_limb) - 1 - prime + b
-    assert_bn_subi(a, b, prime)
-
-
-def test_bn_subtractmod_1(r, prime):
-    assert_bn_subtractmod(r.rand_int_256(), r.rand_int_256(), prime)
-
-
-def test_bn_subtractmod_2(r, prime):
-    while True:
-        a = r.rand_int_normalized()
-        b = r.rand_int_reduced(prime)
-        if a + 2 * prime - b < 2 ** (limbs_number * bits_per_limb):
-            break
-    assert_bn_subtractmod(a, b, prime)
-
-
-def test_bn_subtractmod_3(prime):
-    b = 2 * prime - 1
-    a = 2 ** (limbs_number * bits_per_limb) - 1 - (2 * prime - b)
-    assert_bn_subtractmod(a, b, prime)
-
-
-def test_bn_subtract_1(r):
-    a = r.rand_int_256()
-    b = r.rand_int_256()
-    if a < b:
-        a, b = b, a
-    assert_bn_subtract(a, b)
-
-
-def test_bn_subtract_2(r):
-    a = r.rand_int_normalized()
-    b = r.rand_int_normalized()
-    if a < b:
-        a, b = b, a
-    assert_bn_subtract(a, b)
-
-
-def test_bn_long_division(r):
-    x = r.rand_int_normalized()
-    d = r.randrange(1, 61304 + 1)
-    assert_bn_long_division(x, d)
-
-
-def test_bn_divmod58(r):
-    x = r.rand_int_normalized()
-    assert_bn_divmod58(x)
-
-
-def test_bn_divmod1000(r):
-    x = r.rand_int_normalized()
-    assert_bn_divmod1000(x)
-
-
-def test_bn_divmod10(r):
-    x = r.rand_int_normalized()
-    assert_bn_divmod10(x)
-
-
-@pytest.mark.parametrize(
-    "decimals,exponent,trailing,prefix,suffix,thousands,value",
-    itertools.product(
-        range(0, 5),
-        range(-5, 5),
-        [True, False],
-        ["", "prefix"],
-        ["", "suffix"],
-        ["", ",", " "],
-        [123, 120, 123_456, 12_345, 100001, 10001000],
-    ),
-)
-def test_bn_format(decimals, exponent, trailing, prefix, suffix, thousands, value):
-    assert_bn_format(value, prefix, suffix, decimals, exponent, trailing, thousands)

+ 0 - 9815
crypto/tests/test_check.c

@@ -1,9815 +0,0 @@
-/**
- * Copyright (c) 2013-2014 Tomas Dzetkulic
- * Copyright (c) 2013-2014 Pavol Rusnak
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <check.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "check_mem.h"
-
-#ifdef VALGRIND
-#include <valgrind/memcheck.h>
-#include <valgrind/valgrind.h>
-#endif
-
-#include "options.h"
-
-#include "address.h"
-#include "aes/aes.h"
-#include "base32.h"
-#include "base58.h"
-#include "bignum.h"
-#include "bip32.h"
-#include "bip39.h"
-#include "blake256.h"
-#include "blake2b.h"
-#include "blake2s.h"
-#include "cardano.h"
-#include "chacha_drbg.h"
-#include "curves.h"
-#include "ecdsa.h"
-#include "ed25519-donna/ed25519-donna.h"
-#include "ed25519-donna/ed25519-keccak.h"
-#include "ed25519-donna/ed25519.h"
-#include "hmac_drbg.h"
-#include "memzero.h"
-#include "monero/monero.h"
-#include "nem.h"
-#include "nist256p1.h"
-#include "pbkdf2.h"
-#include "rand.h"
-#include "rc4.h"
-#include "rfc6979.h"
-#include "script.h"
-#include "secp256k1.h"
-#include "sha2.h"
-#include "sha3.h"
-#include "shamir.h"
-#include "slip39.h"
-#include "slip39_wordlist.h"
-#include "zkp_bip340.h"
-#include "zkp_context.h"
-#include "zkp_ecdsa.h"
-
-#ifdef VALGRIND
-/*
- * This is a clever trick to make Valgrind's Memcheck verify code
- * is constant-time with respect to secret data.
- */
-
-/* Call after secret data is written, before first use */
-#define MARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len)
-/* Call before secret data is freed or to mark non-secret data (public keys or
- * signatures) */
-#define UNMARK_SECRET_DATA(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len)
-#else
-#define MARK_SECRET_DATA(addr, len)
-#define UNMARK_SECRET_DATA(addr, len)
-#endif
-
-#define FROMHEX_MAXLEN 512
-
-#define VERSION_PUBLIC 0x0488b21e
-#define VERSION_PRIVATE 0x0488ade4
-
-#define DECRED_VERSION_PUBLIC 0x02fda926
-#define DECRED_VERSION_PRIVATE 0x02fda4e8
-
-const uint8_t *fromhex(const char *str) {
-  static uint8_t buf[FROMHEX_MAXLEN];
-  size_t len = strlen(str) / 2;
-  if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN;
-  for (size_t i = 0; i < len; i++) {
-    uint8_t c = 0;
-    if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4;
-    if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F')
-      c += (10 + (str[i * 2] & ~0x20) - 'A') << 4;
-    if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9')
-      c += (str[i * 2 + 1] - '0');
-    if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F')
-      c += (10 + (str[i * 2 + 1] & ~0x20) - 'A');
-    buf[i] = c;
-  }
-  return buf;
-}
-
-void nem_private_key(const char *reversed_hex, ed25519_secret_key private_key) {
-  const uint8_t *reversed_key = fromhex(reversed_hex);
-  for (size_t j = 0; j < sizeof(ed25519_secret_key); j++) {
-    private_key[j] = reversed_key[sizeof(ed25519_secret_key) - j - 1];
-  }
-}
-
-START_TEST(test_bignum_read_be) {
-  bignum256 a;
-  uint8_t input[32];
-
-  memcpy(
-      input,
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      32);
-
-  bn_read_be(input, &a);
-
-  bignum256 b = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
-                  0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
-
-  for (int i = 0; i < 9; i++) {
-    ck_assert_uint_eq(a.val[i], b.val[i]);
-  }
-}
-END_TEST
-
-START_TEST(test_bignum_write_be) {
-  bignum256 a = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
-                  0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
-  uint8_t tmp[32];
-
-  bn_write_be(&a, tmp);
-
-  ck_assert_mem_eq(
-      tmp,
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bignum_is_equal) {
-  bignum256 a = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
-                  0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
-  bignum256 b = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
-                  0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
-  bignum256 c = {{
-      0,
-  }};
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-  ck_assert_int_eq(bn_is_equal(&c, &c), 1);
-  ck_assert_int_eq(bn_is_equal(&a, &c), 0);
-}
-END_TEST
-
-START_TEST(test_bignum_zero) {
-  bignum256 a;
-  bignum256 b;
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  bn_zero(&b);
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_is_zero) {
-  bignum256 a;
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  ck_assert_int_eq(bn_is_zero(&a), 1);
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  ck_assert_int_eq(bn_is_zero(&a), 0);
-
-  bn_read_be(
-      fromhex(
-          "1000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  ck_assert_int_eq(bn_is_zero(&a), 0);
-
-  bn_read_be(
-      fromhex(
-          "f000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  ck_assert_int_eq(bn_is_zero(&a), 0);
-}
-END_TEST
-
-START_TEST(test_bignum_one) {
-  bignum256 a;
-  bignum256 b;
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  bn_one(&b);
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_read_le) {
-  bignum256 a;
-  bignum256 b;
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      &a);
-  bn_read_le(
-      fromhex(
-          "d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"),
-      &b);
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_write_le) {
-  bignum256 a;
-  bignum256 b;
-  uint8_t tmp[32];
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      &a);
-  bn_write_le(&a, tmp);
-
-  bn_read_le(tmp, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  bn_read_be(
-      fromhex(
-          "d58b6de8051f031eeca2c6d7fbe1b5d37c4314fe1068f96352dd0d8b85ce5ec5"),
-      &a);
-  bn_read_be(tmp, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_read_uint32) {
-  bignum256 a;
-  bignum256 b;
-
-  // lowest 30 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000003fffffff"),
-      &a);
-  bn_read_uint32(0x3fffffff, &b);
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // bit 31 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000040000000"),
-      &a);
-  bn_read_uint32(0x40000000, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_read_uint64) {
-  bignum256 a;
-  bignum256 b;
-
-  // lowest 30 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000003fffffff"),
-      &a);
-  bn_read_uint64(0x3fffffff, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // bit 31 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000040000000"),
-      &a);
-  bn_read_uint64(0x40000000, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // bit 33 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000100000000"),
-      &a);
-  bn_read_uint64(0x100000000LL, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // bit 61 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000002000000000000000"),
-      &a);
-  bn_read_uint64(0x2000000000000000LL, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // all 64 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000ffffffffffffffff"),
-      &a);
-  bn_read_uint64(0xffffffffffffffffLL, &b);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_write_uint32) {
-  bignum256 a;
-
-  // lowest 29 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000001fffffff"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint32(&a), 0x1fffffff);
-
-  // lowest 30 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000003fffffff"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint32(&a), 0x3fffffff);
-
-  // bit 31 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000040000000"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint32(&a), 0x40000000);
-}
-END_TEST
-
-START_TEST(test_bignum_write_uint64) {
-  bignum256 a;
-
-  // lowest 30 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000003fffffff"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint64(&a), 0x3fffffff);
-
-  // bit 31 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000040000000"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint64(&a), 0x40000000);
-
-  // bit 33 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000100000000"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint64(&a), 0x100000000LL);
-
-  // bit 61 set
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000002000000000000000"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint64(&a), 0x2000000000000000LL);
-
-  // all 64 bits set
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000ffffffffffffffff"),
-      &a);
-  ck_assert_uint_eq(bn_write_uint64(&a), 0xffffffffffffffffLL);
-}
-END_TEST
-
-START_TEST(test_bignum_copy) {
-  bignum256 a;
-  bignum256 b;
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      &a);
-  bn_copy(&a, &b);
-
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_is_even) {
-  bignum256 a;
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      &a);
-  ck_assert_int_eq(bn_is_even(&a), 0);
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"),
-      &a);
-  ck_assert_int_eq(bn_is_even(&a), 1);
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"),
-      &a);
-  ck_assert_int_eq(bn_is_even(&a), 1);
-}
-END_TEST
-
-START_TEST(test_bignum_is_odd) {
-  bignum256 a;
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"),
-      &a);
-  ck_assert_int_eq(bn_is_odd(&a), 1);
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd2"),
-      &a);
-  ck_assert_int_eq(bn_is_odd(&a), 0);
-
-  bn_read_be(
-      fromhex(
-          "c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd0"),
-      &a);
-  ck_assert_int_eq(bn_is_odd(&a), 0);
-}
-END_TEST
-
-START_TEST(test_bignum_is_less) {
-  bignum256 a;
-  bignum256 b;
-
-  bn_read_uint32(0x1234, &a);
-  bn_read_uint32(0x8765, &b);
-
-  ck_assert_int_eq(bn_is_less(&a, &b), 1);
-  ck_assert_int_eq(bn_is_less(&b, &a), 0);
-
-  bn_zero(&a);
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &b);
-
-  ck_assert_int_eq(bn_is_less(&a, &b), 1);
-  ck_assert_int_eq(bn_is_less(&b, &a), 0);
-}
-END_TEST
-
-START_TEST(test_bignum_bitcount) {
-  bignum256 a, b;
-
-  bn_zero(&a);
-  ck_assert_int_eq(bn_bitcount(&a), 0);
-
-  bn_one(&a);
-  ck_assert_int_eq(bn_bitcount(&a), 1);
-
-  // test for 10000 and 11111 when i=5
-  for (int i = 2; i <= 256; i++) {
-    bn_one(&a);
-    bn_one(&b);
-    for (int j = 2; j <= i; j++) {
-      bn_lshift(&a);
-      bn_lshift(&b);
-      bn_addi(&b, 1);
-    }
-    ck_assert_int_eq(bn_bitcount(&a), i);
-    ck_assert_int_eq(bn_bitcount(&b), i);
-  }
-
-  bn_read_uint32(0x3fffffff, &a);
-  ck_assert_int_eq(bn_bitcount(&a), 30);
-
-  bn_read_uint32(0xffffffff, &a);
-  ck_assert_int_eq(bn_bitcount(&a), 32);
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  ck_assert_int_eq(bn_bitcount(&a), 256);
-}
-END_TEST
-
-START_TEST(test_bignum_digitcount) {
-  bignum256 a;
-
-  bn_zero(&a);
-  ck_assert_int_eq(bn_digitcount(&a), 1);
-
-  // test for (10^i) and (10^i) - 1
-  uint64_t m = 1;
-  for (int i = 0; i <= 19; i++, m *= 10) {
-    bn_read_uint64(m, &a);
-    ck_assert_int_eq(bn_digitcount(&a), i + 1);
-
-    uint64_t n = m - 1;
-    bn_read_uint64(n, &a);
-    ck_assert_int_eq(bn_digitcount(&a), n == 0 ? 1 : i);
-  }
-
-  bn_read_uint32(0x3fffffff, &a);
-  ck_assert_int_eq(bn_digitcount(&a), 10);
-
-  bn_read_uint32(0xffffffff, &a);
-  ck_assert_int_eq(bn_digitcount(&a), 10);
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  ck_assert_int_eq(bn_digitcount(&a), 78);
-}
-END_TEST
-
-START_TEST(test_bignum_format_uint64) {
-  char buf[128], str[128];
-  size_t r;
-  // test for (10^i) and (10^i) - 1
-  uint64_t m = 1;
-  for (int i = 0; i <= 19; i++, m *= 10) {
-    sprintf(str, "%" PRIu64, m);
-    r = bn_format_uint64(m, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-    ck_assert_uint_eq(r, strlen(str));
-    ck_assert_str_eq(buf, str);
-
-    uint64_t n = m - 1;
-    sprintf(str, "%" PRIu64, n);
-    r = bn_format_uint64(n, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-    ck_assert_uint_eq(r, strlen(str));
-    ck_assert_str_eq(buf, str);
-  }
-}
-END_TEST
-
-START_TEST(test_bignum_format) {
-  bignum256 a;
-  char buf[128];
-  size_t r;
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 20, 0, true, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 22);
-  ck_assert_str_eq(buf, "0.00000000000000000000");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 5, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, -5, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, "", "", 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, "SFFX", 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1 + 4);
-  ck_assert_str_eq(buf, "0SFFX");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, "PRFX", NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 4 + 1);
-  ck_assert_str_eq(buf, "PRFX0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, "PRFX", "SFFX", 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 4 + 1 + 4);
-  ck_assert_str_eq(buf, "PRFX0SFFX");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "1");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 6, 6, true, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 8);
-  ck_assert_str_eq(buf, "1.000000");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 1, 5, true, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 7);
-  ck_assert_str_eq(buf, "10000.0");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000001"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 1, 5, true, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 8);
-  ck_assert_str_eq(buf, "10,000.0");
-
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000000001e240"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, true, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 7);
-  ck_assert_str_eq(buf, "123,456");
-
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000000001e240"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 1, true, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 9);
-  ck_assert_str_eq(buf, "1,234,560");
-
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000000001e240"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 5, true, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 14);
-  ck_assert_str_eq(buf, "12,345,600,000");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000002"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "2");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000005"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "5");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000009"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "9");
-
-  bn_read_be(
-      fromhex(
-          "000000000000000000000000000000000000000000000000000000000000000a"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 2);
-  ck_assert_str_eq(buf, "10");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000014"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 2);
-  ck_assert_str_eq(buf, "20");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000032"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 2);
-  ck_assert_str_eq(buf, "50");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000063"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 2);
-  ck_assert_str_eq(buf, "99");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000064"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 3);
-  ck_assert_str_eq(buf, "100");
-
-  bn_read_be(
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000c8"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 3);
-  ck_assert_str_eq(buf, "200");
-
-  bn_read_be(
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000001f4"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 3);
-  ck_assert_str_eq(buf, "500");
-
-  bn_read_be(
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000003e7"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 3);
-  ck_assert_str_eq(buf, "999");
-
-  bn_read_be(
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000003e8"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 4);
-  ck_assert_str_eq(buf, "1000");
-
-  bn_read_be(
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000003e8"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 5);
-  ck_assert_str_eq(buf, "1,000");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000989680"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 7, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 1);
-  ck_assert_str_eq(buf, "1");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 78);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "7584007913129639935");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 1, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 79);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "758400791312963993.5");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 2, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 79);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "75840079131296399.35");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 8, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 79);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "75840079131.29639935");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 9, 0, false, ',', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 101);
-  ck_assert_str_eq(
-      buf,
-      "115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,"
-      "665,640,564,039,457,584,007,913.129639935");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 9, 0, false, ' ', buf, sizeof(buf));
-  ck_assert_uint_eq(r, 101);
-  ck_assert_str_eq(
-      buf,
-      "115 792 089 237 316 195 423 570 985 008 687 907 853 269 984 "
-      "665 640 564 039 457 584 007 913.129639935");
-
-  bn_read_be(
-      fromhex(
-          "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3bbb00"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 8, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 70);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "75840079131");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 79);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "7.584007913129639935");
-
-  bn_read_be(
-      fromhex(
-          "fffffffffffffffffffffffffffffffffffffffffffffffff7e52fe5afe40000"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 60);
-  ck_assert_str_eq(
-      buf, "115792089237316195423570985008687907853269984665640564039457");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 78, 0, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 80);
-  ck_assert_str_eq(buf,
-                   "0."
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "7584007913129639935");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, NULL, NULL, 0, 10, false, 0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 88);
-  ck_assert_str_eq(buf,
-                   "11579208923731619542357098500868790785326998466564056403945"
-                   "75840079131296399350000000000");
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-  r = bn_format(&a, "quite a long prefix", "even longer suffix", 60, 0, false,
-                0, buf, sizeof(buf));
-  ck_assert_uint_eq(r, 116);
-  ck_assert_str_eq(buf,
-                   "quite a long "
-                   "prefix115792089237316195."
-                   "42357098500868790785326998466564056403945758400791312963993"
-                   "5even longer suffix");
-
-  bn_read_be(
-      fromhex(
-          "0000000000000000000000000000000000000000000000000123456789abcdef"),
-      &a);
-  memset(buf, 'a', sizeof(buf));
-  r = bn_format(&a, "prefix", "suffix", 10, 0, false, 0, buf, 31);
-  ck_assert_str_eq(buf, "prefix8198552.9216486895suffix");
-  ck_assert_uint_eq(r, 30);
-
-  memset(buf, 'a', sizeof(buf));
-  r = bn_format(&a, "prefix", "suffix", 10, 0, false, 0, buf, 30);
-  ck_assert_uint_eq(r, 0);
-  ck_assert_str_eq(buf, "");
-}
-END_TEST
-
-START_TEST(test_bignum_sqrt) {
-  uint32_t quadratic_residua[] = {
-      1,   2,   4,   8,   9,   11,  15,  16,  17,  18,  19,  21,  22,  25,  29,
-      30,  31,  32,  34,  35,  36,  38,  39,  42,  43,  44,  47,  49,  50,  58,
-      59,  60,  61,  62,  64,  65,  67,  68,  69,  70,  71,  72,  76,  78,  81,
-      83,  84,  86,  88,  91,  94,  98,  99,  100, 103, 107, 111, 115, 116, 118,
-      120, 121, 122, 123, 124, 127, 128, 130, 131, 134, 135, 136, 137, 138, 139,
-      140, 142, 144, 149, 152, 153, 156, 159, 161, 162, 165, 166, 167, 168, 169,
-      171, 172, 176, 181, 182, 185, 187, 188, 189, 191, 193, 196, 197, 198, 200,
-      205, 206, 209, 214, 219, 222, 223, 225, 229, 230, 231, 232, 233, 236, 237,
-      239, 240, 242, 244, 246, 248, 254, 255, 256, 259, 260, 261, 262, 265, 267,
-      268, 269, 270, 272, 274, 275, 276, 277, 278, 279, 280, 281, 284, 285, 287,
-      288, 289, 291, 293, 298, 299, 303, 304, 306, 311, 312, 315, 318, 319, 322,
-      323, 324, 327, 330, 331, 332, 334, 336, 337, 338, 339, 341, 342, 344, 349,
-      351, 352, 353, 357, 359, 361, 362, 364, 365, 370, 371, 373, 374, 375, 376,
-      378, 379, 382, 383, 385, 386, 387, 389, 392, 394, 395, 396, 399, 400, 409,
-      410, 412, 418, 421, 423, 425, 428, 429, 431, 435, 438, 439, 441, 443, 444,
-      445, 446, 450, 453, 458, 460, 461, 462, 463, 464, 465, 466, 467, 471, 472,
-      473, 474, 475, 478, 479, 480, 481, 484, 485, 487, 488, 489, 492, 493, 496,
-      503, 505, 508, 510, 511, 512, 517, 518, 519, 520, 521, 522, 523, 524, 525,
-      527, 529, 530, 531, 533, 534, 536, 537, 538, 539, 540, 541, 544, 545, 547,
-      548, 549, 550, 551, 552, 553, 554, 556, 557, 558, 560, 562, 563, 565, 568,
-      570, 571, 574, 576, 578, 582, 585, 586, 587, 589, 595, 596, 597, 598, 599,
-      603, 606, 607, 608, 609, 612, 613, 619, 621, 622, 623, 624, 625, 630, 633,
-      636, 638, 639, 644, 645, 646, 648, 649, 651, 653, 654, 660, 662, 663, 664,
-      665, 668, 671, 672, 673, 674, 676, 678, 679, 681, 682, 684, 688, 689, 698,
-      702, 704, 705, 706, 707, 714, 715, 718, 722, 723, 724, 725, 728, 729, 730,
-      731, 733, 735, 737, 740, 741, 742, 746, 747, 748, 750, 751, 752, 753, 755,
-      756, 758, 759, 761, 763, 764, 766, 769, 770, 771, 772, 774, 775, 778, 781,
-      784, 785, 788, 789, 790, 791, 792, 797, 798, 799, 800, 813, 815, 817, 818,
-      819, 820, 823, 824, 833, 836, 841, 842, 846, 849, 850, 851, 856, 857, 858,
-      862, 865, 870, 875, 876, 878, 882, 885, 886, 887, 888, 890, 891, 892, 893,
-      895, 899, 900, 903, 906, 907, 911, 913, 915, 916, 919, 920, 921, 922, 924,
-      926, 927, 928, 930, 931, 932, 934, 937, 939, 942, 943, 944, 946, 948, 949,
-      950, 951, 953, 956, 958, 960, 961, 962, 963, 968, 970, 971, 974, 975, 976,
-      977, 978, 984, 986, 987, 992, 995, 999};
-
-  bignum256 a, b;
-
-  bn_zero(&a);
-  b = a;
-  bn_sqrt(&b, &secp256k1.prime);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  bn_one(&a);
-  b = a;
-  bn_sqrt(&b, &secp256k1.prime);
-  ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-
-  // test some quadratic residua
-  for (size_t i = 0; i < sizeof(quadratic_residua) / sizeof(*quadratic_residua);
-       i++) {
-    bn_read_uint32(quadratic_residua[i], &a);
-    b = a;
-    bn_sqrt(&b, &secp256k1.prime);
-    bn_multiply(&b, &b, &secp256k1.prime);
-    bn_mod(&b, &secp256k1.prime);
-    ck_assert_int_eq(bn_is_equal(&a, &b), 1);
-  }
-}
-END_TEST
-
-// https://tools.ietf.org/html/rfc4648#section-10
-START_TEST(test_base32_rfc4648) {
-  static const struct {
-    const char *decoded;
-    const char *encoded;
-    const char *encoded_lowercase;
-  } tests[] = {
-      {"", "", ""},
-      {"f", "MY", "my"},
-      {"fo", "MZXQ", "mzxq"},
-      {"foo", "MZXW6", "mzxw6"},
-      {"foob", "MZXW6YQ", "mzxw6yq"},
-      {"fooba", "MZXW6YTB", "mzxw6ytb"},
-      {"foobar", "MZXW6YTBOI", "mzxw6ytboi"},
-  };
-
-  char buffer[64];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    const char *in = tests[i].decoded;
-    const char *out = tests[i].encoded;
-    const char *out_lowercase = tests[i].encoded_lowercase;
-
-    size_t inlen = strlen(in);
-    size_t outlen = strlen(out);
-
-    ck_assert_uint_eq(outlen, base32_encoded_length(inlen));
-    ck_assert_uint_eq(inlen, base32_decoded_length(outlen));
-
-    ck_assert(base32_encode((uint8_t *)in, inlen, buffer, sizeof(buffer),
-                            BASE32_ALPHABET_RFC4648) != NULL);
-    ck_assert_str_eq(buffer, out);
-
-    char *ret = (char *)base32_decode(out, outlen, (uint8_t *)buffer,
-                                      sizeof(buffer), BASE32_ALPHABET_RFC4648);
-    ck_assert(ret != NULL);
-    *ret = '\0';
-    ck_assert_str_eq(buffer, in);
-
-    ret = (char *)base32_decode(out_lowercase, outlen, (uint8_t *)buffer,
-                                sizeof(buffer), BASE32_ALPHABET_RFC4648);
-    ck_assert(ret != NULL);
-    *ret = '\0';
-    ck_assert_str_eq(buffer, in);
-  }
-}
-END_TEST
-
-// from
-// https://github.com/bitcoin/bitcoin/blob/master/src/test/data/base58_keys_valid.json
-START_TEST(test_base58) {
-  static const char *base58_vector[] = {
-      "0065a16059864a2fdbc7c99a4723a8395bc6f188eb",
-      "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
-      "0574f209f6ea907e2ea48f74fae05782ae8a665257",
-      "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
-      "6f53c0307d6851aa0ce7825ba883c6bd9ad242b486",
-      "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
-      "c46349a418fc4578d10a372b54b45c280cc8c4382f",
-      "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
-      "80eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
-      "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
-      "8055c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c401",
-      "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
-      "ef36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
-      "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
-      "efb9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f301",
-      "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
-      "006d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4",
-      "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
-      "05fcc5460dd6e2487c7d75b1963625da0e8f4c5975",
-      "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
-      "6ff1d470f9b02370fdec2e6b708b08ac431bf7a5f7",
-      "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
-      "c4c579342c2c4c9220205e2cdc285617040c924a0a",
-      "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
-      "80a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
-      "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
-      "807d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb401",
-      "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
-      "efd6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
-      "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
-      "efa81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d901",
-      "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
-      "007987ccaa53d02c8873487ef919677cd3db7a6912",
-      "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
-      "0563bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb",
-      "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
-      "6fef66444b5b17f14e8fae6e7e19b045a78c54fd79",
-      "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
-      "c4c3e55fceceaa4391ed2a9677f4a4d34eacd021a0",
-      "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
-      "80e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
-      "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
-      "808248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c01",
-      "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
-      "ef44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
-      "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
-      "efd1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c6901",
-      "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
-      "00adc1cc2081a27206fae25792f28bbc55b831549d",
-      "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
-      "05188f91a931947eddd7432d6e614387e32b244709",
-      "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
-      "6f1694f5bc1a7295b600f40018a618a6ea48eeb498",
-      "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
-      "c43b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3",
-      "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
-      "80091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
-      "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
-      "80ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af01",
-      "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
-      "efb4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
-      "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
-      "efe7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef01",
-      "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
-      "00c4c1b72491ede1eedaca00618407ee0b772cad0d",
-      "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
-      "05f6fe69bcb548a829cce4c57bf6fff8af3a5981f9",
-      "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
-      "6f261f83568a098a8638844bd7aeca039d5f2352c0",
-      "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
-      "c4e930e1834a4d234702773951d627cce82fbb5d2e",
-      "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
-      "80d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
-      "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
-      "80b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b301",
-      "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
-      "ef037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
-      "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
-      "ef6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de01",
-      "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
-      "005eadaf9bb7121f0f192561a5a62f5e5f54210292",
-      "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
-      "053f210e7277c899c3a155cc1c90f4106cbddeec6e",
-      "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
-      "6fc8a3c2a09a298592c3e180f02487cd91ba3400b5",
-      "myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
-      "c499b31df7c9068d1481b596578ddbb4d3bd90baeb",
-      "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
-      "80c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
-      "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
-      "8007f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd01",
-      "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
-      "efea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
-      "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
-      "ef0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c01",
-      "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
-      "001ed467017f043e91ed4c44b4e8dd674db211c4e6",
-      "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
-      "055ece0cadddc415b1980f001785947120acdb36fc",
-      "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
-      0,
-      0,
-  };
-  const char **raw = base58_vector;
-  const char **str = base58_vector + 1;
-  uint8_t rawn[34];
-  char strn[53];
-  int r;
-  while (*raw && *str) {
-    int len = strlen(*raw) / 2;
-
-    memcpy(rawn, fromhex(*raw), len);
-    r = base58_encode_check(rawn, len, HASHER_SHA2D, strn, sizeof(strn));
-    ck_assert_int_eq((size_t)r, strlen(*str) + 1);
-    ck_assert_str_eq(strn, *str);
-
-    r = base58_decode_check(strn, HASHER_SHA2D, rawn, len);
-    ck_assert_int_eq(r, len);
-    ck_assert_mem_eq(rawn, fromhex(*raw), len);
-
-    raw += 2;
-    str += 2;
-  }
-}
-END_TEST
-
-START_TEST(test_bignum_divmod) {
-  uint32_t r;
-  int i;
-
-  bignum256 a;
-  uint32_t ar[] = {15, 14, 55, 29, 44, 24, 53, 49, 18, 55, 2,  28, 5,  4,  12,
-                   43, 18, 37, 28, 14, 30, 46, 12, 11, 17, 10, 10, 13, 24, 45,
-                   4,  33, 44, 42, 2,  46, 34, 43, 45, 28, 21, 18, 13, 17};
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &a);
-
-  i = 0;
-  while (!bn_is_zero(&a) && i < 44) {
-    bn_divmod58(&a, &r);
-    ck_assert_uint_eq(r, ar[i]);
-    i++;
-  }
-  ck_assert_int_eq(i, 44);
-
-  bignum256 b;
-  uint32_t br[] = {935, 639, 129, 913, 7,   584, 457, 39, 564,
-                   640, 665, 984, 269, 853, 907, 687, 8,  985,
-                   570, 423, 195, 316, 237, 89,  792, 115};
-
-  bn_read_be(
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      &b);
-  i = 0;
-  while (!bn_is_zero(&b) && i < 26) {
-    bn_divmod1000(&b, &r);
-    ck_assert_uint_eq(r, br[i]);
-    i++;
-  }
-  ck_assert_int_eq(i, 26);
-}
-END_TEST
-
-// test vector 1 from
-// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-1
-START_TEST(test_bip32_vector_1) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   SECP256K1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqji"
-                   "ChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2"
-                   "gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 0);
-  ck_assert_uint_eq(fingerprint, 0x3442193e);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4"
-                   "cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP"
-                   "6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1);
-  ck_assert_uint_eq(fingerprint, 0x5c1bd648);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSx"
-                   "qu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFH"
-                   "KkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0xbef5a2f9);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptW"
-                   "mT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgq"
-                   "FJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0xee7ab90c);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Ty"
-                   "h8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJ"
-                   "AyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2'/2/1000000000]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1000000000);
-  ck_assert_uint_eq(fingerprint, 0xd880d7d8);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8"
-                   "kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNT"
-                   "EcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-}
-END_TEST
-
-// test vector 2 from
-// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-2
-START_TEST(test_bip32_vector_2) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, SECP256K1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGds"
-                   "o3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSC"
-                   "Gu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0xbd16bee5);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT"
-                   "3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGm"
-                   "XUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483647);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x5a61ff8e);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYE"
-                   "eEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ"
-                   "85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 1);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0xd8ab4937);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd"
-                   "25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5Ew"
-                   "VvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1/2147483646']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483646);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x78412e3a);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz"
-                   "7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJ"
-                   "bZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1/2147483646'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 2);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x31a507b8);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw"
-                   "7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLF"
-                   "bdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, SECP256K1_NAME, &node);
-
-  // test public derivation
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_public_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0xbd16bee5);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"),
-      33);
-}
-END_TEST
-
-// test vector 3 from
-// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-3
-START_TEST(test_bip32_vector_3) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45"
-          "d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"),
-      64, SECP256K1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7"
-                   "KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhR"
-                   "oP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu"
-                   "2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrAD"
-                   "WgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-}
-END_TEST
-
-// test vector 4 from
-// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-4
-START_TEST(test_bip32_vector_4) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678"),
-      32, SECP256K1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_int_eq(fingerprint, 0x00000000);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7f"
-                   "RDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuy"
-                   "u5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaAL"
-                   "mPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xf"
-                   "FEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 1);
-  ck_assert_int_eq(r, 1);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  hdnode_serialize_private(&node, fingerprint, VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJ"
-                   "eHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1");
-  r = hdnode_deserialize_private(str, VERSION_PRIVATE, SECP256K1_NAME, &node2,
-                                 NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, VERSION_PUBLIC, str, sizeof(str));
-  ck_assert_str_eq(str,
-                   "xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d"
-                   "88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt");
-  r = hdnode_deserialize_public(str, VERSION_PUBLIC, SECP256K1_NAME, &node2,
-                                NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-}
-END_TEST
-
-START_TEST(test_bip32_compare) {
-  HDNode node1, node2, node3;
-  int i, r;
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node1);
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node2);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  for (i = 0; i < 100; i++) {
-    memcpy(&node3, &node1, sizeof(HDNode));
-    ck_assert_int_eq(hdnode_fill_public_key(&node3), 0);
-    r = hdnode_private_ckd(&node1, i);
-    ck_assert_int_eq(r, 1);
-    r = hdnode_public_ckd(&node2, i);
-    ck_assert_int_eq(r, 1);
-    r = hdnode_public_ckd(&node3, i);
-    ck_assert_int_eq(r, 1);
-    ck_assert_uint_eq(node1.depth, node2.depth);
-    ck_assert_uint_eq(node1.depth, node3.depth);
-    ck_assert_uint_eq(node1.child_num, node2.child_num);
-    ck_assert_uint_eq(node1.child_num, node3.child_num);
-    ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32);
-    ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32);
-    ck_assert_mem_eq(
-        node2.private_key,
-        fromhex(
-            "0000000000000000000000000000000000000000000000000000000000000000"),
-        32);
-    ck_assert_mem_eq(
-        node3.private_key,
-        fromhex(
-            "0000000000000000000000000000000000000000000000000000000000000000"),
-        32);
-    ck_assert_int_eq(hdnode_fill_public_key(&node1), 0);
-    ck_assert_mem_eq(node1.public_key, node2.public_key, 33);
-    ck_assert_mem_eq(node1.public_key, node3.public_key, 33);
-  }
-}
-END_TEST
-
-START_TEST(test_bip32_optimized) {
-  HDNode root;
-  hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root);
-  ck_assert_int_eq(hdnode_fill_public_key(&root), 0);
-
-  curve_point pub;
-  ecdsa_read_pubkey(&secp256k1, root.public_key, &pub);
-
-  HDNode node;
-  char addr1[MAX_ADDR_SIZE], addr2[MAX_ADDR_SIZE];
-
-  for (int i = 0; i < 40; i++) {
-    // unoptimized
-    memcpy(&node, &root, sizeof(HDNode));
-    hdnode_public_ckd(&node, i);
-    ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-    ecdsa_get_address(node.public_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                      addr1, sizeof(addr1));
-    // optimized
-    hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0,
-                                        HASHER_SHA2_RIPEMD, HASHER_SHA2D, addr2,
-                                        sizeof(addr2), 0);
-    // check
-    ck_assert_str_eq(addr1, addr2);
-  }
-}
-END_TEST
-
-START_TEST(test_bip32_cache_1) {
-  HDNode node1, node2;
-  int i, r;
-
-  // test 1 .. 8
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node1);
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node2);
-
-  uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004,
-                   0x80000005, 0x80000006, 0x80000007, 0x80000008};
-
-  for (i = 0; i < 8; i++) {
-    r = hdnode_private_ckd(&node1, ii[i]);
-    ck_assert_int_eq(r, 1);
-  }
-  r = hdnode_private_ckd_cached(&node2, ii, 8, NULL);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
-
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node1);
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node2);
-
-  // test 1 .. 7, 20
-  ii[7] = 20;
-  for (i = 0; i < 8; i++) {
-    r = hdnode_private_ckd(&node1, ii[i]);
-    ck_assert_int_eq(r, 1);
-  }
-  r = hdnode_private_ckd_cached(&node2, ii, 8, NULL);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
-
-  // test different root node
-  hdnode_from_seed(
-      fromhex(
-          "000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node1);
-  hdnode_from_seed(
-      fromhex(
-          "000000002ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, SECP256K1_NAME, &node2);
-
-  for (i = 0; i < 8; i++) {
-    r = hdnode_private_ckd(&node1, ii[i]);
-    ck_assert_int_eq(r, 1);
-  }
-  r = hdnode_private_ckd_cached(&node2, ii, 8, NULL);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(&node1, &node2, sizeof(HDNode));
-}
-END_TEST
-
-START_TEST(test_bip32_cache_2) {
-  HDNode nodea[9], nodeb[9];
-  int i, j, r;
-
-  for (j = 0; j < 9; j++) {
-    hdnode_from_seed(
-        fromhex(
-            "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d627"
-            "88f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-        64, SECP256K1_NAME, &(nodea[j]));
-    hdnode_from_seed(
-        fromhex(
-            "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d627"
-            "88f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-        64, SECP256K1_NAME, &(nodeb[j]));
-  }
-
-  uint32_t ii[] = {0x80000001, 0x80000002, 0x80000003, 0x80000004,
-                   0x80000005, 0x80000006, 0x80000007, 0x80000008};
-  for (j = 0; j < 9; j++) {
-    // non cached
-    for (i = 1; i <= j; i++) {
-      r = hdnode_private_ckd(&(nodea[j]), ii[i - 1]);
-      ck_assert_int_eq(r, 1);
-    }
-    // cached
-    r = hdnode_private_ckd_cached(&(nodeb[j]), ii, j, NULL);
-    ck_assert_int_eq(r, 1);
-  }
-
-  ck_assert_mem_eq(&(nodea[0]), &(nodeb[0]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[1]), &(nodeb[1]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[2]), &(nodeb[2]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[3]), &(nodeb[3]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[4]), &(nodeb[4]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[5]), &(nodeb[5]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[6]), &(nodeb[6]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[7]), &(nodeb[7]), sizeof(HDNode));
-  ck_assert_mem_eq(&(nodea[8]), &(nodeb[8]), sizeof(HDNode));
-}
-END_TEST
-
-START_TEST(test_bip32_nist_seed) {
-  HDNode node;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446"),
-      32, NIST256P1_NAME, &node);
-
-  // [Chain m]
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "3b8c18469a4634517d6d0b65448f8e6c62091b45540a1743c5846be55d47d88f"),
-      32);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "7762f9729fed06121fd13f326884c82f59aa95c57ac492ce8c9654e60efd130c"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0383619fadcde31063d8c5cb00dbfe1713f3e6fa169d8541a798752a1c1ca0cb20"),
-      33);
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "aa305bc8df8d0951f0cb29ad4568d7707cbdf2c6ce7e8d481fec69c7ff5e9446"),
-      32, NIST256P1_NAME, &node);
-
-  // [Chain m]
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "a81d21f36f987fa0be3b065301bfb6aa9deefbf3dfef6744c37b9a4abc3c68f1"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0e49dc46ce1d8c29d9b80a05e40f5d0cd68cbf02ae98572186f5343be18084bf"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03aaa4c89acd9a98935330773d3dae55122f3591bac4a40942681768de8df6ba63"),
-      33);
-}
-END_TEST
-
-START_TEST(test_bip32_nist_vector_1) {
-  HDNode node;
-  uint32_t fingerprint;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   NIST256P1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8"),
-      33);
-
-  // [Chain m/0']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 0);
-  ck_assert_uint_eq(fingerprint, 0xbe6105b5);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c"),
-      33);
-
-  // [Chain m/0'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1);
-  ck_assert_uint_eq(fingerprint, 0x9b02312f);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844"),
-      33);
-
-  // [Chain m/0'/1/2']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0xb98005c1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0"),
-      33);
-
-  // [Chain m/0'/1/2'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0x0e9f3274);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20"),
-      33);
-
-  // [Chain m/0'/1/2'/2/1000000000]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1000000000);
-  ck_assert_uint_eq(fingerprint, 0x8b2b5c4b);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4"),
-      33);
-}
-END_TEST
-
-START_TEST(test_bip32_nist_vector_2) {
-  HDNode node;
-  uint32_t fingerprint;
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, NIST256P1_NAME, &node);
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa"),
-      33);
-
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x607f628f);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"),
-      33);
-
-  // [Chain m/0/2147483647']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483647);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x946d2a54);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76"),
-      33);
-
-  // [Chain m/0/2147483647'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 1);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x218182d8);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64"),
-      33);
-
-  // [Chain m/0/2147483647'/1/2147483646']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483646);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x931223e4);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933"),
-      33);
-
-  // [Chain m/0/2147483647'/1/2147483646'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 2);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x956c4629);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f"),
-      33);
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, NIST256P1_NAME, &node);
-
-  // test public derivation
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_public_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x607f628f);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      32);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc"),
-      33);
-}
-END_TEST
-
-START_TEST(test_bip32_nist_compare) {
-  HDNode node1, node2, node3;
-  int i, r;
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, NIST256P1_NAME, &node1);
-  hdnode_from_seed(
-      fromhex(
-          "301133282ad079cbeb59bc446ad39d333928f74c46997d3609cd3e2801ca69d62788"
-          "f9f174429946ff4e9be89f67c22fae28cb296a9b37734f75e73d1477af19"),
-      64, NIST256P1_NAME, &node2);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  for (i = 0; i < 100; i++) {
-    memcpy(&node3, &node1, sizeof(HDNode));
-    ck_assert_int_eq(hdnode_fill_public_key(&node3), 0);
-    r = hdnode_private_ckd(&node1, i);
-    ck_assert_int_eq(r, 1);
-    r = hdnode_public_ckd(&node2, i);
-    ck_assert_int_eq(r, 1);
-    r = hdnode_public_ckd(&node3, i);
-    ck_assert_int_eq(r, 1);
-    ck_assert_uint_eq(node1.depth, node2.depth);
-    ck_assert_uint_eq(node1.depth, node3.depth);
-    ck_assert_uint_eq(node1.child_num, node2.child_num);
-    ck_assert_uint_eq(node1.child_num, node3.child_num);
-    ck_assert_mem_eq(node1.chain_code, node2.chain_code, 32);
-    ck_assert_mem_eq(node1.chain_code, node3.chain_code, 32);
-    ck_assert_mem_eq(
-        node2.private_key,
-        fromhex(
-            "0000000000000000000000000000000000000000000000000000000000000000"),
-        32);
-    ck_assert_mem_eq(
-        node3.private_key,
-        fromhex(
-            "0000000000000000000000000000000000000000000000000000000000000000"),
-        32);
-    ck_assert_int_eq(hdnode_fill_public_key(&node1), 0);
-    ck_assert_mem_eq(node1.public_key, node2.public_key, 33);
-    ck_assert_mem_eq(node1.public_key, node3.public_key, 33);
-  }
-}
-END_TEST
-
-START_TEST(test_bip32_nist_repeat) {
-  HDNode node, node2;
-  uint32_t fingerprint;
-  int r;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   NIST256P1_NAME, &node);
-
-  // [Chain m/28578']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 28578);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0xbe6105b5);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "e94c8ebe30c2250a14713212f6449b20f3329105ea15b652ca5bdfc68f6c65c2"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "06f0db126f023755d0b8d86d4591718a5210dd8d024e3e14b6159d63f53aa669"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02519b5554a4872e8c9c1c847115363051ec43e93400e030ba3c36b52a3e70a5b7"),
-      33);
-
-  memcpy(&node2, &node, sizeof(HDNode));
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node2, 33941);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x3e2b7bc6);
-  ck_assert_mem_eq(
-      node2.chain_code,
-      fromhex(
-          "9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"),
-      32);
-  ck_assert_mem_eq(
-      node2.private_key,
-      fromhex(
-          "092154eed4af83e078ff9b84322015aefe5769e31270f62c3f66c33888335f3a"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(
-      node2.public_key,
-      fromhex(
-          "0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"),
-      33);
-
-  memcpy(&node2, &node, sizeof(HDNode));
-  memzero(&node2.private_key, 32);
-  r = hdnode_public_ckd(&node2, 33941);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x3e2b7bc6);
-  ck_assert_mem_eq(
-      node2.chain_code,
-      fromhex(
-          "9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(
-      node2.public_key,
-      fromhex(
-          "0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120"),
-      33);
-}
-END_TEST
-
-// test vector 1 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors
-START_TEST(test_bip32_ed25519_vector_1) {
-  HDNode node;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   ED25519_NAME, &node);
-
-  // [Chain m]
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "01a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"),
-      33);
-
-  // [Chain m/0']
-  hdnode_private_ckd_prime(&node, 0);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "018c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"),
-      33);
-
-  // [Chain m/0'/1']
-  hdnode_private_ckd_prime(&node, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "011932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187"),
-      33);
-
-  // [Chain m/0'/1'/2']
-  hdnode_private_ckd_prime(&node, 2);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "01ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1"),
-      33);
-
-  // [Chain m/0'/1'/2'/2']
-  hdnode_private_ckd_prime(&node, 2);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "018abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c"),
-      33);
-
-  // [Chain m/0'/1'/2'/2'/1000000000']
-  hdnode_private_ckd_prime(&node, 1000000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "013c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"),
-      33);
-}
-END_TEST
-
-// test vector 2 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors
-START_TEST(test_bip32_ed25519_vector_2) {
-  HDNode node;
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, ED25519_NAME, &node);
-
-  // [Chain m]
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "018fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a"),
-      33);
-
-  // [Chain m/0']
-  r = hdnode_private_ckd_prime(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0186fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037"),
-      33);
-
-  // [Chain m/0'/2147483647']
-  r = hdnode_private_ckd_prime(&node, 2147483647);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "015ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d"),
-      33);
-
-  // [Chain m/0'/2147483647'/1']
-  r = hdnode_private_ckd_prime(&node, 1);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "012e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45"),
-      33);
-
-  // [Chain m/0'/2147483647'/1'/2147483646']
-  r = hdnode_private_ckd_prime(&node, 2147483646);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "01e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b"),
-      33);
-
-  // [Chain m/0'/2147483647'/1'/2147483646'/2']
-  r = hdnode_private_ckd_prime(&node, 2);
-  ck_assert_int_eq(r, 1);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0147150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0"),
-      33);
-}
-END_TEST
-
-// test vector 1 from
-// https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go
-START_TEST(test_bip32_decred_vector_1) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   SECP256K1_NAME, &node);
-
-  // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in
-  // hdnode_from_seed
-  node.curve = &secp256k1_decred_info;
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3hCznBesA6jBtmoyVFPfyMSZ1qYZ3WdjdebquvkEfmRfxC9VFEFi2YD"
-                   "aJqHnx7uGe75eGSa3Mn3oHK11hBW7KZUrPxwbCPBmuCi1nwm182s");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZ9169KDAEUnyoBhjjmT2VaEodr6pUTDoqCEAeqgbfr2JfkB88BbK77j"
-                   "bTYbcYXb2FVz7DKBdW4P618yd51MwF8DjKVopSbS7Lkgi6bowX5w");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 0);
-  ck_assert_uint_eq(fingerprint, 0xbc495588);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3kUQDBztdyjKuwnaL3hfKYpT7W6X2huYH5d61YSWFBebSYwEBHAXJkC"
-                   "pQ7rvMAxPzKqxVCGLvBqWvGxXjAyMJsV1XwKkfnQCM9KctC8k8bk");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZCGVaKZBiMo7pMgLaZm1qmchjWenTeVcUdFQkTNsFGFEA6xs4EW8PKi"
-                   "qYqP7HBAitt9Hw16VQkQ1tjsZQSHNWFc6bEK6bLqrbco24FzBTY4");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1);
-  ck_assert_uint_eq(fingerprint, 0xc67bc2ef);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3nRtCZ5VAoHW4RUwQgRafSNRPUDFrmsgyY71A5eoZceVfuyL9SbZe2r"
-                   "cbwDW2UwpkEniE4urffgbypegscNchPajWzy9QS4cRxF8QYXsZtq");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZEDyZgdnFBMHxqNhfCUwBfAg1UmXHiTmB5jKtzbAZhF8PTzy2PwAicN"
-                   "dkg1CmW6TARxQeUbgC7nAQenJts4YoG3KMiqcjsjgeMvwLc43w6C");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2']
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd_prime(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0xe7072187);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3pYtkZK168vgrU38gXkUSjHQ2LGpEUzQ9fXrR8fGUR59YviSnm6U82X"
-                   "jQYhpJEUPnVcC9bguJBQU5xVM4VFcDHu9BgScGPA6mQMH4bn5Cth");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZGLz7gsJAWzUksvtw3opxx5eeLq5fRaUMDABA3bdUVfnGUk5fiS5Cc3"
-                   "kZGTjWtYr3jrEavQQnAF6jv2WCpZtFX4uFgifXqev6ED1TM9rTCB");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 2);
-  ck_assert_uint_eq(fingerprint, 0xbcbbc1c4);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3r7zqYFjT3NiNzdnwGxGpYh6S1TJCp1zA6mSEGaqLBJFnCB94cRMp7Y"
-                   "YLR49aTZHZ7ya1CXwQJ6rodKeU9NgQTxkPSK7pzgZRgjYkQ7rgJh");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZHv6Cfp2XRSWHQXZBo1dLmVM421Zdkc4MePkyBXCLFttVkCmwZkxth4"
-                   "ZV9PzkFP3DtD5xcVq2CPSYpJMWMaoxu1ixz4GNZFVcE2xnHP6chJ");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0'/1/2'/2/1000000000]
-  fingerprint = hdnode_fingerprint(&node);
-  hdnode_private_ckd(&node, 1000000000);
-  ck_assert_uint_eq(fingerprint, 0xe58b52e4);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3tJXnTDSb3uE6Euo6WvvhFKfBMNfxuJt5smqyPoHEoomoBMQyhYoQSK"
-                   "JAHWtWxmuqdUVb8q9J2NaTkF6rYm6XDrSotkJ55bM21fffa7VV97");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZL6d9amjfRy1zeoZM2zHDU7uoMvwPqtxHRQAiJjeEtQQWjP3retQV1q"
-                   "KJyzUd6ZJNgbJGXjtc5pdoBcTTYTLoxQzvV9JJCzCjB2eCWpRf8T");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-}
-END_TEST
-
-// test vector 2 from
-// https://github.com/decred/dcrd/blob/master/hdkeychain/extendedkey_test.go
-START_TEST(test_bip32_decred_vector_2) {
-  HDNode node, node2, node3;
-  uint32_t fingerprint;
-  char str[XPUB_MAXLEN];
-  int r;
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, SECP256K1_NAME, &node);
-
-  // secp256k1_decred_info.bip32_name != "Bitcoin seed" so we cannot use it in
-  // hdnode_from_seed
-  node.curve = &secp256k1_decred_info;
-
-  // [Chain m]
-  fingerprint = 0;
-  ck_assert_uint_eq(fingerprint, 0x00000000);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3hCznBesA6jBtPKJbQTxRZAKG2gyj8tZKEPaCsV4e9YYFBAgRP2eTSP"
-                   "Aeu4r8dTMt9q51j2Vdt5zNqj7jbtovvocrP1qLj6WUTLF9xYQt4y");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZ9169KDAEUnynoD4qvXJwmxZt3FFA5UdWn1twnRReE9AxjCKJLNFY1u"
-                   "BoegbFmwzA4Du7yqnu8tLivhrCCH6P3DgBS1HH5vmf8MpNXvvYT9");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x2524c9d3);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3jMy45BuuDETfxi59P8NTSjHPrNVq4wPRfLgRd57923L2hosj5NUEqi"
-                   "LYQ4i7fJtUpiXZLr2wUeToJY2Tm5sCpAJdajEHDmieVJiPQNXwu9");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZBA4RCkCybJFaNbqPuBiyfXY1rvmG1XTdCy1AY1U96dxkFqWc2i5KRE"
-                   "Mh7NYPpy7ZPMhdpFMAesex3JdFDfX4J5FEW3HjSacqEYPfwb9Cj7");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483647);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x6035c6ad);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3mgHPRgK838mLK6T1p6WeBoJoJtXA1pGTHjqFuyHekcM7UTuER8fGwe"
-                   "RRsoLqSuHa98uskVPnJnfWZEBUC1AVmXnSCPDvUFKydXNnnPHTuQ");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZDUNkZEcCRCZEizDGL9sAQbZRKSnaxQLeqN9zpueeqCyq2VY7NUGMXA"
-                   "SacsK96S8XzNjq3YgFgwLtj8MJBToW6To9U5zxuazEyh89bjR1xA");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 1);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x36fc7080);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3oFqwZZ9bJcUmhAeJyyshvrTWtrAsHfcRYQbEzNiiH5nGvM6wVTDn6w"
-                   "oQEz92b2EHTYZBtLi82jKEnxSouA3cVaW8YWBsw5c3f4mwAhA3d2");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZF3wJh7SfggGg74QZW3EE9ei8uQSJEFgd62uyuK5iMgQzUNjpSnprgT"
-                   "pYz3d6Q3fXXtEEXQqpzWcP4LUVuXFsgA8JKt1Hot5kyUk4pPRhDz");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1/2147483646']
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd_prime(&node, 2147483646);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x45309b4c);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3qF3177i87wMirg6sraDvqty8yZg6THpXFPSXuM5AShBiiUQbq8FhSZ"
-                   "DGkYmBNR3RKfBrxzkKDBpsRFJfTnQfLsvpPPqRnakat6hHQA43X9");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZH38NEg1CW19dGZs8NdaT4hDkz7wXPstio1mGpHSAXHpSGW3UnTrn25"
-                   "ERT1Mp8ae5GMoQHMbgQiPrChMXQMdx3UqS8YqFkT1pqait8fY92u");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // [Chain m/0/2147483647'/1/2147483646'/2]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_private_ckd(&node, 2);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x3491a5e6);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"),
-      33);
-  hdnode_serialize_private(&node, fingerprint, DECRED_VERSION_PRIVATE, str,
-                           sizeof(str));
-  ck_assert_str_eq(str,
-                   "dprv3s15tfqzxhw8Kmo7RBEqMeyvC7uGekLniSmvbs3bckpxQ6ks1KKqfmH"
-                   "144Jgh3PLxkyZRcS367kp7DrtUmnG16NpnsoNhxSXRgKbJJ7MUQR");
-  r = hdnode_deserialize_private(str, DECRED_VERSION_PRIVATE,
-                                 SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_int_eq(hdnode_fill_public_key(&node2), 0);
-  ck_assert_mem_eq(&node, &node2, sizeof(HDNode));
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZJoBFoQJ35zvEBgsfhJBssnAp8TY5gvruzQFLmyxcqRb7enVtGfSkLo"
-                   "2CkAZJMpa6T2fx6fUtvTgXtUvSVgAZ56bEwGxQsToeZfFV8VadE1");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  memcpy(&node3, &node, sizeof(HDNode));
-  memzero(&node3.private_key, 32);
-  ck_assert_mem_eq(&node2, &node3, sizeof(HDNode));
-
-  // init m
-  hdnode_deserialize_public(
-      "dpubZF4LSCdF9YKZfNzTVYhz4RBxsjYXqms8AQnMBHXZ8GUKoRSigG7kQnKiJt5pzk93Q8Fx"
-      "cdVBEkQZruSXduGtWnkwXzGnjbSovQ97dCxqaXc",
-      DECRED_VERSION_PUBLIC, SECP256K1_DECRED_NAME, &node, NULL);
-
-  // test public derivation
-  // [Chain m/0]
-  fingerprint = hdnode_fingerprint(&node);
-  r = hdnode_public_ckd(&node, 0);
-  ck_assert_int_eq(r, 1);
-  ck_assert_uint_eq(fingerprint, 0x6a19cfb3);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "dcfe00831741a3a4803955147cdfc7053d69b167b1d03b5f9e63934217a005fd"),
-      32);
-  ck_assert_mem_eq(
-      node.public_key,
-      fromhex(
-          "029555ea7bde276cd2c42c4502f40b5d16469fb310ae3aeee2a9000455f41b0866"),
-      33);
-  hdnode_serialize_public(&node, fingerprint, DECRED_VERSION_PUBLIC, str,
-                          sizeof(str));
-  ck_assert_str_eq(str,
-                   "dpubZHJs2Z3PtHbbpaXQCi5wBKPhU8tC5ztBKUYBCYNGKk8eZ1EmBs3MhnL"
-                   "JbxHFMAahGnDnZT7qZxC7AXKP8PB6BDNUZgkG77moNMRmXyQ6s6s");
-  r = hdnode_deserialize_public(str, DECRED_VERSION_PUBLIC,
-                                SECP256K1_DECRED_NAME, &node2, NULL);
-  ck_assert_int_eq(r, 0);
-  ck_assert_mem_eq(&node2, &node, sizeof(HDNode));
-}
-END_TEST
-
-static void test_ecdsa_get_public_key33_helper(int (*ecdsa_get_public_key33_fn)(
-    const ecdsa_curve *, const uint8_t *, uint8_t *)) {
-  uint8_t privkey[32] = {0};
-  uint8_t pubkey[65] = {0};
-  const ecdsa_curve *curve = &secp256k1;
-  int res = 0;
-
-  memcpy(
-      privkey,
-      fromhex(
-          "c46f5b217f04ff28886a89d3c762ed84e5fa318d1c9a635d541131e69f1f49f5"),
-      32);
-  res = ecdsa_get_public_key33_fn(curve, privkey, pubkey);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "0232b062e9153f573c220b1be0299d6447e81577274bf11a7c08dff71384c6b6ec"),
-      33);
-
-  memcpy(
-      privkey,
-      fromhex(
-          "3b90a4de80fb00d77795762c389d1279d4b4ab5992ae3cde6bc12ca63116f74c"),
-      32);
-  res = ecdsa_get_public_key33_fn(curve, privkey, pubkey);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "0332b062e9153f573c220b1be0299d6447e81577274bf11a7c08dff71384c6b6ec"),
-      33);
-}
-
-START_TEST(test_ecdsa_get_public_key33) {
-  test_ecdsa_get_public_key33_helper(ecdsa_get_public_key33);
-}
-END_TEST
-
-START_TEST(test_zkp_ecdsa_get_public_key33) {
-  test_ecdsa_get_public_key33_helper(zkp_ecdsa_get_public_key33);
-}
-END_TEST
-
-static void test_ecdsa_get_public_key65_helper(int (*ecdsa_get_public_key65_fn)(
-    const ecdsa_curve *, const uint8_t *, uint8_t *)) {
-  uint8_t privkey[32] = {0};
-  uint8_t pubkey[65] = {0};
-  const ecdsa_curve *curve = &secp256k1;
-  int res = 0;
-
-  memcpy(
-      privkey,
-      fromhex(
-          "c46f5b217f04ff28886a89d3c762ed84e5fa318d1c9a635d541131e69f1f49f5"),
-      32);
-  res = ecdsa_get_public_key65_fn(curve, privkey, pubkey);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "0432b062e9153f573c220b1be0299d6447e81577274bf11a7c08dff71384c6b6ec"
-          "179ca56b637a57e0fcd28cefa10c9433dc30532682647f4daa053d43d5cc960a"),
-      65);
-}
-
-START_TEST(test_ecdsa_get_public_key65) {
-  test_ecdsa_get_public_key65_helper(ecdsa_get_public_key65);
-}
-END_TEST
-
-START_TEST(test_zkp_ecdsa_get_public_key65) {
-  test_ecdsa_get_public_key65_helper(zkp_ecdsa_get_public_key65);
-}
-END_TEST
-
-static void test_ecdsa_recover_pub_from_sig_helper(int (
-    *ecdsa_recover_pub_from_sig_fn)(const ecdsa_curve *, uint8_t *,
-                                    const uint8_t *, const uint8_t *, int)) {
-  int res;
-  uint8_t digest[32];
-  uint8_t pubkey[65];
-  const ecdsa_curve *curve = &secp256k1;
-
-  // sha2(sha2("\x18Bitcoin Signed Message:\n\x0cHello World!"))
-  memcpy(
-      digest,
-      fromhex(
-          "de4e9524586d6fce45667f9ff12f661e79870c4105fa0fb58af976619bb11432"),
-      32);
-  // r = 2:  Four points should exist
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000020123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 0);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "043fc5bf5fec35b6ffe6fd246226d312742a8c296bfa57dd22da509a2e348529b7dd"
-          "b9faf8afe1ecda3c05e7b2bda47ee1f5a87e952742b22afca560b29d972fcf"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000020123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 1);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "0456d8089137b1fd0d890f8c7d4a04d0fd4520a30b19518ee87bd168ea12ed809032"
-          "9274c4c6c0d9df04515776f2741eeffc30235d596065d718c3973e19711ad0"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000020123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 2);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "04cee0e740f41aab39156844afef0182dea2a8026885b10454a2d539df6f6df9023a"
-          "bfcb0f01c50bef3c0fa8e59a998d07441e18b1c60583ef75cc8b912fb21a15"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000020123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 3);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "0490d2bd2e9a564d6e1d8324fc6ad00aa4ae597684ecf4abea58bdfe7287ea4fa729"
-          "68c2e5b0b40999ede3d7898d94e82c3f8dc4536a567a4bd45998c826a4c4b2"),
-      65);
-  // The point at infinity is not considered to be a valid public key.
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "220cf4c7b6d568f2256a8c30cc1784a625a28c3627dac404aa9a9ecd08314ec81a88"
-          "828f20d69d102bab5de5f6ee7ef040cb0ff7b8e1ba3f29d79efb5250f47d"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      digest,
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000000"),
-      32);
-  // r = 7:  No point P with P.x = 7,  but P.x = (order + 7) exists
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000070123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 2);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b040"
-          "de78f8dbda700f4d3cd7ee21b3651a74c7661809699d2be7ea0992b0d39797"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000070123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 3);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "044d81bb47a31ffc6cf1f780ecb1e201ec47214b651650867c07f13ad06e12a1b0bf"
-          "21870724258ff0b2c32811de4c9ae58b3899e7f69662d41815f66c4f2c6498"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000070123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      digest,
-      fromhex(
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-      32);
-  // r = 1:  Two points P with P.x = 1,  but P.x = (order + 7) doesn't exist
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000010123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 0);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "045d330b2f89dbfca149828277bae852dd4aebfe136982cb531a88e9e7a89463fe71"
-          "519f34ea8feb9490c707f14bc38c9ece51762bfd034ea014719b7c85d2871b"),
-      65);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000010123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 1);
-  ck_assert_int_eq(res, 0);
-  ck_assert_mem_eq(
-      pubkey,
-      fromhex(
-          "049e609c3950e70d6f3e3f3c81a473b1d5ca72739d51debdd80230ae80cab05134a9"
-          "4285375c834a417e8115c546c41da83a263087b79ef1cae25c7b3c738daa2b"),
-      65);
-
-  // r = 0 is always invalid
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000010123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 2);
-  ck_assert_int_eq(res, 1);
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000000123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-  // r >= order is always invalid
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-  // check that overflow of r is handled
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "000000000000000000000000000000014551231950B75FC4402DA1722FC9BAEE0123"
-          "456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
-      digest, 2);
-  ck_assert_int_eq(res, 1);
-  // s = 0 is always invalid
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "00000000000000000000000000000000000000000000000000000000000000020000"
-          "000000000000000000000000000000000000000000000000000000000000"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-  // s >= order is always invalid
-  res = ecdsa_recover_pub_from_sig_fn(
-      curve, pubkey,
-      fromhex(
-          "0000000000000000000000000000000000000000000000000000000000000002ffff"
-          "fffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
-      digest, 0);
-  ck_assert_int_eq(res, 1);
-}
-
-START_TEST(test_ecdsa_recover_pub_from_sig) {
-  test_ecdsa_recover_pub_from_sig_helper(ecdsa_recover_pub_from_sig);
-}
-END_TEST
-
-START_TEST(test_zkp_ecdsa_recover_pub_from_sig) {
-  test_ecdsa_recover_pub_from_sig_helper(zkp_ecdsa_recover_pub_from_sig);
-}
-END_TEST
-
-static void test_ecdsa_verify_digest_helper(int (*ecdsa_verify_digest_fn)(
-    const ecdsa_curve *, const uint8_t *, const uint8_t *, const uint8_t *)) {
-  int res;
-  uint8_t digest[32];
-  uint8_t pubkey[65];
-  uint8_t sig[64];
-  const ecdsa_curve *curve = &secp256k1;
-
-  // Signature verification for a digest which is equal to the group order.
-  // https://github.com/trezor/trezor-firmware/pull/1374
-  memcpy(
-      pubkey,
-      fromhex(
-          "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179848"
-          "3ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"),
-      sizeof(pubkey));
-  memcpy(
-      digest,
-      fromhex(
-          "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
-      sizeof(digest));
-  memcpy(sig,
-         fromhex(
-             "a0b37f8fba683cc68f6574cd43b39f0343a50008bf6ccea9d13231d9e7e2e1e41"
-             "1edc8d307254296264aebfc3dc76cd8b668373a072fd64665b50000e9fcce52"),
-         sizeof(sig));
-  res = ecdsa_verify_digest_fn(curve, pubkey, sig, digest);
-  ck_assert_int_eq(res, 0);
-}
-
-START_TEST(test_ecdsa_verify_digest) {
-  test_ecdsa_verify_digest_helper(ecdsa_verify_digest);
-}
-END_TEST
-
-START_TEST(test_zkp_ecdsa_verify_digest) {
-  test_ecdsa_verify_digest_helper(zkp_ecdsa_verify_digest);
-}
-END_TEST
-
-#define test_deterministic(KEY, MSG, K)           \
-  do {                                            \
-    sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \
-    init_rfc6979(fromhex(KEY), buf, NULL, &rng);  \
-    generate_k_rfc6979(&k, &rng);                 \
-    bn_write_be(&k, buf);                         \
-    ck_assert_mem_eq(buf, fromhex(K), 32);        \
-  } while (0)
-
-START_TEST(test_rfc6979) {
-  bignum256 k;
-  uint8_t buf[32];
-  rfc6979_state rng;
-
-  test_deterministic(
-      "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721",
-      "sample",
-      "a6e3c57dd01abe90086538398355dd4c3b17aa873382b0f24d6129493d8aad60");
-  test_deterministic(
-      "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
-      "sample",
-      "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3");
-  test_deterministic(
-      "0000000000000000000000000000000000000000000000000000000000000001",
-      "Satoshi Nakamoto",
-      "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15");
-  test_deterministic(
-      "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
-      "Satoshi Nakamoto",
-      "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90");
-  test_deterministic(
-      "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181",
-      "Alan Turing",
-      "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1");
-  test_deterministic(
-      "0000000000000000000000000000000000000000000000000000000000000001",
-      "All those moments will be lost in time, like tears in rain. Time to "
-      "die...",
-      "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3");
-  test_deterministic(
-      "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2",
-      "There is a computer disease that anybody who works with computers knows "
-      "about. It's a very serious disease and it interferes completely with "
-      "the work. The trouble with computers is that you 'play' with them!",
-      "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d");
-}
-END_TEST
-
-static void test_ecdsa_sign_digest_deterministic_helper(
-    int (*ecdsa_sign_digest_fn)(const ecdsa_curve *, const uint8_t *,
-                                const uint8_t *, uint8_t *, uint8_t *,
-                                int (*)(uint8_t by, uint8_t sig[64]))) {
-  static struct {
-    const char *priv_key;
-    const char *digest;
-    const char *sig;
-  } tests[] = {
-      {"312155017c70a204106e034520e0cdf17b3e54516e2ece38e38e38e38e38e38e",
-       "ffffffffffffffffffffffffffffffff20202020202020202020202020202020",
-       "e3d70248ea2fc771fc8d5e62d76b9cfd5402c96990333549eaadce1ae9f737eb"
-       "5cfbdc7d1e0ec18cc9b57bbb18f0a57dc929ec3c4dfac9073c581705015f6a8a"},
-      {"312155017c70a204106e034520e0cdf17b3e54516e2ece38e38e38e38e38e38e",
-       "2020202020202020202020202020202020202020202020202020202020202020",
-       "40666188895430715552a7e4c6b53851f37a93030fb94e043850921242db78e8"
-       "75aa2ac9fd7e5a19402973e60e64382cdc29a09ebf6cb37e92f23be5b9251aee"},
-  };
-
-  const ecdsa_curve *curve = &secp256k1;
-  uint8_t priv_key[32] = {0};
-  uint8_t digest[32] = {0};
-  uint8_t expected_sig[64] = {0};
-  uint8_t computed_sig[64] = {0};
-  int res = 0;
-
-  for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-    memcpy(priv_key, fromhex(tests[i].priv_key), 32);
-    memcpy(digest, fromhex(tests[i].digest), 32);
-    memcpy(expected_sig, fromhex(tests[i].sig), 64);
-
-    res =
-        ecdsa_sign_digest_fn(curve, priv_key, digest, computed_sig, NULL, NULL);
-    ck_assert_int_eq(res, 0);
-    ck_assert_mem_eq(expected_sig, computed_sig, 64);
-  }
-}
-
-START_TEST(test_ecdsa_sign_digest_deterministic) {
-  test_ecdsa_sign_digest_deterministic_helper(ecdsa_sign_digest);
-}
-END_TEST
-
-START_TEST(test_zkp_ecdsa_sign_digest_deterministic) {
-  test_ecdsa_sign_digest_deterministic_helper(zkp_ecdsa_sign_digest);
-}
-END_TEST
-
-// test vectors from
-// http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors
-START_TEST(test_aes) {
-  aes_encrypt_ctx ctxe;
-  aes_decrypt_ctx ctxd;
-  uint8_t ibuf[16], obuf[16], iv[16], cbuf[16];
-  const char **ivp, **plainp, **cipherp;
-
-  // ECB
-  static const char *ecb_vector[] = {
-      // plain                            cipher
-      "6bc1bee22e409f96e93d7e117393172a",
-      "f3eed1bdb5d2a03c064b5a7e3db181f8",
-      "ae2d8a571e03ac9c9eb76fac45af8e51",
-      "591ccb10d410ed26dc5ba74a31362870",
-      "30c81c46a35ce411e5fbc1191a0a52ef",
-      "b6ed21b99ca6f4f9f153e7b1beafed1d",
-      "f69f2445df4f9b17ad2b417be66c3710",
-      "23304b7a39f9f3ff067d8d8f9e24ecc7",
-      0,
-      0,
-  };
-  plainp = ecb_vector;
-  cipherp = ecb_vector + 1;
-  while (*plainp && *cipherp) {
-    // encrypt
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(ibuf, fromhex(*plainp), 16);
-    aes_ecb_encrypt(ibuf, obuf, 16, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*cipherp), 16);
-    // decrypt
-    aes_decrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxd);
-    memcpy(ibuf, fromhex(*cipherp), 16);
-    aes_ecb_decrypt(ibuf, obuf, 16, &ctxd);
-    ck_assert_mem_eq(obuf, fromhex(*plainp), 16);
-    plainp += 2;
-    cipherp += 2;
-  }
-
-  // CBC
-  static const char *cbc_vector[] = {
-      // iv                               plain cipher
-      "000102030405060708090A0B0C0D0E0F",
-      "6bc1bee22e409f96e93d7e117393172a",
-      "f58c4c04d6e5f1ba779eabfb5f7bfbd6",
-      "F58C4C04D6E5F1BA779EABFB5F7BFBD6",
-      "ae2d8a571e03ac9c9eb76fac45af8e51",
-      "9cfc4e967edb808d679f777bc6702c7d",
-      "9CFC4E967EDB808D679F777BC6702C7D",
-      "30c81c46a35ce411e5fbc1191a0a52ef",
-      "39f23369a9d9bacfa530e26304231461",
-      "39F23369A9D9BACFA530E26304231461",
-      "f69f2445df4f9b17ad2b417be66c3710",
-      "b2eb05e2c39be9fcda6c19078c6a9d1b",
-      0,
-      0,
-      0,
-  };
-  ivp = cbc_vector;
-  plainp = cbc_vector + 1;
-  cipherp = cbc_vector + 2;
-  while (*plainp && *cipherp) {
-    // encrypt
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*plainp), 16);
-    aes_cbc_encrypt(ibuf, obuf, 16, iv, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*cipherp), 16);
-    // decrypt
-    aes_decrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxd);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*cipherp), 16);
-    aes_cbc_decrypt(ibuf, obuf, 16, iv, &ctxd);
-    ck_assert_mem_eq(obuf, fromhex(*plainp), 16);
-    ivp += 3;
-    plainp += 3;
-    cipherp += 3;
-  }
-
-  // CFB
-  static const char *cfb_vector[] = {
-      "000102030405060708090A0B0C0D0E0F",
-      "6bc1bee22e409f96e93d7e117393172a",
-      "DC7E84BFDA79164B7ECD8486985D3860",
-      "DC7E84BFDA79164B7ECD8486985D3860",
-      "ae2d8a571e03ac9c9eb76fac45af8e51",
-      "39ffed143b28b1c832113c6331e5407b",
-      "39FFED143B28B1C832113C6331E5407B",
-      "30c81c46a35ce411e5fbc1191a0a52ef",
-      "df10132415e54b92a13ed0a8267ae2f9",
-      "DF10132415E54B92A13ED0A8267AE2F9",
-      "f69f2445df4f9b17ad2b417be66c3710",
-      "75a385741ab9cef82031623d55b1e471",
-      0,
-      0,
-      0,
-  };
-  ivp = cfb_vector;
-  plainp = cfb_vector + 1;
-  cipherp = cfb_vector + 2;
-  while (*plainp && *cipherp) {
-    // encrypt
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*plainp), 16);
-    aes_cfb_encrypt(ibuf, obuf, 16, iv, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*cipherp), 16);
-    // decrypt (uses encryption)
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*cipherp), 16);
-    aes_cfb_decrypt(ibuf, obuf, 16, iv, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*plainp), 16);
-    ivp += 3;
-    plainp += 3;
-    cipherp += 3;
-  }
-
-  // OFB
-  static const char *ofb_vector[] = {
-      "000102030405060708090A0B0C0D0E0F",
-      "6bc1bee22e409f96e93d7e117393172a",
-      "dc7e84bfda79164b7ecd8486985d3860",
-      "B7BF3A5DF43989DD97F0FA97EBCE2F4A",
-      "ae2d8a571e03ac9c9eb76fac45af8e51",
-      "4febdc6740d20b3ac88f6ad82a4fb08d",
-      "E1C656305ED1A7A6563805746FE03EDC",
-      "30c81c46a35ce411e5fbc1191a0a52ef",
-      "71ab47a086e86eedf39d1c5bba97c408",
-      "41635BE625B48AFC1666DD42A09D96E7",
-      "f69f2445df4f9b17ad2b417be66c3710",
-      "0126141d67f37be8538f5a8be740e484",
-      0,
-      0,
-      0,
-  };
-  ivp = ofb_vector;
-  plainp = ofb_vector + 1;
-  cipherp = ofb_vector + 2;
-  while (*plainp && *cipherp) {
-    // encrypt
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*plainp), 16);
-    aes_ofb_encrypt(ibuf, obuf, 16, iv, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*cipherp), 16);
-    // decrypt (uses encryption)
-    aes_encrypt_key256(
-        fromhex(
-            "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-        &ctxe);
-    memcpy(iv, fromhex(*ivp), 16);
-    memcpy(ibuf, fromhex(*cipherp), 16);
-    aes_ofb_decrypt(ibuf, obuf, 16, iv, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*plainp), 16);
-    ivp += 3;
-    plainp += 3;
-    cipherp += 3;
-  }
-
-  // CTR
-  static const char *ctr_vector[] = {
-      // plain                            cipher
-      "6bc1bee22e409f96e93d7e117393172a",
-      "601ec313775789a5b7a7f504bbf3d228",
-      "ae2d8a571e03ac9c9eb76fac45af8e51",
-      "f443e3ca4d62b59aca84e990cacaf5c5",
-      "30c81c46a35ce411e5fbc1191a0a52ef",
-      "2b0930daa23de94ce87017ba2d84988d",
-      "f69f2445df4f9b17ad2b417be66c3710",
-      "dfc9c58db67aada613c2dd08457941a6",
-      0,
-      0,
-  };
-  // encrypt
-  plainp = ctr_vector;
-  cipherp = ctr_vector + 1;
-  memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16);
-  aes_encrypt_key256(
-      fromhex(
-          "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-      &ctxe);
-  while (*plainp && *cipherp) {
-    memcpy(ibuf, fromhex(*plainp), 16);
-    aes_ctr_encrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*cipherp), 16);
-    plainp += 2;
-    cipherp += 2;
-  }
-  // decrypt (uses encryption)
-  plainp = ctr_vector;
-  cipherp = ctr_vector + 1;
-  memcpy(cbuf, fromhex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), 16);
-  aes_encrypt_key256(
-      fromhex(
-          "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
-      &ctxe);
-  while (*plainp && *cipherp) {
-    memcpy(ibuf, fromhex(*cipherp), 16);
-    aes_ctr_decrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
-    ck_assert_mem_eq(obuf, fromhex(*plainp), 16);
-    plainp += 2;
-    cipherp += 2;
-  }
-}
-END_TEST
-
-#define TEST1 "abc"
-#define TEST2_1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-#define TEST2_2a "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-#define TEST2_2b "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
-#define TEST2_2 TEST2_2a TEST2_2b
-#define TEST3 "a" /* times 1000000 */
-#define TEST4a "01234567012345670123456701234567"
-#define TEST4b "01234567012345670123456701234567"
-/* an exact multiple of 512 bits */
-#define TEST4 TEST4a TEST4b /* times 10 */
-
-#define TEST7_1 "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8"
-#define TEST8_1 \
-  "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46"
-#define TEST9_1                                                      \
-  "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \
-  "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \
-  "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \
-  "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \
-  "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a"
-#define TEST10_1                                                     \
-  "\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \
-  "\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \
-  "\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \
-  "\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \
-  "\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \
-  "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \
-  "\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \
-  "\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \
-  "\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \
-  "\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \
-  "\xcd\xbb\xfb"
-#define length(x) (sizeof(x) - 1)
-
-// test vectors from rfc-4634
-START_TEST(test_sha1) {
-  struct {
-    const char *test;
-    int length;
-    int repeatcount;
-    int extrabits;
-    int numberExtrabits;
-    const char *result;
-  } tests[] = {
-      /* 1 */ {TEST1, length(TEST1), 1, 0, 0,
-               "A9993E364706816ABA3E25717850C26C9CD0D89D"},
-      /* 2 */
-      {TEST2_1, length(TEST2_1), 1, 0, 0,
-       "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"},
-      /* 3 */
-      {TEST3, length(TEST3), 1000000, 0, 0,
-       "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"},
-      /* 4 */
-      {TEST4, length(TEST4), 10, 0, 0,
-       "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"},
-      /* 5 */ {"", 0, 0, 0x98, 5, "29826B003B906E660EFF4027CE98AF3531AC75BA"},
-      /* 6 */ {"\x5e", 1, 1, 0, 0, "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2"},
-      /* 7 */
-      {TEST7_1, length(TEST7_1), 1, 0x80, 3,
-       "6239781E03729919C01955B3FFA8ACB60B988340"},
-      /* 8 */
-      {TEST8_1, length(TEST8_1), 1, 0, 0,
-       "82ABFF6605DBE1C17DEF12A394FA22A82B544A35"},
-      /* 9 */
-      {TEST9_1, length(TEST9_1), 1, 0xE0, 3,
-       "8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4"},
-      /* 10 */
-      {TEST10_1, length(TEST10_1), 1, 0, 0,
-       "CB0082C8F197D260991BA6A460E76E202BAD27B3"}};
-
-  for (int i = 0; i < 10; i++) {
-    SHA1_CTX ctx;
-    uint8_t digest[SHA1_DIGEST_LENGTH];
-    sha1_Init(&ctx);
-    /* extra bits are not supported */
-    if (tests[i].numberExtrabits) continue;
-    for (int j = 0; j < tests[i].repeatcount; j++) {
-      sha1_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length);
-    }
-    sha1_Final(&ctx, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA1_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-#define TEST7_256 "\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73"
-#define TEST8_256 \
-  "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52"
-#define TEST9_256                                                    \
-  "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \
-  "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \
-  "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \
-  "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \
-  "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3"
-#define TEST10_256                                                   \
-  "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \
-  "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \
-  "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \
-  "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \
-  "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \
-  "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \
-  "\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \
-  "\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \
-  "\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \
-  "\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \
-  "\x3d\x54\xd6"
-
-// test vectors from rfc-4634
-START_TEST(test_sha256) {
-  struct {
-    const char *test;
-    int length;
-    int repeatcount;
-    int extrabits;
-    int numberExtrabits;
-    const char *result;
-  } tests[] = {
-      /* 1 */ {TEST1, length(TEST1), 1, 0, 0,
-               "BA7816BF8F01CFEA4141"
-               "40DE5DAE2223B00361A396177A9CB410FF61F20015AD"},
-      /* 2 */
-      {TEST2_1, length(TEST2_1), 1, 0, 0,
-       "248D6A61D20638B8"
-       "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1"},
-      /* 3 */
-      {TEST3, length(TEST3), 1000000, 0, 0,
-       "CDC76E5C9914FB92"
-       "81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0"},
-      /* 4 */
-      {TEST4, length(TEST4), 10, 0, 0,
-       "594847328451BDFA"
-       "85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5"},
-      /* 5 */
-      {"", 0, 0, 0x68, 5,
-       "D6D3E02A31A84A8CAA9718ED6C2057BE"
-       "09DB45E7823EB5079CE7A573A3760F95"},
-      /* 6 */
-      {"\x19", 1, 1, 0, 0,
-       "68AA2E2EE5DFF96E3355E6C7EE373E3D"
-       "6A4E17F75F9518D843709C0C9BC3E3D4"},
-      /* 7 */
-      {TEST7_256, length(TEST7_256), 1, 0x60, 3,
-       "77EC1DC8"
-       "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972"},
-      /* 8 */
-      {TEST8_256, length(TEST8_256), 1, 0, 0,
-       "175EE69B02BA"
-       "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8"},
-      /* 9 */
-      {TEST9_256, length(TEST9_256), 1, 0xA0, 3,
-       "3E9AD646"
-       "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9"},
-      /* 10 */
-      {TEST10_256, length(TEST10_256), 1, 0, 0,
-       "97DBCA7D"
-       "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC"},
-  };
-
-  for (int i = 0; i < 10; i++) {
-    SHA256_CTX ctx;
-    uint8_t digest[SHA256_DIGEST_LENGTH];
-    sha256_Init(&ctx);
-    /* extra bits are not supported */
-    if (tests[i].numberExtrabits) continue;
-    for (int j = 0; j < tests[i].repeatcount; j++) {
-      sha256_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length);
-    }
-    sha256_Final(&ctx, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA256_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-#define TEST7_512 "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70"
-#define TEST8_512 \
-  "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0"
-#define TEST9_512                                                    \
-  "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \
-  "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \
-  "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \
-  "\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \
-  "\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \
-  "\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \
-  "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \
-  "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \
-  "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06"
-#define TEST10_512                                                   \
-  "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \
-  "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \
-  "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \
-  "\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \
-  "\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \
-  "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \
-  "\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \
-  "\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \
-  "\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \
-  "\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \
-  "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \
-  "\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \
-  "\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \
-  "\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \
-  "\xfb\x40\xd2"
-
-// test vectors from rfc-4634
-START_TEST(test_sha512) {
-  struct {
-    const char *test;
-    int length;
-    int repeatcount;
-    int extrabits;
-    int numberExtrabits;
-    const char *result;
-  } tests[] = {/* 1 */ {TEST1, length(TEST1), 1, 0, 0,
-                        "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2"
-                        "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD"
-                        "454D4423643CE80E2A9AC94FA54CA49F"},
-               /* 2 */
-               {TEST2_2, length(TEST2_2), 1, 0, 0,
-                "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1"
-                "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A"
-                "C7D329EEB6DD26545E96E55B874BE909"},
-               /* 3 */
-               {TEST3, length(TEST3), 1000000, 0, 0,
-                "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428"
-                "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B"
-                "EB009C5C2C49AA2E4EADB217AD8CC09B"},
-               /* 4 */
-               {TEST4, length(TEST4), 10, 0, 0,
-                "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024"
-                "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51"
-                "0813A39CD5A84C4ACAA64D3F3FB7BAE9"},
-               /* 5 */
-               {"", 0, 0, 0xB0, 5,
-                "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0"
-                "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2"
-                "1B22A84CC03BF8CE4845F34DD5BDBAD4"},
-               /* 6 */
-               {"\xD0", 1, 1, 0, 0,
-                "9992202938E882E73E20F6B69E68A0A7149090423D93C81B"
-                "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A"
-                "D6E74CECE9631BFA8A549B4AB3FBBA15"},
-               /* 7 */
-               {TEST7_512, length(TEST7_512), 1, 0x80, 3,
-                "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71"
-                "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B"
-                "7359B43E64F8BEC3C1F237119986BBB6"},
-               /* 8 */
-               {TEST8_512, length(TEST8_512), 1, 0, 0,
-                "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD"
-                "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398"
-                "8213EB1B16F517AD0DE4B2F0C95C90F8"},
-               /* 9 */
-               {TEST9_512, length(TEST9_512), 1, 0x80, 3,
-                "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6"
-                "82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2"
-                "526F8A0A510E5E53CAFED4355FE7C2F1"},
-               /* 10 */
-               {TEST10_512, length(TEST10_512), 1, 0, 0,
-                "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909"
-                "C1A16A270D48719377966B957A878E720584779A62825C18"
-                "DA26415E49A7176A894E7510FD1451F5"}};
-
-  for (int i = 0; i < 10; i++) {
-    SHA512_CTX ctx;
-    uint8_t digest[SHA512_DIGEST_LENGTH];
-    sha512_Init(&ctx);
-    /* extra bits are not supported */
-    if (tests[i].numberExtrabits) continue;
-    for (int j = 0; j < tests[i].repeatcount; j++) {
-      sha512_Update(&ctx, (const uint8_t *)tests[i].test, tests[i].length);
-    }
-    sha512_Final(&ctx, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA512_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// test vectors from http://www.di-mgt.com.au/sha_testvectors.html
-START_TEST(test_sha3_256) {
-  static const struct {
-    const char *data;
-    const char *hash;
-  } tests[] = {
-      {
-          "",
-          "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
-      },
-      {
-          "abc",
-          "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
-      },
-      {
-          "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-          "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376",
-      },
-      {
-          "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijkl"
-          "mnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
-          "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18",
-      },
-  };
-
-  uint8_t digest[SHA3_256_DIGEST_LENGTH];
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t len = strlen(tests[i].data);
-    sha3_256((uint8_t *)tests[i].data, len, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH);
-
-    // Test progressive hashing.
-    size_t part_len = len;
-    SHA3_CTX ctx;
-    sha3_256_Init(&ctx);
-    sha3_Update(&ctx, (uint8_t *)tests[i].data, part_len);
-    sha3_Update(&ctx, NULL, 0);
-    sha3_Update(&ctx, (uint8_t *)tests[i].data + part_len, len - part_len);
-    sha3_Final(&ctx, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// test vectors from http://www.di-mgt.com.au/sha_testvectors.html
-START_TEST(test_sha3_512) {
-  static const struct {
-    const char *data;
-    const char *hash;
-  } tests[] = {
-      {
-          "",
-          "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2"
-          "123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
-      },
-      {
-          "abc",
-          "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e1"
-          "16e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0",
-      },
-      {
-          "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-          "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee69"
-          "1fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e",
-      },
-      {
-          "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijkl"
-          "mnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
-          "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3"
-          "261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185",
-      },
-  };
-
-  uint8_t digest[SHA3_512_DIGEST_LENGTH];
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t len = strlen(tests[i].data);
-    sha3_512((uint8_t *)tests[i].data, len, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), SHA3_512_DIGEST_LENGTH);
-
-    // Test progressive hashing.
-    size_t part_len = len;
-    SHA3_CTX ctx;
-    sha3_512_Init(&ctx);
-    sha3_Update(&ctx, (const uint8_t *)tests[i].data, part_len);
-    sha3_Update(&ctx, NULL, 0);
-    sha3_Update(&ctx, (const uint8_t *)tests[i].data + part_len,
-                len - part_len);
-    sha3_Final(&ctx, digest);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), SHA3_512_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/0.test-sha3-256.dat
-START_TEST(test_keccak_256) {
-  static const struct {
-    const char *hash;
-    size_t length;
-    const char *data;
-  } tests[] = {
-      {
-          "4e9e79ab7434f6c7401fb3305d55052ee829b9e46d5d05d43b59fefb32e9a619",
-          293,
-          "a6151d4904e18ec288243028ceda30556e6c42096af7150d6a7232ca5dba52bd2192"
-          "e23daa5fa2bea3d4bd95efa2389cd193fcd3376e70a5c097b32c1c62c80af9d71021"
-          "1545f7cdddf63747420281d64529477c61e721273cfd78f8890abb4070e97baa52ac"
-          "8ff61c26d195fc54c077def7a3f6f79b36e046c1a83ce9674ba1983ec2fb58947de6"
-          "16dd797d6499b0385d5e8a213db9ad5078a8e0c940ff0cb6bf92357ea5609f778c3d"
-          "1fb1e7e36c35db873361e2be5c125ea7148eff4a035b0cce880a41190b2e22924ad9"
-          "d1b82433d9c023924f2311315f07b88bfd42850047bf3be785c4ce11c09d7e02065d"
-          "30f6324365f93c5e7e423a07d754eb314b5fe9db4614275be4be26af017abdc9c338"
-          "d01368226fe9af1fb1f815e7317bdbb30a0f36dc69",
-      },
-      {
-          "c1268babc42d00c3463dc388222100f7e525a74a64665c39f112f788ddb5da42",
-          376,
-          "9db801077952c2324e0044a4994edfb09b3edfcf669bfdd029f4bf42d5b0eab3056b"
-          "0bf82708ca7bfadba43c9de806b10a19d0f00c2351ef1086b6b108f306e035c6b61b"
-          "2e70fd7087ba848601c8a3f626a66666423717ef305a1068bfa3a1f7ffc1e5a78cb6"
-          "182ffc8a577ca2a821630bf900d0fbba848bdf94b77c5946771b6c3f8c02269bc772"
-          "ca56098f724536d96be68c284ee1d81697989d40029b8ea63ac1fd85f8b3cae8b194"
-          "f6834ff65a5858f9498ddbb467995eb2d49cdfc6c05d92038c6e9aaeee85f8222b37"
-          "84165f12a2c3df4c7a142e26dddfd831d07e22dfecc0eded48a69c8a9e1b97f1a4e0"
-          "efcd4edd310de0edf82af38a6e4d5ab2a19da586e61210d4f75e7a07e2201f9c8154"
-          "ca52a414a70d2eb2ac1c5b9a2900b4d871f62fa56f70d03b3dd3704bd644808c45a1"
-          "3231918ea884645b8ec054e8bab2935a66811fe590ddc119ae901dfeb54fc2a87c1e"
-          "0a236778baab2fa8843709c6676d3c1888ba19d75ec52d73a7d035c143179b938237"
-          "26b7",
-      },
-      {
-          "e83b50e8c83cb676a7dd64c055f53e5110d5a4c62245ceb8f683fd87b2b3ec77",
-          166,
-          "c070a957550b7b34113ee6543a1918d96d241f27123425db7f7b9004e047ffbe0561"
-          "2e7fa8c54b23c83ea427e625e97b7a28b09a70bf6d91e478eeed01d7907931c29ea8"
-          "6e70f2cdcfb243ccf7f24a1619abf4b5b9e6f75cbf63fc02baf4a820a9790a6b053e"
-          "50fd94e0ed57037cfc2bab4d95472b97d3c25f434f1cc0b1ede5ba7f15907a42a223"
-          "933e5e2dfcb518c3531975268c326d60fa911fbb7997eee3ba87656c4fe7",
-      },
-      {
-          "8ebd2c9d4ff00e285a9b6b140bfc3cef672016f0098100e1f6f250220af7ce1a",
-          224,
-          "b502fbdce4045e49e147eff5463d4b3f37f43461518868368e2c78008c84c2db79d1"
-          "2b58107034f67e7d0abfee67add0342dd23dce623f26b9156def87b1d7ac15a6e073"
-          "01f832610fe869ada13a2b0e3d60aa6bb81bc04487e2e800f5106b0402ee0331df74"
-          "5e021b5ea5e32faf1c7fc1322041d221a54191c0af19948b5f34411937182e30d5cd"
-          "39b5a6c959d77d92d21bb1de51f1b3411cb6eec00600429916227fb62d2c88e69576"
-          "f4ac8e5efcde8efa512cc80ce7fb0dfaa6c74d26e898cefe9d4f7dce232a69f2a6a9"
-          "477aa08366efcdfca117c89cb79eba15a23755e0",
-      },
-      {
-          "db3961fdddd0c314289efed5d57363459a6700a7bd015e7a03d3e1d03f046401",
-          262,
-          "22e203a98ba2c43d8bc3658f0a48a35766df356d6a5e98b0c7222d16d85a00b31720"
-          "7d4aef3fc7cabb67b9d8f5838de0b733e1fd59c31f0667e53286972d7090421ad90d"
-          "54db2ea40047d0d1700c86f53dbf48da532396307e68edad877dcae481848801b0a5"
-          "db44dbdba6fc7c63b5cd15281d57ca9e6be96f530b209b59d6127ad2bd8750f3f807"
-          "98f62521f0d5b42633c2f5a9aaefbed38779b7aded2338d66850b0bb0e33c48e040c"
-          "99f2dcee7a7ebb3d7416e1c5bf038c19d09682dab67c96dbbfad472e45980aa27d1b"
-          "301b15f7de4d4f549bad2501931c9d4f1a3b1692dcb4b1b834ddd4a636126702307d"
-          "daeec61841693b21887d56e76cc2069dafb557fd6682160f",
-      },
-      {
-          "25dd3acacd6bf688c0eace8d33eb7cc550271969142deb769a05b4012f7bb722",
-          122,
-          "99e7f6e0ed46ec866c43a1ab494998d47e9309a79fde2a629eb63bb2160a5ffd0f22"
-          "06de9c32dd20e9b23e57ab7422cf82971cc2873ec0e173fe93281c7b33e1c76ac792"
-          "23a6f435f230bdd30260c00d00986c72a399d3ba70f6e783d834bbf8a6127844def5"
-          "59b8b6db742b2cfd715f7ff29e7b42bf7d567beb",
-      },
-      {
-          "00d747c9045c093484290afc161437f11c2ddf5f8a9fc2acae9c7ef5fcf511e5",
-          440,
-          "50c392f97f8788377f0ab2e2aab196cb017ad157c6f9d022673d39072cc198b06622"
-          "a5cbd269d1516089fa59e28c3373a92bd54b2ebf1a79811c7e40fdd7bce200e80983"
-          "fda6e77fc44c44c1b5f87e01cef2f41e1141103f73364e9c2f25a4597e6517ef31b3"
-          "16300b770c69595e0fa6d011df1566a8676a88c7698562273bbfa217cc69d4b5c89a"
-          "8907b902f7dc14481fefc7da4a810c15a60f5641aae854d2f8cc50cbc393015560f0"
-          "1c94e0d0c075dbcb150ad6eba29dc747919edcaf0231dba3eb3f2b1a87e136a1f0fd"
-          "4b3d8ee61bad2729e9526a32884f7bcfa41e361add1b4c51dc81463528372b4ec321"
-          "244de0c541ba00df22b8773cdf4cf898510c867829fa6b4ff11f9627338b9686d905"
-          "cb7bcdf085080ab842146e0035c808be58cce97827d8926a98bd1ff7c529be3bc14f"
-          "68c91b2ca4d2f6fc748f56bcf14853b7f8b9aa6d388f0fd82f53fdc4bacf9d9ba10a"
-          "165f404cf427e199f51bf6773b7c82531e17933f6d8b8d9181e22f8921a2dbb20fc7"
-          "c8023a87e716e245017c399d0942934f5e085219b3f8d26a196bf8b239438b8e561c"
-          "28a61ff08872ecb052c5fcb19e2fdbc09565924a50ebee1461c4b414219d4257",
-      },
-      {
-          "dadcde7c3603ef419d319ba3d50cf00ad57f3e81566fd11b9b6f461cbb9dcb0f",
-          338,
-          "18e1df97abccc91e07dc7b7ffab5ee8919d5610721453176aa2089fb96d9a477e147"
-          "6f507fa1129f04304e960e8017ff41246cacc0153055fc4b1dc6168a74067ebb077c"
-          "b5aa80a9df6e8b5b821e906531159668c4c164b9e511d8724aedbe17c1f41da88094"
-          "17d3c30b79ea5a2e3c961f6bac5436d9af6be24a36eebcb17863fed82c0eb8962339"
-          "eb612d58659dddd2ea06a120b3a2d8a17050be2de367db25a5bef4290c209bdb4c16"
-          "c4df5a1fe1ead635169a1c35f0a56bc07bcf6ef0e4c2d8573ed7a3b58030fa268c1a"
-          "5974b097288f01f34d5a1087946410688016882c6c7621aad680d9a25c7a3e5dbcbb"
-          "07ffdb7243b91031c08a121b40785e96b7ee46770c760f84aca8f36b7c7da64d25c8"
-          "f73b4d88ff3acb7eeefc0b75144dffea66d2d1f6b42b905b61929ab3f38538393ba5"
-          "ca9d3c62c61f46fa63789cac14e4e1d8722bf03cceef6e3de91f783b0072616c",
-      },
-      {
-          "d184e84a2507fc0f187b640dd5b849a366c0383d9cbdbc6fa30904f054111255",
-          141,
-          "13b8df9c1bcfddd0aa39b3055f52e2bc36562b6677535994b173f07041d141699db4"
-          "2589d6091ef0e71b645b41ab57577f58c98da966562d24823158f8e1d43b54edea4e"
-          "61dd66fe8c59ad8405f5a0d9a3eb509a77ae3d8ae4adf926fd3d8d31c3dcccfc1408"
-          "14541010937024cc554e1daaee1b333a66316e7fbebb07ac8dfb134a918b9090b141"
-          "68012c4824",
-      },
-      {
-          "20c19635364a00b151d0168fe5ae03bac6dd7d06030475b40d2e8c577a192f53",
-          84,
-          "e1e96da4b7d8dcc2b316006503a990ea26a5b200cb7a7edfc14f5ce827f06d8d232e"
-          "c95b1acdc1422ffc16da11d258f0c7b378f026d64c74b2fb41df8bfd3cd30066caec"
-          "dc6f76c8163de9309d9fd0cf33d54a29",
-      },
-      {
-          "86cc2c428d469e43fb4ee8d38dffbf5128d20d1659dbc45edf4a855399ca730e",
-          319,
-          "30391840ad14e66c53e1a5aaa03989ff059940b60c44c3b21295a93d023f2e6c7cdc"
-          "f60208b7d87a7605fb5cee94630d94cad90bc6955328357fa37fea47c09f9cee759c"
-          "31537187321c7d572e3554eeb90f441a9494575454dfbf8cfd86128da15de9418821"
-          "ca158856eb84ff6a29a2c8380711e9e6d4955388374fcd3c1ca45b49e0679fc7157f"
-          "96bc6e4f86ce20a89c12d4449b1ca7056e0b7296fc646f68f6ddbfa6a48e384d63ab"
-          "68bc75fd69a2add59b8e41c4a0f753935df9a703d7df82a430798b0a67710a780614"
-          "85a9d15de16f154582082459b4462485ce8a82d35ac6b9498ae40df3a23d5f00e0e8"
-          "6661cb02c52f677fd374c32969ec63028b5dd2c1d4bce67a6d9f79ba5e7eeb5a2763"
-          "dc9fe2a05aa2ebaad36aaec2541e343a677fb4e6b6a180eff33c93744a4624f6a79f"
-          "054c6c9e9c5b6928dbe7ba5fca",
-      },
-      {
-          "e80eee72a76e6957f7cb7f68c41b92f0ad9aac6e58aa8fc272c1e7364af11c70",
-          108,
-          "3c210ed15889ae938781d2cebd49d4a8007f163ffba1f7669bccdccf6ad5a1418299"
-          "d5f4348f5cd03b0ba9e6999ab154e46836c3546feb395d17bcc60f23d7ba0e8efe6a"
-          "a616c00b6bf552fe1cb5e28e3e7bc39dfc20c63ae3901035e91ddd110e43fe59ed74"
-          "4beeedb6bc1e",
-      },
-      {
-          "f971bbae97dd8a034835269fb246867de358a889de6de13672e771d6fb4c89b7",
-          468,
-          "64e9a3a99c021df8bea59368cfe1cd3b0a4aca33ffcd5cf6028d9307c0b904b8037d"
-          "056a3c12803f196f74c4d360a3132452d365922b1157e5b0d76f91fb94bebfdcb4d5"
-          "0fa23ed5be3d3c5712219e8666debc8abcd5e6c69a542761a6cbbd1b3c0f05248752"
-          "04b64d2788465f90cb19b6f6da9f8bec6d6e684196e713549ec83e47cbaeff77838a"
-          "c4936b312562e2de17c970449d49d214ec2597c6d4f642e6c94a613a0c53285abccd"
-          "7794a3d72241808594fb4e6e4d5d2c310ef1cdcbfd34805ca2408f554797a6cfd49d"
-          "0f25ed8927f206acb127e6436e1234902489ec2e7f3058e26c0eba80341bc7ad0da8"
-          "b8bd80bd1b43c9099269e3f8b68445c69b79d8cf5693d4a0d47a44f9e9114dbb3399"
-          "2d2ea9d3b5b86e4ea57a44a638848de4ac365bb6bb7855305ade62b07ebf0954d70b"
-          "7c2fb5e6fcc154c7a36fb1756df5f20a84d35696627ebf22d44f40f805c0878ad110"
-          "bc17dcd66821084ca87902e05bc0afa61161086956b85a6ea900d35c7784d4c361a4"
-          "3fe294e267d5762408be58962cdb4f45a9c0efd7d2335916df3acb98ccfbcf5ee395"
-          "30540e5f3d3c5f3326a9a536d7bfa37aae2b143e2499b81bf0670e3a418c26c7dc82"
-          "b293d9bd182dd6435670514237df88d8286e19ce93e0a0db2790",
-      },
-      {
-          "b97fd51f4e4eaa40c7a2853010fc46be5be2f43b9520ea0c533b68f728c978a2",
-          214,
-          "ced3a43193caceb269d2517f4ecb892bb7d57d7201869e28e669b0b17d1c44d286e0"
-          "2734e2210ea9009565832975cc6303b9b6008fe1165b99ae5f1b29962ef042ebad8b"
-          "676d7433ed2fe0d0d6f4f32b2cb4c519da61552328c2caea799bb2fd907308173a1c"
-          "d2b798fb0df7d2eaf2ff0be733af74f42889e211843fc80b09952ae7eb246725b91d"
-          "31c1f7a5503fdf3bc9c269c76519cf2dc3225e862436b587bb74adbad88c773056cf"
-          "ea3bddb1f6533c01125eeae0986e5c817359912c9d0472bf8320b824ee097f82a8e0"
-          "5b9f53a5be7d153225de",
-      },
-      {
-          "f0fecf766e4f7522568b3be71843cce3e5fcb10ea96b1a236c8c0a71c9ad55c9",
-          159,
-          "8aca4de41275f5c4102f66266d70cff1a2d56f58df8d12061c64cb6cd8f616a5bf19"
-          "c2bb3c91585c695326f561a2d0eb4eef2e202d82dcc9089e4bee82b62a199a11963c"
-          "d08987d3abd5914def2cdd3c1e4748d46b654f338e3959121e869c18d5327e88090d"
-          "0ba0ac6762a2b14514cc505af7499f1a22f421dbe978494f9ffe1e88f1c59228f21d"
-          "a5bc9fcc911d022300a443bca17258bdd6cfbbf52fde61",
-      },
-      {
-          "5c4f16043c0084bf98499fc7dc4d674ce9c730b7135210acdbf5e41d3dcf317b",
-          87,
-          "01bbc193d0ee2396a7d8267ad63f18149667b31d8f7f48c8bb0c634755febc9ef1a7"
-          "9e93c475f6cd137ee37d4dc243ea2fdcdc0d098844af2208337b7bbf6930e39e74e2"
-          "3952ac1a19b4d38b83810a10c3b069e4fafb06",
-      },
-      {
-          "14b61fc981f7d9449b7b6a2d57eb48cc8f7896f4dced2005291b2a2f38cb4a63",
-          358,
-          "cbc1709a531438d5ead32cea20a9e4ddc0101ec555ab42b2e378145013cc05a97b9e"
-          "2c43c89bfa63ae5e9e9ce1fc022035c6b68f0a906ee1f53396d9dbe41cb2bc4bfeb1"
-          "44b005b0f40e0fec872d9c4aca9929ba3cbacd84c58ab43c26f10d345a24692bbd55"
-          "a76506876768e8e32a461bf160cee953da88920d36ad4aff6eea7126aa6f44a7a6fc"
-          "e770ce43f0f90a20590bdaad3ffcda30ca8e3700f832c62caa5df030c16bcf74aff4"
-          "92466f781eb69863a80663535fc154abd7cfdd02eef1019221cf608b9780f807e507"
-          "fbbf559b1dfe4e971b4d08fe45263a3c697ba90f9f71bec97e12438b4b12f6a84ab6"
-          "6872b888097089d76c9c2502d9ed2eece6bef8eee1d439782e218f5cc75d38f98860"
-          "12cdcb4bbe6caf812e97c5a336bcceae38b1109e3243a291ce23d097aaee7d9a711d"
-          "e6886749a7a6d15d7e7cbc4a51b1b4da9fcf139e4a6fd7dc0bc017db624b17fc9b8f"
-          "847592ed42467c25ad9fe96acbf20c0ffd18",
-      },
-      {
-          "47ec7f3a362becbb110867995a0f066a66152603c4d433f11bf51870c67e2864",
-          354,
-          "0636983353c9ea3f75256ed00b70e8b7cfc6f4e4c0ba3aa9a8da59b6e6ad9dfb5bc2"
-          "c49f48cc0b4237f87dedf34b888e54ecebf1d435bcd4aab72eb4ce39e5262fb68c6f"
-          "86423dac123bf59e903989eda7df4a982822d0831521403cedcfe9a5bbea648bb2e7"
-          "ef8cd81442ea5abe468b3ee8b06376ef8099447255c2fdc1b73af37fe0e0b852ffbc"
-          "9339868db756680db99e6e9837dbd28c39a69f229044ad7ec772524a6e01f679d25f"
-          "dc2e736a2418e5dfd7c2ab1348d0f821b777c975244c6cfc2fca5c36ccae7cf1d07b"
-          "190a9d17a088a1276bd096250b92f53b29b6ef88ef69d744b56fb2ec5078cc0b68a9"
-          "106943ef242b466097b9e29df11eb5cb0c06c29d7917410ba1097215d6aa4dafd90a"
-          "dff0c3e7221b9e8832613bd9aca8bcc6b2aa7b43acedcbc11aee1b5ba56f77a210be"
-          "7cf3485ee813e1126c3eeccd8419bbf22c412cad32cc0fc7a73aca4e379651caac3d"
-          "13d6cf5ca05508fd2d96f3ad94e7",
-      },
-      {
-          "73778e7f1943646a89d3c78909e0afbe584071ba5230546a39cd73e44e36d78a",
-          91,
-          "6217504a26b3395855eab6ddeb79f2e3490d74b80eff343721150ee0c1c02b071867"
-          "43589f93c22a03dc5ed29fb5bf592de0a089763e83e5b95f9dd524d66c8da3e04c18"
-          "14e65e68b2810c1b517648aabc266ad62896c51864a7f4",
-      },
-      {
-          "35ef6868e750cf0c1d5285992c231d93ec644670fb79cf85324067a9f77fde78",
-          185,
-          "0118b7fb15f927a977e0b330b4fa351aeeec299d6ba090eb16e5114fc4a6749e5915"
-          "434a123c112697390c96ea2c26dc613eb5c75f5ecfb6c419317426367e34da0ddc6d"
-          "7b7612cefa70a22fea0025f5186593b22449dab71f90a49f7de7352e54e0c0bd8837"
-          "e661ca2127c3313a7268cafdd5ccfbf3bdd7c974b0e7551a2d96766579ef8d2e1f37"
-          "6af74cd1ab62162fc2dc61a8b7ed4163c1caccf20ed73e284da2ed257ec974eee96b"
-          "502acb2c60a04886465e44debb0317",
-      },
-  };
-
-  uint8_t hash[SHA3_256_DIGEST_LENGTH];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    keccak_256(fromhex(tests[i].data), tests[i].length, hash);
-    ck_assert_mem_eq(hash, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH);
-
-    // Test progressive hashing.
-    size_t part_len = tests[i].length / 2;
-    SHA3_CTX ctx = {0};
-    keccak_256_Init(&ctx);
-    keccak_Update(&ctx, fromhex(tests[i].data), part_len);
-    keccak_Update(&ctx, fromhex(tests[i].data), 0);
-    keccak_Update(&ctx, fromhex(tests[i].data) + part_len,
-                  tests[i].length - part_len);
-    keccak_Final(&ctx, hash);
-    ck_assert_mem_eq(hash, fromhex(tests[i].hash), SHA3_256_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/monero-project/monero/master/tests/hash/tests-extra-blake.txt
-START_TEST(test_blake256) {
-  static const struct {
-    const char *hash;
-    const char *data;
-  } tests[] = {
-      {
-          "716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a",
-          "",
-      },
-      {
-          "e104256a2bc501f459d03fac96b9014f593e22d30f4de525fa680c3aa189eb4f",
-          "cc",
-      },
-      {
-          "8f341148be7e354fdf38b693d8c6b4e0bd57301a734f6fd35cd85b8491c3ddcd",
-          "41fb",
-      },
-      {
-          "bc334d1069099f10c601883ac6f3e7e9787c6aa53171f76a21923cc5ad3ab937",
-          "1f877c",
-      },
-      {
-          "b672a16f53982bab1e77685b71c0a5f6703ffd46a1c834be69f614bd128d658e",
-          "c1ecfdfc",
-      },
-      {
-          "d9134b2899057a7d8d320cc99e3e116982bc99d3c69d260a7f1ed3da8be68d99",
-          "21f134ac57",
-      },
-      {
-          "637923bd29a35aa3ecbbd2a50549fc32c14cf0fdcaf41c3194dd7414fd224815",
-          "c6f50bb74e29",
-      },
-      {
-          "70c092fd5c8c21e9ef4bbc82a5c7819e262a530a748caf285ff0cba891954f1e",
-          "119713cc83eeef",
-      },
-      {
-          "fdf092993edbb7a0dc7ca67f04051bbd14481639da0808947aff8bfab5abed4b",
-          "4a4f202484512526",
-      },
-      {
-          "6f6fc234bf35beae1a366c44c520c59ad5aa70351b5f5085e21e1fe2bfcee709",
-          "1f66ab4185ed9b6375",
-      },
-      {
-          "4fdaf89e2a0e78c000061b59455e0ea93a4445b440e7562c8f0cfa165c93de2e",
-          "eed7422227613b6f53c9",
-      },
-      {
-          "d6b780eee9c811f664393dc2c58b5a68c92b3c9fe9ceb70371d33ece63b5787e",
-          "eaeed5cdffd89dece455f1",
-      },
-      {
-          "d0015071d3e7ed048c764850d76406eceae52b8e2e6e5a2c3aa92ae880485b34",
-          "5be43c90f22902e4fe8ed2d3",
-      },
-      {
-          "9b0207902f9932f7a85c24722e93e31f6ed2c75c406509aa0f2f6d1cab046ce4",
-          "a746273228122f381c3b46e4f1",
-      },
-      {
-          "258020d5b04a814f2b72c1c661e1f5a5c395d9799e5eee8b8519cf7300e90cb1",
-          "3c5871cd619c69a63b540eb5a625",
-      },
-      {
-          "4adae3b55baa907fefc253365fdd99d8398befd0551ed6bf9a2a2784d3c304d1",
-          "fa22874bcc068879e8ef11a69f0722",
-      },
-      {
-          "6dd10d772f8d5b4a96c3c5d30878cd9a1073fa835bfe6d2b924fa64a1fab1711",
-          "52a608ab21ccdd8a4457a57ede782176",
-      },
-      {
-          "0b8741ddf2259d3af2901eb1ae354f22836442c965556f5c1eb89501191cb46a",
-          "82e192e4043ddcd12ecf52969d0f807eed",
-      },
-      {
-          "f48a754ca8193a82643150ab94038b5dd170b4ebd1e0751b78cfb0a98fa5076a",
-          "75683dcb556140c522543bb6e9098b21a21e",
-      },
-      {
-          "5698409ab856b74d9fa5e9b259dfa46001f89041752da424e56e491577b88c86",
-          "06e4efe45035e61faaf4287b4d8d1f12ca97e5",
-      },
-  };
-
-  uint8_t hash[BLAKE256_DIGEST_LENGTH];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t len = strlen(tests[i].data) / 2;
-    blake256(fromhex(tests[i].data), len, hash);
-    ck_assert_mem_eq(hash, fromhex(tests[i].hash), BLAKE256_DIGEST_LENGTH);
-
-    // Test progressive hashing.
-    size_t part_len = len / 2;
-    BLAKE256_CTX ctx;
-    blake256_Init(&ctx);
-    blake256_Update(&ctx, fromhex(tests[i].data), part_len);
-    blake256_Update(&ctx, NULL, 0);
-    blake256_Update(&ctx, fromhex(tests[i].data) + part_len, len - part_len);
-    blake256_Final(&ctx, hash);
-    ck_assert_mem_eq(hash, fromhex(tests[i].hash), BLAKE256_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2b-kat.txt
-START_TEST(test_blake2b) {
-  static const struct {
-    const char *msg;
-    const char *hash;
-  } tests[] = {
-      {
-          "",
-          "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e9"
-          "96e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568",
-      },
-      {
-          "000102",
-          "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e"
-          "364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1",
-      },
-      {
-          "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
-          "22232425262728292a2b2c2d2e2f3031323334353637",
-          "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e7684"
-          "2d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2",
-      },
-      {
-          "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
-          "22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243"
-          "4445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465"
-          "666768696a6b6c6d6e6f",
-          "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c5"
-          "28fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f",
-      },
-  };
-
-  uint8_t key[BLAKE2B_KEY_LENGTH];
-  memcpy(key,
-         fromhex(
-             "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2"
-             "02122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"),
-         BLAKE2B_KEY_LENGTH);
-
-  uint8_t digest[BLAKE2B_DIGEST_LENGTH];
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t msg_len = strlen(tests[i].msg) / 2;
-    blake2b_Key(fromhex(tests[i].msg), msg_len, key, sizeof(key), digest,
-                sizeof(digest));
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), sizeof(digest));
-
-    // Test progressive hashing.
-    size_t part_len = msg_len / 2;
-    BLAKE2B_CTX ctx;
-    ck_assert_int_eq(blake2b_InitKey(&ctx, sizeof(digest), key, sizeof(key)),
-                     0);
-    ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg), part_len), 0);
-    ck_assert_int_eq(blake2b_Update(&ctx, NULL, 0), 0);
-    ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg) + part_len,
-                                    msg_len - part_len),
-                     0);
-    ck_assert_int_eq(blake2b_Final(&ctx, digest, sizeof(digest)), 0);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), BLAKE2B_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-// Blake2b-256 personalized, a la ZCash
-// Test vectors from https://zips.z.cash/zip-0243
-START_TEST(test_blake2bp) {
-  static const struct {
-    const char *msg;
-    const char *personal;
-    const char *hash;
-  } tests[] = {
-      {
-          "",
-          "ZcashPrevoutHash",
-          "d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136",
-      },
-      {
-          "",
-          "ZcashSequencHash",
-          "a5f25f01959361ee6eb56a7401210ee268226f6ce764a4f10b7f29e54db37272",
-
-      },
-      {
-          "e7719811893e0000095200ac6551ac636565b2835a0805750200025151",
-          "ZcashOutputsHash",
-          "ab6f7f6c5ad6b56357b5f37e16981723db6c32411753e28c175e15589172194a",
-      },
-      {
-          "0bbe32a598c22adfb48cef72ba5d4287c0cefbacfd8ce195b4963c34a94bba7a1"
-          "75dae4b090f47a068e227433f9e49d3aa09e356d8d66d0c0121e91a3c4aa3f27fa1b"
-          "63396e2b41d",
-          "ZcashPrevoutHash",
-          "cacf0f5210cce5fa65a59f314292b3111d299e7d9d582753cf61e1e408552ae4",
-      }};
-
-  uint8_t digest[32];
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t msg_len = strlen(tests[i].msg) / 2;
-
-    // Test progressive hashing.
-    size_t part_len = msg_len / 2;
-    BLAKE2B_CTX ctx;
-    ck_assert_int_eq(
-        blake2b_InitPersonal(&ctx, sizeof(digest), tests[i].personal,
-                             strlen(tests[i].personal)),
-        0);
-    ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg), part_len), 0);
-    ck_assert_int_eq(blake2b_Update(&ctx, NULL, 0), 0);
-    ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg) + part_len,
-                                    msg_len - part_len),
-                     0);
-    ck_assert_int_eq(blake2b_Final(&ctx, digest, sizeof(digest)), 0);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), sizeof(digest));
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2s-kat.txt
-START_TEST(test_blake2s) {
-  static const struct {
-    const char *msg;
-    const char *hash;
-  } tests[] = {
-      {
-          "",
-          "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49",
-      },
-      {
-          "000102",
-          "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b",
-      },
-      {
-          "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
-          "22232425262728292a2b2c2d2e2f3031323334353637",
-          "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806",
-      },
-      {
-          "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
-          "22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243"
-          "4445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465"
-          "666768696a6b6c6d6e6f",
-          "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c",
-      },
-  };
-
-  uint8_t key[BLAKE2S_KEY_LENGTH];
-  memcpy(
-      key,
-      fromhex(
-          "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"),
-      BLAKE2S_KEY_LENGTH);
-
-  uint8_t digest[BLAKE2S_DIGEST_LENGTH];
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t msg_len = strlen(tests[i].msg) / 2;
-    blake2s_Key(fromhex(tests[i].msg), msg_len, key, sizeof(key), digest,
-                sizeof(digest));
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), sizeof(digest));
-
-    // Test progressive hashing.
-    size_t part_len = msg_len / 2;
-    BLAKE2S_CTX ctx;
-    ck_assert_int_eq(blake2s_InitKey(&ctx, sizeof(digest), key, sizeof(key)),
-                     0);
-    ck_assert_int_eq(blake2s_Update(&ctx, fromhex(tests[i].msg), part_len), 0);
-    ck_assert_int_eq(blake2s_Update(&ctx, NULL, 0), 0);
-    ck_assert_int_eq(blake2s_Update(&ctx, fromhex(tests[i].msg) + part_len,
-                                    msg_len - part_len),
-                     0);
-    ck_assert_int_eq(blake2s_Final(&ctx, digest, sizeof(digest)), 0);
-    ck_assert_mem_eq(digest, fromhex(tests[i].hash), BLAKE2S_DIGEST_LENGTH);
-  }
-}
-END_TEST
-
-#include <stdio.h>
-
-START_TEST(test_chacha_drbg) {
-  char entropy[] =
-      "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d";
-  char nonce[] = "0e66f71edc43e42a45ad3c6fc6cdc4df";
-  char reseed[] =
-      "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552";
-  char expected[] =
-      "e172c5d18f3e8c77e9f66f9e1c24560772117161a9a0a237ab490b0769ad5d910f5dfb36"
-      "22edc06c18be0495c52588b200893d90fd80ff2149ead0c45d062c90f5890149c0f9591c"
-      "41bf4110865129a0fe524f210cca1340bd16f71f57906946cbaaf1fa863897d70d203b5a"
-      "f9996f756eec08861ee5875f9d915adcddc38719";
-  uint8_t result[128];
-  uint8_t null_bytes[128] = {0};
-
-  uint8_t nonce_bytes[16];
-  memcpy(nonce_bytes, fromhex(nonce), sizeof(nonce_bytes));
-  CHACHA_DRBG_CTX ctx;
-  chacha_drbg_init(&ctx, fromhex(entropy), strlen(entropy) / 2, nonce_bytes,
-                   strlen(nonce) / 2);
-  chacha_drbg_reseed(&ctx, fromhex(reseed), strlen(reseed) / 2, NULL, 0);
-  chacha_drbg_generate(&ctx, result, sizeof(result));
-  chacha_drbg_generate(&ctx, result, sizeof(result));
-  ck_assert_mem_eq(result, fromhex(expected), sizeof(result));
-
-  for (size_t i = 0; i <= sizeof(result); ++i) {
-    chacha_drbg_init(&ctx, fromhex(entropy), strlen(entropy) / 2, nonce_bytes,
-                     strlen(nonce) / 2);
-    chacha_drbg_reseed(&ctx, fromhex(reseed), strlen(reseed) / 2, NULL, 0);
-    chacha_drbg_generate(&ctx, result, sizeof(result) - 13);
-    memset(result, 0, sizeof(result));
-    chacha_drbg_generate(&ctx, result, i);
-    ck_assert_mem_eq(result, fromhex(expected), i);
-    ck_assert_mem_eq(result + i, null_bytes, sizeof(result) - i);
-  }
-}
-END_TEST
-
-START_TEST(test_pbkdf2_hmac_sha256) {
-  uint8_t k[64];
-
-  // test vectors from
-  // https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
-  pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4,
-                     1, k, 32);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"),
-      32);
-
-  pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4,
-                     2, k, 32);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"),
-      32);
-
-  pbkdf2_hmac_sha256((const uint8_t *)"password", 8, (const uint8_t *)"salt", 4,
-                     4096, k, 32);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"),
-      32);
-
-  pbkdf2_hmac_sha256((const uint8_t *)"passwordPASSWORDpassword", 3 * 8,
-                     (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt",
-                     9 * 4, 4096, k, 40);
-  ck_assert_mem_eq(k,
-                   fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4"
-                           "e2a1fb8dd53e1c635518c7dac47e9"),
-                   40);
-
-  pbkdf2_hmac_sha256((const uint8_t *)"pass\x00word", 9,
-                     (const uint8_t *)"sa\x00lt", 5, 4096, k, 16);
-  ck_assert_mem_eq(k, fromhex("89b69d0516f829893c696226650a8687"), 16);
-
-  // test vector from https://tools.ietf.org/html/rfc7914.html#section-11
-  pbkdf2_hmac_sha256((const uint8_t *)"passwd", 6, (const uint8_t *)"salt", 4,
-                     1, k, 64);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca"
-          "9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"),
-      64);
-}
-END_TEST
-
-// test vectors from
-// http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors
-START_TEST(test_pbkdf2_hmac_sha512) {
-  uint8_t k[64];
-
-  pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 1, k,
-                     64);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d"
-          "470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"),
-      64);
-
-  pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 2, k,
-                     64);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76c"
-          "ab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"),
-      64);
-
-  pbkdf2_hmac_sha512((uint8_t *)"password", 8, (const uint8_t *)"salt", 4, 4096,
-                     k, 64);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f"
-          "30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"),
-      64);
-
-  pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3 * 8,
-                     (const uint8_t *)"saltSALTsaltSALTsaltSALTsaltSALTsalt",
-                     9 * 4, 4096, k, 64);
-  ck_assert_mem_eq(
-      k,
-      fromhex(
-          "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b"
-          "59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"),
-      64);
-}
-END_TEST
-
-START_TEST(test_hmac_drbg) {
-  char entropy[] =
-      "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d";
-  char nonce[] = "0e66f71edc43e42a45ad3c6fc6cdc4df";
-  char reseed[] =
-      "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552";
-  char expected[] =
-      "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215"
-      "000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9e"
-      "c3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6"
-      "a38cc5b6499dc43f7f2bd09e1e0f8f5885935124";
-  uint8_t result[128];
-  uint8_t null_bytes[128] = {0};
-
-  uint8_t nonce_bytes[16];
-  memcpy(nonce_bytes, fromhex(nonce), sizeof(nonce_bytes));
-  HMAC_DRBG_CTX ctx;
-  hmac_drbg_init(&ctx, fromhex(entropy), strlen(entropy) / 2, nonce_bytes,
-                 strlen(nonce) / 2);
-  hmac_drbg_reseed(&ctx, fromhex(reseed), strlen(reseed) / 2, NULL, 0);
-  hmac_drbg_generate(&ctx, result, sizeof(result));
-  hmac_drbg_generate(&ctx, result, sizeof(result));
-  ck_assert_mem_eq(result, fromhex(expected), sizeof(result));
-
-  for (size_t i = 0; i <= sizeof(result); ++i) {
-    hmac_drbg_init(&ctx, fromhex(entropy), strlen(entropy) / 2, nonce_bytes,
-                   strlen(nonce) / 2);
-    hmac_drbg_reseed(&ctx, fromhex(reseed), strlen(reseed) / 2, NULL, 0);
-    hmac_drbg_generate(&ctx, result, sizeof(result) - 13);
-    memset(result, 0, sizeof(result));
-    hmac_drbg_generate(&ctx, result, i);
-    ck_assert_mem_eq(result, fromhex(expected), i);
-    ck_assert_mem_eq(result + i, null_bytes, sizeof(result) - i);
-  }
-}
-END_TEST
-
-START_TEST(test_mnemonic) {
-  static const char *vectors[] = {
-      "00000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon about",
-      "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a698"
-      "7599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "yellow",
-      "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe12"
-      "96106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607",
-      "80808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage above",
-      "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12"
-      "eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8",
-      "ffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
-      "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a1333257291"
-      "7f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069",
-      "000000000000000000000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon agent",
-      "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a"
-      "565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal will",
-      "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c39"
-      "2d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd",
-      "808080808080808080808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter always",
-      "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ff"
-      "b796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65",
-      "ffffffffffffffffffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "when",
-      "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b433"
-      "48d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528",
-      "0000000000000000000000000000000000000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon art",
-      "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d"
-      "73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal winner thank year wave sausage "
-      "worth title",
-      "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad"
-      "717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87",
-      "8080808080808080808080808080808080808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter advice cage absurd "
-      "amount doctor acoustic bless",
-      "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af"
-      "0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f",
-      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "zoo zoo zoo zoo zoo vote",
-      "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a"
-      "5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad",
-      "77c2b00716cec7213839159e404db50d",
-      "jelly better achieve collect unaware mountain thought cargo oxygen act "
-      "hood bridge",
-      "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f67"
-      "2a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff",
-      "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b",
-      "renew stay biology evidence goat welcome casual join adapt armor "
-      "shuffle fault little machine walk stumble urge swap",
-      "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c"
-      "69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5",
-      "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982",
-      "dignity pass list indicate nasty swamp pool script soccer toe leaf "
-      "photo multiply desk host tomato cradle drill spread actor shine dismiss "
-      "champion exotic",
-      "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20"
-      "af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67",
-      "0460ef47585604c5660618db2e6a7e7f",
-      "afford alter spike radar gate glance object seek swamp infant panel "
-      "yellow",
-      "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f"
-      "8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4",
-      "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f",
-      "indicate race push merry suffer human cruise dwarf pole review arch "
-      "keep canvas theme poem divorce alter left",
-      "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe"
-      "2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba",
-      "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416",
-      "clutch control vehicle tonight unusual clog visa ice plunge glimpse "
-      "recipe series open hour vintage deposit universe tip job dress radar "
-      "refuse motion taste",
-      "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f8"
-      "6360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449",
-      "eaebabb2383351fd31d703840b32e9e2",
-      "turtle front uncle idea crush write shrug there lottery flower risk "
-      "shell",
-      "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c40"
-      "4f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c",
-      "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78",
-      "kiss carry display unusual confirm curtain upgrade antique rotate hello "
-      "void custom frequent obey nut hole price segment",
-      "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b0794"
-      "03485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79",
-      "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef",
-      "exile ask congress lamp submit jacket era scheme attend cousin alcohol "
-      "catch course end lucky hurt sentence oven short ball bird grab wing top",
-      "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b1"
-      "4d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c",
-      "18ab19a9f54a9274f03e5209a2ac8a91",
-      "board flee heavy tunnel powder denial science ski answer betray cargo "
-      "cat",
-      "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe00"
-      "5831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8",
-      "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4",
-      "board blade invite damage undo sun mimic interest slam gaze truly "
-      "inherit resist great inject rocket museum chief",
-      "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07"
-      "c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9",
-      "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419",
-      "beyond stage sleep clip because twist token leaf atom beauty genius "
-      "food business side grid unable middle armed observe pair crouch tonight "
-      "away coconut",
-      "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb8"
-      "6a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd",
-      0,
-      0,
-      0,
-  };
-
-  const char **a, **b, **c, *m;
-  uint8_t seed[64];
-
-  a = vectors;
-  b = vectors + 1;
-  c = vectors + 2;
-  while (*a && *b && *c) {
-    m = mnemonic_from_data(fromhex(*a), strlen(*a) / 2);
-    ck_assert_str_eq(m, *b);
-    mnemonic_to_seed(m, "TREZOR", seed, 0);
-    ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2);
-#if USE_BIP39_CACHE
-    // try second time to check whether caching results work
-    mnemonic_to_seed(m, "TREZOR", seed, 0);
-    ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2);
-#endif
-    a += 3;
-    b += 3;
-    c += 3;
-  }
-}
-END_TEST
-
-START_TEST(test_mnemonic_check) {
-  static const char *vectors_ok[] = {
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon about",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "yellow",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage above",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon agent",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal will",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter always",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "when",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon art",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal winner thank year wave sausage "
-      "worth title",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter advice cage absurd "
-      "amount doctor acoustic bless",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "zoo zoo zoo zoo zoo vote",
-      "jelly better achieve collect unaware mountain thought cargo oxygen act "
-      "hood bridge",
-      "renew stay biology evidence goat welcome casual join adapt armor "
-      "shuffle fault little machine walk stumble urge swap",
-      "dignity pass list indicate nasty swamp pool script soccer toe leaf "
-      "photo multiply desk host tomato cradle drill spread actor shine dismiss "
-      "champion exotic",
-      "afford alter spike radar gate glance object seek swamp infant panel "
-      "yellow",
-      "indicate race push merry suffer human cruise dwarf pole review arch "
-      "keep canvas theme poem divorce alter left",
-      "clutch control vehicle tonight unusual clog visa ice plunge glimpse "
-      "recipe series open hour vintage deposit universe tip job dress radar "
-      "refuse motion taste",
-      "turtle front uncle idea crush write shrug there lottery flower risk "
-      "shell",
-      "kiss carry display unusual confirm curtain upgrade antique rotate hello "
-      "void custom frequent obey nut hole price segment",
-      "exile ask congress lamp submit jacket era scheme attend cousin alcohol "
-      "catch course end lucky hurt sentence oven short ball bird grab wing top",
-      "board flee heavy tunnel powder denial science ski answer betray cargo "
-      "cat",
-      "board blade invite damage undo sun mimic interest slam gaze truly "
-      "inherit resist great inject rocket museum chief",
-      "beyond stage sleep clip because twist token leaf atom beauty genius "
-      "food business side grid unable middle armed observe pair crouch tonight "
-      "away coconut",
-      0,
-  };
-  static const char *vectors_fail[] = {
-      "above abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon about",
-      "above winner thank year wave sausage worth useful legal winner thank "
-      "yellow",
-      "above advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage above",
-      "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
-      "above abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon agent",
-      "above winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal will",
-      "above advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter always",
-      "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "when",
-      "above abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon art",
-      "above winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal winner thank year wave sausage "
-      "worth title",
-      "above advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter advice cage absurd "
-      "amount doctor acoustic bless",
-      "above zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "zoo zoo zoo zoo zoo zoo vote",
-      "above better achieve collect unaware mountain thought cargo oxygen act "
-      "hood bridge",
-      "above stay biology evidence goat welcome casual join adapt armor "
-      "shuffle fault little machine walk stumble urge swap",
-      "above pass list indicate nasty swamp pool script soccer toe leaf photo "
-      "multiply desk host tomato cradle drill spread actor shine dismiss "
-      "champion exotic",
-      "above alter spike radar gate glance object seek swamp infant panel "
-      "yellow",
-      "above race push merry suffer human cruise dwarf pole review arch keep "
-      "canvas theme poem divorce alter left",
-      "above control vehicle tonight unusual clog visa ice plunge glimpse "
-      "recipe series open hour vintage deposit universe tip job dress radar "
-      "refuse motion taste",
-      "above front uncle idea crush write shrug there lottery flower risk "
-      "shell",
-      "above carry display unusual confirm curtain upgrade antique rotate "
-      "hello void custom frequent obey nut hole price segment",
-      "above ask congress lamp submit jacket era scheme attend cousin alcohol "
-      "catch course end lucky hurt sentence oven short ball bird grab wing top",
-      "above flee heavy tunnel powder denial science ski answer betray cargo "
-      "cat",
-      "above blade invite damage undo sun mimic interest slam gaze truly "
-      "inherit resist great inject rocket museum chief",
-      "above stage sleep clip because twist token leaf atom beauty genius food "
-      "business side grid unable middle armed observe pair crouch tonight away "
-      "coconut",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon about",
-      "winner thank year wave sausage worth useful legal winner thank yellow",
-      "advice cage absurd amount doctor acoustic avoid letter advice cage "
-      "above",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon agent",
-      "winner thank year wave sausage worth useful legal winner thank year "
-      "wave sausage worth useful legal will",
-      "advice cage absurd amount doctor acoustic avoid letter advice cage "
-      "absurd amount doctor acoustic avoid letter always",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon art",
-      "winner thank year wave sausage worth useful legal winner thank year "
-      "wave sausage worth useful legal winner thank year wave sausage worth "
-      "title",
-      "advice cage absurd amount doctor acoustic avoid letter advice cage "
-      "absurd amount doctor acoustic avoid letter advice cage absurd amount "
-      "doctor acoustic bless",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "zoo zoo zoo zoo vote",
-      "better achieve collect unaware mountain thought cargo oxygen act hood "
-      "bridge",
-      "stay biology evidence goat welcome casual join adapt armor shuffle "
-      "fault little machine walk stumble urge swap",
-      "pass list indicate nasty swamp pool script soccer toe leaf photo "
-      "multiply desk host tomato cradle drill spread actor shine dismiss "
-      "champion exotic",
-      "alter spike radar gate glance object seek swamp infant panel yellow",
-      "race push merry suffer human cruise dwarf pole review arch keep canvas "
-      "theme poem divorce alter left",
-      "control vehicle tonight unusual clog visa ice plunge glimpse recipe "
-      "series open hour vintage deposit universe tip job dress radar refuse "
-      "motion taste",
-      "front uncle idea crush write shrug there lottery flower risk shell",
-      "carry display unusual confirm curtain upgrade antique rotate hello void "
-      "custom frequent obey nut hole price segment",
-      "ask congress lamp submit jacket era scheme attend cousin alcohol catch "
-      "course end lucky hurt sentence oven short ball bird grab wing top",
-      "flee heavy tunnel powder denial science ski answer betray cargo cat",
-      "blade invite damage undo sun mimic interest slam gaze truly inherit "
-      "resist great inject rocket museum chief",
-      "stage sleep clip because twist token leaf atom beauty genius food "
-      "business side grid unable middle armed observe pair crouch tonight away "
-      "coconut",
-      0,
-  };
-
-  const char **m;
-  int r;
-  m = vectors_ok;
-  while (*m) {
-    r = mnemonic_check(*m);
-    ck_assert_int_eq(r, 1);
-    m++;
-  }
-  m = vectors_fail;
-  while (*m) {
-    r = mnemonic_check(*m);
-    ck_assert_int_eq(r, 0);
-    m++;
-  }
-}
-END_TEST
-
-START_TEST(test_mnemonic_to_bits) {
-  static const char *vectors[] = {
-      "00000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon about",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "yellow",
-      "80808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage above",
-      "ffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
-      "000000000000000000000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon agent",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal will",
-      "808080808080808080808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter always",
-      "ffffffffffffffffffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "when",
-      "0000000000000000000000000000000000000000000000000000000000000000",
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon art",
-      "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
-      "legal winner thank year wave sausage worth useful legal winner thank "
-      "year wave sausage worth useful legal winner thank year wave sausage "
-      "worth title",
-      "8080808080808080808080808080808080808080808080808080808080808080",
-      "letter advice cage absurd amount doctor acoustic avoid letter advice "
-      "cage absurd amount doctor acoustic avoid letter advice cage absurd "
-      "amount doctor acoustic bless",
-      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo "
-      "zoo zoo zoo zoo zoo vote",
-      "77c2b00716cec7213839159e404db50d",
-      "jelly better achieve collect unaware mountain thought cargo oxygen act "
-      "hood bridge",
-      "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b",
-      "renew stay biology evidence goat welcome casual join adapt armor "
-      "shuffle fault little machine walk stumble urge swap",
-      "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982",
-      "dignity pass list indicate nasty swamp pool script soccer toe leaf "
-      "photo multiply desk host tomato cradle drill spread actor shine dismiss "
-      "champion exotic",
-      "0460ef47585604c5660618db2e6a7e7f",
-      "afford alter spike radar gate glance object seek swamp infant panel "
-      "yellow",
-      "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f",
-      "indicate race push merry suffer human cruise dwarf pole review arch "
-      "keep canvas theme poem divorce alter left",
-      "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416",
-      "clutch control vehicle tonight unusual clog visa ice plunge glimpse "
-      "recipe series open hour vintage deposit universe tip job dress radar "
-      "refuse motion taste",
-      "eaebabb2383351fd31d703840b32e9e2",
-      "turtle front uncle idea crush write shrug there lottery flower risk "
-      "shell",
-      "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78",
-      "kiss carry display unusual confirm curtain upgrade antique rotate hello "
-      "void custom frequent obey nut hole price segment",
-      "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef",
-      "exile ask congress lamp submit jacket era scheme attend cousin alcohol "
-      "catch course end lucky hurt sentence oven short ball bird grab wing top",
-      "18ab19a9f54a9274f03e5209a2ac8a91",
-      "board flee heavy tunnel powder denial science ski answer betray cargo "
-      "cat",
-      "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4",
-      "board blade invite damage undo sun mimic interest slam gaze truly "
-      "inherit resist great inject rocket museum chief",
-      "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419",
-      "beyond stage sleep clip because twist token leaf atom beauty genius "
-      "food business side grid unable middle armed observe pair crouch tonight "
-      "away coconut",
-      0,
-      0,
-  };
-
-  const char **a, **b;
-  uint8_t mnemonic_bits[64];
-
-  a = vectors;
-  b = vectors + 1;
-  while (*a && *b) {
-    int mnemonic_bits_len = mnemonic_to_bits(*b, mnemonic_bits);
-    ck_assert_int_eq(mnemonic_bits_len % 33, 0);
-    mnemonic_bits_len = mnemonic_bits_len * 4 / 33;
-    ck_assert_uint_eq((size_t)mnemonic_bits_len, strlen(*a) / 2);
-    ck_assert_mem_eq(mnemonic_bits, fromhex(*a), mnemonic_bits_len);
-    a += 2;
-    b += 2;
-  }
-}
-END_TEST
-
-START_TEST(test_mnemonic_find_word) {
-  ck_assert_int_eq(-1, mnemonic_find_word("aaaa"));
-  ck_assert_int_eq(-1, mnemonic_find_word("zzzz"));
-  for (int i = 0; i < BIP39_WORD_COUNT; i++) {
-    const char *word = mnemonic_get_word(i);
-    int index = mnemonic_find_word(word);
-    ck_assert_int_eq(i, index);
-  }
-}
-END_TEST
-
-START_TEST(test_slip39_get_word) {
-  static const struct {
-    const int index;
-    const char *expected_word;
-  } vectors[] = {{573, "member"},
-                 {0, "academic"},
-                 {1023, "zero"},
-                 {245, "drove"},
-                 {781, "satoshi"}};
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); i++) {
-    const char *a = get_word(vectors[i].index);
-    ck_assert_str_eq(a, vectors[i].expected_word);
-  }
-}
-END_TEST
-
-START_TEST(test_slip39_word_index) {
-  uint16_t index;
-  static const struct {
-    const char *word;
-    bool expected_result;
-    uint16_t expected_index;
-  } vectors[] = {{"academic", true, 0},
-                 {"zero", true, 1023},
-                 {"drove", true, 245},
-                 {"satoshi", true, 781},
-                 {"member", true, 573},
-                 // 9999 value is never checked since the word is not in list
-                 {"fakeword", false, 9999}};
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); i++) {
-    bool result = word_index(&index, vectors[i].word, strlen(vectors[i].word));
-    ck_assert_int_eq(result, vectors[i].expected_result);
-    if (result) {
-      ck_assert_uint_eq(index, vectors[i].expected_index);
-    }
-  }
-}
-END_TEST
-
-START_TEST(test_slip39_word_completion_mask) {
-  static const struct {
-    const uint16_t prefix;
-    const uint16_t expected_mask;
-  } vectors[] = {
-      {12, 0xFD},     // 011111101
-      {21, 0xF8},     // 011111000
-      {75, 0xAD},     // 010101101
-      {4, 0x1F7},     // 111110111
-      {738, 0x6D},    // 001101101
-      {9, 0x6D},      // 001101101
-      {0, 0x1FF},     // 111111111
-      {10, 0x00},     // 000000000
-      {255, 0x00},    // 000000000
-      {203, 0x00},    // 000000000
-      {9999, 0x00},   // 000000000
-      {20000, 0x00},  // 000000000
-  };
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); i++) {
-    uint16_t mask = slip39_word_completion_mask(vectors[i].prefix);
-    ck_assert_uint_eq(mask, vectors[i].expected_mask);
-  }
-}
-END_TEST
-
-START_TEST(test_slip39_sequence_to_word) {
-  static const struct {
-    const uint16_t prefix;
-    const char *expected_word;
-  } vectors[] = {
-      {7945, "swimming"}, {646, "pipeline"}, {5, "laden"},  {34, "fiber"},
-      {62, "ocean"},      {0, "academic"},   {10, NULL},    {255, NULL},
-      {203, NULL},        {9999, NULL},      {20000, NULL},
-  };
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); i++) {
-    const char *word = button_sequence_to_word(vectors[i].prefix);
-    if (vectors[i].expected_word != NULL) {
-      ck_assert_str_eq(word, vectors[i].expected_word);
-    } else {
-      ck_assert_ptr_eq(word, NULL);
-    }
-  }
-}
-END_TEST
-
-START_TEST(test_slip39_word_completion) {
-  const char t9[] = {1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5,
-                     6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9};
-  for (size_t i = 0; i < WORDS_COUNT; ++i) {
-    const char *word = slip39_wordlist[i];
-    uint16_t prefix = t9[word[0] - 'a'];
-    for (size_t j = 1; j < 4; ++j) {
-      uint16_t mask = slip39_word_completion_mask(prefix);
-      uint8_t next = t9[word[j] - 'a'];
-      ck_assert_uint_ne(mask & (1 << (next - 1)), 0);
-      prefix = prefix * 10 + next;
-    }
-    ck_assert_str_eq(button_sequence_to_word(prefix), word);
-  }
-}
-END_TEST
-
-START_TEST(test_shamir) {
-#define SHAMIR_MAX_COUNT 16
-  static const struct {
-    const uint8_t result[SHAMIR_MAX_LEN];
-    uint8_t result_index;
-    const uint8_t share_indices[SHAMIR_MAX_COUNT];
-    const uint8_t share_values[SHAMIR_MAX_COUNT][SHAMIR_MAX_LEN];
-    uint8_t share_count;
-    size_t len;
-    bool ret;
-  } vectors[] = {{{7,   151, 168, 57,  186, 104, 218, 21, 209, 96,  106,
-                   152, 252, 35,  210, 208, 43,  47,  13, 21,  142, 122,
-                   24,  42,  149, 192, 95,  24,  240, 24, 148, 110},
-                  0,
-                  {2},
-                  {
-                      {7,   151, 168, 57,  186, 104, 218, 21, 209, 96,  106,
-                       152, 252, 35,  210, 208, 43,  47,  13, 21,  142, 122,
-                       24,  42,  149, 192, 95,  24,  240, 24, 148, 110},
-                  },
-                  1,
-                  32,
-                  true},
-
-                 {{53},
-                  255,
-                  {14, 10, 1, 13, 8, 7, 3, 11, 9, 4, 6, 0, 5, 12, 15, 2},
-                  {
-                      {114},
-                      {41},
-                      {116},
-                      {67},
-                      {198},
-                      {109},
-                      {232},
-                      {39},
-                      {90},
-                      {241},
-                      {156},
-                      {75},
-                      {46},
-                      {181},
-                      {144},
-                      {175},
-                  },
-                  16,
-                  1,
-                  true},
-
-                 {{91, 188, 226, 91, 254, 197, 225},
-                  1,
-                  {5, 1, 10},
-                  {
-                      {129, 18, 104, 86, 236, 73, 176},
-                      {91, 188, 226, 91, 254, 197, 225},
-                      {69, 53, 151, 204, 224, 37, 19},
-                  },
-                  3,
-                  7,
-                  true},
-
-                 {{0},
-                  1,
-                  {5, 1, 1},
-                  {
-                      {129, 18, 104, 86, 236, 73, 176},
-                      {91, 188, 226, 91, 254, 197, 225},
-                      {69, 53, 151, 204, 224, 37, 19},
-                  },
-                  3,
-                  7,
-                  false},
-
-                 {{0},
-                  255,
-                  {3, 12, 3},
-                  {
-                      {100, 176, 99, 142, 115, 192, 138},
-                      {54, 139, 99, 172, 29, 137, 58},
-                      {216, 119, 222, 40, 87, 25, 147},
-                  },
-                  3,
-                  7,
-                  false},
-
-                 {{163, 120, 30, 243, 179, 172, 196, 137, 119, 17},
-                  3,
-                  {1, 0, 12},
-                  {{80, 180, 198, 131, 111, 251, 45, 181, 2, 242},
-                   {121, 9, 79, 98, 132, 164, 9, 165, 19, 230},
-                   {86, 52, 173, 138, 189, 223, 122, 102, 248, 157}},
-                  3,
-                  10,
-                  true}};
-
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); ++i) {
-    uint8_t result[SHAMIR_MAX_LEN];
-    const uint8_t *share_values[SHAMIR_MAX_COUNT];
-    for (size_t j = 0; j < vectors[i].share_count; ++j) {
-      share_values[j] = vectors[i].share_values[j];
-    }
-    ck_assert_int_eq(shamir_interpolate(result, vectors[i].result_index,
-                                        vectors[i].share_indices, share_values,
-                                        vectors[i].share_count, vectors[i].len),
-                     vectors[i].ret);
-    if (vectors[i].ret == true) {
-      ck_assert_mem_eq(result, vectors[i].result, vectors[i].len);
-    }
-  }
-}
-END_TEST
-
-START_TEST(test_address) {
-  char address[36];
-  uint8_t pub_key[65];
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"),
-      33);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "139MaMHp3Vjo8o4x8N1ZLWEtovLGvBsg6s");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mhfJsQNnrXB3uuYZqvywARTDfuvyjg4RBh");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "MxiimznnxsqMfLKTQBL8Z2PoY9jKpjgkCu");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LMNJqZbe89yrPbm7JVzrcXJf28hZ1rKPaH");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FXK52G2BbzRLaQ651U12o23DU5cEQdhvU6");
-  ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                                address, sizeof(address));
-  ck_assert_str_eq(address, "34PyTHn74syS796eTgsyoLfwoBC3cwLn6p");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"),
-      33);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "19Ywfm3witp6C1yBMy4NRYHY2347WCRBfQ");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mp4txp8vXvFLy8So5Y2kFTVrt2epN6YzdP");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "N58JsQYveGueiZDgdnNwe4SSkGTAToutAY");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LTmtvyMmoZ49SpfLY73fhZMJEFRPdyohKh");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "Fdif7fnKHPVddczJF53qt45rgCL51yWN6x");
-  ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                                address, sizeof(address));
-  ck_assert_str_eq(address, "35trq6eeuHf6VL9L8pQv46x3vegHnHoTuB");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"),
-      33);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "1FWE2bn3MWhc4QidcF6AvEWpK77sSi2cAP");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mv2BKes2AY8rqXCFKp4Yk9j9B6iaMfWRLN");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "NB5bEFH2GtoAawy8t4Qk8kfj3LWvQs3MhB");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LZjBHp5sSAwfKDQnnP5UCFaaXKV9YheGxQ");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FjfwUWWQv1P9W1jkVM5eNkK8yGPq5XyZZy");
-  ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                                address, sizeof(address));
-  ck_assert_str_eq(address, "3456DYaKUWuY6RWWw8Hp5CftHLcQN29h9Y");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"),
-      33);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "1yrZb8dhdevoqpUEGi2tUccUEeiMKeLcs");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mgVoreDcWf6BaxJ5wqgQiPpwLEFRLSr8U8");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "MwZDmEdcd1kVLP4yW62c6zmXCU3mNbveDo");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LLCopoSTnHtz4eWdQQhLAVgNgT1zTi4QBK");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FW9a1Vs1G8LUFSqb7NhWLzQw8PvfwAxmxA");
-  ecdsa_get_address_segwit_p2sh(pub_key, 5, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                                address, sizeof(address));
-  ck_assert_str_eq(address, "3DBU4tJ9tkMR9fnmCtjW48kjvseoNLQZXd");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054"
-          "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"),
-      65);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "194SZbL75xCCGBbKtMsyWLE5r9s2V6mhVM");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "moaPreR5tydT3J4wbvrMLFSQi9TjPCiZc6");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "N4domEq61LHkniqqABCYirNzaPG5NRU8GH");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LTHPpodwAcSFWzHV4VsGnMHr4NEJajMnKX");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FdEA1W4UeSsjhncSmTsSxr2QWK8z2xGkjc");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3"
-          "961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"),
-      65);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "1A2WfBD4BJFwYHFPc5KgktqtbdJLBuVKc4");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mpYTxEJ2zKhCKPj1KeJ4ap4DTcu39T3uzD");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "N5bsrpi36gMW4pVtsteFyQzoKrhPE7nkxK");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LUFTvPWtFxVzo5wYnDJz2uueoqfcMYiuxH");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FeCE75wRjnwUytGWVBKADQeDFnaHpJ8t3B");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2"
-          "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"),
-      65);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "19J81hrPnQxg9UGx45ibTieCkb2ttm8CLL");
-  ecdsa_get_address(pub_key, 111, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "mop5JkwNbSPvvakZmegyHdrXcadbjLazww");
-  ecdsa_get_address(pub_key, 52, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "N4sVDMMNho4Eg1XTKu3AgEo7UpRwq3aNbn");
-  ecdsa_get_address(pub_key, 48, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "LTX5GvADs5CjQGy7EDhtjjhxxoQB2Uhicd");
-  ecdsa_get_address(pub_key, 36, HASHER_SHA2_RIPEMD, HASHER_GROESTLD_TRUNC,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "FdTqTcamLueDb5J4wBi4vESXQkJrS54H6k");
-}
-END_TEST
-
-START_TEST(test_pubkey_validity) {
-  uint8_t pub_key[65];
-  curve_point pub;
-  int res;
-  const ecdsa_curve *curve = &secp256k1;
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"),
-      33);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"),
-      33);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"),
-      33);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"),
-      33);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054"
-          "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"),
-      65);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3"
-          "961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"),
-      65);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2"
-          "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"),
-      65);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 1);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2"
-          "a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf00000000"),
-      65);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 0);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2"
-          "a59ebddbdac9e87b816307a7ed5b8211111111111111111111111111111111"),
-      65);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 0);
-
-  memcpy(pub_key, fromhex("00"), 1);
-  res = ecdsa_read_pubkey(curve, pub_key, &pub);
-  ck_assert_int_eq(res, 0);
-}
-END_TEST
-
-START_TEST(test_pubkey_uncompress) {
-  uint8_t pub_key[65];
-  uint8_t uncompressed[65];
-  int res;
-  const ecdsa_curve *curve = &secp256k1;
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"),
-      33);
-  res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      uncompressed,
-      fromhex(
-          "0426659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37b3"
-          "cfbad6b39a8ce8cb3a675f53b7b57e120fe067b8035d771fd99e3eba7cf4de"),
-      65);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"),
-      33);
-  res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      uncompressed,
-      fromhex(
-          "04433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7feeb"
-          "4c25bcb840f720a16e8857a011e6b91e0ab2d03dbb5f9762844bb21a7b8ca7"),
-      65);
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054"
-          "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"),
-      65);
-  res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      uncompressed,
-      fromhex(
-          "0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054"
-          "201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"),
-      65);
-
-  memcpy(pub_key, fromhex("00"), 1);
-  res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
-  ck_assert_int_eq(res, 0);
-}
-END_TEST
-
-START_TEST(test_wif) {
-  uint8_t priv_key[32];
-  char wif[53];
-
-  memcpy(
-      priv_key,
-      fromhex(
-          "1111111111111111111111111111111111111111111111111111111111111111"),
-      32);
-  ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp");
-  ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "cN9spWsvaxA8taS7DFMxnk1yJD2gaF2PX1npuTpy3vuZFJdwavaw");
-
-  memcpy(
-      priv_key,
-      fromhex(
-          "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
-      32);
-  ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN");
-  ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "cV1ysqy3XUVSsPeKeugH2Utm6ZC1EyeArAgvxE73SiJvfa6AJng7");
-
-  memcpy(
-      priv_key,
-      fromhex(
-          "47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"),
-      32);
-  ecdsa_get_wif(priv_key, 0x80, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq");
-  ecdsa_get_wif(priv_key, 0xEF, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "cPzbT6tbXyJNWY6oKeVabbXwSvsN6qhTHV8ZrtvoDBJV5BRY1G5Q");
-}
-END_TEST
-
-START_TEST(test_address_decode) {
-  int res;
-  uint8_t decode[MAX_ADDR_RAW_SIZE];
-
-  res = ecdsa_address_decode("1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("00c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21);
-
-  res = ecdsa_address_decode("myTPjxggahXyAzuMcYp5JTkbybANyLsYBW", 111,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("6fc4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21);
-
-  res = ecdsa_address_decode("NEWoeZ6gh4CGvRgFAoAGh4hBqpxizGT6gZ", 52,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("34c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21);
-
-  res = ecdsa_address_decode("LdAPi7uXrLLmeh7u57pzkZc3KovxEDYRJq", 48,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("30c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"), 21);
-
-  res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21);
-
-  res = ecdsa_address_decode("mrdwvWkma2D6n9mGsbtkazedQQuoksnqJV", 111,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("6f79fbfc3f34e7745860d76137da68f362380c606c"), 21);
-
-  res = ecdsa_address_decode("N7hMq7AmgNsQXaYARrEwybbDGei9mcPNqr", 52,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("3479fbfc3f34e7745860d76137da68f362380c606c"), 21);
-
-  res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 48,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("3079fbfc3f34e7745860d76137da68f362380c606c"), 21);
-
-  // invalid char
-  res = ecdsa_address_decode("1JwSSubhmg6i000jtyqhUYYH7bZg3Lfy1T", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-
-  // invalid address
-  res = ecdsa_address_decode("1111Subhmg6iPtRjtyqhUYYH7bZg3Lfy1T", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-
-  // invalid version
-  res = ecdsa_address_decode("LWLwtfycqf1uFqypLAug36W4kdgNwrZdNs", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-}
-END_TEST
-
-START_TEST(test_ecdsa_der) {
-  static const struct {
-    const char *r;
-    const char *s;
-    const char *der;
-  } vectors[] = {
-      {
-          "9a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b70771",
-          "2b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede781",
-          "30450221009a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8"
-          "b7077102202b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5"
-          "ede781",
-      },
-      {
-          "6666666666666666666666666666666666666666666666666666666666666666",
-          "7777777777777777777777777777777777777777777777777777777777777777",
-          "30440220666666666666666666666666666666666666666666666666666666666666"
-          "66660220777777777777777777777777777777777777777777777777777777777777"
-          "7777",
-      },
-      {
-          "6666666666666666666666666666666666666666666666666666666666666666",
-          "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
-          "30450220666666666666666666666666666666666666666666666666666666666666"
-          "6666022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-          "eeeeee",
-      },
-      {
-          "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
-          "7777777777777777777777777777777777777777777777777777777777777777",
-          "3045022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-          "eeeeee02207777777777777777777777777777777777777777777777777777777777"
-          "777777",
-      },
-      {
-          "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
-          "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-          "3046022100eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-          "eeeeee022100ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-          "ffffffff",
-      },
-      {
-          "0000000000000000000000000000000000000000000000000000000000000066",
-          "0000000000000000000000000000000000000000000000000000000000000077",
-          "3006020166020177",
-      },
-      {
-          "0000000000000000000000000000000000000000000000000000000000000066",
-          "00000000000000000000000000000000000000000000000000000000000000ee",
-          "3007020166020200ee",
-      },
-      {
-          "00000000000000000000000000000000000000000000000000000000000000ee",
-          "0000000000000000000000000000000000000000000000000000000000000077",
-          "3007020200ee020177",
-      },
-      {
-          "00000000000000000000000000000000000000000000000000000000000000ee",
-          "00000000000000000000000000000000000000000000000000000000000000ff",
-          "3008020200ee020200ff",
-      },
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "3006020100020100",
-      },
-  };
-
-  uint8_t sig[64];
-  uint8_t der[72];
-  uint8_t out[72];
-  for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); ++i) {
-    size_t der_len = strlen(vectors[i].der) / 2;
-    memcpy(der, fromhex(vectors[i].der), der_len);
-    memcpy(sig, fromhex(vectors[i].r), 32);
-    memcpy(sig + 32, fromhex(vectors[i].s), 32);
-    ck_assert_int_eq(ecdsa_sig_to_der(sig, out), der_len);
-    ck_assert_mem_eq(out, der, der_len);
-    ck_assert_int_eq(ecdsa_sig_from_der(der, der_len, out), 0);
-    ck_assert_mem_eq(out, sig, 64);
-  }
-}
-END_TEST
-
-static void test_codepoints_curve(const ecdsa_curve *curve) {
-  int i, j;
-  bignum256 a;
-  curve_point p, p1;
-  for (i = 0; i < 64; i++) {
-    for (j = 0; j < 8; j++) {
-      bn_zero(&a);
-      a.val[(4 * i) / BN_BITS_PER_LIMB] = (uint32_t)(2 * j + 1)
-                                          << (4 * i % BN_BITS_PER_LIMB);
-      bn_normalize(&a);
-      // note that this is not a trivial test.  We add 64 curve
-      // points in the table to get that particular curve point.
-      scalar_multiply(curve, &a, &p);
-      ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point));
-      bn_zero(&p.y);  // test that point_multiply curve, is not a noop
-      point_multiply(curve, &a, &curve->G, &p);
-      ck_assert_mem_eq(&p, &curve->cp[i][j], sizeof(curve_point));
-      // mul 2 test. this should catch bugs
-      bn_lshift(&a);
-      bn_mod(&a, &curve->order);
-      p1 = curve->cp[i][j];
-      point_double(curve, &p1);
-      // note that this is not a trivial test.  We add 64 curve
-      // points in the table to get that particular curve point.
-      scalar_multiply(curve, &a, &p);
-      ck_assert_mem_eq(&p, &p1, sizeof(curve_point));
-      bn_zero(&p.y);  // test that point_multiply curve, is not a noop
-      point_multiply(curve, &a, &curve->G, &p);
-      ck_assert_mem_eq(&p, &p1, sizeof(curve_point));
-    }
-  }
-}
-
-START_TEST(test_codepoints_secp256k1) { test_codepoints_curve(&secp256k1); }
-END_TEST
-START_TEST(test_codepoints_nist256p1) { test_codepoints_curve(&nist256p1); }
-END_TEST
-
-static void test_mult_border_cases_curve(const ecdsa_curve *curve) {
-  bignum256 a;
-  curve_point p;
-  curve_point expected;
-  bn_zero(&a);  // a == 0
-  scalar_multiply(curve, &a, &p);
-  ck_assert(point_is_infinity(&p));
-  point_multiply(curve, &a, &p, &p);
-  ck_assert(point_is_infinity(&p));
-  point_multiply(curve, &a, &curve->G, &p);
-  ck_assert(point_is_infinity(&p));
-
-  bn_addi(&a, 1);  // a == 1
-  scalar_multiply(curve, &a, &p);
-  ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point));
-  point_multiply(curve, &a, &curve->G, &p);
-  ck_assert_mem_eq(&p, &curve->G, sizeof(curve_point));
-
-  bn_subtract(&curve->order, &a, &a);  // a == -1
-  expected = curve->G;
-  bn_subtract(&curve->prime, &expected.y, &expected.y);
-  scalar_multiply(curve, &a, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-  point_multiply(curve, &a, &curve->G, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-
-  bn_subtract(&curve->order, &a, &a);
-  bn_addi(&a, 1);  // a == 2
-  expected = curve->G;
-  point_add(curve, &expected, &expected);
-  scalar_multiply(curve, &a, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-  point_multiply(curve, &a, &curve->G, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-
-  bn_subtract(&curve->order, &a, &a);  // a == -2
-  expected = curve->G;
-  point_add(curve, &expected, &expected);
-  bn_subtract(&curve->prime, &expected.y, &expected.y);
-  scalar_multiply(curve, &a, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-  point_multiply(curve, &a, &curve->G, &p);
-  ck_assert_mem_eq(&p, &expected, sizeof(curve_point));
-}
-
-START_TEST(test_mult_border_cases_secp256k1) {
-  test_mult_border_cases_curve(&secp256k1);
-}
-END_TEST
-START_TEST(test_mult_border_cases_nist256p1) {
-  test_mult_border_cases_curve(&nist256p1);
-}
-END_TEST
-
-static void test_scalar_mult_curve(const ecdsa_curve *curve) {
-  int i;
-  // get two "random" numbers
-  bignum256 a = curve->G.x;
-  bignum256 b = curve->G.y;
-  curve_point p1, p2, p3;
-  for (i = 0; i < 1000; i++) {
-    /* test distributivity: (a + b)G = aG + bG */
-    bn_mod(&a, &curve->order);
-    bn_mod(&b, &curve->order);
-    scalar_multiply(curve, &a, &p1);
-    scalar_multiply(curve, &b, &p2);
-    bn_addmod(&a, &b, &curve->order);
-    bn_mod(&a, &curve->order);
-    scalar_multiply(curve, &a, &p3);
-    point_add(curve, &p1, &p2);
-    ck_assert_mem_eq(&p2, &p3, sizeof(curve_point));
-    // new "random" numbers
-    a = p3.x;
-    b = p3.y;
-  }
-}
-
-START_TEST(test_scalar_mult_secp256k1) { test_scalar_mult_curve(&secp256k1); }
-END_TEST
-START_TEST(test_scalar_mult_nist256p1) { test_scalar_mult_curve(&nist256p1); }
-END_TEST
-
-static void test_point_mult_curve(const ecdsa_curve *curve) {
-  int i;
-  // get two "random" numbers and a "random" point
-  bignum256 a = curve->G.x;
-  bignum256 b = curve->G.y;
-  curve_point p = curve->G;
-  curve_point p1, p2, p3;
-  for (i = 0; i < 200; i++) {
-    /* test distributivity: (a + b)P = aP + bP */
-    bn_mod(&a, &curve->order);
-    bn_mod(&b, &curve->order);
-    ck_assert_int_eq(point_multiply(curve, &a, &p, &p1), 0);
-    ck_assert_int_eq(point_multiply(curve, &b, &p, &p2), 0);
-    bn_addmod(&a, &b, &curve->order);
-    bn_mod(&a, &curve->order);
-    ck_assert_int_eq(point_multiply(curve, &a, &p, &p3), 0);
-    point_add(curve, &p1, &p2);
-    ck_assert_mem_eq(&p2, &p3, sizeof(curve_point));
-    // new "random" numbers and a "random" point
-    a = p1.x;
-    b = p1.y;
-    p = p3;
-  }
-}
-
-START_TEST(test_point_mult_secp256k1) { test_point_mult_curve(&secp256k1); }
-END_TEST
-START_TEST(test_point_mult_nist256p1) { test_point_mult_curve(&nist256p1); }
-END_TEST
-
-static void test_scalar_point_mult_curve(const ecdsa_curve *curve) {
-  int i;
-  // get two "random" numbers
-  bignum256 a = curve->G.x;
-  bignum256 b = curve->G.y;
-  curve_point p1, p2;
-  for (i = 0; i < 200; i++) {
-    /* test commutativity and associativity:
-     * a(bG) = (ab)G = b(aG)
-     */
-    bn_mod(&a, &curve->order);
-    bn_mod(&b, &curve->order);
-    ck_assert_int_eq(scalar_multiply(curve, &a, &p1), 0);
-    ck_assert_int_eq(point_multiply(curve, &b, &p1, &p1), 0);
-
-    ck_assert_int_eq(scalar_multiply(curve, &b, &p2), 0);
-    ck_assert_int_eq(point_multiply(curve, &a, &p2, &p2), 0);
-
-    ck_assert_mem_eq(&p1, &p2, sizeof(curve_point));
-
-    bn_multiply(&a, &b, &curve->order);
-    bn_mod(&b, &curve->order);
-    ck_assert_int_eq(scalar_multiply(curve, &b, &p2), 0);
-
-    ck_assert_mem_eq(&p1, &p2, sizeof(curve_point));
-
-    // new "random" numbers
-    a = p1.x;
-    b = p1.y;
-  }
-}
-
-START_TEST(test_scalar_point_mult_secp256k1) {
-  test_scalar_point_mult_curve(&secp256k1);
-}
-END_TEST
-START_TEST(test_scalar_point_mult_nist256p1) {
-  test_scalar_point_mult_curve(&nist256p1);
-}
-END_TEST
-
-START_TEST(test_ed25519) {
-  // test vectors from
-  // https://github.com/torproject/tor/blob/master/src/test/ed25519_vectors.inc
-  static const char *vectors[] = {
-      "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d3"
-      "6",  // secret
-      "c2247870536a192d142d056abefca68d6193158e7c1a59c1654c954eccaff89"
-      "4",  // public
-      "d23188eac3773a316d46006fa59c095060be8b1a23582a0dd99002a82a0662bd"
-      "246d8449e172e04c5f46ac0d1404cebe4aabd8a75a1457aa06cae41f3334f10"
-      "4",  // selfsig
-      "fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128"
-      "d",
-      "1519a3b15816a1aafab0b213892026ebf5c0dc232c58b21088d88cb90e9b940"
-      "d",
-      "3a785ac1201c97ee5f6f0d99323960d5f264c7825e61aa7cc81262f15bef75eb"
-      "4fa5723add9b9d45b12311b6d403eb3ac79ff8e4e631fc3cd51e4ad2185b200"
-      "b",
-      "67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0"
-      "e",
-      "081faa81992e360ea22c06af1aba096e7a73f1c665bc8b3e4e531c46455fd1d"
-      "d",
-      "cf431fd0416bfbd20c9d95ef9b723e2acddffb33900edc72195dea95965d52d8"
-      "88d30b7b8a677c0bd8ae1417b1e1a0ec6700deadd5d8b54b6689275e04a0450"
-      "9",
-      "d51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a"
-      "6",
-      "73cfa1189a723aad7966137cbffa35140bb40d7e16eae4c40b79b5f0360dd65"
-      "a",
-      "2375380cd72d1a6c642aeddff862be8a5804b916acb72c02d9ed052c1561881a"
-      "a658a5af856fcd6d43113e42f698cd6687c99efeef7f2ce045824440d26c5d0"
-      "0",
-      "5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb43"
-      "3",
-      "66c1a77104d86461b6f98f73acf3cd229c80624495d2d74d6fda1e940080a96"
-      "b",
-      "2385a472f599ca965bbe4d610e391cdeabeba9c336694b0d6249e551458280be"
-      "122c2441dd9746a81bbfb9cd619364bab0df37ff4ceb7aefd24469c39d3bc50"
-      "8",
-      "eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b8"
-      "6",
-      "d21c294db0e64cb2d8976625786ede1d9754186ae8197a64d72f68c792eecc1"
-      "9",
-      "e500cd0b8cfff35442f88008d894f3a2fa26ef7d3a0ca5714ae0d3e2d40caae5"
-      "8ba7cdf69dd126994dad6be536fcda846d89dd8138d1683cc144c8853dce760"
-      "7",
-      "4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533"
-      "d",
-      "c4d58b4cf85a348ff3d410dd936fa460c4f18da962c01b1963792b9dcc8a6ea"
-      "6",
-      "d187b9e334b0050154de10bf69b3e4208a584e1a65015ec28b14bcc252cf84b8"
-      "baa9c94867daa60f2a82d09ba9652d41e8dde292b624afc8d2c26441b95e3c0"
-      "e",
-      "c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290"
-      "b",
-      "95126f14d86494020665face03f2d42ee2b312a85bc729903eb17522954a1c4"
-      "a",
-      "815213640a643d198bd056e02bba74e1c8d2d931643e84497adf3347eb485079"
-      "c9afe0afce9284cdc084946b561abbb214f1304ca11228ff82702185cf28f60"
-      "d",
-      0,
-      0,
-      0,
-  };
-  const char **ssk, **spk, **ssig;
-  ssk = vectors;
-  spk = vectors + 1;
-  ssig = vectors + 2;
-  ed25519_public_key pk;
-  ed25519_secret_key sk;
-  ed25519_signature sig;
-  while (*ssk && *spk && *ssig) {
-    memcpy(sk, fromhex(*ssk), 32);
-    MARK_SECRET_DATA(sk, sizeof(sk));
-
-    ed25519_publickey(sk, pk);
-    UNMARK_SECRET_DATA(pk, sizeof(pk));
-    ck_assert_mem_eq(pk, fromhex(*spk), 32);
-
-    ed25519_sign(pk, 32, sk, sig);
-    UNMARK_SECRET_DATA(sig, sizeof(sig));
-    ck_assert_mem_eq(sig, fromhex(*ssig), 64);
-
-    ssk += 3;
-    spk += 3;
-    ssig += 3;
-
-    UNMARK_SECRET_DATA(sk, sizeof(sk));
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/2.test-sign.dat
-START_TEST(test_ed25519_keccak) {
-  static const struct {
-    const char *private_key;
-    const char *public_key;
-    const char *signature;
-    size_t length;
-    const char *data;
-  } tests[] = {
-      {
-          "abf4cf55a2b3f742d7543d9cc17f50447b969e6e06f5ea9195d428ab12b7318d",
-          "8a558c728c21c126181e5e654b404a45b4f0137ce88177435a69978cc6bec1f4",
-          "d9cec0cc0e3465fab229f8e1d6db68ab9cc99a18cb0435f70deb6100948576cd5c0a"
-          "a1feb550bdd8693ef81eb10a556a622db1f9301986827b96716a7134230c",
-          41,
-          "8ce03cd60514233b86789729102ea09e867fc6d964dea8c2018ef7d0a2e0e24bf7e3"
-          "48e917116690b9",
-      },
-      {
-          "6aa6dad25d3acb3385d5643293133936cdddd7f7e11818771db1ff2f9d3f9215",
-          "bbc8cbb43dda3ecf70a555981a351a064493f09658fffe884c6fab2a69c845c6",
-          "98bca58b075d1748f1c3a7ae18f9341bc18e90d1beb8499e8a654c65d8a0b4fbd2e0"
-          "84661088d1e5069187a2811996ae31f59463668ef0f8cb0ac46a726e7902",
-          49,
-          "e4a92208a6fc52282b620699191ee6fb9cf04daf48b48fd542c5e43daa9897763a19"
-          "9aaa4b6f10546109f47ac3564fade0",
-      },
-      {
-          "8e32bc030a4c53de782ec75ba7d5e25e64a2a072a56e5170b77a4924ef3c32a9",
-          "72d0e65f1ede79c4af0ba7ec14204e10f0f7ea09f2bc43259cd60ea8c3a087e2",
-          "ef257d6e73706bb04878875c58aa385385bf439f7040ea8297f7798a0ea30c1c5eff"
-          "5ddc05443f801849c68e98111ae65d088e726d1d9b7eeca2eb93b677860c",
-          40,
-          "13ed795344c4448a3b256f23665336645a853c5c44dbff6db1b9224b5303b6447fbf"
-          "8240a2249c55",
-      },
-      {
-          "c83ce30fcb5b81a51ba58ff827ccbc0142d61c13e2ed39e78e876605da16d8d7",
-          "3ec8923f9ea5ea14f8aaa7e7c2784653ed8c7de44e352ef9fc1dee81fc3fa1a3",
-          "0c684e71b35fed4d92b222fc60561db34e0d8afe44bdd958aaf4ee965911bef59912"
-          "36f3e1bced59fc44030693bcac37f34d29e5ae946669dc326e706e81b804",
-          49,
-          "a2704638434e9f7340f22d08019c4c8e3dbee0df8dd4454a1d70844de11694f4c8ca"
-          "67fdcb08fed0cec9abb2112b5e5f89",
-      },
-      {
-          "2da2a0aae0f37235957b51d15843edde348a559692d8fa87b94848459899fc27",
-          "d73d0b14a9754eec825fcb25ef1cfa9ae3b1370074eda53fc64c22334a26c254",
-          "6f17f7b21ef9d6907a7ab104559f77d5a2532b557d95edffd6d88c073d87ac00fc83"
-          "8fc0d05282a0280368092a4bd67e95c20f3e14580be28d8b351968c65e03",
-          40,
-          "d2488e854dbcdfdb2c9d16c8c0b2fdbc0abb6bac991bfe2b14d359a6bc99d66c00fd"
-          "60d731ae06d0",
-      },
-      {
-          "0c066261fb1b18ebf2a9bcdeda81eb47d5a3745438b3d0b9d19b75885ad0a154",
-          "2e5773f0e725024bc0359ce93a44e15d6507e7b160b6c592200385fee4a269cf",
-          "13b5d2dd1b04f62cc2ec1544fed256423684f2dbca4538ceddda1d15c59dc7196c87"
-          "840ea303ea30f4f6914a6ec9167841980c1d717f47fd641225068de88507",
-          41,
-          "f15cb706e29fcfbcb324e38cbac62bb355deddb845c142e970f0c029ea4d05e59fd6"
-          "adf85573cf1775",
-      },
-      {
-          "ef3d8e22a592f04c3a31aa736e10901757a821d053f1a49a525b4ec91eacdee3",
-          "72a2b4910a502b30e13a96aba643c59c79328c1ba1462be6f254e817ef157fee",
-          "95f2437a0210d2d2f125a3c377ed666c0d596cd104185e70204924a182a11a6eb3bd"
-          "ba4395bbfc3f4e827d38805752657ee52d1ce0f17e70f59bfd4999282509",
-          50,
-          "6c3e4387345740b8d62cf0c9dec48f98c292539431b2b54020d8072d9cb55f0197f7"
-          "d99ff066afcf9e41ea8b7aea78eb082d",
-      },
-      {
-          "f7fb79743e9ba957d2a4f1bd95ceb1299552abecaf758bf840d2dc2c09f3e3cb",
-          "8b7d7531280f76a8abac8293d87508e3953894087112ae01b6ad32485d4e9b67",
-          "c868ecf31cee783fe8799ac7e6a662431c822967351d8b79687f4ddf608f79a080c4"
-          "ff9eed4fdee8c99fe1be905f734cae2a172f1cfdb00771625c0695a5260e",
-          42,
-          "55d8e60c307ee533b1af9ff677a2de40a6eace722bcc9eb5d79907b420e533bc06db"
-          "674dafbd9f43d672",
-      },
-      {
-          "8cc9a2469a77fad18b44b871b2b6932cd354641d2d1e84403f746c4fff829791",
-          "aed5da202d4983dac560faf6704dc76ac111616318570e244043e82ed1bbcd2b",
-          "aee9616db4135150818eaffa3e4503c2d7e9e834847a4c7d0a8856e952761d361a65"
-          "7104d36950c9b75770ded00d56a96e06f383fa2406bc935dcf51f272300e",
-          42,
-          "d9b8be2f71b83261304e333d6e35563dc3c36c2eb5a23e1461b6e95aa7c6f381f9c3"
-          "bd39deaa1b6df2f9",
-      },
-      {
-          "a247abbef0c1affbf021d1aff128888550532fc0edd77bc39f6ef5312317ec47",
-          "98ededbad1e5ad7a0d5a0cf4fcd7a794eb5c6900a65e7e921884a636f19b131d",
-          "f8cc02933851432f0c5df0b70f2067f740ccb72de7d6fa1e9a9b0d6de1402b9c6c52"
-          "5fd848e45aaaac1423b52880ec3474a2f64b38db6fc8e008d95a310e6e0c",
-          47,
-          "4a5f07eb713932532fc3132c96efdc45862fe7a954c1d2ae4640afdf4728fb58c65e"
-          "8a4ebfe0d53d5797d5146442b9",
-      },
-      {
-          "163d69079ddad1f16695c47d81c3b72f869b2fdd50e6e47113db6c85051a6ede",
-          "93fe602642ee5773f4aaf6a3bc21e98e354035225353f419e78e43c3ec36c88a",
-          "da747fa2cb47aae1effc1e4cfde0e39fa79937948592a712a7665bf948b8311e7f3f"
-          "80f966301679520d5c2afa3eadd60e061f0d264887500d8d03a17e10fd02",
-          41,
-          "65fe5c1a0214a59644892e5ac4216f09fbb4e191b89bfb63d6540177d25ef9e37148"
-          "50b8453bd6b2b6",
-      },
-      {
-          "7b061bf90eb760971b9ec66a96fd6609635ca4b531f33e3c126b9ae6fdb3d491",
-          "cb392ebb6912df4111efeeb1278160daf9da396e9291b83979a5ac479f7276d2",
-          "f6eebe86f7ea672e0707ee518e1798d6fbd118c11b2aa30be07d10e3882e3721f203"
-          "0f9f044b77c3a7a9a2f1feba7e7ce75d1f7f3807a96a764fded35d341d02",
-          45,
-          "a17f5ce39b9ba7b7cf1147e515d6aa84b22fd0e2d8323a91367198fc6c3aff04ebb2"
-          "1fc2bdbe7bc0364e8040a9",
-      },
-      {
-          "c9f8ccbf761cec00ab236c52651e76b5f46d90f8936d44d40561ed5c277104de",
-          "a3192641e343b669ffd43677c2e5cd4efaed174e876141f1d773bd6cfe30d875",
-          "d44f884ec9eae2e99e74194b5acc769b7aa369aaad359e92ba6ff0fe629af2a9a715"
-          "6c19b720e7de8c7f03c039563f160948073cab6f99b26a56a8bb1023ba08",
-          47,
-          "3d7e33b0ecead8269966e9dcd192b73eb8a12573fc8a5fdfbe5753541026ef2e49f5"
-          "280cba9bc2515a049b3a1c1b49",
-      },
-      {
-          "ebfa409ac6f987df476858dd35310879bf564eeb62984a52115d2e6c24590124",
-          "7bb1601fe7215f3f4da9c8ab5e804dc58f57ba41b03223f57ec80d9c9a2dd0e1",
-          "f3e7c1abfcc9f35556cb1e4c5a2b34445177ac188312d9148f1d1d8467ea8411fa3c"
-          "da031d023034e45bbe407ef7d1b937bfb098266138857d35cb4efe407306",
-          52,
-          "0c37564f718eda683aa6f3e9ab2487620b1a8b5c8f20adb3b2d7550af0d635371e53"
-          "1f27cebe76a2abcc96de0875bdae987a45ac",
-      },
-      {
-          "f993f61902b7da332f2bb001baa7accaf764d824eb0cd073315f7ec43158b8fb",
-          "55fc8e0da1b454cab6ddefb235311db2b01504bf9ac3f71c7e3f3d0d1f09f80b",
-          "178bd147673c0ca330e45da63cbd1f1811906bd5284bb44e4bb00f7d7163d1f39697"
-          "5610b6f71c1ae4686466fad4c5e7bb9685099e21ca4f1a45bb3fcf56ae0c",
-          42,
-          "b7dd613bc9c364d9eeb9a52636d72bc881dfc81a836b6537bbb928bff5b738313589"
-          "47ea9edea1570550",
-      },
-      {
-          "05188c09c31b4bb63f0d49b47ccc1654c2aba907b8c6c0a82ee403e950169167",
-          "e096d808dfabe8e44eb74950199dadcd586f9de6b141a0ce85ab94b3d97866eb",
-          "669491c8eb7cedbbc0252f3eafb048b39a2a37f60ac87837777c72c879ac8b726c39"
-          "e10060750c2f539102999b71889746111bc5f71ec8c158cc81cf566aef03",
-          44,
-          "bb8e22469d1c7f1d5418563e8781f69eccb56678bd36d8919f358c2778562ff6b50d"
-          "e916c12d44f1a778a7f3",
-      },
-      {
-          "eabe57e1a916ebbffa4ba7abc7f23e83d4deb1338816cc1784d7495d92e98d0b",
-          "3aad275642f48a46ed1032f3de9f4053e0fd35cf217e065d2e4579c3683932f7",
-          "b2e9dac2c83942ca374f29c8eff5a30c377c3db3c1c645e593e524d17484e7705b11"
-          "f79573e2d63495fc3ce3bf216a209f0cb7bea477ae0f8bd297f193af8805",
-          44,
-          "3f2c2d6682ee597f2a92d7e560ac53d5623550311a4939d68adfb904045ed8d215a9"
-          "fdb757a2368ea4d89f5f",
-      },
-      {
-          "fef7b893b4b517fab68ca12d36b603bc00826bf3c9b31a05149642ae10bb3f55",
-          "b3fb891868708dfa5da5b9b5234058767ab42c117f12c3228c02a1976d1c0f83",
-          "6243e289314b7c7587802909a9be6173a916b36f9de1e164954dfe5d1ebd57c869a7"
-          "9552d770e13b51855502be6b15e7be42a3675298a81284df58e609b06503",
-          47,
-          "38c69f884045cdbeebe4478fdbd1ccc6cf00a08d8a3120c74e7167d3a2e26a67a043"
-          "b8e5bd198f7b0ce0358cef7cf9",
-      },
-      {
-          "16228bec9b724300a37e88e535fc1c58548d34d7148b57c226f2b3af974c1822",
-          "3c92423a8360c9a5d9a093730d72831bec4601dcadfe84de19fc8c8f91fc3d4b",
-          "6aebfa9a4294ec888d54bcb517fcb6821e4c16d2708a2afe701f431a28149ff4f139"
-          "f9d16a52a63f1f91baf4c8dea37710c73f25c263a8035a39cc118ad0280f",
-          44,
-          "a3d7b122cd4431b396b20d8cc46cc73ed4a5253a44a76fc83db62cdc845a2bf7081d"
-          "069a857955a161cccf84",
-      },
-      {
-          "2dc3f5f0a0bc32c6632534e1e8f27e59cbe0bf7617d31aff98098e974c828be7",
-          "b998a416edc28ded988dcacb1caf2bd96c87354b0d1eeccb6980e54a3104f21f",
-          "76a2ddfc4bea48c47e0c82bcbfee28a37c61ec626af39a468e643e0ef9f6533056a5"
-          "a0b44e64d614ba3c641a40e5b003a99463445ae2c3c8e1e9882092d74b07",
-          42,
-          "bdae276d738b9758ea3d322b54fd12fe82b767e8d817d8ef3d41f78705748e28d15e"
-          "9c506962a1b85901",
-      },
-  };
-
-  ed25519_secret_key private_key;
-  ed25519_public_key public_key;
-  ed25519_signature signature;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    nem_private_key(tests[i].private_key, private_key);
-    MARK_SECRET_DATA(private_key, sizeof(private_key));
-
-    ed25519_publickey_keccak(private_key, public_key);
-    UNMARK_SECRET_DATA(public_key, sizeof(public_key));
-    ck_assert_mem_eq(public_key, fromhex(tests[i].public_key), 32);
-
-    ed25519_sign_keccak(fromhex(tests[i].data), tests[i].length, private_key,
-                        signature);
-    UNMARK_SECRET_DATA(signature, sizeof(signature));
-    ck_assert_mem_eq(signature, fromhex(tests[i].signature), 64);
-
-    UNMARK_SECRET_DATA(private_key, sizeof(private_key));
-  }
-}
-END_TEST
-
-START_TEST(test_ed25519_cosi) {
-  const int MAXN = 10;
-  ed25519_secret_key keys[MAXN];
-  ed25519_public_key pubkeys[MAXN];
-  ed25519_secret_key nonces[MAXN];
-  ed25519_public_key Rs[MAXN];
-  ed25519_cosi_signature sigs[MAXN];
-  uint8_t msg[32];
-  rfc6979_state rng;
-  int res;
-
-  init_rfc6979(
-      fromhex(
-          "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36"),
-      fromhex(
-          "26659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"),
-      NULL, &rng);
-
-  for (int N = 1; N < 11; N++) {
-    ed25519_public_key pk;
-    ed25519_public_key R;
-    ed25519_signature sig;
-    /* phase 0: create priv/pubkeys and combine pubkeys */
-    for (int j = 0; j < N; j++) {
-      generate_rfc6979(keys[j], &rng);
-      ed25519_publickey(keys[j], pubkeys[j]);
-    }
-    res = ed25519_cosi_combine_publickeys(pk, pubkeys, N);
-    ck_assert_int_eq(res, 0);
-
-    generate_rfc6979(msg, &rng);
-
-    /* phase 1: create nonces, commitments (R values) and combine commitments */
-    for (int j = 0; j < N; j++) {
-      ed25519_cosi_commit(nonces[j], Rs[j]);
-    }
-    res = ed25519_cosi_combine_publickeys(R, Rs, N);
-    ck_assert_int_eq(res, 0);
-
-    MARK_SECRET_DATA(keys, sizeof(keys));
-    /* phase 2: sign and combine signatures */
-    for (int j = 0; j < N; j++) {
-      res = ed25519_cosi_sign(msg, sizeof(msg), keys[j], nonces[j], R, pk,
-                              sigs[j]);
-      ck_assert_int_eq(res, 0);
-    }
-    UNMARK_SECRET_DATA(sigs, sizeof(sigs));
-
-    ed25519_cosi_combine_signatures(sig, R, sigs, N);
-
-    /* check signature */
-    res = ed25519_sign_open(msg, sizeof(msg), pk, sig);
-    ck_assert_int_eq(res, 0);
-
-    UNMARK_SECRET_DATA(keys, sizeof(keys));
-  }
-}
-END_TEST
-
-START_TEST(test_ed25519_modl_add) {
-  char tests[][3][65] = {
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0000000000000000000000000000000000000000000000000000000000000000",
-      },
-
-      {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a",
-       "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"},
-
-      {"0100000000000000000000000000000000000000000000000000000000000000",
-       "0200000000000000000000000000000000000000000000000000000000000000",
-       "0300000000000000000000000000000000000000000000000000000000000000"},
-
-      {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0a00000000000000000000000000000000000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000000"},
-
-      {"f7bb3bf42b3e58e2edd06f173fc7bfbc7aaf657217946b75648447101136aa08",
-       "3c16b013109cc27ff39805be2abe04ba4cd6a8526a1d3023047693e950936c06",
-       "33d2eb073cda1a62e16975d56985c476c7850ec581b19b9868fadaf961c9160f"},
-  };
-
-  unsigned char buff[32];
-  bignum256modm a = {0}, b = {0}, c = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i][0]), 32);
-    expand256_modm(b, fromhex(tests[i][1]), 32);
-    add256_modm(c, a, b);
-    contract256_modm(buff, c);
-    ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_ed25519_modl_neg) {
-  char tests[][2][65] = {
-      {"05d0f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "e803000000000000000000000000000000000000000000000000000000000000"},
-
-      {"4d4df45c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "a086010000000000000000000000000000000000000000000000000000000000"},
-
-      {"25958944a1b7d4073975ca48996a1d740d0ed98ceec366760c5358da681e9608",
-       "c83e6c1879ab3d509d272d5a458fc1a0f2f12673113c9989f3aca72597e16907"},
-
-      {"0100000000000000000000000000000000000000000000000000000000000000",
-       "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"},
-
-      {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0100000000000000000000000000000000000000000000000000000000000000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000000"},
-  };
-
-  unsigned char buff[32];
-  bignum256modm a = {0}, b = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i][0]), 32);
-    neg256_modm(b, a);
-    contract256_modm((unsigned char *)buff, b);
-    ck_assert_mem_eq(buff, fromhex(tests[i][1]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_ed25519_modl_sub) {
-  char tests[][3][65] = {
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0000000000000000000000000000000000000000000000000000000000000000",
-      },
-
-      {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a",
-       "53732f60e51ee3a48d21d2d526548c0dadbb79a185678fd7710613d0e76aad0c",
-       "8859d1d1deee0767a4ff1b72a3e0d0327573c69bbff5fc07cfa61414e6ef3b0e"},
-
-      {"9d91e26dbe7a14fdca9f5b20d13e828dc8c1ffe03fe90136a6bba507436ce500",
-       "9ca406705ccce65eb8cbf63706d3df09fcc67216c0dc3990270731aacbb2e607",
-       "eec0d15a7c1140f6e8705c8ba9658198ccfa8cca7f0cc8a57eb4745d77b9fe08"},
-
-      {"eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "eef80ad5a9aad8b35b84f6a4eb3a7e2b222f403d455d8cdf40ad27e4cd5ae90a"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "39897fbebf137a34572b014b0638ac0186d17874e3cc142ebdfe24327f5b8509",
-       "b44a769e5a4f98237f71f657d8c132137a2e878b1c33ebd14201dbcd80a47a06"},
-
-      {"0200000000000000000000000000000000000000000000000000000000000000",
-       "e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0c00000000000000000000000000000000000000000000000000000000000000"},
-
-      {"e3d3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0800000000000000000000000000000000000000000000000000000000000000",
-       "dbd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"},
-
-      {"ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010",
-       "0100000000000000000000000000000000000000000000000000000000000000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000010",
-       "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "ffffff3f00000000000000000000000000000000000000000000000000000010",
-       "eed3f51c1a631258d69cf7a2def9de1400000000000000000000000000000000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000010"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "e75f947f11d49d25a137fac8757538a980dec23811235cf63c48ee6bc6e4ed03",
-       "067461dd088f74323565fdd96884a66b7f213dc7eedca309c3b71194391b120c"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "ecd3f55c1a631258d69cf7a2def9de140000000000000000000000000000ff0f",
-       "0100000000000000000000000000000000000000000000000000000000000100"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "edd3f55c1a631258d69cf7a2def9de140000000000000000000004000000ff0f",
-       "0000000000000000000000000000000000000000000000000000fcffffff0000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "edd3f55c1a631258d69cf7a2def9de150000c0ffffffffffffffffffffffff0f",
-       "000000000000000000000000000000ffffff3f00000000000000000000000000"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "edd3f55c1a631258d69cf7a2def9de1200000000000000000000000000000110",
-       "edd3f55c1a631258d69cf7a2def9de160000000000000000000000000000ff0f"},
-
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "edd3f55c1a631258d69cf7a2def9de1300000000000000000000000000000010",
-       "0000000000000000000000000000000100000000000000000000000000000000"},
-  };
-
-  unsigned char buff[32];
-  bignum256modm a = {0}, b = {0}, c = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i][0]), 32);
-    expand256_modm(b, fromhex(tests[i][1]), 32);
-    sub256_modm(c, a, b);
-    contract256_modm(buff, c);
-    ck_assert_mem_eq(buff, fromhex(tests[i][2]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_ge25519_double_scalarmult_vartime2) {
-  char tests[][5][65] = {
-      {"c537208ed4985e66e9f7a35c9a69448a732ba93960bbbd2823604f7ae9e3ed08",
-       "365233e5af17c8888d5ce508787464f4642e91a6212b1b104e6c3769535601b1",
-       "a84f871580176708b4ac21843cb197ad96e8456034442b50859c83c5807b9901",
-       "f022360d1bce903fa3ac58ae42f997328b31f477b8d576a9f6d26fc1d08f14ea",
-       "bf25da82c6b210948b823ae48422a2dcd205d3c94842e68ac27e5cbeaa704ebc"},
-      {"4abfabc0dda33588a98127ef3bfe724fed286395fe15932e898b5621661ea102",
-       "e5fd79d03f5df8edfc8def663dcb96bba6cadf857f2ae6f6f51f52f8d14079b7",
-       "4754c286b23e3c1b50054fe3937ebdc4ec01b28da5d05fb6111798b42fc5bf06",
-       "b7e7f9464b98de5bfcf6b02c1b7053cc359df407ad59d943523c6d2ee773b2f6",
-       "6d7d5f729bfa4882dbff8e477cd2b4c354ba347f10e7b178a24f3f16a4e0fec6"},
-      {"19f2af4d04cb8181f1fe0d01fe9bb9ecc476c67ceb4a9830dae1bc7fe5fe3b04",
-       "d3c462f4f30991220387a1fbbd1ba1dc45ce058c70a8fb1475071e7b4f0fc463",
-       "577790e025c1fd2014db44a8d613c4e2ab1f248a4a6d14b5d39cbbafd7b20f06",
-       "1376c6837f131f6cd1a45b1056297d2314aa0ac5f7d581d2d878261eb3259b4d",
-       "ce790760ada87dd819b59e4f6765d836d346567ec34f02bbcfcae0585c1d758f"},
-      {"cf209db9e7ee85f1e648924ec97edd86b56a833b25707519d4fbe64fd50e150a",
-       "804f0806087dc665a26230ed5fd44c062980ee182a6bd7dbdb33df018c983778",
-       "30d3c448cb08935309753b3051366f52328ca1d9a0b63c72b989edee0da32b0e",
-       "98e3c973a7e85b5eab8111521c66ca584bed5597f060ab0c6b5cdeece502ac48",
-       "2646276e1305396a1b2473690066011a39789570a09e10ce1a013c8f32cd5bea"},
-      {"b0a0ffeea67b656c4c585ba58ff528a6f45d2f915db98e4a14a8ff17f27fc105",
-       "4fabe16274f6af526ee053028485db6acd13804e02dcdddccc4183a319ab9e1c",
-       "1e140bb08a936ac6b7437644ca0769f3c165c7aa5501d49f064a0346179b4008",
-       "68fc1be64fb68761542a655b8dbebf50980f1fbc1845528df8d8a06bf89a1495",
-       "7dab86994b47014efe38493fc2b62ffcead806da6e0d73c992db8cb5618a19dc"},
-      {"0fee422c2294b06ca83bc3704384dffc580e7ff5921881e51a755e5f9b80af03",
-       "4359a663ead3f7ffc3a0ead5c3c2bde348017e7bfa620f21759c32e469a16dfe",
-       "532066e3eec29334fffc37b17178dfbac3bee15f7845f01449ddbaf5e57a7b0c",
-       "32e46c2fb99402837631c8175db31cdd334c145f922be9070d62e6d9c493c3ea",
-       "8c7b7d2d61cdb648960434d894787426a76d16dd46949c7aa4b85dcf1054b4d5"},
-      {"3a712d5b7ceb5257dcf6e6bb06548de6ef3deba5d456cd91fc305a12b46b5d01",
-       "5e7da62e3ec42cf3e554639dd4d2006754ee6839b720cadba94a26b73b1665ee",
-       "2a518ecab17a2d9dde219c775bcf4f2306b190bef2dea34fb65b8e4dccc13405",
-       "3b5d66a4dfb068923b3bc21cc8b40b59e12f845e0b85a86d394db0fa310bf185",
-       "2ec17f1cc0be093e9cdb741a991c0f417230dea275cd7babdad35e949e250521"},
-      {"5f815f2d65cef584c5e5d48b2d3d3e4cae310d70b328f88af6e9f63c52b4c90d",
-       "8a539a8c6b2339922b31cf4bc064f1fedeb3912fd89585d79dfcff2a60aee295",
-       "385f7132b72db04146b9e472736b32adfca29556b4775a743c18e2bfab939007",
-       "884aaf96d625968ddb2582922a87abca131272884c47f6b86890ebccf0a79d5b",
-       "a7afdaf24fe8472d8b89e95c3ce4a40bdf700af7cedee44ed3aa5ccca09839bd"},
-      {"a043340d072df16a8ab5135f8c1d601bff14c5aba01b9212b886ad71fe164506",
-       "52f6de5fa0fae32d4020a54d395319509d6b92092a0bf849fb34e73f8e71fc99",
-       "37d7472d360164da29e6dcb8f9796976022571c5df4ddf7e30e9a579ba13d509",
-       "8c369e3fd5b1112e4437b1f09e987acca4966f2f8c5227eb15ace240a2c64cc7",
-       "fc795fe7baff5c3ac98366e6882f25874ea2b0a649d16f139e5c54ea47042a1e"},
-      {"97a3268db03fa184c8cba020bf216fc789292fa9615a28962385b86870ffd70f",
-       "a76c215587022bb9252ece4c5afeb0e65b820834cd41ac76e6c062d3eea75dc6",
-       "8310271017154cbddf7005e24eb9a9a86777b3f42fa5e35095eafaac4eb24802",
-       "b822665c2406083c851ecaa91ea67aa740c057e7679b5755cee60a6c63f17fd6",
-       "f83e2444527056eba595d49bde40b2e8da76d2c145f203331d26e94560993fbc"},
-      {"edaad13efad39f26298e86ba8d06a46e59122232c9529bd22f2f656595421e00",
-       "f38e56a79f5159eb3b581dea537ec12c9c6fac381b2cf6073e27fc621197cb62",
-       "1eea79485954b5958d9d5478f86133af1088806d923535d483b115ab23099a0f",
-       "b32c5e57d57db7a349f4ab845f12a5045c52b4a7a5bce7fd54a1a255b0118185",
-       "3bfb42b4ffd2c6cfc8cce9e4187dc6fbcaecd9d44a4ca1d2b68b97410bb25b81"},
-      {"b15eaebe0fc83cb11d755a6f067b710204d4a59101078d8286454b652879080a",
-       "4667a2e61d9df1690f5c33c4168e480f7e26d2f0998168ebdc0a39712946f741",
-       "125379da1a88bfdf5b928f8795d3ea5415ef8c3d9106eb16934c3842873fd707",
-       "8727a692a25e38b1afa98e3dd5bf88815dec6d9810c1fd8a31b56b3de8630f1e",
-       "540883dde400b909e9955a276c20e13d99252ebe542750b8bfbbe5c3b87c51e3"},
-      {"e42bdd4af3121bea644a90a76b2007615621ee5b842b9a74c4334ac309478706",
-       "6dc4ab715d3bb975ebfd0f08e2b6f3f39922d0121ae518a8f8d2952ea2fe0b5d",
-       "0285059b0095c97f4a50d43c7726c64c2830bf2b55dfa934ebba7ad71064dc07",
-       "f738c0a3cee31fd8f438f282aa6c823fccfa49cf7b5c86fbf9d56bf0394b6d8d",
-       "a1bd106841e55010decd95a170a1d0dd11780fd00759819e024b15ea3a83b4be"},
-      {"5077c30fd08795dbdc7a230c050ca07e316fa3b040fd0dac45907036ab25dd0e",
-       "96f0897f000e49e2439a9166cab40ebc125a31b82851f0541516c19683e7bfaf",
-       "2b67d79a2efdc6451508e7f3c97c4a61b135bb839c02338bb444ef8208dd970b",
-       "7ef4cd7cdc29c2b88ccff49898b5d0b7be5993f93c5772476feec9dc57d7b6e3",
-       "62449b901b25760c964704b28efc184fbd5947e83851ebaf3bbfeb6f742f679f"},
-      {"a4b3ce6928fe8f77d13e65ae255eee8310ab0d75bca47028b4570f0511a66006",
-       "4e9da8d77ee337e3bcce3730ccfff2121728641c7bb4fdeb2155890f998af09a",
-       "ff01a5075569d0f6afee45da065c72f5841f46ce772917ef75eb4d230473580f",
-       "36ca32da8a10f4083f5a60ee21868d9d448548d49c56f19cbe6005005e34f816",
-       "99df362a3b762cc1cbb70bc5ddff3c8614ed306037013102e387ef32e7f2494f"},
-      {"074aa76351dceb752aa09887d9aca932d5821f58eedb4988fd64d8548e3f2c09",
-       "588b4552f3b98b2f77aee2ef8cc72f88acd424c4373b3e3626393ed2ea24cbda",
-       "f2d9175633f2e3c661b01172b4b4176850cd5b3098ffb0f927e0a5e19c1c8a02",
-       "a6c34868736b2517fd46f57a4e30805ffd475e44a8b1413078f43d9cb3d6edd6",
-       "46e1e7d7b1e939dd5c07c8363af01f4f9dae7c3d10f237ff9776ddc4a1903771"},
-      {"ae1c8abd5a542208ee0aa93ffbf0b8e5a957edc4854fe2b48153c5c85bbf3d08",
-       "5e084b9541a70bd5bef400be6525c5a806a5b7fb12de38b07dcd35a22c57edbe",
-       "d95f179a215fb322d81720bf3aecde78d6d676d6f941455d0e0920f1e3619707",
-       "c3e5d43221824de51d8f95705de69c80a2440c0483ca88549d639aee15390429",
-       "df9fea42d3b5ac243244abb4ca4948a69493becddc5d5906f9a4e4c5645b0eab"},
-      {"2f1c5adedb7341dc7638bafacc6024bd48255197ea2347fc05714b9341dd4403",
-       "47f55263001542f796c928988f641f59d0cd43294fc8d8616b184bfe9dddf368",
-       "aa5e884e782ab116151c609680c37b1a49b52f23bce5e2ebf28dd8532510d20b",
-       "ef2d6d97ad1a18edfce6450c1e70295b2c7ed2bc749ea8b438a523eae078d1f3",
-       "2396a355c6ae8e2ac24da8f55a674c96fc4cc69b38678b2bd8eb91b96f462bca"},
-      {"0242e14105ced74e91cf4d4dcd22a9c09279018901d2fb8319eb54c2a1c4900a",
-       "fcb62a6c520d31fa46efeb4a1000330653b3402f575c2ddc0c688f527e7b97be",
-       "73a7e2e0602e5345f040dedc4db67f6d8e37c5fca3bbb124fa43963d76dbbb08",
-       "152bf4a3305c656f77e292b1256cc470da4d3f6efc3667199db4316d7f431174",
-       "c21ba2080013dfb225e06378d9ac27df623df552526cfddbf9e71bb1d4705dd9"},
-      {"07fab4fc7b02fbcf868ffb0326cf60425fef2af1fbad83a8926cc62c2b5dff05",
-       "29ff12c5e052eb5829e8334e0e082c5edde1f293d2b4ed499a79bcca20e48010",
-       "97afb3dd9167877b432a23503aad1ab39188b9be07cc124ceb3fbdbd8d8b890a",
-       "ed121240a2f4591eeedbfd880305ccd17e522673900b03279fb66e73583514ae",
-       "b27f209e88ce5701766565e231e8123adb1df9c9f1dc461920acbc2b38d9f6d7"},
-  };
-
-  unsigned char buff[32];
-  bignum256modm a = {0}, b = {0};
-  ge25519 A, B, R;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i][0]), 32);
-    expand256_modm(b, fromhex(tests[i][2]), 32);
-    ge25519_unpack_negative_vartime(&A, fromhex(tests[i][1]));
-    curve25519_neg(A.x, A.x);
-    curve25519_neg(A.t, A.t);
-    ge25519_unpack_negative_vartime(&B, fromhex(tests[i][3]));
-    curve25519_neg(B.x, B.x);
-    curve25519_neg(B.t, B.t);
-    ge25519_double_scalarmult_vartime2(&R, &A, a, &B, b);
-    ge25519_pack(buff, &R);
-    ck_assert_mem_eq(buff, fromhex(tests[i][4]), 32);
-  }
-}
-END_TEST
-
-static void test_bip32_ecdh_init_node(HDNode *node, const char *seed_str,
-                                      const char *curve_name) {
-  hdnode_from_seed((const uint8_t *)seed_str, strlen(seed_str), curve_name,
-                   node);
-  ck_assert_int_eq(hdnode_fill_public_key(node), 0);
-  if (node->public_key[0] == 1) {
-    node->public_key[0] = 0x40;  // Curve25519 public keys start with 0x40 byte
-  }
-}
-
-static void test_bip32_ecdh(const char *curve_name, int expected_key_size,
-                            const uint8_t *expected_key) {
-  int res, key_size;
-  HDNode alice, bob;
-  uint8_t session_key1[expected_key_size], session_key2[expected_key_size];
-
-  test_bip32_ecdh_init_node(&alice, "Alice", curve_name);
-  test_bip32_ecdh_init_node(&bob, "Bob", curve_name);
-
-  // Generate shared key from Alice's secret key and Bob's public key
-  res = hdnode_get_shared_key(&alice, bob.public_key, session_key1, &key_size);
-  ck_assert_int_eq(res, 0);
-  ck_assert_int_eq(key_size, expected_key_size);
-  ck_assert_mem_eq(session_key1, expected_key, key_size);
-
-  // Generate shared key from Bob's secret key and Alice's public key
-  res = hdnode_get_shared_key(&bob, alice.public_key, session_key2, &key_size);
-  ck_assert_int_eq(res, 0);
-  ck_assert_int_eq(key_size, expected_key_size);
-  ck_assert_mem_eq(session_key2, expected_key, key_size);
-}
-
-START_TEST(test_bip32_ecdh_nist256p1) {
-  test_bip32_ecdh(
-      NIST256P1_NAME, 65,
-      fromhex(
-          "044aa56f917323f071148cd29aa423f6bee96e7fe87f914d0b91a0f95388c6631646"
-          "ea92e882773d7b0b1bec356b842c8559a1377673d3965fb931c8fe51e64873"));
-}
-END_TEST
-
-START_TEST(test_bip32_ecdh_curve25519) {
-  test_bip32_ecdh(CURVE25519_NAME, 33,
-                  fromhex("04f34e35516325bb0d4a58507096c444a05ba13524ccf66910f1"
-                          "1ce96c62224169"));
-}
-END_TEST
-
-START_TEST(test_bip32_ecdh_errors) {
-  HDNode node;
-  const uint8_t peer_public_key[65] = {0};  // invalid public key
-  uint8_t session_key[65];
-  int res, key_size = 0;
-
-  test_bip32_ecdh_init_node(&node, "Seed", ED25519_NAME);
-  res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size);
-  ck_assert_int_eq(res, 1);
-  ck_assert_int_eq(key_size, 0);
-
-  test_bip32_ecdh_init_node(&node, "Seed", CURVE25519_NAME);
-  res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size);
-  ck_assert_int_eq(res, 1);
-  ck_assert_int_eq(key_size, 0);
-
-  test_bip32_ecdh_init_node(&node, "Seed", NIST256P1_NAME);
-  res = hdnode_get_shared_key(&node, peer_public_key, session_key, &key_size);
-  ck_assert_int_eq(res, 1);
-  ck_assert_int_eq(key_size, 0);
-}
-END_TEST
-
-START_TEST(test_output_script) {
-  static const char *vectors[] = {
-      "76A914010966776006953D5567439E5E39F86A0D273BEE88AC",
-      "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
-      "A914010966776006953D5567439E5E39F86A0D273BEE87",
-      "31nVrspaydBz8aMpxH9WkS2DuhgqS1fCuG",
-      "0014010966776006953D5567439E5E39F86A0D273BEE",
-      "p2xtZoXeX5X8BP8JfFhQK2nD3emtjch7UeFm",
-      "00200102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
-      "7XhPD7te3C6CVKnJWUhrTJbFTwudhHqfrjpS59AS6sMzL4RYFiCNg",
-      0,
-      0,
-  };
-  const char **scr, **adr;
-  scr = vectors;
-  adr = vectors + 1;
-  char address[60];
-  while (*scr && *adr) {
-    int r =
-        script_output_to_address(fromhex(*scr), strlen(*scr) / 2, address, 60);
-    ck_assert_uint_eq((size_t)r, strlen(*adr) + 1);
-    ck_assert_str_eq(address, *adr);
-    scr += 2;
-    adr += 2;
-  }
-}
-END_TEST
-
-START_TEST(test_ethereum_pubkeyhash) {
-  uint8_t pubkeyhash[20];
-  int res;
-  HDNode node;
-
-  // init m
-  hdnode_from_seed(fromhex("000102030405060708090a0b0c0d0e0f"), 16,
-                   SECP256K1_NAME, &node);
-
-  // [Chain m]
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("056db290f8ba3250ca64a45d16284d04bc6f5fbf"), 20);
-
-  // [Chain m/0']
-  hdnode_private_ckd_prime(&node, 0);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("bf6e48966d0dcf553b53e7b56cb2e0e72dca9e19"), 20);
-
-  // [Chain m/0'/1]
-  hdnode_private_ckd(&node, 1);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("29379f45f515c494483298225d1b347f73d1babf"), 20);
-
-  // [Chain m/0'/1/2']
-  hdnode_private_ckd_prime(&node, 2);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("d8e85fbbb4b3b3c71c4e63a5580d0c12fb4d2f71"), 20);
-
-  // [Chain m/0'/1/2'/2]
-  hdnode_private_ckd(&node, 2);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("1d3462d2319ac0bfc1a52e177a9d372492752130"), 20);
-
-  // [Chain m/0'/1/2'/2/1000000000]
-  hdnode_private_ckd(&node, 1000000000);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("73659c60270d326c06ac204f1a9c63f889a3d14b"), 20);
-
-  // init m
-  hdnode_from_seed(
-      fromhex(
-          "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c"
-          "999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"),
-      64, SECP256K1_NAME, &node);
-
-  // [Chain m]
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("6dd2a6f3b05fd15d901fbeec61b87a34bdcfb843"), 20);
-
-  // [Chain m/0]
-  hdnode_private_ckd(&node, 0);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("abbcd4471a0b6e76a2f6fdc44008fe53831e208e"), 20);
-
-  // [Chain m/0/2147483647']
-  hdnode_private_ckd_prime(&node, 2147483647);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("40ef2cef1b2588ae862e7a511162ec7ff33c30fd"), 20);
-
-  // [Chain m/0/2147483647'/1]
-  hdnode_private_ckd(&node, 1);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("3f2e8905488f795ebc84a39560d133971ccf9b50"), 20);
-
-  // [Chain m/0/2147483647'/1/2147483646']
-  hdnode_private_ckd_prime(&node, 2147483646);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("a5016fdf975f767e4e6f355c7a82efa69bf42ea7"), 20);
-
-  // [Chain m/0/2147483647'/1/2147483646'/2]
-  hdnode_private_ckd(&node, 2);
-  res = hdnode_get_ethereum_pubkeyhash(&node, pubkeyhash);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(pubkeyhash,
-                   fromhex("8ff2a9f7e7917804e8c8ec150d931d9c5a6fbc50"), 20);
-}
-END_TEST
-
-START_TEST(test_ethereum_address) {
-  static const char *vectors[] = {"0x52908400098527886E0F7030069857D2E4169EE7",
-                                  "0x8617E340B3D01FA5F11F306F4090FD50E238070D",
-                                  "0xde709f2102306220921060314715629080e2fb77",
-                                  "0x27b1fdb04752bbc536007a920d24acb045561c26",
-                                  "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
-                                  "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359",
-                                  "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB",
-                                  "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb",
-                                  "0x5A4EAB120fB44eb6684E5e32785702FF45ea344D",
-                                  "0x5be4BDC48CeF65dbCbCaD5218B1A7D37F58A0741",
-                                  "0xa7dD84573f5ffF821baf2205745f768F8edCDD58",
-                                  "0x027a49d11d118c0060746F1990273FcB8c2fC196",
-                                  "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
-                                  0};
-  uint8_t addr[20];
-  char address[43];
-  const char **vec = vectors;
-  while (*vec) {
-    memcpy(addr, fromhex(*vec + 2), 20);
-    ethereum_address_checksum(addr, address, false, 0);
-    ck_assert_str_eq(address, *vec);
-    vec++;
-  }
-}
-END_TEST
-
-// test vectors from
-// https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md
-START_TEST(test_rsk_address) {
-  uint8_t addr[20];
-  char address[43];
-
-  static const char *rskip60_chain30[] = {
-      "0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD",
-      "0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359",
-      "0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB",
-      "0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB", 0};
-  const char **vec = rskip60_chain30;
-  while (*vec) {
-    memcpy(addr, fromhex(*vec + 2), 20);
-    ethereum_address_checksum(addr, address, true, 30);
-    ck_assert_str_eq(address, *vec);
-    vec++;
-  }
-
-  static const char *rskip60_chain31[] = {
-      "0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd",
-      "0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359",
-      "0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB",
-      "0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB", 0};
-  vec = rskip60_chain31;
-  while (*vec) {
-    memcpy(addr, fromhex(*vec + 2), 20);
-    ethereum_address_checksum(addr, address, true, 31);
-    ck_assert_str_eq(address, *vec);
-    vec++;
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/1.test-keys.dat
-START_TEST(test_nem_address) {
-  static const struct {
-    const char *private_key;
-    const char *public_key;
-    const char *address;
-  } tests[] = {
-      {
-          "575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced",
-          "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
-          "NDD2CT6LQLIYQ56KIXI3ENTM6EK3D44P5JFXJ4R4",
-      },
-      {
-          "5b0e3fa5d3b49a79022d7c1e121ba1cbbf4db5821f47ab8c708ef88defc29bfe",
-          "96eb2a145211b1b7ab5f0d4b14f8abc8d695c7aee31a3cfc2d4881313c68eea3",
-          "NABHFGE5ORQD3LE4O6B7JUFN47ECOFBFASC3SCAC",
-      },
-      {
-          "738ba9bb9110aea8f15caa353aca5653b4bdfca1db9f34d0efed2ce1325aeeda",
-          "2d8425e4ca2d8926346c7a7ca39826acd881a8639e81bd68820409c6e30d142a",
-          "NAVOZX4HDVOAR4W6K4WJHWPD3MOFU27DFHC7KZOZ",
-      },
-      {
-          "e8bf9bc0f35c12d8c8bf94dd3a8b5b4034f1063948e3cc5304e55e31aa4b95a6",
-          "4feed486777ed38e44c489c7c4e93a830e4c4a907fa19a174e630ef0f6ed0409",
-          "NBZ6JK5YOCU6UPSSZ5D3G27UHAPHTY5HDQMGE6TT",
-      },
-      {
-          "c325ea529674396db5675939e7988883d59a5fc17a28ca977e3ba85370232a83",
-          "83ee32e4e145024d29bca54f71fa335a98b3e68283f1a3099c4d4ae113b53e54",
-          "NCQW2P5DNZ5BBXQVGS367DQ4AHC3RXOEVGRCLY6V",
-      },
-      {
-          "a811cb7a80a7227ae61f6da536534ee3c2744e3c7e4b85f3e0df3c6a9c5613df",
-          "6d34c04f3a0e42f0c3c6f50e475ae018cfa2f56df58c481ad4300424a6270cbb",
-          "NA5IG3XFXZHIPJ5QLKX2FBJPEZYPMBPPK2ZRC3EH",
-      },
-      {
-          "9c66de1ec77f4dfaaebdf9c8bc599ca7e8e6f0bc71390ffee2c9dd3f3619242a",
-          "a8fefd72a3b833dc7c7ed7d57ed86906dac22f88f1f4331873eb2da3152a3e77",
-          "NAABHVFJDBM74XMJJ52R7QN2MTTG2ZUXPQS62QZ7",
-      },
-      {
-          "c56bc16ecf727878c15e24f4ae68569600ac7b251218a44ef50ce54175776edc",
-          "c92f761e6d83d20068fd46fe4bd5b97f4c6ba05d23180679b718d1f3e4fb066e",
-          "NCLK3OLMHR3F2E3KSBUIZ4K5PNWUDN37MLSJBJZP",
-      },
-      {
-          "9dd73599283882fa1561ddfc9be5830b5dd453c90465d3fe5eeb646a3606374e",
-          "eaf16a4833e59370a04ccd5c63395058de34877b48c17174c71db5ed37b537ed",
-          "ND3AHW4VTI5R5QE5V44KIGPRU5FBJ5AFUCJXOY5H",
-      },
-      {
-          "d9639dc6f49dad02a42fd8c217f1b1b4f8ce31ccd770388b645e639c72ff24fa",
-          "0f74a2f537cd9c986df018994dde75bdeee05e35eb9fe27adf506ca8475064f7",
-          "NCTZ4YAP43ONK3UYTASQVNDMBO24ZHJE65F3QPYE",
-      },
-      {
-          "efc1992cd50b70ca55ac12c07aa5d026a8b78ffe28a7dbffc9228b26e02c38c1",
-          "2ebff201255f6cf948c78f528658b99a7c13ac791942fa22d59af610558111f5",
-          "NDQ2TMCMXBSFPZQPE2YKH6XLC24HD6LUMN6Z4GIC",
-      },
-      {
-          "143a815e92e43f3ed1a921ee48cd143931b88b7c3d8e1e981f743c2a5be3c5ba",
-          "419ed11d48730e4ae2c93f0ea4df853b8d578713a36dab227517cf965861af4e",
-          "NA32IDDW2C53BDSBJNFL3Z6UU3J5CJZJMCZDXCF4",
-      },
-      {
-          "bc1a082f5ac6fdd3a83ade211e5986ac0551bad6c7da96727ec744e5df963e2a",
-          "a160e6f9112233a7ce94202ed7a4443e1dac444b5095f9fecbb965fba3f92cac",
-          "NADUCEQLC3FTGB25GTA5HOUTB53CBVQNVOIP7NTJ",
-      },
-      {
-          "4e47b4c6f4c7886e49ec109c61f4af5cfbb1637283218941d55a7f9fe1053f72",
-          "fbb91b16df828e21a9802980a44fc757c588bc1382a4cea429d6fa2ae0333f56",
-          "NBAF3BFLLPWH33MYE6VUPP5T6DQBZBKIDEQKZQOE",
-      },
-      {
-          "efc4389da48ce49f85365cfa578c746530e9eac42db1b64ec346119b1becd347",
-          "2232f24dda0f2ded3ecd831210d4e8521a096b50cadd5a34f3f7083374e1ec12",
-          "NBOGTK2I2ATOGGD7ZFJHROG5MWL7XCKAUKSWIVSA",
-      },
-      {
-          "bdba57c78ca7da16a3360efd13f06276284db8c40351de7fcd38ba0c35ac754d",
-          "c334c6c0dad5aaa2a0d0fb4c6032cb6a0edd96bf61125b5ea9062d5a00ee0eee",
-          "NCLERTEFYXKLK7RA4MVACEFMXMK3P7QMWTM7FBW2",
-      },
-      {
-          "20694c1ec3c4a311bcdb29ed2edc428f6d4f9a4c429ad6a5bf3222084e35695f",
-          "518c4de412efa93de06a55947d11f697639443916ec8fcf04ebc3e6d17d0bd93",
-          "NB5V4BPIJHXVONO7UGMJDPFARMFA73BOBNOOYCOV",
-      },
-      {
-          "e0d4f3760ac107b33c22c2cac24ab2f520b282684f5f66a4212ff95d926323ce",
-          "b3d16f4ead9de67c290144da535a0ed2504b03c05e5f1ceb8c7863762f786857",
-          "NC4PBAO5TPCAVQKBVOC4F6DMZP3CFSQBU46PSKBD",
-      },
-      {
-          "efa9afc617412093c9c7a7c211a5332dd556f941e1a88c494ec860608610eea2",
-          "7e7716e4cebceb731d6f1fd28676f34888e9a0000fcfa1471db1c616c2ddf559",
-          "NCFW2LPXIWLBWAQN2QVIWEOD7IVDO3HQBD2OU56K",
-      },
-      {
-          "d98499b3db61944684ce06a91735af4e14105338473fcf6ebe2b0bcada3dfd21",
-          "114171230ad6f8522a000cdc73fbc5c733b30bb71f2b146ccbdf34499f79a810",
-          "NCUKWDY3J3THKQHAKOK5ALF6ANJQABZHCH7VN6DP",
-      },
-  };
-
-  HDNode node;
-  ed25519_secret_key private_key;
-  uint8_t chain_code[32];
-  char address[41];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    nem_private_key(tests[i].private_key, private_key);
-
-    ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key,
-                               ED25519_KECCAK_NAME, &node));
-
-    ck_assert(hdnode_get_nem_address(&node, NEM_NETWORK_MAINNET, address));
-    ck_assert_str_eq(address, tests[i].address);
-
-    ck_assert_mem_eq(&node.public_key[1], fromhex(tests[i].public_key), 32);
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/3.test-derive.dat
-START_TEST(test_nem_derive) {
-  static const struct {
-    const char *salt;
-    const char *private_key;
-    const char *public_key;
-    const char *mul;
-    const char *shared_key;
-  } tests[] = {
-      {
-          "ad63ac08f9afc85eb0bf4f8881ca6eaa0215924c87aa2f137d56109bb76c6f98",
-          "e8857f8e488d4e6d4b71bcd44bb4cff49208c32651e1f6500c3b58cafeb8def6",
-          "9d8e5f200b05a2638fb084a375408cabd6d5989590d96e3eea5f2cb34668178e",
-          "a8352060ba5718745ee4d78b9df564e0fbe13f50d50ab15a8dd524159d81d18b",
-          "990a5f611c65fbcde735378bdec38e1039c5466503511e8c645bbe42795c752b",
-      },
-      {
-          "96104f0a28f9cca40901c066cd435134662a3b053eb6c8df80ee0d05dc941963",
-          "d7f67b5f52cbcd1a1367e0376a8eb1012b634acfcf35e8322bae8b22bb9e8dea",
-          "9735c92d150dcee0ade5a8d1822f46a4db22c9cda25f33773ae856fe374a3e8a",
-          "ea14d521d83328dba70982d42094300585818cc2da609fdb1f73bb32235576ff",
-          "b498aa21d4ba4879ea9fd4225e93bacc760dcd9c119f8f38ab0716457d1a6f85",
-      },
-      {
-          "d8f94a0bbb1de80aea17aab42e2ffb982e73fc49b649a318479e951e392d8728",
-          "d026ddb445fb3bbf3020e4b55ed7b5f9b7fd1278c34978ca1a6ed6b358dadbae",
-          "d19e6beca3b26b9d1abc127835ebeb7a6c19c33dec8ec472e1c4d458202f4ec8",
-          "0d561f54728ad837ae108ec66c2ece2bb3b26041d3ee9b77fdc6d36d9ebfb2e3",
-          "d012afe3d1d932304e613c91545bf571cf2c7281d6cafa8e81393a551f675540",
-      },
-      {
-          "3f8c969678a8abdbfb76866a142c284a6f01636c1c1607947436e0d2c30d5245",
-          "c522b38c391d1c3fa539cc58802bc66ac34bb3c73accd7f41b47f539bedcd016",
-          "ea5b6a0053237f7712b1d2347c447d3e83e0f2191762d07e1f53f8eb7f2dfeaa",
-          "23cccd3b63a9456e4425098b6df36f28c8999461a85e4b2b0c8d8f53c62c9ea9",
-          "7e27efa50eed1c2ac51a12089cbab6a192624709c7330c016d5bc9af146584c1",
-      },
-      {
-          "e66415c58b981c7f1f2b8f45a42149e9144616ff6de49ff83d97000ac6f6f992",
-          "2f1b82be8e65d610a4e588f000a89a733a9de98ffc1ac9d55e138b3b0a855da0",
-          "65aeda1b47f66c978a4a41d4dcdfbd8eab5cdeb135695c2b0c28f54417b1486d",
-          "43e5b0a5cc8146c03ac63e6f8cf3d8825a9ca1ed53ea4a88304af4ddf5461b33",
-          "bb4ab31c334e55d378937978c90bb33779b23cd5ef4c68342a394f4ec8fa1ada",
-      },
-      {
-          "58487c9818c9d28ddf97cb09c13331941e05d0b62bf4c35ee368de80b552e4d1",
-          "f3869b68183b2e4341307653e8f659bd7cd20e37ea5c00f5a9e203a8fa92359a",
-          "c7e4153a18b4162f5c1f60e1ba483264aa5bb3f4889dca45b434fcd30b9cf56f",
-          "5ae9408ab3156b8828c3e639730bd5e5db93d7afe2cee3fcda98079316c5bb3a",
-          "0224d85ae8f17bfe127ec24b8960b7639a0dbde9c8c39a0575b939448687bb14",
-      },
-      {
-          "ad66f3b654844e53d6fb3568134fae75672ba63868c113659d3ca58c2c39d24f",
-          "d38f2ef8dfdc7224fef596130c3f4ff68ac83d3f932a56ee908061466ac28572",
-          "d0c79d0340dc66f0a895ce5ad60a933cf6be659569096fb9d4b81e5d32292372",
-          "1ea22db4708ed585ab541a4c70c3069f8e2c0c1faa188ddade3efaa53c8329f6",
-          "886a7187246934aedf2794748deadfe038c9fd7e78d4b7be76c5a651440ac843",
-      },
-      {
-          "eed48604eab279c6ad8128aa83483a3da0928271a4cae1a5745671284e1fb89d",
-          "e2342a8450fc0adfa0ea2fbd0b1d28f100f0a3a905a3da29de34d1353afa7df7",
-          "d2dbe07e0f2dbc3dbb01c70092e3c4247d12827ddcd8d76534fd740a65c30de2",
-          "4c4b30eb6a2bfa17312f5729b4212cb51c2eee8fbfaea82a0e957ca68f4f6a30",
-          "dcae613ac5641ff9d4c3ca58632245f93b0b8657fe4d48bac7b062cc53dd21ad",
-      },
-      {
-          "f35b315287b268c0d0b386fb5b31810f65e1c4497cffae24527f69a3abac3884",
-          "049016230dbef7a14a439e5ab2f6d12e78cb8df127db4e0c312673b3c361e350",
-          "1b3b1925a8a535cd7d78725d25298f45bba8ca3dee2cdaabf14241c9b51b37c4",
-          "04c9685dae1f8eb72a6438f24a87dc83a56d79c9024edf7e01aa1ae34656f29e",
-          "b48469d0428c223b93cd1fe34bb2cafd3fb78a8fa15f98f89f1ac9c0ce7c9001",
-      },
-      {
-          "d6cf082c5d9a96e756a94a2e27703138580a7c7c1af505c96c3abf7ab6802e1d",
-          "67cd02b0b8b0adcf6fdd4d4d64a1f4193ced68bb8605d0ec941a62011326d140",
-          "a842d5127c93a435e4672dcadd9fccbfd0e9208c79c5404848b298597eccdbdb",
-          "d5c6bd6d81b99659d0bafe91025b6ecf73b16c6b07931cf44718b13f00fde3f7",
-          "8aa160795b587f4be53aa35d26e9b618b4cd6ec765b523bc908e53c258ca8fd4",
-      },
-      {
-          "dda32c91c95527a645b00dd05d13f0b98ed612a726ce5f5221431430b7660944",
-          "eba026f92a8ffb5e95060a22e15d597fe838a99a0b2bbcb423c933b6bc718c50",
-          "7dbaf9c313a1ff9128c54d6cd740c7d0cc46bca588e7910d438dd619ca4fd69a",
-          "5bb20a145de83ba27a0c261e1f54bfd7dcea61888fc2eebbe6166876f7b000b8",
-          "3a96f152ad8bf355cccb307e4a40108aa17f8e925522a2b5bb0b3f1e1a262914",
-      },
-      {
-          "63c500acbd4ff747f7dadde7d3286482894ac4d7fe68f396712bca29879aa65c",
-          "9663cd3c2030a5fe4a3ea3cc9a1d182b3a63ade68616aaeb4caf40b495f6f227",
-          "b1e7d9070ac820d986d839b79f7aa594dcf708473529dad87af8682cc6197374",
-          "1f7a97584d8db9f395b9ac4447de4b33c5c1f5020187cd4996286a49b07eb8a7",
-          "4d2a974ec12dcf525b5654d31053460850c3092648b7e15598b7131d2930e9fb",
-      },
-      {
-          "91f340961029398cc8bcd906388044a6801d24328efdf919d8ed0c609862a073",
-          "45a588500d00142e2226231c01fd11ac6f842ab6a85872418f5b6a1999f8bd98",
-          "397233c96069b6f4a57d6e93f759fa327222eaef71fc981afa673b248206df3f",
-          "062123ef9782e3893f7b2e1d557b4ecce92b9f9aa8577e76380f228b75152f84",
-          "235848cb04230a16d8978aa7c19fe7fbff3ebe29389ea6eb24fb8bc3cb50afc6",
-      },
-      {
-          "46120b4da6ba4eb54fb65213cfef99b812c86f7c42a1de1107f8e8c12c0c3b6b",
-          "cc19a97a99ad71ce348bcf831c0218e6a1f0a8d52186cabe6298b56f24e640f9",
-          "c54631bb62f0f9d86b3301fcb2a671621e655e578c95504af5f78da83f7fec4f",
-          "ab73cc20c75260ff3a7cefea8039291d4d15114a07a9250375628cca32225bb6",
-          "70040a360b6a2dfa881272ef4fa6616e2e8fcc45194fa2a21a1eef1160271cd5",
-      },
-      {
-          "f0a69ded09f1d731ab9561d0c3a40b7ef30bcb2bf60f92beccd8734e2441403d",
-          "ea732822a381c46a7ac9999bf5ef85e16b7460b26aaf6c1a1c6ffa8c8c82c923",
-          "110decbff79c382b1e60af4259564a3c473087792350b24fca98ae9a74ba9dd9",
-          "81bdee95aecdcf821a9d682f79056f1abdcf1245d2f3b55244447881a283e0d4",
-          "1bc29d4470ccf97d4e35e8d3cd4b12e3ebf2cb0a82425d35984aeedf7ad0f6f9",
-      },
-      {
-          "e79cf4536fb1547e57626c0f1a87f71a396fdfb985b00731c0c2876a00645eda",
-          "04213fc02b59c372e3e7f53faa71a2f73b31064102cb6fc8b68432ba7cdf7eb4",
-          "ca1c750aaed53bc30dac07d0696ed86bcd7cdbbcbd3d15bb90d90cb5c6117bac",
-          "c68cd0872a42a3a64e8a229ef7fcad3d722047d5af966f7dda4d4e32d0d57203",
-          "bfdd3d07563d966d95afe4b8abea4b567265fceea8c4ecddb0946256c33e07b2",
-      },
-      {
-          "81a40db4cddaf076e0206bd2b0fa7470a72cc456bad34aa3a0469a4859f286be",
-          "52156799fd86cc63345cdbffd65ef4f5f8df0ffd9906a40af5f41d269bbcff5d",
-          "54d61aa0b0b17a87f1376fe89cd8cd6b314827c1f1b9e5e7b20e7a7eee2a8335",
-          "4553fb2cab8555068c32f86ceb692bbf1c2beeaf21627ef1b1be57344b52eea8",
-          "55096b6710ade3bbe38702458ee13faa10c24413261bc076f17675dcbf2c4ee6",
-      },
-      {
-          "d28e4a9e6832a3a4dad014a2bf1f666f01093cbba8b9ad4d1dcad3ea10cb42b9",
-          "8ca134404c8fa199b0c72cb53cfa0adcf196dfa560fb521017cce5cbace3ba59",
-          "3a6c39a1e5f9f550f1debedd9a0bc84210cce5f9834797db8f14122bf5817e45",
-          "eb632ca818b4f659630226a339a3ce536b31c8e1e686fea8da3760e8abc20b8e",
-          "9fbb3fbaf1cd54ee0cd90685f59b082545983f1f662ef701332379306a6ad546",
-      },
-      {
-          "f9c4bfad9e2a3d98c44c12734881a6f217d6c9523cc210772fad1297993454b4",
-          "b85960fcadda8d0a0960559b6b7818a0d8d4574b4e928b17c9b498fa9ffab4ef",
-          "6a1d0ef23ce0b40a7077ecb7b7264945054e3bdb58ee25e1b0ee8b3e19dbfcdc",
-          "bb145dddcb75074a6a03249fca1aa7d6fa9549e3ed965f138ca5e7071b7878f2",
-          "87d3faea4a98e41009eb8625611ea0fc12094c295af540c126c14a0f55afa76e",
-      },
-      {
-          "656df4789a369d220aceb7b318517787d27004ecccedea019d623bcb2d79f5ff",
-          "acf83e30afb2a5066728ec5d93564c08abe5e68e3a2a2ff953bdcf4d44f9da06",
-          "bdda65efe56d7890286aada1452f62f85ba157d0b4621ba641de15d8d1c9e331",
-          "958beef5dc6babc6de383c32ad7dd3a6d6eb8bb3236ed5558eec0f9eb31e5458",
-          "6f6d4ee36d9d76e462c9635adfbb6073134a276cfc7cb86762004ec47197afa0",
-      },
-  };
-
-  HDNode node;
-  ed25519_secret_key private_key;
-  uint8_t chain_code[32];
-  ed25519_public_key public_key, mul;
-  uint8_t shared_key[SHA3_256_DIGEST_LENGTH];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    nem_private_key(tests[i].private_key, private_key);
-
-    ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key,
-                               ED25519_KECCAK_NAME, &node));
-    memcpy(public_key, fromhex(tests[i].public_key), 32);
-
-    ck_assert(hdnode_get_nem_shared_key(
-        &node, public_key, fromhex(tests[i].salt), mul, shared_key));
-    ck_assert_mem_eq(mul, fromhex(tests[i].mul), sizeof(mul));
-    ck_assert_mem_eq(shared_key, fromhex(tests[i].shared_key),
-                     sizeof(shared_key));
-  }
-}
-END_TEST
-
-// test vectors from
-// https://raw.githubusercontent.com/NemProject/nem-test-vectors/master/4.test-cipher.dat
-START_TEST(test_nem_cipher) {
-  static const struct {
-    const char *private_key;
-    const char *public_key;
-    const char *salt;
-    const char *iv;
-    const char *input;
-    const char *output;
-  } tests[] = {
-      {
-          "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6",
-          "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21",
-          "83616c67f076d356fd1288a6e0fd7a60488ba312a3adf0088b1b33c7655c3e6a",
-          "a73ff5c32f8fd055b09775817a6a3f95",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "70815da779b1b954d7a7f00c16940e9917a0412a06a444b539bf147603eef87f",
-      },
-      {
-          "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6",
-          "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21",
-          "703ce0b1d276b10eef35672df03234385a903460db18ba9d4e05b3ad31abb284",
-          "91246c2d5493867c4fa3e78f85963677",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "564b2f40d42c0efc1bd6f057115a5abd1564cae36d7ccacf5d825d38401aa894",
-      },
-      {
-          "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6",
-          "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21",
-          "b22e8e8e7373ac31ca7f0f6eb8b93130aba5266772a658593f3a11792e7e8d92",
-          "9f8e33d82374dad6aac0e3dbe7aea704",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "7cab88d00a3fc656002eccbbd966e1d5d14a3090d92cf502cdbf843515625dcf",
-      },
-      {
-          "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6",
-          "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21",
-          "af646c54cd153dffe453b60efbceeb85c1e95a414ea0036c4da94afb3366f5d9",
-          "6acdf8e01acc8074ddc807281b6af888",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "aa70543a485b63a4dd141bb7fd78019092ac6fad731e914280a287c7467bae1a",
-      },
-      {
-          "3140f94c79f249787d1ec75a97a885980eb8f0a7d9b7aa03e7200296e422b2b6",
-          "57a70eb553a7b3fd621f0dba6abf51312ea2e2a2a1e19d0305516730f4bcbd21",
-          "d9c0d386636c8a024935c024589f9cd39e820a16485b14951e690a967830e269",
-          "f2e9f18aeb374965f54d2f4e31189a8f",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "33d97c216ea6498dfddabf94c2e2403d73efc495e9b284d9d90aaff840217d25",
-      },
-      {
-          "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a",
-          "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04",
-          "06c227baac1ae3b0b1dc583f4850f13f9ba5d53be4a98fa5c3ea16217847530d",
-          "3735123e78c44895df6ea33fa57e9a72",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "d5b5d66ba8cee0eb7ecf95b143fa77a46d6de13749e12eff40f5a7e649167ccb",
-      },
-      {
-          "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a",
-          "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04",
-          "92f55ba5bc6fc2f23e3eedc299357c71518e36ba2447a4da7a9dfe9dfeb107b5",
-          "1cbc4982e53e370052af97ab088fa942",
-          "86ddb9e713a8ebf67a51830eff03b837e147c20d75e67b2a54aa29e98c",
-          "d48ef1ef526d805656cfc932aff259eadb17aa3391dde1877a722cba31d935b2",
-      },
-      {
-          "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a",
-          "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04",
-          "10f15a39ba49866292a43b7781bc71ca8bbd4889f1616461caf056bcb91b0158",
-          "c40d531d92bfee969dce91417346c892",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "e6d75afdb542785669b42198577c5b358d95397d71ec6f5835dca46d332cc08dbf73"
-          "ea790b7bcb169a65719c0d55054c",
-      },
-      {
-          "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a",
-          "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04",
-          "9c01ed42b219b3bbe1a43ae9d7af5c1dd09363baacfdba8f4d03d1046915e26e",
-          "059a35d5f83249e632790015ed6518b9",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "5ef11aadff2eccee8b712dab968fa842eb770818ec0e6663ed242ea8b6bbc1c66d62"
-          "85ee5b5f03d55dfee382fb4fa25d",
-      },
-      {
-          "d5c0762ecea2cd6b5c56751b58debcb32713aab348f4a59c493e38beb3244f3a",
-          "66a35941d615b5644d19c2a602c363ada8b1a8a0dac3682623852dcab4afac04",
-          "bc1067e2a7415ea45ff1ca9894338c591ff15f2e57ae2789ae31b9d5bea0f11e",
-          "8c73f0d6613898daeefa3cf8b0686d37",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "6d220213b1878cd40a458f2a1e6e3b48040455fdf504dcd857f4f2ca1ad642e3a44f"
-          "c401d04e339d302f66a9fad3d919",
-      },
-      {
-          "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921",
-          "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094",
-          "cf4a21cb790552165827b678ca9695fcaf77566d382325112ff79483455de667",
-          "bfbf5482e06f55b88bdd9e053b7eee6e",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "1198a78c29c215d5c450f7b8513ead253160bc9fde80d9cc8e6bee2efe9713cf5a09"
-          "d6293c41033271c9e8c22036a28b",
-      },
-      {
-          "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921",
-          "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094",
-          "eba5eae8aef79114082c3e70baef95bb02edf13b3897e8be7a70272962ef8838",
-          "af9a56da3da18e2fbd2948a16332532b",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "1062ab5fbbdee9042ad35bdadfd3047c0a2127fe0f001da1be1b0582185edfc9687b"
-          "e8d68f85795833bb04af9cedd3bb",
-      },
-      {
-          "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921",
-          "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094",
-          "518f8dfd0c138f1ffb4ea8029db15441d70abd893c3d767dc668f23ba7770e27",
-          "42d28307974a1b2a2d921d270cfce03b",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "005e49fb7c5da540a84b034c853fc9f78a6b901ea495aed0c2abd4f08f1a96f9ffef"
-          "c6a57f1ac09e0aea95ca0f03ffd8",
-      },
-      {
-          "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921",
-          "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094",
-          "582fdf58b53715c26e10ba809e8f2ab70502e5a3d4e9a81100b7227732ab0bbc",
-          "91f2aad3189bb2edc93bc891e73911ba",
-          "49de3cd5890e0cd0559f143807ff688ff62789b7236a332b7d7255ec0b4e73e6b3a"
-          "4",
-          "821a69cb16c57f0cb866e590b38069e35faec3ae18f158bb067db83a11237d29ab1e"
-          "6b868b3147236a0958f15c2e2167",
-      },
-      {
-          "9ef87ba8aa2e664bdfdb978b98bc30fb61773d9298e7b8c72911683eeff41921",
-          "441e76d7e53be0a967181076a842f69c20fd8c0e3f0ce3aa421b490b059fe094",
-          "a415b4c006118fb72fc37b2746ef288e23ac45c8ff7ade5f368a31557b6ac93a",
-          "2b7c5f75606c0b8106c6489ea5657a9e",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "2781d5ee8ef1cb1596f8902b33dfae5045f84a987ca58173af5830dbce386062",
-      },
-      {
-          "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc",
-          "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
-          "47e73ec362ea82d3a7c5d55532ad51d2cdf5316b981b2b2bd542b0efa027e8ea",
-          "b2193f59030c8d05a7d3577b7f64dd33",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "3f43912db8dd6672b9996e5272e18c4b88fec9d7e8372db9c5f4709a4af1d86f",
-      },
-      {
-          "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc",
-          "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
-          "aaa006c57b6d1e402650577fe9787d8d285f4bacd7c01f998be49c766f8860c7",
-          "130304ddb9adc8870cf56bcae9487b7f",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "878cc7d8c0ef8dac0182a78eedc8080a402f59d8062a6b4ca8f4a74f3c3b3de7",
-      },
-      {
-          "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc",
-          "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
-          "28dc7ccd6c2a939eef64b8be7b9ae248295e7fcd8471c22fa2f98733fea97611",
-          "cb13890d3a11bc0a7433738263006710",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "e74ded846bebfa912fa1720e4c1415e6e5df7e7a1a7fedb5665d68f1763209a4",
-      },
-      {
-          "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc",
-          "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
-          "79974fa2cad95154d0873902c153ccc3e7d54b17f2eeb3f29b6344cad9365a9a",
-          "22123357979d20f44cc8eb0263d84e0e",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "eb14dec7b8b64d81a2ee4db07b0adf144d4f79a519bbf332b823583fa2d45405",
-      },
-      {
-          "ed93c5a101ab53382ceee4f7e6b5aa112621d3bb9d18891509b1834ede235bcc",
-          "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
-          "3409a6f8c4dcd9bd04144eb67e55a98696b674735b01bf1196191f29871ef966",
-          "a823a0965969380ea1f8659ea5fd8fdd",
-          "24512b714aefd5cbc4bcc4ef44ce6c67ffc447c65460a6c6e4a92e85",
-          "00a7eb708eae745847173f8217efb05be13059710aee632e3f471ac3c6202b51",
-      },
-      {
-          "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10",
-          "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c",
-          "c25701b9b7328c4ac3d23223d10623bd527c0a98e38ae9c62fbc403c80ab20ae",
-          "4b4ee0e4443779f3af429a749212f476",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "f39f7d66e0fde39ecdf58be2c0ef361a17cfd6843e310adbe0ec3118cd72800d",
-      },
-      {
-          "a73a0b2686f7d699c018b6b08a352856e556070caa329c26241aec889eefde10",
-          "9b493403bee45ae6277430ef8d0c4163ffd81ace2db6c7821205da09a664a86c",
-          "31d18fdffc480310828778496ff817039df5d6f30bf6d9edd0b4396863d05f93",
-          "418bcbdf52860a450bfacc96920d02cf",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "0e6ce9889fe7b3cd82794b0ae27c1f5985d2f2a1f398371a138f8db1df1f54de",
-      },
-      {
-          "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041",
-          "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9",
-          "56b4c645f81dbfb6ba0c6d3f1626e1e5cd648eeb36562715f7cd7e9ea86a0d7f",
-          "dc9bdce76d68d2e4d72267cf4e72b022",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "dc6f046c3008002041517a7c4f3ababe609cf02616fcccda39c075d1be4175f5",
-      },
-      {
-          "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041",
-          "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9",
-          "df180b91986c8c7000792f96d1faa61e30138330430a402322be1855089b0e7f",
-          "ccf9b77341c866465b474e2f4a3b1cf8",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "94e4ae89041437f39826704f02cb5d775226f34344635e592846417497a5020b",
-      },
-      {
-          "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041",
-          "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9",
-          "a0eee7e84c76e63fdae6e938b43330775eaf17d260e40b98c9e6616b668102a7",
-          "662c681cfec6f6d052ff0e2c1255f2c2",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "70bba3c48be9c75a144b1888ca3d21a6b21f52eec133981a024390a6a0ba36f9",
-      },
-      {
-          "e2e4dee102fad0f47f60202269605589cd9cf70f816b34016796c74b766f3041",
-          "c5ce283033a3255ae14d42dff1e4c18a224ac79d084b285123421b105ee654c9",
-          "c6acd2d90eb782c3053b366680ffa0e148de81fea198c87bb643869fd97e5cb0",
-          "908dc33ba80520f2f0f04e7890e3a3c0",
-          "b6926d0ec82cec86c0d27ec9a33a0e0f",
-          "f6efe1d76d270aac264aa35d03049d9ce63be1996d543aef00559219c8666f71",
-      },
-  };
-
-  HDNode node;
-  ed25519_secret_key private_key;
-  uint8_t chain_code[32];
-  ed25519_public_key public_key;
-  uint8_t salt[sizeof(public_key)];
-
-  uint8_t iv[AES_BLOCK_SIZE];
-  uint8_t buffer[FROMHEX_MAXLEN];
-
-  uint8_t input[FROMHEX_MAXLEN];
-  uint8_t output[FROMHEX_MAXLEN];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    nem_private_key(tests[i].private_key, private_key);
-
-    ck_assert(hdnode_from_xprv(0, 0, chain_code, private_key,
-                               ED25519_KECCAK_NAME, &node));
-    memcpy(public_key, fromhex(tests[i].public_key), 32);
-    memcpy(salt, fromhex(tests[i].salt), sizeof(salt));
-
-    size_t input_size = strlen(tests[i].input) / 2;
-    size_t output_size = strlen(tests[i].output) / 2;
-
-    memcpy(input, fromhex(tests[i].input), input_size);
-    memcpy(output, fromhex(tests[i].output), output_size);
-
-    memcpy(iv, fromhex(tests[i].iv), sizeof(iv));
-    ck_assert(hdnode_nem_encrypt(&node, public_key, iv, salt, input, input_size,
-                                 buffer));
-    ck_assert_uint_eq(output_size, NEM_ENCRYPTED_SIZE(input_size));
-    ck_assert_mem_eq(buffer, output, output_size);
-
-    memcpy(iv, fromhex(tests[i].iv), sizeof(iv));
-    ck_assert(hdnode_nem_decrypt(&node, public_key, iv, salt, output,
-                                 output_size, buffer));
-    ck_assert_uint_eq(input_size, NEM_DECRYPTED_SIZE(buffer, output_size));
-    ck_assert_mem_eq(buffer, input, input_size);
-  }
-}
-END_TEST
-
-START_TEST(test_nem_transaction_transfer) {
-  nem_transaction_ctx ctx;
-
-  uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH];
-
-  // http://bob.nem.ninja:8765/#/transfer/0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "e59ef184a612d4c3c4d89b5950eb57262c69862b2f96e59c5043bf41765c482f"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_transfer(
-      &ctx, NEM_NETWORK_TESTNET, 0, NULL, 0, 0,
-      "TBGIMRE4SBFRUJXMH7DVF2IBY36L2EDWZ37GVSC4", 50000000000000, NULL, 0,
-      false, 0));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "0acbf8df91e6a65dc56c56c43d65f31ff2a6a48d06fc66e78c7f3436faf3e74f"),
-      sizeof(hash));
-
-  // http://bob.nem.ninja:8765/#/transfer/3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_transfer(
-      &ctx, NEM_NETWORK_TESTNET, 14072100, NULL, 194000000, 14075700,
-      "TBLOODPLWOWMZ2TARX4RFPOSOWLULHXMROBN2WXI", 3000000,
-      (uint8_t *)"sending you 3 pairs of paddles\n", 31, false, 2));
-
-  ck_assert(
-      nem_transaction_write_mosaic(&ctx, "gimre.games.pong", "paddles", 2));
-
-  ck_assert(nem_transaction_write_mosaic(&ctx, "nem", "xem", 44000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "3409d9ece28d6296d6d5e220a7e3cb8641a3fb235ffcbd20c95da64f003ace6c"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/transfer/e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "8d07f90fb4bbe7715fa327c926770166a11be2e494a970605f2e12557f66c9b9"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_transfer(
-      &ctx, NEM_NETWORK_MAINNET, 0, NULL, 0, 0,
-      "NBT3WHA2YXG2IR4PWKFFMO772JWOITTD2V4PECSB", 5175000000000,
-      (uint8_t *)"Good luck!", 10, false, 0));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "e90e98614c7598fbfa4db5411db1b331d157c2f86b558fb7c943d013ed9f71cb"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/transfer/40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_transfer(
-      &ctx, NEM_NETWORK_MAINNET, 77229, NULL, 30000000, 80829,
-      "NALICEPFLZQRZGPRIJTMJOCPWDNECXTNNG7QLSG3", 30000000,
-      fromhex("4d9dcf9186967d30be93d6d5404ded22812dbbae7c3f0de5"
-              "01bcd7228cba45bded13000eec7b4c6215fc4d3588168c92"
-              "18167cec98e6977359153a4132e050f594548e61e0dc61c1"
-              "53f0f53c5e65c595239c9eb7c4e7d48e0f4bb8b1dd2f5ddc"),
-      96, true, 0));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "40e89160e6f83d37f7c82defc0afe2c1605ae8c919134570a51dd27ea1bb516c"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/transfer/882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "f85ab43dad059b9d2331ddacc384ad925d3467f03207182e01296bacfb242d01"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_transfer(
-      &ctx, NEM_NETWORK_MAINNET, 26730750, NULL, 179500000, 26734350,
-      "NBE223WPKEBHQPCYUC4U4CDUQCRRFMPZLOQLB5OP", 1000000,
-      (uint8_t *)"enjoy! :)", 9, false, 1));
-
-  ck_assert(nem_transaction_write_mosaic(&ctx, "imre.g", "tokens", 1));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "882dca18dcbe075e15e0ec5a1d7e6ccd69cc0f1309ffd3fde227bfbc107b3f6e"),
-      sizeof(hash));
-}
-END_TEST
-
-START_TEST(test_nem_transaction_multisig) {
-  nem_transaction_ctx ctx, other_trans;
-
-  uint8_t buffer[1024], inner[1024];
-  const uint8_t *signature;
-
-  // http://bob.nem.ninja:8765/#/multisig/7d3a7087023ee29005262016706818579a2b5499eb9ca76bad98c1e6f4c46642
-
-  nem_transaction_start(
-      &other_trans,
-      fromhex(
-          "abac2ee3d4aaa7a3bfb65261a00cc04c761521527dd3f2cf741e2815cbba83ac"),
-      inner, sizeof(inner));
-
-  ck_assert(nem_transaction_create_aggregate_modification(
-      &other_trans, NEM_NETWORK_TESTNET, 3939039, NULL, 16000000, 3960639, 1,
-      false));
-
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &other_trans, 2,
-      fromhex(
-          "e6cff9b3725a91f31089c3acca0fac3e341c00b1c8c6e9578f66c4514509c3b3")));
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "59d89076964742ef2a2089d26a5aa1d2c7a7bb052a46c1de159891e91ad3d76e"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_multisig(&ctx, NEM_NETWORK_TESTNET, 3939039,
-                                            NULL, 6000000, 3960639,
-                                            &other_trans));
-
-  signature = fromhex(
-      "933930a8828b560168bddb3137df9252048678d829aa5135fa27bb306ff6562efb927554"
-      "62988b852b0314bde058487d00e47816b6fb7df6bcfd7e1f150d1d00");
-  ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset,
-                                            ctx.public_key, signature),
-                   0);
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "71cba4f2a28fd19f902ba40e9937994154d9eeaad0631d25d525ec37922567d4"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_TESTNET,
-                                                      3939891, NULL, 6000000,
-                                                      3961491, &other_trans));
-
-  signature = fromhex(
-      "a849f13bfeeba808a8a4a79d579febe584d831a3a6ad03da3b9d008530b3d7a79fcf7156"
-      "121cd7ee847029d94af7ea7a683ca8e643dc5e5f489557c2054b830b");
-  ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset,
-                                            ctx.public_key, signature),
-                   0);
-
-  // http://chain.nem.ninja/#/multisig/1016cf3bdd61bd57b9b2b07b6ff2dee390279d8d899265bdc23d42360abe2e6c
-
-  nem_transaction_start(
-      &other_trans,
-      fromhex(
-          "a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"),
-      inner, sizeof(inner));
-
-  ck_assert(nem_transaction_create_provision_namespace(
-      &other_trans, NEM_NETWORK_MAINNET, 59414272, NULL, 20000000, 59500672,
-      "dim", NULL, "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 5000000000));
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "cfe58463f0eaebceb5d00717f8aead49171a5d7c08f6b1299bd534f11715acc9"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_multisig(&ctx, NEM_NETWORK_MAINNET, 59414272,
-                                            NULL, 6000000, 59500672,
-                                            &other_trans));
-
-  signature = fromhex(
-      "52a876a37511068fe214bd710b2284823921ec7318c01e083419a062eae5369c9c11c3ab"
-      "fdb590f65c717fab82873431d52be62e10338cb5656d1833bbdac70c");
-  ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset,
-                                            ctx.public_key, signature),
-                   0);
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "1b49b80203007117d034e45234ffcdf402c044aeef6dbb06351f346ca892bce2"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_MAINNET,
-                                                      59414342, NULL, 6000000,
-                                                      59500742, &other_trans));
-
-  signature = fromhex(
-      "b9a59239e5d06992c28840034ff7a7f13da9c4e6f4a6f72c1b1806c3b602f83a7d727a34"
-      "5371f5d15abf958208a32359c6dd77bde92273ada8ea6fda3dc76b00");
-  ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset,
-                                            ctx.public_key, signature),
-                   0);
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "7ba4b39209f1b9846b098fe43f74381e43cb2882ccde780f558a63355840aa87"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_multisig_signature(&ctx, NEM_NETWORK_MAINNET,
-                                                      59414381, NULL, 6000000,
-                                                      59500781, &other_trans));
-
-  signature = fromhex(
-      "e874ae9f069f0538008631d2df9f2e8a59944ff182e8672f743d2700fb99224aafb7a0ab"
-      "09c4e9ea39ee7c8ca04a8a3d6103ae1122d87772e871761d4f00ca01");
-  ck_assert_int_eq(ed25519_sign_open_keccak(ctx.buffer, ctx.offset,
-                                            ctx.public_key, signature),
-                   0);
-}
-END_TEST
-
-START_TEST(test_nem_transaction_provision_namespace) {
-  nem_transaction_ctx ctx;
-
-  uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH];
-
-  // http://bob.nem.ninja:8765/#/namespace/f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_provision_namespace(
-      &ctx, NEM_NETWORK_TESTNET, 56999445, NULL, 20000000, 57003045, "gimre",
-      NULL, "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "f7cab28da57204d01a907c697836577a4ae755e6c9bac60dcc318494a22debb3"),
-      sizeof(hash));
-
-  // http://bob.nem.ninja:8765/#/namespace/7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_provision_namespace(
-      &ctx, NEM_NETWORK_TESTNET, 21496797, NULL, 108000000, 21500397, "misc",
-      "alice", "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35", 5000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "7ddd5fe607e1bfb5606e0ac576024c318c8300d237273117d4db32a60c49524d"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/namespace/57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "9f3c14f304309c8b72b2821339c4428793b1518bea72d58dd01f19d523518614"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_provision_namespace(
-      &ctx, NEM_NETWORK_MAINNET, 26699717, NULL, 108000000, 26703317, "sex",
-      NULL, "NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA", 50000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "57071aad93ca125dc231dc02c07ad8610cd243d35068f9b36a7d231383907569"),
-      sizeof(hash));
-}
-END_TEST
-
-START_TEST(test_nem_transaction_mosaic_creation) {
-  nem_transaction_ctx ctx;
-
-  uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH];
-
-  // http://bob.nem.ninja:8765/#/mosaic/68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa/0
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_creation(
-      &ctx, NEM_NETWORK_TESTNET, 14070896, NULL, 108000000, 14074496,
-      "gimre.games.pong", "paddles", "Paddles for the bong game.\n", 0, 10000,
-      true, true, 0, 0, NULL, NULL, NULL,
-      "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "68364353c29105e6d361ad1a42abbccbf419cfc7adb8b74c8f35d8f8bdaca3fa"),
-      sizeof(hash));
-
-  // http://bob.nem.ninja:8765/#/mosaic/b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55/0
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "244fa194e2509ac0d2fbc18779c2618d8c2ebb61c16a3bcbebcf448c661ba8dc"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_creation(
-      &ctx, NEM_NETWORK_TESTNET, 21497248, NULL, 108000000, 21500848,
-      "alice.misc", "bar", "Special offer: get one bar extra by bying one foo!",
-      0, 1000, false, true, 1, 1, "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
-      "nem", "xem", "TBMOSAICOD4F54EE5CDMR23CCBGOAM2XSJBR5OLC", 50000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "b2f4a98113ff1f3a8f1e9d7197aa982545297fe0aa3fa6094af8031569953a55"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/mosaic/269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b/0
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "58956ac77951622dc5f1c938affbf017c458e30e6b21ddb5783d38b302531f23"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_creation(
-      &ctx, NEM_NETWORK_MAINNET, 26729938, NULL, 108000000, 26733538, "jabo38",
-      "red_token",
-      "This token is to celebrate the release of Namespaces and Mosaics on the "
-      "NEM system. "
-      "This token was the fist ever mosaic created other than nem.xem. "
-      "There are only 10,000 Red Tokens that will ever be created. "
-      "It has no levy and can be traded freely among third parties.",
-      2, 10000, false, true, 0, 0, NULL, NULL, NULL,
-      "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 50000000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "269c6fda657aba3053a0e5b138c075808cc20e244e1182d9b730798b60a1f77b"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/mosaic/e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6/0
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "a1df5306355766bd2f9a64efdc089eb294be265987b3359093ae474c051d7d5a"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_creation(
-      &ctx, NEM_NETWORK_MAINNET, 69251020, NULL, 20000000, 69337420, "dim",
-      "coin", "DIM COIN", 6, 9000000000, false, true, 2, 10,
-      "NCGGLVO2G3CUACVI5GNX2KRBJSQCN4RDL2ZWJ4DP", "dim", "coin",
-      "NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS", 500000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "e8dc14821dbea4831d9051f86158ef348001447968fc22c01644fdaf2bda75c6"),
-      sizeof(hash));
-}
-END_TEST
-
-START_TEST(test_nem_transaction_mosaic_supply_change) {
-  nem_transaction_ctx ctx;
-
-  uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH];
-
-  // http://bigalice2.nem.ninja:7890/transaction/get?hash=33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_supply_change(
-      &ctx, NEM_NETWORK_TESTNET, 14071648, NULL, 108000000, 14075248,
-      "gimre.games.pong", "paddles", 1, 1234));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "33a50fdd4a54913643a580b2af08b9a5b51b7cee922bde380e84c573a7969c50"),
-      sizeof(hash));
-
-  // http://bigalice2.nem.ninja:7890/transaction/get?hash=1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "84afa1bbc993b7f5536344914dde86141e61f8cbecaf8c9cefc07391f3287cf5"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_supply_change(
-      &ctx, NEM_NETWORK_TESTNET, 14126909, NULL, 108000000, 14130509,
-      "jabo38_ltd.fuzzy_kittens_cafe", "coupons", 2, 1));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "1ce8e8894d077a66ff22294b000825d090a60742ec407efd80eb8b19657704f2"),
-      sizeof(hash));
-
-  // http://bigalice3.nem.ninja:7890/transaction/get?hash=694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "b7ccc27b21ba6cf5c699a8dc86ba6ba98950442597ff9fa30e0abe0f5f4dd05d"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_supply_change(
-      &ctx, NEM_NETWORK_MAINNET, 53377685, NULL, 20000000, 53464085, "abvapp",
-      "abv", 1, 9000000));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "694e493e9576d2bcf60d85747e302ac2e1cc27783187947180d4275a713ff1ff"),
-      sizeof(hash));
-
-  // http://bigalice3.nem.ninja:7890/transaction/get?hash=09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "75f001a8641e2ce5c4386883dda561399ed346177411b492a677b73899502f13"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_mosaic_supply_change(
-      &ctx, NEM_NETWORK_MAINNET, 55176304, NULL, 20000000, 55262704, "sushi",
-      "wasabi", 2, 20));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "09836334e123970e068d5b411e4d1df54a3ead10acf1ad5935a2cdd9f9680185"),
-      sizeof(hash));
-}
-END_TEST
-
-START_TEST(test_nem_transaction_aggregate_modification) {
-  nem_transaction_ctx ctx;
-
-  uint8_t buffer[1024], hash[SHA3_256_DIGEST_LENGTH];
-
-  // http://bob.nem.ninja:8765/#/aggregate/6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "462ee976890916e54fa825d26bdd0235f5eb5b6a143c199ab0ae5ee9328e08ce"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_aggregate_modification(
-      &ctx, NEM_NETWORK_TESTNET, 0, NULL, 22000000, 0, 2, false));
-
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "994793ba1c789fa9bdea918afc9b06e2d0309beb1081ac5b6952991e4defd324")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "c54d6e33ed1446eedd7f7a80a588dd01857f723687a09200c1917d5524752f8b")));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "6a55471b17159e5b6cd579c421e95a4e39d92e3f78b0a55ee337e785a601d3a2"),
-      sizeof(hash));
-
-  // http://bob.nem.ninja:8765/#/aggregate/1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "6bf7849c1eec6a2002995cc457dc00c4e29bad5c88de63f51e42dfdcd7b2131d"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_aggregate_modification(
-      &ctx, NEM_NETWORK_TESTNET, 6542254, NULL, 40000000, 6545854, 4, true));
-
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "5f53d076c8c3ec3110b98364bc423092c3ec2be2b1b3c40fd8ab68d54fa39295")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "9eb199c2b4d406f64cb7aa5b2b0815264b56ba8fe44d558a6cb423a31a33c4c2")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "94b2323dab23a3faba24fa6ddda0ece4fbb06acfedd74e76ad9fae38d006882b")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "d88c6ee2a2cd3929d0d76b6b14ecb549d21296ab196a2b3a4cb2536bcce32e87")));
-
-  ck_assert(nem_transaction_write_minimum_cosignatories(&ctx, 2));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "1fbdae5ba753e68af270930413ae90f671eb8ab58988116684bac0abd5726584"),
-      sizeof(hash));
-
-  // http://chain.nem.ninja/#/aggregate/cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c
-
-  nem_transaction_start(
-      &ctx,
-      fromhex(
-          "f41b99320549741c5cce42d9e4bb836d98c50ed5415d0c3c2912d1bb50e6a0e5"),
-      buffer, sizeof(buffer));
-
-  ck_assert(nem_transaction_create_aggregate_modification(
-      &ctx, NEM_NETWORK_MAINNET, 0, NULL, 40000000, 0, 5, false));
-
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "1fbdbdde28daf828245e4533765726f0b7790e0b7146e2ce205df3e86366980b")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "f94e8702eb1943b23570b1b83be1b81536df35538978820e98bfce8f999e2d37")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "826cedee421ff66e708858c17815fcd831a4bb68e3d8956299334e9e24380ba8")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "719862cd7d0f4e875a6a0274c9a1738f38f40ad9944179006a54c34724c1274d")));
-  ck_assert(nem_transaction_write_cosignatory_modification(
-      &ctx, 1,
-      fromhex(
-          "43aa69177018fc3e2bdbeb259c81cddf24be50eef9c5386db51d82386c41475a")));
-
-  keccak_256(ctx.buffer, ctx.offset, hash);
-  ck_assert_mem_eq(
-      hash,
-      fromhex(
-          "cc64ca69bfa95db2ff7ac1e21fe6d27ece189c603200ebc9778d8bb80ca25c3c"),
-      sizeof(hash));
-}
-END_TEST
-
-START_TEST(test_multibyte_address) {
-  uint8_t priv_key[32];
-  char wif[57];
-  uint8_t pub_key[33];
-  char address[40];
-  uint8_t decode[24];
-  int res;
-
-  memcpy(
-      priv_key,
-      fromhex(
-          "47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"),
-      32);
-  ecdsa_get_wif(priv_key, 0, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "13QtoXmbhELWcrwD9YA9KzvXy5rTaptiNuFR8L8ArpBNn4xmQj4N");
-  ecdsa_get_wif(priv_key, 0x12, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif, "3hrF6SFnqzpzABB36uGDf8dJSuUCcMmoJrTmCWMshRkBr2Vx86qJ");
-  ecdsa_get_wif(priv_key, 0x1234, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif,
-                   "CtPTF9awbVbfDWGepGdVhB3nBhr4HktUGya8nf8dLxgC8tbqBreB9");
-  ecdsa_get_wif(priv_key, 0x123456, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif,
-                   "uTrDevVQt5QZgoL3iJ1cPWHaCz7ZMBncM7QXZfCegtxiMHqBvWoYJa");
-  ecdsa_get_wif(priv_key, 0x12345678, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif,
-                   "4zZWMzv1SVbs95pmLXWrXJVp9ntPEam1mfwb6CXBLn9MpWNxLg9huYgv");
-  ecdsa_get_wif(priv_key, 0xffffffff, HASHER_SHA2D, wif, sizeof(wif));
-  ck_assert_str_eq(wif,
-                   "y9KVfV1RJXcTxpVjeuh6WYWh8tMwnAUeyUwDEiRviYdrJ61njTmnfUjE");
-
-  memcpy(
-      pub_key,
-      fromhex(
-          "0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71"),
-      33);
-  ecdsa_get_address(pub_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8");
-  ecdsa_get_address(pub_key, 0x12, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq");
-  ecdsa_get_address(pub_key, 0x1234, HASHER_SHA2_RIPEMD, HASHER_SHA2D, address,
-                    sizeof(address));
-  ck_assert_str_eq(address, "ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV");
-  ecdsa_get_address(pub_key, 0x123456, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq");
-  ecdsa_get_address(pub_key, 0x12345678, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44");
-  ecdsa_get_address(pub_key, 0xffffffff, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                    address, sizeof(address));
-  ck_assert_str_eq(address, "3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT");
-
-  res = ecdsa_address_decode("1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", 0,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("0079fbfc3f34e7745860d76137da68f362380c606c"), 21);
-  res = ecdsa_address_decode("8SCrMR2yYF7ciqoDbav7VLLTsVx5dTVPPq", 0x12,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("1279fbfc3f34e7745860d76137da68f362380c606c"), 21);
-  res = ecdsa_address_decode("ZLH8q1UgMPg8o2s1MD55YVMpPV7vqms9kiV", 0x1234,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(decode,
-                   fromhex("123479fbfc3f34e7745860d76137da68f362380c606c"), 21);
-  res = ecdsa_address_decode("3ThqvsQVFnbiF66NwHtfe2j6AKn75DpLKpQSq", 0x123456,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      decode, fromhex("12345679fbfc3f34e7745860d76137da68f362380c606c"), 21);
-  res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44",
-                             0x12345678, HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      decode, fromhex("1234567879fbfc3f34e7745860d76137da68f362380c606c"), 21);
-  res = ecdsa_address_decode("3diW7paWGJyZRLGqMJZ55DMfPExob8QxQHkrfYT",
-                             0xffffffff, HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      decode, fromhex("ffffffff79fbfc3f34e7745860d76137da68f362380c606c"), 21);
-
-  // wrong length
-  res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44", 0x123456,
-                             HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-
-  // wrong address prefix
-  res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL44",
-                             0x22345678, HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-
-  // wrong checksum
-  res = ecdsa_address_decode("BrsGxAHga3VbopvSnb3gmLvMBhJNCGuDxBZL45",
-                             0x12345678, HASHER_SHA2D, decode);
-  ck_assert_int_eq(res, 0);
-}
-END_TEST
-
-// https://tools.ietf.org/html/rfc6229#section-2
-START_TEST(test_rc4_rfc6229) {
-  static const size_t offsets[] = {
-      0x0, 0xf0, 0x1f0, 0x2f0, 0x3f0, 0x5f0, 0x7f0, 0xbf0, 0xff0,
-  };
-
-  static const struct {
-    char key[65];
-    char vectors[sizeof(offsets) / sizeof(*offsets)][65];
-  } tests[] = {
-      {"0102030405",
-       {
-           "b2396305f03dc027ccc3524a0a1118a8"
-           "6982944f18fc82d589c403a47a0d0919",
-           "28cb1132c96ce286421dcaadb8b69eae"
-           "1cfcf62b03eddb641d77dfcf7f8d8c93",
-           "42b7d0cdd918a8a33dd51781c81f4041"
-           "6459844432a7da923cfb3eb4980661f6",
-           "ec10327bde2beefd18f9277680457e22"
-           "eb62638d4f0ba1fe9fca20e05bf8ff2b",
-           "45129048e6a0ed0b56b490338f078da5"
-           "30abbcc7c20b01609f23ee2d5f6bb7df",
-           "3294f744d8f9790507e70f62e5bbceea"
-           "d8729db41882259bee4f825325f5a130",
-           "1eb14a0c13b3bf47fa2a0ba93ad45b8b"
-           "cc582f8ba9f265e2b1be9112e975d2d7",
-           "f2e30f9bd102ecbf75aaade9bc35c43c"
-           "ec0e11c479dc329dc8da7968fe965681",
-           "068326a2118416d21f9d04b2cd1ca050"
-           "ff25b58995996707e51fbdf08b34d875",
-       }},
-      {"01020304050607",
-       {
-           "293f02d47f37c9b633f2af5285feb46b"
-           "e620f1390d19bd84e2e0fd752031afc1",
-           "914f02531c9218810df60f67e338154c"
-           "d0fdb583073ce85ab83917740ec011d5",
-           "75f81411e871cffa70b90c74c592e454"
-           "0bb87202938dad609e87a5a1b079e5e4",
-           "c2911246b612e7e7b903dfeda1dad866"
-           "32828f91502b6291368de8081de36fc2",
-           "f3b9a7e3b297bf9ad804512f9063eff1"
-           "8ecb67a9ba1f55a5a067e2b026a3676f",
-           "d2aa902bd42d0d7cfd340cd45810529f"
-           "78b272c96e42eab4c60bd914e39d06e3",
-           "f4332fd31a079396ee3cee3f2a4ff049"
-           "05459781d41fda7f30c1be7e1246c623",
-           "adfd3868b8e51485d5e610017e3dd609"
-           "ad26581c0c5be45f4cea01db2f3805d5",
-           "f3172ceffc3b3d997c85ccd5af1a950c"
-           "e74b0b9731227fd37c0ec08a47ddd8b8",
-       }},
-      {"0102030405060708",
-       {
-           "97ab8a1bf0afb96132f2f67258da15a8"
-           "8263efdb45c4a18684ef87e6b19e5b09",
-           "9636ebc9841926f4f7d1f362bddf6e18"
-           "d0a990ff2c05fef5b90373c9ff4b870a",
-           "73239f1db7f41d80b643c0c52518ec63"
-           "163b319923a6bdb4527c626126703c0f",
-           "49d6c8af0f97144a87df21d91472f966"
-           "44173a103b6616c5d5ad1cee40c863d0",
-           "273c9c4b27f322e4e716ef53a47de7a4"
-           "c6d0e7b226259fa9023490b26167ad1d",
-           "1fe8986713f07c3d9ae1c163ff8cf9d3"
-           "8369e1a965610be887fbd0c79162aafb",
-           "0a0127abb44484b9fbef5abcae1b579f"
-           "c2cdadc6402e8ee866e1f37bdb47e42c",
-           "26b51ea37df8e1d6f76fc3b66a7429b3"
-           "bc7683205d4f443dc1f29dda3315c87b",
-           "d5fa5a3469d29aaaf83d23589db8c85b"
-           "3fb46e2c8f0f068edce8cdcd7dfc5862",
-       }},
-      {"0102030405060708090a",
-       {
-           "ede3b04643e586cc907dc21851709902"
-           "03516ba78f413beb223aa5d4d2df6711",
-           "3cfd6cb58ee0fdde640176ad0000044d"
-           "48532b21fb6079c9114c0ffd9c04a1ad",
-           "3e8cea98017109979084b1ef92f99d86"
-           "e20fb49bdb337ee48b8d8dc0f4afeffe",
-           "5c2521eacd7966f15e056544bea0d315"
-           "e067a7031931a246a6c3875d2f678acb",
-           "a64f70af88ae56b6f87581c0e23e6b08"
-           "f449031de312814ec6f319291f4a0516",
-           "bdae85924b3cb1d0a2e33a30c6d79599"
-           "8a0feddbac865a09bcd127fb562ed60a",
-           "b55a0a5b51a12a8be34899c3e047511a"
-           "d9a09cea3ce75fe39698070317a71339",
-           "552225ed1177f44584ac8cfa6c4eb5fc"
-           "7e82cbabfc95381b080998442129c2f8",
-           "1f135ed14ce60a91369d2322bef25e3c"
-           "08b6be45124a43e2eb77953f84dc8553",
-       }},
-      {"0102030405060708090a0b0c0d0e0f10",
-       {
-           "9ac7cc9a609d1ef7b2932899cde41b97"
-           "5248c4959014126a6e8a84f11d1a9e1c",
-           "065902e4b620f6cc36c8589f66432f2b"
-           "d39d566bc6bce3010768151549f3873f",
-           "b6d1e6c4a5e4771cad79538df295fb11"
-           "c68c1d5c559a974123df1dbc52a43b89",
-           "c5ecf88de897fd57fed301701b82a259"
-           "eccbe13de1fcc91c11a0b26c0bc8fa4d",
-           "e7a72574f8782ae26aabcf9ebcd66065"
-           "bdf0324e6083dcc6d3cedd3ca8c53c16",
-           "b40110c4190b5622a96116b0017ed297"
-           "ffa0b514647ec04f6306b892ae661181",
-           "d03d1bc03cd33d70dff9fa5d71963ebd"
-           "8a44126411eaa78bd51e8d87a8879bf5",
-           "fabeb76028ade2d0e48722e46c4615a3"
-           "c05d88abd50357f935a63c59ee537623",
-           "ff38265c1642c1abe8d3c2fe5e572bf8"
-           "a36a4c301ae8ac13610ccbc12256cacc",
-       }},
-      {"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20",
-       {
-           "eaa6bd25880bf93d3f5d1e4ca2611d91"
-           "cfa45c9f7e714b54bdfa80027cb14380",
-           "114ae344ded71b35f2e60febad727fd8"
-           "02e1e7056b0f623900496422943e97b6",
-           "91cb93c787964e10d9527d999c6f936b"
-           "49b18b42f8e8367cbeb5ef104ba1c7cd",
-           "87084b3ba700bade955610672745b374"
-           "e7a7b9e9ec540d5ff43bdb12792d1b35",
-           "c799b596738f6b018c76c74b1759bd90"
-           "7fec5bfd9f9b89ce6548309092d7e958",
-           "40f250b26d1f096a4afd4c340a588815"
-           "3e34135c79db010200767651cf263073",
-           "f656abccf88dd827027b2ce917d464ec"
-           "18b62503bfbc077fbabb98f20d98ab34",
-           "8aed95ee5b0dcbfbef4eb21d3a3f52f9"
-           "625a1ab00ee39a5327346bddb01a9c18",
-           "a13a7c79c7e119b5ab0296ab28c300b9"
-           "f3e4c0a2e02d1d01f7f0a74618af2b48",
-       }},
-      {"833222772a",
-       {
-           "80ad97bdc973df8a2e879e92a497efda"
-           "20f060c2f2e5126501d3d4fea10d5fc0",
-           "faa148e99046181fec6b2085f3b20ed9"
-           "f0daf5bab3d596839857846f73fbfe5a",
-           "1c7e2fc4639232fe297584b296996bc8"
-           "3db9b249406cc8edffac55ccd322ba12",
-           "e4f9f7e0066154bbd125b745569bc897"
-           "75d5ef262b44c41a9cf63ae14568e1b9",
-           "6da453dbf81e82334a3d8866cb50a1e3"
-           "7828d074119cab5c22b294d7a9bfa0bb",
-           "adb89cea9a15fbe617295bd04b8ca05c"
-           "6251d87fd4aaae9a7e4ad5c217d3f300",
-           "e7119bd6dd9b22afe8f89585432881e2"
-           "785b60fd7ec4e9fcb6545f350d660fab",
-           "afecc037fdb7b0838eb3d70bcd268382"
-           "dbc1a7b49d57358cc9fa6d61d73b7cf0",
-           "6349d126a37afcba89794f9804914fdc"
-           "bf42c3018c2f7c66bfde524975768115",
-       }},
-      {"1910833222772a",
-       {
-           "bc9222dbd3274d8fc66d14ccbda6690b"
-           "7ae627410c9a2be693df5bb7485a63e3",
-           "3f0931aa03defb300f060103826f2a64"
-           "beaa9ec8d59bb68129f3027c96361181",
-           "74e04db46d28648d7dee8a0064b06cfe"
-           "9b5e81c62fe023c55be42f87bbf932b8",
-           "ce178fc1826efecbc182f57999a46140"
-           "8bdf55cd55061c06dba6be11de4a578a",
-           "626f5f4dce652501f3087d39c92cc349"
-           "42daac6a8f9ab9a7fd137c6037825682",
-           "cc03fdb79192a207312f53f5d4dc33d9"
-           "f70f14122a1c98a3155d28b8a0a8a41d",
-           "2a3a307ab2708a9c00fe0b42f9c2d6a1"
-           "862617627d2261eab0b1246597ca0ae9",
-           "55f877ce4f2e1ddbbf8e13e2cde0fdc8"
-           "1b1556cb935f173337705fbb5d501fc1",
-           "ecd0e96602be7f8d5092816cccf2c2e9"
-           "027881fab4993a1c262024a94fff3f61",
-       }},
-      {"641910833222772a",
-       {
-           "bbf609de9413172d07660cb680716926"
-           "46101a6dab43115d6c522b4fe93604a9",
-           "cbe1fff21c96f3eef61e8fe0542cbdf0"
-           "347938bffa4009c512cfb4034b0dd1a7",
-           "7867a786d00a7147904d76ddf1e520e3"
-           "8d3e9e1caefcccb3fbf8d18f64120b32",
-           "942337f8fd76f0fae8c52d7954810672"
-           "b8548c10f51667f6e60e182fa19b30f7",
-           "0211c7c6190c9efd1237c34c8f2e06c4"
-           "bda64f65276d2aacb8f90212203a808e",
-           "bd3820f732ffb53ec193e79d33e27c73"
-           "d0168616861907d482e36cdac8cf5749",
-           "97b0f0f224b2d2317114808fb03af7a0"
-           "e59616e469787939a063ceea9af956d1",
-           "c47e0dc1660919c11101208f9e69aa1f"
-           "5ae4f12896b8379a2aad89b5b553d6b0",
-           "6b6b098d0c293bc2993d80bf0518b6d9"
-           "8170cc3ccd92a698621b939dd38fe7b9",
-       }},
-      {"8b37641910833222772a",
-       {
-           "ab65c26eddb287600db2fda10d1e605c"
-           "bb759010c29658f2c72d93a2d16d2930",
-           "b901e8036ed1c383cd3c4c4dd0a6ab05"
-           "3d25ce4922924c55f064943353d78a6c",
-           "12c1aa44bbf87e75e611f69b2c38f49b"
-           "28f2b3434b65c09877470044c6ea170d",
-           "bd9ef822de5288196134cf8af7839304"
-           "67559c23f052158470a296f725735a32",
-           "8bab26fbc2c12b0f13e2ab185eabf241"
-           "31185a6d696f0cfa9b42808b38e132a2",
-           "564d3dae183c5234c8af1e51061c44b5"
-           "3c0778a7b5f72d3c23a3135c7d67b9f4",
-           "f34369890fcf16fb517dcaae4463b2dd"
-           "02f31c81e8200731b899b028e791bfa7",
-           "72da646283228c14300853701795616f"
-           "4e0a8c6f7934a788e2265e81d6d0c8f4",
-           "438dd5eafea0111b6f36b4b938da2a68"
-           "5f6bfc73815874d97100f086979357d8",
-       }},
-      {"ebb46227c6cc8b37641910833222772a",
-       {
-           "720c94b63edf44e131d950ca211a5a30"
-           "c366fdeacf9ca80436be7c358424d20b",
-           "b3394a40aabf75cba42282ef25a0059f"
-           "4847d81da4942dbc249defc48c922b9f",
-           "08128c469f275342adda202b2b58da95"
-           "970dacef40ad98723bac5d6955b81761",
-           "3cb89993b07b0ced93de13d2a11013ac"
-           "ef2d676f1545c2c13dc680a02f4adbfe",
-           "b60595514f24bc9fe522a6cad7393644"
-           "b515a8c5011754f59003058bdb81514e",
-           "3c70047e8cbc038e3b9820db601da495"
-           "1175da6ee756de46a53e2b075660b770",
-           "00a542bba02111cc2c65b38ebdba587e"
-           "5865fdbb5b48064104e830b380f2aede",
-           "34b21ad2ad44e999db2d7f0863f0d9b6"
-           "84a9218fc36e8a5f2ccfbeae53a27d25",
-           "a2221a11b833ccb498a59540f0545f4a"
-           "5bbeb4787d59e5373fdbea6c6f75c29b",
-       }},
-      {"c109163908ebe51debb46227c6cc8b37641910833222772a",
-       {
-           "54b64e6b5a20b5e2ec84593dc7989da7"
-           "c135eee237a85465ff97dc03924f45ce",
-           "cfcc922fb4a14ab45d6175aabbf2d201"
-           "837b87e2a446ad0ef798acd02b94124f",
-           "17a6dbd664926a0636b3f4c37a4f4694"
-           "4a5f9f26aeeed4d4a25f632d305233d9",
-           "80a3d01ef00c8e9a4209c17f4eeb358c"
-           "d15e7d5ffaaabc0207bf200a117793a2",
-           "349682bf588eaa52d0aa1560346aeafa"
-           "f5854cdb76c889e3ad63354e5f7275e3",
-           "532c7ceccb39df3236318405a4b1279c"
-           "baefe6d9ceb651842260e0d1e05e3b90",
-           "e82d8c6db54e3c633f581c952ba04207"
-           "4b16e50abd381bd70900a9cd9a62cb23",
-           "3682ee33bd148bd9f58656cd8f30d9fb"
-           "1e5a0b8475045d9b20b2628624edfd9e",
-           "63edd684fb826282fe528f9c0e9237bc"
-           "e4dd2e98d6960fae0b43545456743391",
-       }},
-      {"1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a",
-       {
-           "dd5bcb0018e922d494759d7c395d02d3"
-           "c8446f8f77abf737685353eb89a1c9eb",
-           "af3e30f9c095045938151575c3fb9098"
-           "f8cb6274db99b80b1d2012a98ed48f0e",
-           "25c3005a1cb85de076259839ab7198ab"
-           "9dcbc183e8cb994b727b75be3180769c",
-           "a1d3078dfa9169503ed9d4491dee4eb2"
-           "8514a5495858096f596e4bcd66b10665",
-           "5f40d59ec1b03b33738efa60b2255d31"
-           "3477c7f764a41baceff90bf14f92b7cc",
-           "ac4e95368d99b9eb78b8da8f81ffa795"
-           "8c3c13f8c2388bb73f38576e65b7c446",
-           "13c4b9c1dfb66579eddd8a280b9f7316"
-           "ddd27820550126698efaadc64b64f66e",
-           "f08f2e66d28ed143f3a237cf9de73559"
-           "9ea36c525531b880ba124334f57b0b70",
-           "d5a39e3dfcc50280bac4a6b5aa0dca7d"
-           "370b1c1fe655916d97fd0d47ca1d72b8",
-       }}};
-
-  RC4_CTX ctx;
-  uint8_t key[64];
-  uint8_t buffer[0x1010];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    size_t length = strlen(tests[i].key) / 2;
-    memcpy(key, fromhex(tests[i].key), length);
-    memzero(buffer, sizeof(buffer));
-
-    rc4_init(&ctx, key, length);
-    rc4_encrypt(&ctx, buffer, sizeof(buffer));
-
-    for (size_t j = 0; j < (sizeof(offsets) / sizeof(*offsets)); j++) {
-      size_t size = strlen(tests[i].vectors[j]) / 2;
-      ck_assert_mem_eq(&buffer[offsets[j]], fromhex(tests[i].vectors[j]), size);
-    }
-  }
-}
-END_TEST
-
-static void test_compress_coord(const char *k_raw) {
-  const ecdsa_curve *curve = &secp256k1;
-  curve_point expected_coords;
-
-  bignum256 k = {0};
-
-  bn_read_be(fromhex(k_raw), &k);
-
-  point_multiply(curve, &k, &curve->G, &expected_coords);
-
-  uint8_t compress[33] = {0};
-  compress_coords(&expected_coords, compress);
-
-  bignum256 x = {0}, y = {0};
-  bn_read_be(compress + 1, &x);
-  uncompress_coords(curve, compress[0], &x, &y);
-
-  ck_assert(bn_is_equal(&expected_coords.x, &x));
-  ck_assert(bn_is_equal(&expected_coords.y, &y));
-}
-
-START_TEST(test_compress_coords) {
-  static const char *k_raw[] = {
-      "dc05960ac673fd59554c98655e26722d007bb7ada0c8ff00883fdee70783d0be",
-      "41e41e0a218c980411108a0a58cf88f528c828b4d6f0d2c86234bc2504bdc3cd",
-      "1d963ddcb79f6028a32cadd2421ff7fff969bff5774f73063dab41519b3da175",
-      "2414141f96da0874dbc374b58861589935b7f940806ddf8d2e6b911f62e240f3",
-      "01cc1fb182e29f60fe43e22d250de34f2d3f956bbef2aa9b182d09e5d9176873",
-      "89b3d621d813682692fd61b2baea6b2ea696a44abc76925d29c4887fc4db9367",
-      "20c80c633e05a3a7dfac05fa0e0a7c7a6b708b02323e687735cff81ea5944f59",
-      "5a803c263aa93a4f74648066c03e63fb00641193bae93dfa254dabd634e8b49c",
-      "05efbcc87007797dca68315b9271ac8fb75bddbece53f4dcbfb83fc21cb91fc0",
-      "0bed78ef43474630bd646eef2d7ec19a1acb8e9eecf6a0a3ac7241ac40a7706f",
-  };
-
-  for (int i = 0; i < (int)(sizeof(k_raw) / sizeof(*k_raw)); i++)
-    test_compress_coord(k_raw[i]);
-}
-END_TEST
-
-START_TEST(test_zkp_bip340_sign) {
-  static struct {
-    const char *priv_key;
-    const char *pub_key;
-    const char *aux_input;
-    const char *digest;
-    const char *sig;
-  } tests[] = {
-      // Test vectors from
-      // https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv
-      {"0000000000000000000000000000000000000000000000000000000000000003",
-       "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4"
-       "A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0"},
-      {"B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF",
-       "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "0000000000000000000000000000000000000000000000000000000000000001",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11"
-       "AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A"},
-      {"C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9",
-       "DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8",
-       "C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906",
-       "7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C",
-       "5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB74587"
-       "9A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7"},
-      {"0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710",
-       "25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517",
-       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-       "7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9"
-       "CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3"},
-      // https://github.com/bitcoin/bips/pull/1225/commits/f7af1f73b287c14cf2f63afcb8d199feaf6ab5e1
-      {"2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9",
-       "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "7e584883b084ace0469c6962a9a7d2a9060e1f3c218ab40d32c77651482122bc",
-       "aab8fce3c4d7f359577a338676c9580d6946d7d8f899a48a4e1dcc63611e8f654eab719"
-       "2d43e6d6b9c7c95322338edbc5af21e88b43df36a989ba559d473f32a"},
-      {"ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080",
-       "147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d",
-       "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed"
-       "4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f"},
-      {"97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d",
-       "e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "6ffd256e108685b41831385f57eebf2fca041bc6b5e607ea11b3e03d4cf9d9ba",
-       "f78cf3fe8410326ba95b7119cac657b2d86a461dc0767d7b68cb516f3d8bac64ed027fb"
-       "710b5962d01c42dadaf4dec5731371c6c7850854cc68054eb8f4de80b"},
-      {"a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501",
-       "91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "9f90136737540ccc18707e1fd398ad222a1a7e4dd65cbfd22dbe4660191efa58",
-       "69599256a182e89be95c098b03200b958220ee400c42779cd05cdbf9fa2d5c8060a48c1"
-       "463c9fadf6aea0395b70ebf937fbae0dd2d83185c1d9f675dac8d06f5"},
-      {"241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901",
-       "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "835c9ab6084ed9a8ae9b7cda21e0aa797aca3b76a54bd1e3c7db093f6c57e23f",
-       "882a50af428ea47ee84462fcb481033db9c8b1ea6f2b77c9a8e4d8135a1c0771ee8dbcd"
-       "24ea671576ab441bdb2ab3f85f20675ca4c59889bab719b062abfd064"},
-      {"9822270935e156a1b9b28940e7b94a06934a51ddabdd49dd43e8010adc98dfa3",
-       "0f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "df1cca638283c667084b8ffe6bf6e116cc5a53cf7ae1202c5fee45a9085f1ba5",
-       "1ec324f9ccc982286a10017daa22ead5087d9f2eff58dd6173d7d608eb959be6be2f3df"
-       "0a25a7890c99a9259c9eab33d71a6c163cabb442aa3a5e5d613611420"},
-      {"8e575b74b70d573b05558883743a72d1ccc326b4c299ea3412a29d3b83e801e4",
-       "053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587",
-       "0000000000000000000000000000000000000000000000000000000000000000",
-       "30319859ca79ea1b7a9782e9daebc46e4ca4ca2bc04c9c53b2ec87fa83a526bd",
-       "7e6c212ebe04e8241bee0151b0d3230aa22dec9dbdd8197ebd3ff616b9e4b47dccee08a"
-       "32a52a77d60587a77e7d7b5d1d113235d38921740ffdbe795459637ff"}};
-
-  int res = 0;
-  uint8_t priv_key[32] = {0};
-  uint8_t expected_pub_key[32] = {0};
-  uint8_t aux_input[32] = {0};
-  uint8_t digest[32] = {0};
-  uint8_t expected_sig[64] = {0};
-  uint8_t pub_key[32] = {0};
-  uint8_t sig[64] = {0};
-
-  for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-    memcpy(priv_key, fromhex(tests[i].priv_key), 32);
-    memcpy(expected_pub_key, fromhex(tests[i].pub_key), 32);
-    memcpy(aux_input, fromhex(tests[i].aux_input), 32);
-    memcpy(digest, fromhex(tests[i].digest), 32);
-    memcpy(expected_sig, fromhex(tests[i].sig), 64);
-
-    zkp_bip340_get_public_key(priv_key, pub_key);
-    ck_assert_mem_eq(expected_pub_key, pub_key, 32);
-
-    res = zkp_bip340_sign_digest(priv_key, digest, sig, aux_input);
-    ck_assert_mem_eq(expected_sig, sig, 64);
-    ck_assert_int_eq(res, 0);
-  }
-}
-END_TEST
-
-START_TEST(test_zkp_bip340_verify) {
-  static struct {
-    const char *pub_key;
-    const char *digest;
-    const char *sig;
-    const int res;
-  } tests[] = {
-      // Test vectors from
-      // https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv
-      {"D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9",
-       "4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703",
-       "00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB15"
-       "48AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4",
-       0},
-      {"EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4"
-       "C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
-       1},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC2794"
-       "4640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3"
-       "EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B"
-       "3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "0000000000000000000000000000000000000000000000000000000000000000123DDA8"
-       "328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "00000000000000000000000000000000000000000000000000000000000000017615FBA"
-       "F5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4"
-       "C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4"
-       "C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
-       5},
-      {"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFF"
-       "FFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
-       5},
-      {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30",
-       "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
-       "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4"
-       "C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
-       1},
-      // https://github.com/bitcoin/bips/pull/1225/commits/f7af1f73b287c14cf2f63afcb8d199feaf6ab5e1
-      {"53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
-       "7e584883b084ace0469c6962a9a7d2a9060e1f3c218ab40d32c77651482122bc",
-       "aab8fce3c4d7f359577a338676c9580d6946d7d8f899a48a4e1dcc63611e8f654eab719"
-       "2d43e6d6b9c7c95322338edbc5af21e88b43df36a989ba559d473f32a",
-       0},
-      {"147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3",
-       "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d",
-       "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed"
-       "4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f",
-       0},
-      {"e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e",
-       "6ffd256e108685b41831385f57eebf2fca041bc6b5e607ea11b3e03d4cf9d9ba",
-       "f78cf3fe8410326ba95b7119cac657b2d86a461dc0767d7b68cb516f3d8bac64ed027fb"
-       "710b5962d01c42dadaf4dec5731371c6c7850854cc68054eb8f4de80b",
-       0},
-      {"91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605",
-       "9f90136737540ccc18707e1fd398ad222a1a7e4dd65cbfd22dbe4660191efa58",
-       "69599256a182e89be95c098b03200b958220ee400c42779cd05cdbf9fa2d5c8060a48c1"
-       "463c9fadf6aea0395b70ebf937fbae0dd2d83185c1d9f675dac8d06f5",
-       0},
-      {"75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
-       "835c9ab6084ed9a8ae9b7cda21e0aa797aca3b76a54bd1e3c7db093f6c57e23f",
-       "882a50af428ea47ee84462fcb481033db9c8b1ea6f2b77c9a8e4d8135a1c0771ee8dbcd"
-       "24ea671576ab441bdb2ab3f85f20675ca4c59889bab719b062abfd064",
-       0},
-      {"0f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561",
-       "df1cca638283c667084b8ffe6bf6e116cc5a53cf7ae1202c5fee45a9085f1ba5",
-       "1ec324f9ccc982286a10017daa22ead5087d9f2eff58dd6173d7d608eb959be6be2f3df"
-       "0a25a7890c99a9259c9eab33d71a6c163cabb442aa3a5e5d613611420",
-       0},
-      {"053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587",
-       "30319859ca79ea1b7a9782e9daebc46e4ca4ca2bc04c9c53b2ec87fa83a526bd",
-       "7e6c212ebe04e8241bee0151b0d3230aa22dec9dbdd8197ebd3ff616b9e4b47dccee08a"
-       "32a52a77d60587a77e7d7b5d1d113235d38921740ffdbe795459637ff",
-       0},
-
-  };
-
-  int res = 0;
-  uint8_t pub_key[32] = {0};
-  uint8_t digest[32] = {0};
-  uint8_t sig[64] = {0};
-
-  for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-    memcpy(pub_key, fromhex(tests[i].pub_key), 32);
-    memcpy(digest, fromhex(tests[i].digest), 32);
-    memcpy(sig, fromhex(tests[i].sig), 64);
-
-    res = zkp_bip340_verify_digest(pub_key, sig, digest);
-    ck_assert_int_eq(res, tests[i].res);
-  }
-}
-END_TEST
-
-START_TEST(test_zkp_bip340_tweak) {
-  static struct {
-    const char *root_hash;
-    const char *internal_priv;
-    const char *output_priv;
-    const char *internal_pub;
-    const char *output_pub;
-  } tests[] = {
-      // https://github.com/bitcoin/bips/blob/master/bip-0086/
-      {NULL, "41f41d69260df4cf277826a9b65a3717e4eeddbeedf637f212ca096576479361",
-       "eaac016f36e8c18347fbacf05ab7966708fbfce7ce3bf1dc32a09dd0645db038",
-       "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
-       "a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c"},
-      {NULL, "86c68ac0ed7df88cbdd08a847c6d639f87d1234d40503abf3ac178ef7ddc05dd",
-       "0b6f18573f75c454efb43d2bfc7c91f7f88cb802c45a7821e820402fcf2836d3",
-       "83dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145",
-       "a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb"},
-      {NULL, "6ccbca4a02ac648702dde463d9c1b0d328a4df1e068ef9dc2bc788b33a4f0412",
-       "c3074682f4c54d9801da58a52aaf0e28c089d5f8c6847dc8829734bbe3f60647",
-       "399f1b2f4393f29a18c937859c5dd8a77350103157eb880f02e8c08214277cef",
-       "882d74e5d0572d5a816cef0041a96b6c1de832f6f9676d9605c44d5e9a97d3dc"},
-      // https://github.com/bitcoin-core/btcdeb/blob/master/doc/tapscript-example-with-tap.md
-      {"41646f8c1fe2a96ddad7f5471bc4fee7da98794ef8c45a4f4fc6a559d60c9f6b",
-       "1229101a0fcf2104e8808dab35661134aa5903867d44deb73ce1c7e4eb925be8",
-       "4fe6b3e5fbd61870577980ad5e4e13080776069f0fb3c1e353572e0c4993abc1",
-       "f30544d6009c8d8d94f5d030b2e844b1a3ca036255161c479db1cca5b374dd1c",
-       "a5ba0871796eb49fb4caa6bf78e675b9455e2d66e751676420f8381d5dda8951"},
-      // https://github.com/bitcoin/bips/pull/1225/commits/f7af1f73b287c14cf2f63afcb8d199feaf6ab5e1
-      {NULL, "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa",
-       "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9",
-       "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
-       "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343"},
-      {"5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21",
-       "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f",
-       "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080",
-       "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
-       "147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3"},
-      {"c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b",
-       "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64",
-       "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d",
-       "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820",
-       "e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e"},
-      {"ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2",
-       "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e",
-       "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501",
-       "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f",
-       "91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605"},
-      {"2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
-       "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8",
-       "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901",
-       "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
-       "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831"},
-      {"f3004d6c183e038105d436db1424f321613366cbb7b05939bf05d763a9ebb962",
-       "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103",
-       "9822270935e156a1b9b28940e7b94a06934a51ddabdd49dd43e8010adc98dfa3",
-       "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592",
-       "0f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561"},
-      {"d9c2c32808b41c0301d876d49c0af72e1d98e84b99ca9b4bb67fea1a7424b755",
-       "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa",
-       "8e575b74b70d573b05558883743a72d1ccc326b4c299ea3412a29d3b83e801e4",
-       "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
-       "053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587"},
-  };
-
-  int res = 0;
-  uint8_t internal_priv[32] = {0};
-  uint8_t output_priv[32] = {0};
-  uint8_t internal_pub[32] = {0};
-  uint8_t output_pub[32] = {0};
-  uint8_t result[32] = {0};
-
-  for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-    memcpy(internal_priv, fromhex(tests[i].internal_priv), 32);
-    memcpy(output_priv, fromhex(tests[i].output_priv), 32);
-    memcpy(internal_pub, fromhex(tests[i].internal_pub), 32);
-    memcpy(output_pub, fromhex(tests[i].output_pub), 32);
-    const uint8_t *root_hash = NULL;
-    if (tests[i].root_hash != NULL) {
-      root_hash = fromhex(tests[i].root_hash);
-    }
-
-    res = zkp_bip340_get_public_key(internal_priv, result);
-    ck_assert_int_eq(res, 0);
-    ck_assert_mem_eq(internal_pub, result, 32);
-
-    res = zkp_bip340_get_public_key(output_priv, result);
-    ck_assert_int_eq(res, 0);
-    ck_assert_mem_eq(output_pub, result, 32);
-
-    res = zkp_bip340_tweak_private_key(internal_priv, root_hash, result);
-    ck_assert_int_eq(res, 0);
-    ck_assert_mem_eq(output_priv, result, 32);
-
-    res = zkp_bip340_tweak_public_key(internal_pub, root_hash, result);
-    ck_assert_int_eq(res, 0);
-    ck_assert_mem_eq(output_pub, result, 32);
-  }
-}
-END_TEST
-
-START_TEST(test_zkp_bip340_verify_publickey) {
-  static struct {
-    const char *public_key;
-    const int result;
-  } tests[] = {
-      // Test vectors 0, 5 and 14 from
-      // https://github.com/bitcoin/bips/blob/afa13249ed45826c2d7086714026c9bc1ccbf963/bip-0340/test-vectors.csv
-      {"F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", 0},
-      {"EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34", 1},
-      {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30", 1}};
-
-  int result = 0;
-  uint8_t public_key[32] = {0};
-
-  for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-    memcpy(public_key, fromhex(tests[i].public_key), 32);
-    result = zkp_bip340_verify_publickey(public_key);
-    ck_assert_int_eq(result, tests[i].result);
-  }
-}
-END_TEST
-
-static int my_strncasecmp(const char *s1, const char *s2, size_t n) {
-  size_t i = 0;
-  while (i < n) {
-    char c1 = s1[i];
-    char c2 = s2[i];
-    if (c1 >= 'A' && c1 <= 'Z') c1 = (c1 - 'A') + 'a';
-    if (c2 >= 'A' && c2 <= 'Z') c2 = (c2 - 'A') + 'a';
-    if (c1 < c2) return -1;
-    if (c1 > c2) return 1;
-    if (c1 == 0) return 0;
-    ++i;
-  }
-  return 0;
-}
-
-#include "test_check_cashaddr.h"
-#include "test_check_segwit.h"
-
-#if USE_CARDANO
-#include "test_check_cardano.h"
-#endif
-
-#if USE_MONERO
-#include "test_check_monero.h"
-#endif
-
-// define test suite and cases
-Suite *test_suite(void) {
-  Suite *s = suite_create("trezor-crypto");
-  TCase *tc;
-
-  tc = tcase_create("bignum");
-  tcase_add_test(tc, test_bignum_read_be);
-  tcase_add_test(tc, test_bignum_write_be);
-  tcase_add_test(tc, test_bignum_is_equal);
-  tcase_add_test(tc, test_bignum_zero);
-  tcase_add_test(tc, test_bignum_is_zero);
-  tcase_add_test(tc, test_bignum_one);
-  tcase_add_test(tc, test_bignum_read_le);
-  tcase_add_test(tc, test_bignum_write_le);
-  tcase_add_test(tc, test_bignum_read_uint32);
-  tcase_add_test(tc, test_bignum_read_uint64);
-  tcase_add_test(tc, test_bignum_write_uint32);
-  tcase_add_test(tc, test_bignum_write_uint64);
-  tcase_add_test(tc, test_bignum_copy);
-  tcase_add_test(tc, test_bignum_is_even);
-  tcase_add_test(tc, test_bignum_is_odd);
-  tcase_add_test(tc, test_bignum_bitcount);
-  tcase_add_test(tc, test_bignum_digitcount);
-  tcase_add_test(tc, test_bignum_is_less);
-  tcase_add_test(tc, test_bignum_format);
-  tcase_add_test(tc, test_bignum_format_uint64);
-  tcase_add_test(tc, test_bignum_sqrt);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("base32");
-  tcase_add_test(tc, test_base32_rfc4648);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("base58");
-  tcase_add_test(tc, test_base58);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bignum_divmod");
-  tcase_add_test(tc, test_bignum_divmod);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip32");
-  tcase_add_test(tc, test_bip32_vector_1);
-  tcase_add_test(tc, test_bip32_vector_2);
-  tcase_add_test(tc, test_bip32_vector_3);
-  tcase_add_test(tc, test_bip32_vector_4);
-  tcase_add_test(tc, test_bip32_compare);
-  tcase_add_test(tc, test_bip32_optimized);
-  tcase_add_test(tc, test_bip32_cache_1);
-  tcase_add_test(tc, test_bip32_cache_2);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip32-nist");
-  tcase_add_test(tc, test_bip32_nist_seed);
-  tcase_add_test(tc, test_bip32_nist_vector_1);
-  tcase_add_test(tc, test_bip32_nist_vector_2);
-  tcase_add_test(tc, test_bip32_nist_compare);
-  tcase_add_test(tc, test_bip32_nist_repeat);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip32-ed25519");
-  tcase_add_test(tc, test_bip32_ed25519_vector_1);
-  tcase_add_test(tc, test_bip32_ed25519_vector_2);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip32-ecdh");
-  tcase_add_test(tc, test_bip32_ecdh_nist256p1);
-  tcase_add_test(tc, test_bip32_ecdh_curve25519);
-  tcase_add_test(tc, test_bip32_ecdh_errors);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip32-decred");
-  tcase_add_test(tc, test_bip32_decred_vector_1);
-  tcase_add_test(tc, test_bip32_decred_vector_2);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ecdsa");
-  tcase_add_test(tc, test_ecdsa_get_public_key33);
-  tcase_add_test(tc, test_ecdsa_get_public_key65);
-  tcase_add_test(tc, test_ecdsa_recover_pub_from_sig);
-  tcase_add_test(tc, test_ecdsa_verify_digest);
-  tcase_add_test(tc, test_zkp_ecdsa_get_public_key33);
-  tcase_add_test(tc, test_zkp_ecdsa_get_public_key65);
-  tcase_add_test(tc, test_zkp_ecdsa_recover_pub_from_sig);
-  tcase_add_test(tc, test_zkp_ecdsa_verify_digest);
-#if USE_RFC6979
-  tcase_add_test(tc, test_ecdsa_sign_digest_deterministic);
-  tcase_add_test(tc, test_zkp_ecdsa_sign_digest_deterministic);
-#endif
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("rfc6979");
-  tcase_add_test(tc, test_rfc6979);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("address");
-  tcase_add_test(tc, test_address);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("address_decode");
-  tcase_add_test(tc, test_address_decode);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ethereum_address");
-  tcase_add_test(tc, test_ethereum_address);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("rsk_address");
-  tcase_add_test(tc, test_rsk_address);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("wif");
-  tcase_add_test(tc, test_wif);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ecdsa_der");
-  tcase_add_test(tc, test_ecdsa_der);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("aes");
-  tcase_add_test(tc, test_aes);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("sha2");
-  tcase_add_test(tc, test_sha1);
-  tcase_add_test(tc, test_sha256);
-  tcase_add_test(tc, test_sha512);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("sha3");
-  tcase_add_test(tc, test_sha3_256);
-  tcase_add_test(tc, test_sha3_512);
-  tcase_add_test(tc, test_keccak_256);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("blake");
-  tcase_add_test(tc, test_blake256);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("blake2");
-  tcase_add_test(tc, test_blake2b);
-  tcase_add_test(tc, test_blake2bp);
-  tcase_add_test(tc, test_blake2s);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("chacha_drbg");
-  tcase_add_test(tc, test_chacha_drbg);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("pbkdf2");
-  tcase_add_test(tc, test_pbkdf2_hmac_sha256);
-  tcase_add_test(tc, test_pbkdf2_hmac_sha512);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("hmac_drbg");
-  tcase_add_test(tc, test_hmac_drbg);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("bip39");
-  tcase_add_test(tc, test_mnemonic);
-  tcase_add_test(tc, test_mnemonic_check);
-  tcase_add_test(tc, test_mnemonic_to_bits);
-  tcase_add_test(tc, test_mnemonic_find_word);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("slip39");
-  tcase_add_test(tc, test_slip39_get_word);
-  tcase_add_test(tc, test_slip39_word_index);
-  tcase_add_test(tc, test_slip39_word_completion_mask);
-  tcase_add_test(tc, test_slip39_sequence_to_word);
-  tcase_add_test(tc, test_slip39_word_completion);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("shamir");
-  tcase_add_test(tc, test_shamir);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("pubkey_validity");
-  tcase_add_test(tc, test_pubkey_validity);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("pubkey_uncompress");
-  tcase_add_test(tc, test_pubkey_uncompress);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("codepoints");
-  tcase_add_test(tc, test_codepoints_secp256k1);
-  tcase_add_test(tc, test_codepoints_nist256p1);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("mult_border_cases");
-  tcase_add_test(tc, test_mult_border_cases_secp256k1);
-  tcase_add_test(tc, test_mult_border_cases_nist256p1);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("scalar_mult");
-  tcase_add_test(tc, test_scalar_mult_secp256k1);
-  tcase_add_test(tc, test_scalar_mult_nist256p1);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("point_mult");
-  tcase_add_test(tc, test_point_mult_secp256k1);
-  tcase_add_test(tc, test_point_mult_nist256p1);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("scalar_point_mult");
-  tcase_add_test(tc, test_scalar_point_mult_secp256k1);
-  tcase_add_test(tc, test_scalar_point_mult_nist256p1);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ed25519");
-  tcase_add_test(tc, test_ed25519);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ed25519_keccak");
-  tcase_add_test(tc, test_ed25519_keccak);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ed25519_cosi");
-  tcase_add_test(tc, test_ed25519_cosi);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ed25519_modm");
-  tcase_add_test(tc, test_ed25519_modl_add);
-  tcase_add_test(tc, test_ed25519_modl_neg);
-  tcase_add_test(tc, test_ed25519_modl_sub);
-  suite_add_tcase(s, tc);
-
-#if USE_MONERO
-  tc = tcase_create("ed25519_ge");
-  tcase_add_test(tc, test_ge25519_double_scalarmult_vartime2);
-  suite_add_tcase(s, tc);
-#endif
-
-  tc = tcase_create("script");
-  tcase_add_test(tc, test_output_script);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("ethereum_pubkeyhash");
-  tcase_add_test(tc, test_ethereum_pubkeyhash);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("nem_address");
-  tcase_add_test(tc, test_nem_address);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("nem_encryption");
-  tcase_add_test(tc, test_nem_derive);
-  tcase_add_test(tc, test_nem_cipher);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("nem_transaction");
-  tcase_add_test(tc, test_nem_transaction_transfer);
-  tcase_add_test(tc, test_nem_transaction_multisig);
-  tcase_add_test(tc, test_nem_transaction_provision_namespace);
-  tcase_add_test(tc, test_nem_transaction_mosaic_creation);
-  tcase_add_test(tc, test_nem_transaction_mosaic_supply_change);
-  tcase_add_test(tc, test_nem_transaction_aggregate_modification);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("multibyte_address");
-  tcase_add_test(tc, test_multibyte_address);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("rc4");
-  tcase_add_test(tc, test_rc4_rfc6229);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("segwit");
-  tcase_add_test(tc, test_segwit);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("cashaddr");
-  tcase_add_test(tc, test_cashaddr);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("compress_coords");
-  tcase_add_test(tc, test_compress_coords);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("zkp_bip340");
-  tcase_add_test(tc, test_zkp_bip340_sign);
-  tcase_add_test(tc, test_zkp_bip340_verify);
-  tcase_add_test(tc, test_zkp_bip340_tweak);
-  tcase_add_test(tc, test_zkp_bip340_verify_publickey);
-  suite_add_tcase(s, tc);
-
-#if USE_CARDANO
-  tc = tcase_create("bip32-cardano");
-
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_1);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_2);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_3);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_4);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_5);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_6);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_7);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_8);
-  tcase_add_test(tc, test_bip32_cardano_hdnode_vector_9);
-
-  tcase_add_test(tc, test_cardano_ledger_vector_1);
-  tcase_add_test(tc, test_cardano_ledger_vector_2);
-  tcase_add_test(tc, test_cardano_ledger_vector_3);
-
-  tcase_add_test(tc, test_ed25519_cardano_sign_vectors);
-  suite_add_tcase(s, tc);
-#endif
-
-#if USE_MONERO
-  tc = tcase_create("xmr_base58");
-  tcase_add_test(tc, test_xmr_base58);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("xmr_crypto");
-  tcase_add_test(tc, test_xmr_getset256_modm);
-  tcase_add_test(tc, test_xmr_cmp256_modm);
-  tcase_add_test(tc, test_xmr_copy_check_modm);
-  tcase_add_test(tc, test_xmr_mulsub256_modm);
-  tcase_add_test(tc, test_xmr_muladd256_modm);
-  tcase_add_test(tc, test_xmr_curve25519_set);
-  tcase_add_test(tc, test_xmr_curve25519_consts);
-  tcase_add_test(tc, test_xmr_curve25519_tests);
-  tcase_add_test(tc, test_xmr_curve25519_expand_reduce);
-  tcase_add_test(tc, test_xmr_ge25519_base);
-  tcase_add_test(tc, test_xmr_ge25519_check);
-  tcase_add_test(tc, test_xmr_ge25519_scalarmult_base_wrapper);
-  tcase_add_test(tc, test_xmr_ge25519_scalarmult);
-  tcase_add_test(tc, test_xmr_ge25519_ops);
-  suite_add_tcase(s, tc);
-
-  tc = tcase_create("xmr_xmr");
-  tcase_add_test(tc, test_xmr_check_point);
-  tcase_add_test(tc, test_xmr_h);
-  tcase_add_test(tc, test_xmr_fast_hash);
-  tcase_add_test(tc, test_xmr_hasher);
-  tcase_add_test(tc, test_xmr_hash_to_scalar);
-  tcase_add_test(tc, test_xmr_hash_to_ec);
-  tcase_add_test(tc, test_xmr_derivation_to_scalar);
-  tcase_add_test(tc, test_xmr_generate_key_derivation);
-  tcase_add_test(tc, test_xmr_derive_private_key);
-  tcase_add_test(tc, test_xmr_derive_public_key);
-  tcase_add_test(tc, test_xmr_add_keys2);
-  tcase_add_test(tc, test_xmr_add_keys3);
-  tcase_add_test(tc, test_xmr_get_subaddress_secret_key);
-  tcase_add_test(tc, test_xmr_gen_c);
-  tcase_add_test(tc, test_xmr_varint);
-  suite_add_tcase(s, tc);
-#endif
-  return s;
-}
-
-// run suite
-int main(void) {
-  assert(zkp_context_init() == 0);
-  int number_failed;
-  Suite *s = test_suite();
-  SRunner *sr = srunner_create(s);
-  srunner_run_all(sr, CK_VERBOSE);
-  number_failed = srunner_ntests_failed(sr);
-  srunner_free(sr);
-  if (number_failed == 0) {
-    printf("PASSED ALL TESTS\n");
-  }
-  return number_failed;
-}

+ 0 - 571
crypto/tests/test_check_cardano.h

@@ -1,571 +0,0 @@
-// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128
-START_TEST(test_ed25519_cardano_sign_vectors) {
-  ed25519_public_key public_key;
-  ed25519_secret_key secret_key;
-  ed25519_secret_key secret_key_extension;
-  ed25519_signature signature;
-
-  static const char *vectors[] = {
-      "6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea5"
-      "3",  // private key
-      "60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8"
-      "e",  // private key extension
-      "64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe"
-      "1",  // public key
-      "45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c7"
-      "9331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10"
-      "d",  // signature
-
-      "e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830"
-      "c",  // private key
-      "794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a"
-      "4",  // private key extension
-      "95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931d"
-      "f",  // public key
-      "f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b1"
-      "9ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560"
-      "f",  // signature
-
-      "9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0"
-      "c",  // private key
-      "b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedeb"
-      "b",  // private key extension
-      "79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19"
-      "f",  // public key
-      "2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a"
-      "88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800"
-      "f",  // signature
-
-      "52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40"
-      "c",  // private key
-      "6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a2580"
-      "3",  // private key extension
-      "dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d"
-      "6",  // public key
-      "0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a6"
-      "2a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd78160"
-      "2",  // signature
-
-      "11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec0"
-      "4",  // private key
-      "c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a547340235"
-      "2",  // private key extension
-      "839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db7"
-      "8",  // public key
-      "e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f"
-      "9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa490"
-      "5",  // signature
-
-      "5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e50"
-      "5",  // private key
-      "ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098c"
-      "d",  // private key extension
-      "75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb7"
-      "6",  // public key
-      "631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fb"
-      "c10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda59890"
-      "6",  // signature
-
-      "624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50"
-      "d",  // private key
-      "097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b0"
-      "2",  // private key extension
-      "0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b0"
-      "0",  // public key
-      "1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a"
-      "57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f90"
-      "1",  // signature
-
-      0,
-      0,
-  };
-
-  const char **test_data;
-  test_data = vectors;
-  while (*test_data) {
-    memcpy(secret_key, fromhex(*test_data), 32);
-    MARK_SECRET_DATA(secret_key, sizeof(secret_key));
-
-    memcpy(secret_key_extension, fromhex(*(test_data + 1)), 32);
-    MARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
-
-    ed25519_publickey_ext(secret_key, public_key);
-    UNMARK_SECRET_DATA(public_key, sizeof(public_key));
-
-    ck_assert_mem_eq(public_key, fromhex(*(test_data + 2)), 32);
-
-    const uint8_t *message = (const uint8_t *)"Hello World";
-    ed25519_sign_ext(message, 11, secret_key, secret_key_extension, signature);
-    UNMARK_SECRET_DATA(signature, sizeof(signature));
-
-    ck_assert_mem_eq(signature, fromhex(*(test_data + 3)), 64);
-
-    UNMARK_SECRET_DATA(secret_key, sizeof(secret_key));
-    UNMARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
-
-    test_data += 4;
-  }
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_1) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  ck_assert_mem_eq(
-      cardano_secret,
-      fromhex(
-          "08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"
-          "daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"
-          "affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"),
-      96);
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "9a1d04808b4c0682816961cf666e82a7fd35949658aba5354c517eccf12aacb4"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_2) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "104c6a0736e501c9bfe2966ba3773f5320495b19c3f2ed222234850af2ccd5b1"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "6064bf06b2e981d7c9792b1482eeecd40ec3cfa12143f4a1f149d48ce8b6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "64aa9a16331f14c981b769efcf96addcc4c6db44047fe7a7feae0be23d33bf54"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "c651c14a13c2311fc30a7acf244add1fdac3683e7ba89b4571e4cbcab509b915"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_3) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000001);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "da99870d7e69de2a76f255ba8c7ed22428c7e5b0a8df978753c707c95ec3d4ca"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "c85fa69f4a1891fd98d1d1fc5f0cf9b1d6e44b0e6906744ab23ea766edb6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "b4fc241feffe840b8a54a26ab447f5a5caa31032db3a8091fca14f38b86ed539"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "5a5b0c92530cd366f05cf072509c806f904262c259e79a0080bbd5ee35706bb1"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_4) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "b40c44dfd9be08591b62be7f9991c85f812d8196927f3c824d9fcb17d275089e"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "d064dcf1449d9c3e47f5b422680343561989035bf2e4e23fc34cb61fedb6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "a3071959013af95aaecf78a7a2e1b9838bbbc4864d6a8a2295243782078345cd"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "aaaca5e7adc69a03ef1f5c017ed02879e8ca871df028461ed9bf19fb8fa15038"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_5) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-  hdnode_private_ckd(&node, 0x80000002);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "2593896baf92f6ab2c0f253787ab16be0244ba95e0d48ba09da1a7fd3f926c72"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "0811b6d5d6f7120cb05d4ce5453d6ce42825c2a8e53b6d370a6b05ccf4b6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "5bebf1eea68acd04932653d944b064b10baaf5886dd73c185cc285059bf93363"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "1c87a32c5babad2fe33e0586bdc523574c6126f8368bc76598e17ea46201f980"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_6) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0x80000002);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "fe8c6c2ab1e30385513fcffb49dcfe3e7805260425ea76b3b72b9f5bbe3b3d40"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "6019b9f5ef6ca530b657bcdb500de5455db8d51afb951fa045b6fbb3f6b6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "466332cb097934b43008701e7e27044aa56c7859019e4eba18d91a3bea23dff7"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "0b8f04755481ced76b4e5795aaafdb3cbd757c10fe60e9c58f48cf29a7ec3575"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_7) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "ring crime symptom enough erupt lady behave ramp apart settle citizen "
-      "junk",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 132);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0xBB9ACA00);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "ff77c08d37471c1d4cedd3fae2642c009324d9712492efc74dedab09c9bf973c"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "488f34840bba516f7920f91676b8681d0dd833b4ce14468e0810b255f9b6ea46"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "01eccef768a79859f824a1d3c3e35e131184e2940c3fca9a4c9b307741f65363"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "148605be54585773b44ba87e79265149ae444c4cc37cb1f8db8c08482fba293b"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_8) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "found differ bulb shadow wrist blue bind vessel deposit tip pelican "
-      "action surprise weapon check fiction muscle this",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 198);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0xBB9ACA00);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "6fb22a4531ad79e828c4907c5fff3ecf686c16cb195f81243f1f0330173380e4"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "a0baa34e4e24f0500ed6e5e90ab41984b965b7464b0b28640528778dd8a6b854"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "170e0d3b65ba8d71f27a6db60d0ac26dcb16e52e08cc259db72066f206b258d5"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "3dae0c06d87db618d73ee808425898cdd882f9eb43bf139c6b3a4760551ee89f"),
-      32);
-}
-END_TEST
-
-START_TEST(test_bip32_cardano_hdnode_vector_9) {
-  HDNode node;
-
-  uint8_t mnemonic_bits[66];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-  int mnemonic_bits_len = mnemonic_to_bits(
-      "balance exotic ranch knife glory slow tape favorite yard gym awake "
-      "ill exist useless parent aim pig stay effort into square gasp credit "
-      "butter",
-      mnemonic_bits);
-  ck_assert_int_eq(mnemonic_bits_len, 264);
-  secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits,
-                                     mnemonic_bits_len / 8, cardano_secret,
-                                     NULL);
-  hdnode_from_secret_cardano(cardano_secret, &node);
-
-  hdnode_private_ckd(&node, 0x80000000);
-  hdnode_private_ckd(&node, 0x80000001);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0x80000002);
-  hdnode_private_ckd(&node, 0xBB9ACA00);
-
-  ck_assert_mem_eq(
-      node.chain_code,
-      fromhex(
-          "9b226add79f90086ea18b260da633089fe121db758aa31284ad1affaf3c9bb68"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key,
-      fromhex(
-          "38eb2a79486e516cb6658700503a3e2c870c03e9d1aec731f780aa6fb7f7de44"),
-      32);
-  ck_assert_mem_eq(
-      node.private_key_extension,
-      fromhex(
-          "80d2c677638e5dbd4395cdec279bf2a42077f2797c9e887949d37cdb317fce6a"),
-      32);
-  ck_assert_int_eq(hdnode_fill_public_key(&node), 0);
-  ck_assert_mem_eq(
-      node.public_key + 1,
-      fromhex(
-          "115a365b2aad1d8eba7d379de518f1fa8553855110af24e5695011c32ce9a300"),
-      32);
-}
-END_TEST
-
-START_TEST(test_cardano_ledger_vector_1) {
-  uint8_t seed[512 / 8];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-
-  const char *mnemonic =
-      "recall grace sport punch exhibit mad harbor stand obey "
-      "short width stem awkward used stairs wool ugly "
-      "trap season stove worth toward congress jaguar";
-
-  mnemonic_to_seed(mnemonic, "", seed, NULL);
-  const int res =
-      secret_from_seed_cardano_ledger(seed, sizeof(seed), cardano_secret);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      cardano_secret,
-      fromhex(
-          "a08cf85b564ecf3b947d8d4321fb96d70ee7bb760877e371899b14e2ccf88658"
-          "104b884682b57efd97decbb318a45c05a527b9cc5c2f64f7352935a049ceea60"
-          "680d52308194ccef2a18e6812b452a5815fbd7f5babc083856919aaf668fe7e4"),
-      CARDANO_SECRET_LENGTH);
-}
-END_TEST
-
-START_TEST(test_cardano_ledger_vector_2) {
-  uint8_t seed[512 / 8];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-
-  const char *mnemonic =
-      "correct cherry mammal bubble want mandate polar hazard "
-      "crater better craft exotic choice fun tourist census "
-      "gap lottery neglect address glow carry old business";
-
-  mnemonic_to_seed(mnemonic, "", seed, NULL);
-  const int res =
-      secret_from_seed_cardano_ledger(seed, sizeof(seed), cardano_secret);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      cardano_secret,
-      fromhex(
-          "587c6774357ecbf840d4db6404ff7af016dace0400769751ad2abfc77b9a3844"
-          "cc71702520ef1a4d1b68b91187787a9b8faab0a9bb6b160de541b6ee62469901"
-          "fc0beda0975fe4763beabd83b7051a5fd5cbce5b88e82c4bbaca265014e524bd"),
-      CARDANO_SECRET_LENGTH);
-}
-END_TEST
-
-START_TEST(test_cardano_ledger_vector_3) {
-  uint8_t seed[512 / 8];
-  uint8_t cardano_secret[CARDANO_SECRET_LENGTH];
-
-  const char *mnemonic =
-      "abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon abandon "
-      "abandon abandon abandon abandon abandon abandon abandon art";
-
-  mnemonic_to_seed(mnemonic, "foo", seed, NULL);
-  const int res =
-      secret_from_seed_cardano_ledger(seed, sizeof(seed), cardano_secret);
-  ck_assert_int_eq(res, 1);
-  ck_assert_mem_eq(
-      cardano_secret,
-      fromhex(
-          "f053a1e752de5c26197b60f032a4809f08bb3e5d90484fe42024be31efcba757"
-          "8d914d3ff992e21652fee6a4d99f6091006938fac2c0c0f9d2de0ba64b754e92"
-          "a4f3723f23472077aa4cd4dd8a8a175dba07ea1852dad1cf268c61a2679c3890"),
-      CARDANO_SECRET_LENGTH);
-}
-END_TEST

+ 0 - 76
crypto/tests/test_check_cashaddr.h

@@ -1,76 +0,0 @@
-#include "cash_addr.h"
-
-static const char* valid_cashchecksum[] = {
-    "prefix:x64nx6hz",
-    "p:gpf8m4h7",
-    "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn",
-    "bchtest:testnetaddress4d6njnut",
-    "bchreg:555555555555555555555555555555555555555555555udxmlmrz",
-};
-
-struct valid_cashaddr_data {
-  const char* legacy;
-  const char* cashaddress;
-};
-
-static struct valid_cashaddr_data valid_cashaddr[] = {
-    {"1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu",
-     "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"},
-    {"1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR",
-     "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"},
-    {"16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb",
-     "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"},
-    {"3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC",
-     "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"},
-    {"3LDsS579y7sruadqu11beEJoTjdFiFCdX4",
-     "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"},
-    {"31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw",
-     "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"}};
-
-START_TEST(test_cashaddr) {
-  size_t i;
-  for (i = 0; i < sizeof(valid_cashchecksum) / sizeof(valid_cashchecksum[0]);
-       ++i) {
-    uint8_t data[82];
-    char rebuild[92];
-    char hrp[84];
-    size_t data_len;
-    int res = cash_decode(hrp, data, &data_len, valid_cashchecksum[i]);
-    ck_assert_int_eq(res, 1);
-    res = cash_encode(rebuild, hrp, data, data_len);
-    ck_assert_int_eq(res, 1);
-    ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashchecksum[i], 92), 0);
-  }
-  for (i = 0; i < sizeof(valid_cashaddr) / sizeof(valid_cashaddr[0]); ++i) {
-    uint8_t prog[65];
-    size_t prog_len;
-    const char* hrp = "bitcoincash";
-    uint8_t rawdata[65];
-    size_t rawdata_len;
-    char rebuild[93];
-    int ret =
-        cash_addr_decode(prog, &prog_len, hrp, valid_cashaddr[i].cashaddress);
-    ck_assert_int_eq(ret, 1);
-    ck_assert_uint_eq(prog_len, 21);
-    rawdata_len = base58_decode_check(valid_cashaddr[i].legacy, HASHER_SHA2D,
-                                      rawdata, sizeof(rawdata));
-    ck_assert_uint_eq(rawdata_len, 21);
-
-    int addr_type = -1;
-    if (rawdata[0] == 0) {
-      addr_type = 0x00;  // P2PKH
-    } else if (rawdata[0] == 5) {
-      addr_type = 0x08;  // P2SH
-    } else {
-      ck_abort();
-    }
-    ck_assert_uint_eq(prog[0], addr_type);
-
-    ck_assert_int_eq(memcmp(rawdata + 1, prog + 1, 20), 0);
-    ret = cash_addr_encode(rebuild, hrp, prog, 21);
-    ck_assert_int_eq(ret, 1);
-    ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashaddr[i].cashaddress, 92),
-                     0);
-  }
-}
-END_TEST

+ 0 - 1132
crypto/tests/test_check_monero.h

@@ -1,1132 +0,0 @@
-#if USE_MONERO
-START_TEST(test_xmr_base58) {
-  static const struct {
-    uint64_t tag;
-    char *v1;
-    char *v2;
-  } tests[] = {
-      {0x12,
-       "3bec484c5d7f0246af520aab550452b5b6013733feabebd681c4a60d457b7fc12d5918e"
-       "31d3c003da3c778592c07b398ad6f961a67082a75fd49394d51e69bbe",
-       "43tpGG9PKbwCpjRvNLn1jwXPpnacw2uVUcszAtgmDiVcZK4VgHwjJT9BJz1WGF9eMxSYASp"
-       "8yNMkuLjeQfWqJn3CNWdWfzV"},
-      {0x12,
-       "639050436fa36c8288706771412c5972461578d564188cd7fc6f81d6973d064fa461afe"
-       "66fb23879936d7225051bebbf7f3ae0c801a90bb99fbb346b2fd4d702",
-       "45PwgoUKaDHNqLL8o3okzLL7biv7GqPVmd8LTcTrYVrMEKdSYwFcyJfMLSRpfU3nh8Z2m81"
-       "FJD4sUY3nXCdGe61k1HAp8T1"},
-      {53,
-       "5a10cca900ee47a7f412cd661b29f5ab356d6a1951884593bb170b5ec8b6f2e83b1da41"
-       "1527d062c9fedeb2dad669f2f5585a00a88462b8c95c809a630e5734c",
-       "9vacMKaj8JJV6MnwDzh2oNVdwTLJfTDyNRiB6NzV9TT7fqvzLivH2dB8Tv7VYR3ncn8vCb3"
-       "KdNMJzQWrPAF1otYJ9cPKpkr"},
-      {0x12, "", "35EMFRj"},
-      {53, "d910642d8b3372fe72676dbc925277974d0401d387e4024",
-       "A1PkB4pLAiVjZTJpWewswLSJor6eEYDHj35UiF7"},
-  };
-
-  uint8_t rawn[512];
-  char strn[512];
-  int r;
-  uint64_t tag;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    const char *raw = tests[i].v1;
-    const char *str = tests[i].v2;
-    const size_t len = strlen(raw) / 2;
-
-    memcpy(rawn, fromhex(raw), len);
-
-    r = xmr_base58_addr_encode_check(tests[i].tag, rawn, len, strn,
-                                     sizeof(strn));
-    ck_assert_uint_eq((size_t)r, strlen(str));
-    ck_assert_mem_eq(strn, str, r);
-
-    r = xmr_base58_addr_decode_check(strn, r, &tag, rawn, len);
-    ck_assert_uint_eq((size_t)r, len);
-    ck_assert_mem_eq(rawn, fromhex(raw), len);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_getset256_modm) {
-  static const struct {
-    uint64_t val;
-    int r;
-    char *a;
-  } tests[] = {
-      {0x0, 1,
-       "0000000000000000000000000000000000000000000000000000000000000000"},
-      {0x7fffffffULL, 1,
-       "ffffff7f00000000000000000000000000000000000000000000000000000000"},
-      {0x7fffffffffffffffULL, 1,
-       "ffffffffffffff7f000000000000000000000000000000000000000000000000"},
-      {0xdeadc0deULL, 1,
-       "dec0adde00000000000000000000000000000000000000000000000000000000"},
-      {0x0, 0,
-       "dec0adde000000000000000000000000000000000000000000000000000000ff"},
-      {0x0, 0,
-       "ffffffffffffffffff0000000000000000000000000000000000000000000000"},
-  };
-
-  uint8_t rawn[32];
-  uint64_t v1;
-  bignum256modm a1 = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    int get_res = tests[i].r;
-    if (get_res) {
-      set256_modm(a1, tests[i].val);
-      ck_assert_int_eq(get256_modm(&v1, a1), 1);
-      ck_assert(v1 == tests[i].val);
-
-      contract256_modm(rawn, a1);
-      ck_assert_mem_eq(rawn, fromhex(tests[i].a), 32);
-
-    } else {
-      expand256_modm(a1, fromhex(tests[i].a), 32);
-      ck_assert_int_eq(get256_modm(&v1, a1), 0);
-    }
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_cmp256_modm) {
-  static const struct {
-    char *a;
-    char *b;
-    int res_eq;
-    int res_cmp;
-    int res_is_zero_a;
-  } tests[] = {
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "0000000000000000000000000000000000000000000000000000000000000000", 1, 0,
-       1},
-      {"0000000000000000000000000000000000000000000000000000000000000000",
-       "0100000000000000000000000000000000000000000000000000000000000000", 0,
-       -1, 1},
-      {"dec0adde00000000000000000000000000000000000000000000000000000000",
-       "dec0adde00000000000000000000000000000000000000000000000000000000", 1, 0,
-       0},
-      {"863346d8863c461cde2ec7c2759352c2b952228f33a86ca06bb79574bbe5c30d",
-       "3ddbd65a6d3ba5e2ab120603685a353a27ce3fd21dfdbea7952d2dd26f1ca00a", 0, 1,
-       0},
-      {"f7667f392edbea6e224b1aa9fbf2a3b238b4f977fb4a8f39130cc45f49b5c40a",
-       "b41b9b1e7e80be71cf290ed4bded58924086b8ac6bdfa1faa0c80c255f074d07", 0, 1,
-       0},
-      {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27501",
-       "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 0,
-       -1, 0},
-      {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504",
-       "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 1, 0,
-       0},
-      {"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504",
-       "0e4005c7826de8f9978749903f41efd140e4ae6d3bed09e558fcce8367b27504", 0,
-       -1, 0},
-  };
-
-  bignum256modm a1 = {0}, a2 = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a1, fromhex(tests[i].a), 32);
-    expand256_modm(a2, fromhex(tests[i].b), 32);
-
-    ck_assert_int_eq(eq256_modm(a1, a2), tests[i].res_eq);
-    ck_assert_int_eq(cmp256_modm(a1, a2), tests[i].res_cmp);
-    ck_assert_int_eq(iszero256_modm(a1), tests[i].res_is_zero_a);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_copy_check_modm) {
-  static const struct {
-    int check;
-    char *a;
-  } tests[] = {
-      {0, "0000000000000000000000000000000000000000000000000000000000000000"},
-      {1, "ffffff7f00000000000000000000000000000000000000000000000000000000"},
-      {1, "ffffffffffffff7f000000000000000000000000000000000000000000000000"},
-      {1, "dec0adde00000000000000000000000000000000000000000000000000000000"},
-      {0, "dec0adde000000000000000000000fffffffffffffffffffffffffffffffffff"},
-  };
-
-  bignum256modm a1 = {0}, a2 = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand_raw256_modm(a1, fromhex(tests[i].a));
-    copy256_modm(a2, a1);
-    ck_assert_int_eq(eq256_modm(a1, a2), 1);
-    ck_assert_int_eq(check256_modm(a1), tests[i].check);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_mulsub256_modm) {
-  static const struct {
-    char *a;
-    char *b;
-    char *c;
-    char *r;
-  } tests[] = {
-      {
-          "713c199348cf7d14b67ae6265ea49c02c8647f07afcbcb6f8d3254b3db972e02",
-          "4e48a7b7a03ab1106fdfa9441a03c97c644395a12ac4b8effac7344e0719c200",
-          "1a5711b8c43bcab0161a620368d82727e1d027dc248f420d9bb4db2486c16405",
-          "6edcc08aa6ec3a5b3d333b5f826be7de9c268be8aaf9521586fbcccbed3b1c0c",
-      },
-      {
-          "d4ade2c62d34af8cfd9daec6f46bf7e57962a8aa46935cb11fab64fa599b4700",
-          "22ea7989a9f4d34cd8c9442e03b5062dfe8493757cd18a63411cb1a25e44960f",
-          "772053e613f0859387badcefeb7fbe551a05b00b9337539c8d72661de5929806",
-          "a5063258df4520b33e97c0a46d80feeace5c251fc7ef7a938d160b8f25795106",
-      },
-      {
-          "01fd2ef25c8221277a2b6daf1f1642bacb8d6ac0dd4f62731cdd73e26eb77900",
-          "0611b9357530aa638428002769ce0ad553421e971bea1f10d7009bf26d9af805",
-          "dfece232068b2f8059ca569f345baaed13ab464eb3bebb99de5625dc90a8cf03",
-          "85752e62bd8085c7c02d5edeb74969d22f1a5bb34349258d2e96de300176bb07",
-      },
-  };
-
-  bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i].a), 32);
-    expand256_modm(b, fromhex(tests[i].b), 32);
-    expand256_modm(c, fromhex(tests[i].c), 32);
-    expand256_modm(r, fromhex(tests[i].r), 32);
-    mulsub256_modm(r2, a, b, c);
-    ck_assert_int_eq(eq256_modm(r, r2), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_muladd256_modm) {
-  static const struct {
-    char *a;
-    char *b;
-    char *c;
-    char *r;
-  } tests[] = {
-      {
-          "7c3fd8abfbe2be3739d91679ac8dbda086961b941e0d4a00561f758927d8aa09",
-          "ac2d8d37e4f344aa4040d0f0fc29d45423ab7e69ecacb94ca9fc36819e0e990e",
-          "2f03f1bac09bc7d002848b68be069dc98b2db028390ae37e13a5166fcae08105",
-          "dce113add3392f08e3b38b7d31e237eba5066e5a95a1fdbf755b92d05e1ec70b",
-      },
-      {
-          "6979b70f6198d043f4b14e2069f7b89cc9f09e3465e71d472946443989e0e80c",
-          "8dd5177bc8d7c5bd58c0be74b336952a73ac259ebb812ac8cd755773c6aab807",
-          "d7658e508a7454ccfb29e2890d6156ac10e18ebe6e00cc5a2d2d87a5080c7f06",
-          "51b33f6263772781cdbab26ef48870eaf94899894a437dac39496f15b9d0ae00",
-      },
-      {
-          "ebfdb4eabedb1fb9a45b3204735b0511871e20358392fa16a851c519e3a29b09",
-          "59d98831e9f9e24260158986c4d4035438de9b8876cc11bdcf4c364c75f72908",
-          "93bce4764eee97dc67f2e37da40bc5641f2cdc637285d273287a3d4383b68f02",
-          "21547ca6855c85d5adcd673b9d801d0cb0f10dced8f8b68a8c2f74163defde0e",
-      },
-  };
-
-  bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i].a), 32);
-    expand256_modm(b, fromhex(tests[i].b), 32);
-    expand256_modm(c, fromhex(tests[i].c), 32);
-    expand256_modm(r, fromhex(tests[i].r), 32);
-    muladd256_modm(r2, a, b, c);
-    ck_assert_int_eq(eq256_modm(r, r2), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_curve25519_set) {
-  static const struct {
-    uint32_t val;
-    char *a;
-  } tests[] = {
-      {0x0, "0000000000000000000000000000000000000000000000000000000000000000"},
-      {0x1, "0100000000000000000000000000000000000000000000000000000000000000"},
-      {0xdeadc0deUL,
-       "dec0adde00000000000000000000000000000000000000000000000000000000"},
-  };
-
-  unsigned char buff[32];
-  bignum25519 a = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    curve25519_set(a, tests[i].val);
-    curve25519_contract(buff, a);
-    ck_assert_mem_eq(buff, fromhex(tests[i].a), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_curve25519_consts) {
-  char *d = "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352";
-  char *d2 = "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624";
-  char *sqrtneg1 =
-      "b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b";
-
-  unsigned char buff[32];
-  bignum25519 a = {0};
-
-  curve25519_set_d(a);
-  curve25519_contract(buff, a);
-  ck_assert_mem_eq(buff, fromhex(d), 32);
-
-  curve25519_set_2d(a);
-  curve25519_contract(buff, a);
-  ck_assert_mem_eq(buff, fromhex(d2), 32);
-
-  curve25519_set_sqrtneg1(a);
-  curve25519_contract(buff, a);
-  ck_assert_mem_eq(buff, fromhex(sqrtneg1), 32);
-}
-END_TEST
-
-START_TEST(test_xmr_curve25519_tests) {
-  static const struct {
-    char *a;
-    int res_neg;
-    int res_nonzero;
-  } tests[] = {
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          0,
-          0,
-      },
-      {
-          "0100000000000000000000000000000000000000000000000000000000000000",
-          1,
-          1,
-      },
-      {
-          "05737aa6100ee54283dc0d483b8e39e61846f6b3736908243d0c824d250b3139",
-          1,
-          1,
-      },
-      {
-          "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
-          1,
-          1,
-      },
-      {
-          "02587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
-          0,
-          1,
-      },
-  };
-
-  bignum25519 a = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    curve25519_expand(a, fromhex(tests[i].a));
-    ck_assert_int_eq(curve25519_isnegative(a), tests[i].res_neg);
-    ck_assert_int_eq(curve25519_isnonzero(a), tests[i].res_nonzero);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_curve25519_expand_reduce) {
-  static const struct {
-    char *a;
-    char *b;
-  } tests[] = {
-      {"dec0adde00000000000000000000000000000000000000000000000000000000",
-       "dec0adde00000000000000000000000000000000000000000000000000000000"},
-      {"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
-       "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15"},
-      {"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bcff",
-       "a8587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc7f"},
-      {"95587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bcff",
-       "a8587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bc7f"},
-  };
-
-  unsigned char buff[32];
-  bignum25519 a = {0};
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    curve25519_expand_reduce(a, fromhex(tests[i].a));
-    curve25519_contract(buff, a);
-    ck_assert_mem_eq(buff, fromhex(tests[i].b), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_ge25519_base) {
-  unsigned char buff[32];
-  char *base =
-      "5866666666666666666666666666666666666666666666666666666666666666";
-  ge25519 b;
-  ge25519_set_base(&b);
-  ge25519_pack(buff, &b);
-  ck_assert_mem_eq(buff, fromhex(base), 32);
-}
-END_TEST
-
-START_TEST(test_xmr_ge25519_check) {
-  static const struct {
-    char *x;
-    char *y;
-    char *z;
-    char *t;
-    int r;
-  } tests[] = {
-      {"4ff97748221f954414f836d84e8e7e207786bcd20eb67044756dca307e792c60",
-       "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63",
-       "0100000000000000000000000000000000000000000000000000000000000000",
-       "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 1},
-      {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
-       "ca48045f790145a1eec3946dfd73747fde0fdb4238607e0a203f8ef5bef90e0e",
-       "0100000000000000000000000000000000000000000000000000000000000000",
-       "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 1},
-      {"4ff97748221f954414f836d84e8e7e207786bcd20eb6704475ffca307e792c60",
-       "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63",
-       "0100000000000000000000000000000000000000000000000000000000000000",
-       "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 0},
-      {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
-       "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e",
-       "0100000000000000000000000000000000000000000000000000000000000000",
-       "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0},
-      {"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
-       "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e",
-       "0100000000000000000000000000000000000000000000000000000000000000",
-       "6c5e5ffae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0},
-  };
-
-  struct ge25519_t p;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    curve25519_expand_reduce(p.x, fromhex(tests[i].x));
-    curve25519_expand_reduce(p.y, fromhex(tests[i].y));
-    curve25519_expand_reduce(p.z, fromhex(tests[i].z));
-    curve25519_expand_reduce(p.t, fromhex(tests[i].t));
-    ck_assert_int_eq(ge25519_check(&p), tests[i].r);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_ge25519_scalarmult_base_wrapper) {
-  static const struct {
-    char *sc;
-    char *pt;
-  } tests[] = {
-      {
-          "40be740e26bd1c84f5a8fec737c0ed30e87bd45adfcd91e320f8dfb68b1a870e",
-          "b7a8b2f3dbfd41b38d20aec733a316dbfc2633503799cd36f38570cafc8ea887",
-      },
-      {
-          "1b3746add992215d427e43a58354c11ff9e6dfa1c187250938f7f9334fa41d05",
-          "e2a1bfbe38a9749fe6ede79d923b778fa4c89393473d633bec01fa68617d0828",
-      },
-      {
-          "69af25c54090a9746d3f6043348452429ffd53c1530fa114fd0055b70d61020f",
-          "6bf1783b0a7495d5f6c36605dca95e723ca120a306c255084787f09b12771124",
-      },
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "0100000000000000000000000000000000000000000000000000000000000000",
-      },
-      {
-          "0100000000000000000000000000000000000000000000000000000000000000",
-          "5866666666666666666666666666666666666666666666666666666666666666",
-      },
-      {
-          "0800000000000000000000000000000000000000000000000000000000000000",
-          "b4b937fca95b2f1e93e41e62fc3c78818ff38a66096fad6e7973e5c90006d321",
-      },
-      {
-          "ffffffffffffffff000000000000000000000000000000000000000000000000",
-          "e185757a3fdc6519a6e7bebd97aa52bdc999e4c87d5c3aad0d995763ab6c6985",
-      },
-  };
-
-  ge25519 pt, pt2;
-  bignum256modm sc;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(sc, fromhex(tests[i].sc), 32);
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-    ge25519_scalarmult_base_wrapper(&pt2, sc);
-    ck_assert_int_eq(ge25519_eq(&pt, &pt2), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_ge25519_scalarmult) {
-  static const struct {
-    char *sc;
-    char *pt;
-    char *pt2;
-  } tests[] = {
-      {
-          "0000000000000000000000000000000000000000000000000000000000000000",
-          "5cbb3b2784c16f0e7eb4f2a7f93288552bb24ec51c5e01504c1e6885cfbca6d0",
-          "0100000000000000000000000000000000000000000000000000000000000000",
-      },
-      {
-          "0100000000000000000000000000000000000000000000000000000000000000",
-          "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6",
-          "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6",
-      },
-      {
-          "3930000000000000000000000000000000000000000000000000000000000000",
-          "2835b3983e3cc01a640fd188bf6bbbafbf997a3344d800eed22e4e82a412941c",
-          "2fe8b2dd0f23e02fca6989e170135584d684583c0a44f6a7d3ebd964685d36c7",
-      },
-      {
-          "ffffffffffffffff000000000000000000000000000000000000000000000000",
-          "bb8af7a53a8f1b477c810e833a84cdc789a6b81a6b6417be4f97ffd9ae0fe0b8",
-          "3a5c9a7dacca9dd8827881f38c36aad7d402a5efc2cab58c7553b903876e1491",
-      },
-      {
-          "864203a09e1c788a482685c739af07355ebb2c840b7de6af87eff5f19ee3b807",
-          "d404a9bbf351e7320ea6d11cdeeccaf505f706731cb5e5d839b950edb7ba6286",
-          "11e09c89e0be7663e0e2d4a01fb05d6a3fd84a78a6fa4fd7daaacf2d19311a38",
-      },
-      {
-          "3e01f05920a238e33766814d10f0c3a3e975072399ad90a823d4808db1d85209",
-          "52a2d35798a0ac209b8fa194fe398b869aba5f20d80ee3d8ca77759a8e0bae0d",
-          "4256addc2f036150f3fdc0a7905f01285239d6dd4eecc4be8e3b134eef4639fe",
-      },
-      {
-          "ad63d591716a9e89a024a074bc6ce661268d1bb3665f91e8b981f189b1a49507",
-          "3928bde7a92e1341c3dfee35a66fa5639204f5b9747963278af430145028648d",
-          "9c959003ba91004956df98800a5024d94031db5ac659675b26350657d93c34f9",
-      },
-  };
-
-  ge25519 pt, pt2, pt3;
-  bignum256modm sc;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(sc, fromhex(tests[i].sc), 32);
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-    ge25519_unpack_vartime(&pt2, fromhex(tests[i].pt2));
-    ge25519_scalarmult(&pt3, &pt, sc);
-    ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_ge25519_ops) {
-  int tests[] = {1, 2, 7, 8, 637, 9912, 12345};
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    struct ge25519_t a, b, c, d;
-    bignum256modm s1 = {0}, s2 = {0}, s3 = {0}, s4 = {0};
-
-    set256_modm(s1, tests[i]);
-    set256_modm(s2, 8 * tests[i]);
-    set256_modm(s3, 8);
-    set256_modm(s4, 2);
-
-    ge25519_scalarmult_base_niels(&a, ge25519_niels_base_multiples, s1);
-    ge25519_scalarmult_base_niels(&b, ge25519_niels_base_multiples, s2);
-    ge25519_scalarmult(&c, &a, s4);
-    ge25519_scalarmult(&c, &c, s4);
-    ge25519_scalarmult(&c, &c, s4);
-    ck_assert_int_eq(ge25519_eq(&c, &b), 1);
-    ck_assert_int_eq(ge25519_eq(&a, &b), 0);
-
-    ge25519_scalarmult_base_wrapper(&a, s1);
-    ge25519_mul8(&b, &a);
-    ge25519_scalarmult_base_wrapper(&c, s2);
-    ck_assert_int_eq(ge25519_eq(&b, &c), 1);
-
-    ge25519_scalarmult(&d, &a, s3);
-    ck_assert_int_eq(ge25519_eq(&d, &c), 1);
-
-    ge25519_copy(&a, &b);
-    ge25519_neg_full(&b);
-    ck_assert_int_eq(ge25519_eq(&b, &c), 0);
-
-    ge25519_add(&c, &a, &b, 0);
-    set256_modm(s2, 0);
-    ge25519_scalarmult_base_wrapper(&a, s2);
-    ck_assert_int_eq(ge25519_eq(&a, &c), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_check_point) {
-  static const struct {
-    char *p;
-    bool on;
-  } tests[] = {
-      {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608",
-       true},
-      {"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5",
-       true},
-      {"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808",
-       true},
-      {"00000000000000c60073ec000000000000ff0000000000000000000000000080",
-       false},
-      {"00000000000000004e0000000000000000000000000000000000000000000000",
-       false},
-      {"0000008b0000000000000000b200000000000000000000000000000000000080",
-       false},
-      {"a0953eebe2f676256c37af4f6f84f32d397aaf3b73606e96c5ddfcecbb1ceec8",
-       false},
-      {"a82cd837efee505ec8425769ea925bee869ec3c78a57708c64c2ef2bd6ad3b88",
-       false},
-      {"031c56cfc99758f6f025630e77c6dea0b853c3ab0bf6cf8c8dab03d1a4618178",
-       false},
-  };
-
-  ge25519 tmp;
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    int res = ge25519_unpack_negative_vartime(&tmp, fromhex(tests[i].p));
-    ck_assert_int_eq(ge25519_check(&tmp), tests[i].on);
-    ck_assert_int_eq(res, tests[i].on);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_h) {
-  char *H = "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94";
-  ge25519 H2, Z;
-  ge25519_p1p1 P_11;
-  ge25519_pniels P_ni;
-  uint8_t buff[32] = {0};
-
-  ge25519_pack(buff, &xmr_h);
-  ck_assert_mem_eq(buff, fromhex(H), 32);
-
-  int res = ge25519_unpack_vartime(&H2, buff);
-  ck_assert_int_eq(res, 1);
-  ck_assert_int_eq(ge25519_eq(&xmr_h, &xmr_h), 1);
-  ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1);
-
-  res = ge25519_unpack_negative_vartime(&H2, buff);
-  ck_assert_int_eq(res, 1);
-  ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 0);
-  ge25519_neg_full(&H2);
-  ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1);
-
-  ge25519_full_to_pniels(&P_ni, &xmr_h);
-  ge25519_pnielsadd_p1p1(&P_11, &H2, &P_ni, 1);
-  ge25519_p1p1_to_full(&H2, &P_11);
-  ge25519_set_neutral(&Z);
-  ck_assert_int_eq(ge25519_eq(&Z, &H2), 1);
-}
-END_TEST
-
-START_TEST(test_xmr_fast_hash) {
-  uint8_t hash[32];
-  char tests[][2][65] = {
-      {"", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"},
-      {"00",
-       "bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"},
-      {"000102",
-       "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"},
-      {"000102030405",
-       "51e8babe8b42352100dffa7f7b3843c95245d3d545c6cbf5052e80258ae80627"},
-      {"000102030406",
-       "74e7a0111ee2390dc68269a549a76dcfb553ca1260035eae982d669ff6494f32"},
-      {"000102030407",
-       "3a81c5d02a87786343f88414aae150a09f6933b1d3bb660d0a9ac54e12e5cd86"},
-      {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64",
-       "7fb4d1c8e32f7414fe8c7b2774ec05bff6845e4278565d17f95559513a244da2"},
-      {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
-       "2998fe52f8b9883149babd9c546912c3edfbd3cd98896a0e57b1b5929fa5ff7b"},
-  };
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    xmr_fast_hash(hash, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
-    ck_assert_mem_eq(hash, fromhex(tests[i][1]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_hasher) {
-  Hasher hasher;
-  uint8_t hash[32];
-
-  static const struct {
-    char *chunk[3];
-    char *hash;
-  } tests[] = {
-      {{"00", "01", "02"},
-       "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"},
-      {{"001122334455667788", "00", ""},
-       "72a228ee8d0d01c815f112ce315cfc215a0594abcec24162304ae0ffda139d9e"},
-      {{"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", "",
-        "00112233445566"},
-       "c3deafd96ff10cc190c6024548c344f6401cfe5151ab2fcd40df7cc501147e01"},
-  };
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    xmr_hasher_init(&hasher);
-    for (int j = 0; j < 3; j++) {
-      xmr_hasher_update(&hasher, fromhex(tests[i].chunk[j]),
-                        strlen(tests[i].chunk[j]) / 2);
-    }
-    xmr_hasher_final(&hasher, hash);
-    ck_assert_mem_eq(hash, fromhex(tests[i].hash), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_hash_to_scalar) {
-  bignum256modm a1;
-  unsigned char out[32];
-  char tests[][2][65] = {
-      {"", "4a078e76cd41a3d3b534b83dc6f2ea2de500b653ca82273b7bfad8045d85a400"},
-      {"00",
-       "5497c9b6a7059553835f85118dc089d66512f7b477d66591ff96a9e064bcc90a"},
-      {"000102",
-       "5727ca206dbafa2e099b022ed528f5bdf7874e3ec09c8f012159dfeeaab2b106"},
-      {"000102030405",
-       "7740cf04577c107153a50b3abe44859f5245d3d545c6cbf5052e80258ae80607"},
-      {"000102030406",
-       "ad6bbffaceb8020543ac82bcadb9d090b553ca1260035eae982d669ff6494f02"},
-      {"000102030407",
-       "d2e116e9576ee5a29011c8fcb41259f99e6933b1d3bb660d0a9ac54e12e5cd06"},
-      {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64",
-       "3d6d3727dc50bca39e6ccfc9c12950eef5845e4278565d17f95559513a244d02"},
-      {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
-       "aecc45c83f0408c96c70f8273e94f930edfbd3cd98896a0e57b1b5929fa5ff0b"},
-  };
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    xmr_hash_to_scalar(a1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
-    contract256_modm(out, a1);
-    ck_assert_mem_eq(out, fromhex(tests[i][1]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_hash_to_ec) {
-  ge25519 p1;
-  unsigned char out[32];
-  char tests[][2][65] = {
-      {"", "d6d7d783ab18e1be65586adb7902a4175b737ef0b902875e1d1d5c5cf0478c0b"},
-      {"00",
-       "8e2fecb36320bc4e192e10ef54afc7c83fbeb0c38b7debd4fea51301f0bd4f3d"},
-      {"000102",
-       "73b233e2e75d81b9657a857e38e7ab2bc3600e5c56622b9fe4b976ff312220fa"},
-      {"000102030405",
-       "bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808"},
-      {"000102030406",
-       "525567a6a40a94f2d916bc1efea234bbd3b9162403ec2faba871a90f8d0d487e"},
-      {"000102030407",
-       "99b1be2a92cbd22b24b48fb7a9daadd4d13a56915c4f6ed696f271ad5bdbc149"},
-      {"42f6835bf83114a1f5f6076fe79bdfa0bd67c74b88f127d54572d3910dd09201",
-       "54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5"},
-      {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
-       "001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608"},
-  };
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    xmr_hash_to_ec(&p1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
-    ge25519_pack(out, &p1);
-    ck_assert_mem_eq(out, fromhex(tests[i][1]), 32);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_derivation_to_scalar) {
-  static const struct {
-    char *pt;
-    uint32_t idx;
-    char *sc;
-  } tests[] = {
-      {
-          "c655b2d9d2670a1c9f26f7586b6d6b1ec5173b8b33bca64c3d305a42d66738b1",
-          0,
-          "ca7ce31b273dd1ac00dc3553e654fb66036804800e27c826bd2b78649243900b",
-      },
-      {
-          "2b1dbd7a007dcc4d729fa8359705595599737fcef60afb36b379fe033095dca7",
-          1,
-          "60afd5a63b14845d3b92d16eac386713e4ff617fdc5c1a07c3212098c1f5610c",
-      },
-      {
-          "a48ed3797225dab4b4316b5e40107b6bd63e5f4dc517ba602774d703576ec771",
-          24,
-          "fe81804091e50a5c2233faa6277360fbe1948ea15dddbae62c1d40bbd1918606",
-      },
-      {
-          "fa27b5b39741f5341b4e89269e3a05ff7e76ec7739843872468fc4bec8475410",
-          65537,
-          "1ba36841f57aa8b799c4dd02b39d53e5fb7780d3f09f91a57a86dcb418d8d506",
-      },
-  };
-
-  ge25519 pt;
-  bignum256modm sc, sc2;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(sc, fromhex(tests[i].sc), 32);
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-
-    xmr_derivation_to_scalar(sc2, &pt, tests[i].idx);
-    ck_assert_int_eq(eq256_modm(sc, sc2), 1);
-
-    xmr_derivation_to_scalar(sc2, &pt, tests[i].idx + 1);
-    ck_assert_int_eq(eq256_modm(sc, sc2), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_generate_key_derivation) {
-  static const struct {
-    char *pt;
-    char *sc;
-    char *r;
-  } tests[] = {
-      {
-          "38f94f27c8037aff025e365275ed1029fd636dda5f69e5f98fdcf92e0a28f31a",
-          "8f1c73ee5327a43264a7b60b9e7882312b582f33e89846a8694dbf094bb3a90a",
-          "1fbfe4dcc8c824c274649545f297fa320cd4c1689b1d0ff4887567c4d4a75649",
-      },
-      {
-          "26785c3941a32f194228eb659c5ee305e63868896defc50ee6c4e0e92d1e246a",
-          "dbbffec4686ba8ab25e2f1b04c0e7ae51c5143c91353bfb5998430ebe365a609",
-          "cca34db8dd682ec164d8973b555253934596b77849ef7709d9321121c25aba02",
-      },
-      {
-          "43505a8ce7248f70d3aae4f57fb59c254ce2b2a0cc2bcf50f2344e51d59b36b3",
-          "19a802e35f6ff94efe96ec016effe04e635bbd9c1ce2612d5ba2ee4659456b06",
-          "fc6c93a93f77ff89c18b9abf95b28ec8591ab97eee8e4afee93aa766a4bd3934",
-      },
-  };
-
-  ge25519 pt, pt2, pt3;
-  bignum256modm sc;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(sc, fromhex(tests[i].sc), 32);
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-    ge25519_unpack_vartime(&pt2, fromhex(tests[i].r));
-    xmr_generate_key_derivation(&pt3, &pt, sc);
-    ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1);
-    ck_assert_int_eq(ge25519_eq(&pt3, &pt), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_derive_private_key) {
-  static const struct {
-    char *pt;
-    uint32_t idx;
-    char *base;
-    char *r;
-  } tests[] = {
-      {
-          "0541d8f069e5e80a892e39bbf1944ef578008cf9ecf1d100760a05858c1b709e",
-          0,
-          "76967eeb0a3d181bb0b384be71c680a4287599f27b2ddbd07f8e06ab6f2c880e",
-          "45728c5cb658e470790f124a01699d2126832b7e5c6b7760b6f11119b96ad603",
-      },
-      {
-          "fc6e0bd785a84e62c9ac8a97e0e604a79494bc2cf7b3b38ef8af7791c87b5bb8",
-          1,
-          "32fbe149562b7ccb34bc4105b87b2a834024799336c8eea5e94df77f1ae9a807",
-          "64508e83bbadf63f8ecfae4d9dcdd39a4ba23508a545e1a37026f0fa2539d601",
-      },
-      {
-          "f6bd7a72dc9444dc7e09a0eb4d312d36fe173693d6405b132a5b090297a04ea9",
-          65537,
-          "333a8fcce6726457e4222a87b9b475c1fcf985f756c2029fcb39184c0a5c4804",
-          "37c16a22da4c0082ebf4bf807403b169f75142a9bd8560ed45f3f9347218260e",
-      },
-  };
-
-  ge25519 pt;
-  bignum256modm base, res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(base, fromhex(tests[i].base), 32);
-    expand256_modm(res_exp, fromhex(tests[i].r), 32);
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-
-    xmr_derive_private_key(res, &pt, tests[i].idx, base);
-    ck_assert_int_eq(eq256_modm(res, res_exp), 1);
-    ck_assert_int_eq(eq256_modm(res, base), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_derive_public_key) {
-  static const struct {
-    char *pt;
-    uint32_t idx;
-    char *base;
-    char *r;
-  } tests[] = {
-      {
-          "653f03e7766d472826aa49793bc0cfde698e6745ae5e4217980ba307739f2ed9",
-          0,
-          "2a393f0858732970ac8dea003b17e1ce9371f0a045bd9b7af0d998262739f4cc",
-          "f7a3db27c45f265f6a68a30137ca44289a6cf1a6db2cf482c59ebfb0142ad419",
-      },
-      {
-          "338e93f61e6470a5cc71c07b8caedd1a9a28da037aab65c1ca5538501b012c81",
-          1,
-          "af3a1d39397d778731c4510110fd117dc02f756e390713d58f94a06203ce39eb",
-          "779e2a043c881f06aba1952741fd753098615c4fafa8f62748467ab9bac43241",
-      },
-      {
-          "7735e9476440927b89b18d7a1e0645b218a1a6d28c642aebb16c1dba0926d5e4",
-          65537,
-          "62c3eed062bd602f7f2164c69ad0b5a8eb3ea560c930f6b41abfc1c4839ea432",
-          "6da4ebd29498d16c4e813abb3e328c83f9b01a7ba1da6e818071f8ec563626c8",
-      },
-  };
-
-  ge25519 pt, base, res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
-    ge25519_unpack_vartime(&base, fromhex(tests[i].base));
-    ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
-
-    xmr_derive_public_key(&res, &pt, tests[i].idx, &base);
-
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-    ck_assert_int_eq(ge25519_eq(&res, &base), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_add_keys2) {
-  static const struct {
-    char *a;
-    char *b;
-    char *B;
-    char *r;
-  } tests[] = {
-      {
-          "631238da9578d7cb8db16fc4322671bfcb251cc5228b060664800ec1895be608",
-          "f9a73fca0be058415a148f9e2871be59e1fc7ae6f6193199125237e0d7c1630f",
-          "ef5ca4fc90f330e825adcdc953da0b3becd853aa819219842790bb39775f2255",
-          "06623fd0e7a3d787a4d224f6ca2fdab2dcd9d1221578515974b9c4dee65fdcf5",
-      },
-      {
-          "dac2e629e5c75c312253b19d1d3a0a423158fdd9cdcf4c7a7bf2717d0b748602",
-          "0483d98d750d4977b499cefd558a0a61580823a37da2b011501e24718e6c7f0a",
-          "51fd3cd2f1a603ec7be3b35da9c105d91c4304e6a63facf48d7730712cedc0ee",
-          "f7a5d645ba01a5b7ccbe9636d14422bb587fc529317b23761f0e39222b783b87",
-      },
-      {
-          "817c4d2fd3e841d860bdab6b7ccf098f3e637eca468d0a3825c50b71f61d0e0c",
-          "1f6c4795d7fb0d53b5775874ac4c0963607d2b7bd11a7c5d10735badc4a27207",
-          "bef0e0ed09d602bbe1dd38358b5f8fca27fcad60a69440f104441c3fc68df9c7",
-          "bc0fc824d74eca0e10eacd0bc2f3322e0bcb02a44ce53f2f5f1fc472f99be8d2",
-      },
-  };
-
-  bignum256modm a, b;
-  ge25519 B, res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i].a), 32);
-    expand256_modm(b, fromhex(tests[i].b), 32);
-    ge25519_unpack_vartime(&B, fromhex(tests[i].B));
-    ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
-
-    xmr_add_keys2(&res, a, b, &B);
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-    ck_assert_int_eq(ge25519_eq(&res, &B), 0);
-
-    xmr_add_keys2_vartime(&res, a, b, &B);
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-    ck_assert_int_eq(ge25519_eq(&res, &B), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_add_keys3) {
-  static const struct {
-    char *a;
-    char *A;
-    char *b;
-    char *B;
-    char *r;
-  } tests[] = {
-      {
-          "7048b8c4603ae194c502fa458b0e11a4c7a330852bbef66b7c1d67e9f919f509",
-          "9167c5b182758699baeb421e7f1200272fc775e4c7c7c183cc47261dccbb569f",
-          "c2cb2bc0249fc7be8eb9b3bed7d37aa6f2c3f433abb3a4a00b13bed64b61f30b",
-          "b3ec53b07a1be70ac8d0fa365b86f0d6d4cbf98641e7704b3d684558e2ea59ef",
-          "4dc016d702d599bde5eaeb2bf0c2d0d3f6b9cede961bc539bcb369c3b3086358",
-      },
-      {
-          "e9794a6652940474958936f07f3904d514228553247633cfb7ae8ffa9fa0f406",
-          "0e51cea6df2f6f56a9935689364f0d295a7c89f51d40efb2518c17d1b9db792b",
-          "c132e7be08afdd93984c52c6e1c596edc6b8fc8f1faed95f55e2f819ee806706",
-          "1a0e03c6858f6cf1b43f4b8456c03144af553bbbd050e152834fd1615b577cb3",
-          "088f19c6727f8704373d391a36c230395d386f69edb4151ecf8afcd27793fff5",
-      },
-      {
-          "88920b0c96b15cc04e879f53a76f85f3c7a2a5f275b2772b5b74ee83372aea00",
-          "e95731ab61a98fedcded475cf21b4ecf2ef9f1adecefba8fdc476a5bb1cf60f9",
-          "c86026b66c1045fb69e4f24ff6c15d4fad4d565e646938a2ffb7db37ccb4100d",
-          "d80cbf2986c12e4c7ebac1e55abbdfc4212c00aec8bc90c965becf863262a074",
-          "047cebaeb3ec2132e7386ba52531b04070206ba1106565c0fbd7d7280694568a",
-      },
-  };
-
-  bignum256modm a, b;
-  ge25519 A, B, res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i].a), 32);
-    expand256_modm(b, fromhex(tests[i].b), 32);
-    ge25519_unpack_vartime(&A, fromhex(tests[i].A));
-    ge25519_unpack_vartime(&B, fromhex(tests[i].B));
-    ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
-
-    xmr_add_keys3(&res, a, &A, b, &B);
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-    ck_assert_int_eq(ge25519_eq(&res, &B), 0);
-
-    xmr_add_keys3_vartime(&res, a, &A, b, &B);
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-    ck_assert_int_eq(ge25519_eq(&res, &B), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_get_subaddress_secret_key) {
-  static const struct {
-    uint32_t major, minor;
-    char *m;
-    char *r;
-  } tests[] = {
-      {
-          0,
-          0,
-          "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
-          "8a510a9fe1824b49abbae05958084f9c9098775f29e15427309177882471cf01",
-      },
-      {
-          0,
-          1,
-          "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
-          "2bbc9366c04abb0523e2b2d6e709670ffe6645bacedfee968d9c6bc8eefe9c0f",
-      },
-      {
-          100,
-          100,
-          "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
-          "c3837d41fedeaed126cf4fc1a5ea47b8b7f38f6a64aa534e3dd45a3c93f37600",
-      },
-  };
-
-  bignum256modm m, res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(m, fromhex(tests[i].m), 32);
-    expand256_modm(res_exp, fromhex(tests[i].r), 32);
-    xmr_get_subaddress_secret_key(res, tests[i].major, tests[i].minor, m);
-
-    ck_assert_int_eq(eq256_modm(res, res_exp), 1);
-    ck_assert_int_eq(eq256_modm(res, m), 0);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_gen_c) {
-  static const struct {
-    char *a;
-    uint64_t amount;
-    char *r;
-  } tests[] = {
-      {
-          "e3e6558c291bbb98aa691d068b67d59dc520afb23fdd51bf65283626fc2ad903",
-          0,
-          "ef19d73bdf3749240b80ee7695f53ad7c2fc2cf868a93209799f41212d099750",
-      },
-      {
-          "6788c9579c377f3228680bd0e6d01b1ee0c763b35ed39d36fa2146cc2ee16e0e",
-          1,
-          "4913b9af4f2725d87a4404c22cf366597d1c1e6a1f510ae14081d8b7c5a9de77",
-      },
-      {
-          "ad9e89d67012935540427c241756d6a9d260c5e134603c41d31e24f8651bef08",
-          65537,
-          "f005721da08f24e68314abed3ddfd94165e4be3813398fb126e3f366820b9c90",
-      },
-      {
-          "fdbb70ff07be24d98de3bffa0a33756646497224318fb7fe136f0e7789d12607",
-          0xffffffffffffffffULL,
-          "a9c38927f299c5f14c98a1a9c9981e59c606ff597274b9b709e1356f12e1498c",
-      },
-  };
-
-  bignum256modm a;
-  ge25519 res, res_exp;
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    expand256_modm(a, fromhex(tests[i].a), 32);
-    ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
-    xmr_gen_c(&res, a, tests[i].amount);
-
-    ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
-  }
-}
-END_TEST
-
-START_TEST(test_xmr_varint) {
-  static const struct {
-    uint64_t x;
-    char *r;
-  } tests[] = {
-      {
-          0,
-          "00",
-      },
-      {
-          24,
-          "18",
-      },
-      {
-          65535,
-          "ffff03",
-      },
-      {
-          65537,
-          "818004",
-      },
-      {
-          0x7fffffffULL,
-          "ffffffff07",
-      },
-      {
-          0xffffffffULL,
-          "ffffffff0f",
-      },
-      {
-          0xffffffffffffffffULL,
-          "ffffffffffffffffff01",
-      },
-      {
-          0xdeadc0deULL,
-          "de81b7f50d",
-      },
-  };
-
-  uint64_t val;
-  unsigned char buff[64];
-
-  for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-    int s1 = xmr_size_varint(tests[i].x);
-    int written = 0;
-    int read = 0;
-
-    ck_assert_uint_eq((size_t)s1, strlen(tests[i].r) / 2);
-    written = xmr_write_varint(buff, sizeof(buff), tests[i].x);
-    ck_assert_int_eq(s1, written);
-    ck_assert_mem_eq(buff, fromhex(tests[i].r), strlen(tests[i].r) / 2);
-
-    read = xmr_read_varint(buff, sizeof(buff), &val);
-    ck_assert_int_eq(read, written);
-    ck_assert(tests[i].x == val);
-  }
-}
-END_TEST
-#endif

+ 0 - 254
crypto/tests/test_check_segwit.h

@@ -1,254 +0,0 @@
-#include "segwit_addr.h"
-
-struct checksum_vectors_data {
-  const char* str;
-  bech32_encoding spec;
-};
-
-static struct checksum_vectors_data checksum_vectors[] = {
-    // BIP-173 valid
-    {"A12UEL5L", BECH32_ENCODING_BECH32},
-    {"a12uel5l", BECH32_ENCODING_BECH32},
-    {"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcha"
-     "ractersbio1tt5tgs",
-     BECH32_ENCODING_BECH32},
-    {"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", BECH32_ENCODING_BECH32},
-    {"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
-     "qqqqqqqqqqqc8247j",
-     BECH32_ENCODING_BECH32},
-    {"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
-     BECH32_ENCODING_BECH32},
-    {"?1ezyfcl", BECH32_ENCODING_BECH32},
-    // BIP-350 valid
-    {"A1LQFN3A", BECH32_ENCODING_BECH32M},
-    {"a1lqfn3a", BECH32_ENCODING_BECH32M},
-    {"an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbio"
-     "andnumber11sg7hg6",
-     BECH32_ENCODING_BECH32M},
-    {"abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", BECH32_ENCODING_BECH32M},
-    {"11lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
-     "lllllllllllludsr8",
-     BECH32_ENCODING_BECH32M},
-    {"split1checkupstagehandshakeupstreamerranterredcaperredlc445v",
-     BECH32_ENCODING_BECH32M},
-    {"?1v759aa", BECH32_ENCODING_BECH32M},
-    // BIP-173 invalid
-    {" 1nwldj5", BECH32_ENCODING_NONE},
-    {"\x7f"
-     "1axkwrx",
-     BECH32_ENCODING_NONE},
-    {"\x80"
-     "1eym55h",
-     BECH32_ENCODING_NONE},
-    {"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedch"
-     "aractersbio1569pvx",
-     BECH32_ENCODING_NONE},
-    {"pzry9x0s0muk", BECH32_ENCODING_NONE},
-    {"1pzry9x0s0muk", BECH32_ENCODING_NONE},
-    {"x1b4n0q5v", BECH32_ENCODING_NONE},
-    {"li1dgmt3", BECH32_ENCODING_NONE},
-    {"de1lg7wt\xff", BECH32_ENCODING_NONE},
-    {"A1G7SGD8", BECH32_ENCODING_NONE},
-    {"10a06t8", BECH32_ENCODING_NONE},
-    {"1qzzfhee", BECH32_ENCODING_NONE},
-    // BIP-350 invalid
-    {" 1xj0phk", BECH32_ENCODING_NONE},
-    {"\x7f"
-     "1g6xzxy",
-     BECH32_ENCODING_NONE},
-    {"\x80"
-     "1vctc34",
-     BECH32_ENCODING_NONE},
-    {"an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbi"
-     "o"
-     "andnumber11d6pts4",
-     BECH32_ENCODING_NONE},
-    {"qyrz8wqd2c9m", BECH32_ENCODING_NONE},
-    {"1qyrz8wqd2c9m", BECH32_ENCODING_NONE},
-    {"y1b0jsk6g", BECH32_ENCODING_NONE},
-    {"lt1igcx5c0", BECH32_ENCODING_NONE},
-    {"in1muywd", BECH32_ENCODING_NONE},
-    {"mm1crxm3i", BECH32_ENCODING_NONE},
-    {"au1s5cgom", BECH32_ENCODING_NONE},
-    {"M1VUXWEZ", BECH32_ENCODING_NONE},
-    {"16plkw9", BECH32_ENCODING_NONE},
-    {"1p2gdwpf", BECH32_ENCODING_NONE},
-};
-
-struct valid_address_data {
-  const char* address;
-  size_t scriptPubKeyLen;
-  const uint8_t scriptPubKey[42];
-};
-
-struct invalid_address_data {
-  const char* hrp;
-  int version;
-  size_t program_length;
-};
-
-static struct valid_address_data valid_address[] = {
-    // BIP-173
-    {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
-     22,
-     {0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
-      0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}},
-    {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
-     34,
-     {0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04, 0xbd,
-      0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d,
-      0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}},
-    {"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
-     34,
-     {0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, 0xb2,
-      0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c,
-      0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}},
-    // BIP-350
-    {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
-     22,
-     {0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
-      0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}},
-    {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
-     34,
-     {0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04, 0xbd,
-      0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d,
-      0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}},
-    {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6"
-     "y",
-     42,
-     {0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
-      0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6,
-      0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c,
-      0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}},
-    {"BC1SW50QGDZ25J", 4, {0x60, 0x02, 0x75, 0x1e}},
-    {"bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs",
-     18,
-     {0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
-      0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23}},
-    {"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
-     34,
-     {0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, 0xb2,
-      0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c,
-      0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}},
-    {"tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c",
-     34,
-     {0x51, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, 0xb2,
-      0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c,
-      0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}},
-    {"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0",
-     34,
-     {0x51, 0x20, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0,
-      0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce,
-      0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98}},
-};
-
-static const char* invalid_address[] = {
-    // BIP-173
-    "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
-    "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5",
-    "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
-    "bc1rw5uspcuh",
-    "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs"
-    "90",
-    "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
-    "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
-    "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du",
-    "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
-    "bc1gmk9yu",
-    // BIP-350
-    "tc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq5zuyut",
-    "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd",
-    "tb1z0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqglt7rf",
-    "BC1S0XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ54WELL",
-    "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kemeawh",
-    "tb1q0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq24jc47",
-    "bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4",
-    "BC130XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ7ZWS8R",
-    "bc1pw5dgrnzv",
-    "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zge"
-    "av",
-    "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
-    "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47Zagq",
-    "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf",
-    "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j",
-    "bc1gmk9yu",
-};
-
-static struct invalid_address_data invalid_address_enc[] = {
-    {"BC", 0, 20}, {"bc", 0, 21}, {"bc", 17, 32}, {"bc", 1, 1}, {"bc", 16, 41},
-};
-
-static void segwit_scriptpubkey(uint8_t* scriptpubkey, size_t* scriptpubkeylen,
-                                int witver, const uint8_t* witprog,
-                                size_t witprog_len) {
-  scriptpubkey[0] = witver ? (0x50 + witver) : 0;
-  scriptpubkey[1] = witprog_len;
-  memcpy(scriptpubkey + 2, witprog, witprog_len);
-  *scriptpubkeylen = witprog_len + 2;
-}
-
-START_TEST(test_segwit) {
-  size_t i;
-  for (i = 0; i < sizeof(checksum_vectors) / sizeof(checksum_vectors[0]); ++i) {
-    uint8_t data[82];
-    char hrp[84];
-    size_t data_len;
-    bech32_encoding res =
-        bech32_decode(hrp, data, &data_len, checksum_vectors[i].str);
-    ck_assert_int_eq(res, checksum_vectors[i].spec);
-    if (checksum_vectors[i].spec == BECH32_ENCODING_NONE) {
-      continue;
-    }
-    // the following check makes only sense for valid addresses
-    char rebuild[92];
-    int resi =
-        bech32_encode(rebuild, hrp, data, data_len, checksum_vectors[i].spec);
-    ck_assert_int_eq(resi, 1);
-    ck_assert_int_eq(my_strncasecmp(rebuild, checksum_vectors[i].str, 92), 0);
-  }
-  for (i = 0; i < sizeof(valid_address) / sizeof(valid_address[0]); ++i) {
-    uint8_t witprog[40];
-    size_t witprog_len;
-    int witver;
-    const char* hrp = "bc";
-    if (memcmp(valid_address[i].address, "tb1", 3) == 0) {
-      hrp = "tb";
-    }
-    uint8_t scriptpubkey[42];
-    size_t scriptpubkey_len;
-    char rebuild[93];
-    int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp,
-                                 valid_address[i].address);
-    ck_assert_int_eq(ret, 1);
-    segwit_scriptpubkey(scriptpubkey, &scriptpubkey_len, witver, witprog,
-                        witprog_len);
-    ck_assert_uint_eq(scriptpubkey_len, valid_address[i].scriptPubKeyLen);
-    ck_assert_int_eq(
-        memcmp(scriptpubkey, valid_address[i].scriptPubKey, scriptpubkey_len),
-        0);
-    ck_assert_int_eq(
-        segwit_addr_encode(rebuild, hrp, witver, witprog, witprog_len), 1);
-    ck_assert_int_eq(my_strncasecmp(valid_address[i].address, rebuild, 93), 0);
-  }
-  for (i = 0; i < sizeof(invalid_address) / sizeof(invalid_address[0]); ++i) {
-    uint8_t witprog[40];
-    size_t witprog_len;
-    int witver;
-    int ret = segwit_addr_decode(&witver, witprog, &witprog_len, "bc",
-                                 invalid_address[i]);
-    ck_assert_int_eq(ret, 0);
-    ret = segwit_addr_decode(&witver, witprog, &witprog_len, "tb",
-                             invalid_address[i]);
-    ck_assert_int_eq(ret, 0);
-  }
-  for (i = 0; i < sizeof(invalid_address_enc) / sizeof(invalid_address_enc[0]);
-       ++i) {
-    char rebuild[93];
-    static const uint8_t program[42] = {0};
-    int ret = segwit_addr_encode(rebuild, invalid_address_enc[i].hrp,
-                                 invalid_address_enc[i].version, program,
-                                 invalid_address_enc[i].program_length);
-    ck_assert_int_eq(ret, 0);
-  }
-}
-END_TEST

+ 0 - 381
crypto/tests/test_curves.py

@@ -1,381 +0,0 @@
-#!/usr/bin/py.test
-import binascii
-import ctypes as c
-import hashlib
-import os
-import random
-
-import curve25519
-import ecdsa
-import pytest
-
-
-def bytes2num(s):
-    res = 0
-    for i, b in enumerate(reversed(bytearray(s))):
-        res += b << (i * 8)
-    return res
-
-
-curves = {"nist256p1": ecdsa.curves.NIST256p, "secp256k1": ecdsa.curves.SECP256k1}
-
-
-class Point:
-    def __init__(self, name, x, y):
-        self.curve = name
-        self.x = x
-        self.y = y
-
-
-points = [
-    Point(
-        "secp256k1",
-        0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
-        0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
-    ),
-    Point(
-        "secp256k1",
-        0x1,
-        0x4218F20AE6C646B363DB68605822FB14264CA8D2587FDD6FBC750D587E76A7EE,
-    ),
-    Point(
-        "secp256k1",
-        0x2,
-        0x66FBE727B2BA09E09F5A98D70A5EFCE8424C5FA425BBDA1C511F860657B8535E,
-    ),
-    Point(
-        "secp256k1",
-        0x1B,
-        0x1ADCEA1CF831B0AD1653E769D1A229091D0CC68D4B0328691B9CAACC76E37C90,
-    ),
-    Point(
-        "nist256p1",
-        0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296,
-        0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5,
-    ),
-    Point(
-        "nist256p1",
-        0x0,
-        0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4,
-    ),
-    Point(
-        "nist256p1",
-        0x0,
-        0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B,
-    ),
-    Point(
-        "nist256p1",
-        0xAF8BBDFE8CDD5577ACBF345B543D28CF402F4E94D3865B97EA0787F2D3AA5D22,
-        0x35802B8B376B995265918B078BC109C21A535176585C40F519ACA52D6AFC147C,
-    ),
-    Point(
-        "nist256p1",
-        0x80000,
-        0x580610071F440F0DCC14A22E2D5D5AFC1224C0CD11A3B4B51B8ECD2224EE1CE2,
-    ),
-]
-
-random_iters = int(os.environ.get("ITERS", 1))
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-lib = c.cdll.LoadLibrary(os.path.join(DIR, "libtrezor-crypto.so"))
-if not lib.zkp_context_is_initialized():
-    assert lib.zkp_context_init() == 0
-
-BIGNUM = c.c_uint32 * 9
-
-
-class curve_info(c.Structure):
-    _fields_ = [("bip32_name", c.c_char_p), ("params", c.c_void_p)]
-
-
-class curve_point(c.Structure):
-    _fields_ = [("x", BIGNUM), ("y", BIGNUM)]
-
-
-class ecdsa_curve(c.Structure):
-    _fields_ = [
-        ("prime", BIGNUM),
-        ("G", curve_point),
-        ("order", BIGNUM),
-        ("order_half", BIGNUM),
-        ("a", c.c_int),
-        ("b", BIGNUM),
-    ]
-
-
-lib.get_curve_by_name.restype = c.POINTER(curve_info)
-
-
-class Random(random.Random):
-    def randbytes(self, n):
-        buf = (c.c_uint8 * n)()
-        for i in range(n):
-            buf[i] = self.randrange(0, 256)
-        return buf
-
-    def randpoint(self, curve):
-        k = self.randrange(0, curve.order)
-        return k * curve.generator
-
-
-def int2bn(x, bn_type=BIGNUM):
-    b = bn_type()
-    b._int = x
-    for i in range(len(b)):
-        b[i] = x % (1 << 29)
-        x = x >> 29
-    return b
-
-
-def bn2int(b):
-    x = 0
-    for i in range(len(b)):
-        x += b[i] << (29 * i)
-    return x
-
-
-@pytest.fixture(params=range(random_iters))
-def r(request):
-    seed = request.param
-    return Random(seed + int(os.environ.get("SEED", 0)))
-
-
-def get_curve_obj(name):
-    curve_ptr = lib.get_curve_by_name(bytes(name, "ascii")).contents.params
-    assert curve_ptr, "curve {} not found".format(name)
-    curve_obj = curves[name]
-    curve_obj.ptr = c.cast(curve_ptr, c.POINTER(ecdsa_curve))
-    curve_obj.p = curve_obj.curve.p()  # shorthand
-    return curve_obj
-
-
-@pytest.fixture(params=list(sorted(curves)))
-def curve(request):
-    return get_curve_obj(request.param)
-
-
-@pytest.fixture(params=points)
-def point(request):
-    name = request.param.curve
-    curve_ptr = lib.get_curve_by_name(bytes(name, "ascii")).contents.params
-    assert curve_ptr, "curve {} not found".format(name)
-    curve_obj = curves[name]
-    curve_obj.ptr = c.c_void_p(curve_ptr)
-    curve_obj.p = ecdsa.ellipticcurve.Point(
-        curve_obj.curve, request.param.x, request.param.y
-    )
-    return curve_obj
-
-
-POINT = BIGNUM * 2
-
-
-def to_POINT(p):
-    return POINT(int2bn(p.x()), int2bn(p.y()))
-
-
-def from_POINT(p):
-    return (bn2int(p[0]), bn2int(p[1]))
-
-
-JACOBIAN = BIGNUM * 3
-
-
-def to_JACOBIAN(jp):
-    return JACOBIAN(int2bn(jp[0]), int2bn(jp[1]), int2bn(jp[2]))
-
-
-def from_JACOBIAN(p):
-    return (bn2int(p[0]), bn2int(p[1]), bn2int(p[2]))
-
-
-def test_curve_parameters(curve):
-    assert curve.curve.p() == bn2int(curve.ptr.contents.prime)
-    assert curve.generator.x() == bn2int(curve.ptr.contents.G.x)
-    assert curve.generator.y() == bn2int(curve.ptr.contents.G.y)
-    assert curve.order == bn2int(curve.ptr.contents.order)
-    assert curve.order // 2 == bn2int(curve.ptr.contents.order_half)
-    assert curve.curve.a() == curve.ptr.contents.a
-    assert curve.curve.b() == bn2int(curve.ptr.contents.b)
-
-
-def test_point_multiply(curve, r):
-    p = r.randpoint(curve)
-    k = r.randrange(0, 2**256)
-    kp = k * p
-    res = POINT(int2bn(0), int2bn(0))
-    lib.point_multiply(curve.ptr, int2bn(k), to_POINT(p), res)
-    res = from_POINT(res)
-    assert res == (kp.x(), kp.y())
-
-
-def test_point_add(curve, r):
-    p1 = r.randpoint(curve)
-    p2 = r.randpoint(curve)
-    # print '-' * 80
-    q = p1 + p2
-    q1 = to_POINT(p1)
-    q2 = to_POINT(p2)
-    lib.point_add(curve.ptr, q1, q2)
-    q_ = from_POINT(q2)
-    assert q_ == (q.x(), q.y())
-
-
-def test_point_double(curve, r):
-    p = r.randpoint(curve)
-    q = p.double()
-    q_ = to_POINT(p)
-    lib.point_double(curve.ptr, q_)
-    q_ = from_POINT(q_)
-    assert q_ == (q.x(), q.y())
-
-
-def test_point_to_jacobian(curve, r):
-    p = r.randpoint(curve)
-    jp = JACOBIAN()
-    lib.curve_to_jacobian(to_POINT(p), jp, int2bn(curve.p))
-    jx, jy, jz = from_JACOBIAN(jp)
-    assert jx % curve.p == (p.x() * jz**2) % curve.p
-    assert jy % curve.p == (p.y() * jz**3) % curve.p
-
-    q = POINT()
-    lib.jacobian_to_curve(jp, q, int2bn(curve.p))
-    q = from_POINT(q)
-    assert q == (p.x(), p.y())
-
-
-def test_jacobian_add(curve, r):
-    p1 = r.randpoint(curve)
-    p2 = r.randpoint(curve)
-    prime = int2bn(curve.p)
-    q = POINT()
-    jp2 = JACOBIAN()
-    lib.curve_to_jacobian(to_POINT(p2), jp2, prime)
-    lib.point_jacobian_add(to_POINT(p1), jp2, curve.ptr)
-    lib.jacobian_to_curve(jp2, q, prime)
-    q = from_POINT(q)
-    p_ = p1 + p2
-    assert (p_.x(), p_.y()) == q
-
-
-def test_jacobian_add_double(curve, r):
-    p1 = r.randpoint(curve)
-    p2 = p1
-    prime = int2bn(curve.p)
-    q = POINT()
-    jp2 = JACOBIAN()
-    lib.curve_to_jacobian(to_POINT(p2), jp2, prime)
-    lib.point_jacobian_add(to_POINT(p1), jp2, curve.ptr)
-    lib.jacobian_to_curve(jp2, q, prime)
-    q = from_POINT(q)
-    p_ = p1 + p2
-    assert (p_.x(), p_.y()) == q
-
-
-def test_jacobian_double(curve, r):
-    p = r.randpoint(curve)
-    p2 = p.double()
-    prime = int2bn(curve.p)
-    q = POINT()
-    jp = JACOBIAN()
-    lib.curve_to_jacobian(to_POINT(p), jp, prime)
-    lib.point_jacobian_double(jp, curve.ptr)
-    lib.jacobian_to_curve(jp, q, prime)
-    q = from_POINT(q)
-    assert (p2.x(), p2.y()) == q
-
-
-def sigdecode(sig, _):
-    return map(bytes2num, [sig[:32], sig[32:]])
-
-
-def test_sign(curve, r):
-    priv = r.randbytes(32)
-    digest = r.randbytes(32)
-    sig = r.randbytes(64)
-
-    lib.ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0))
-
-    exp = bytes2num(priv)
-    sk = ecdsa.SigningKey.from_secret_exponent(exp, curve, hashfunc=hashlib.sha256)
-    vk = sk.get_verifying_key()
-
-    sig_ref = sk.sign_digest_deterministic(
-        digest, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string_canonize
-    )
-    assert binascii.hexlify(sig) == binascii.hexlify(sig_ref)
-
-    assert vk.verify_digest(sig, digest, sigdecode)
-
-
-def test_sign_zkp(r):
-    curve = get_curve_obj("secp256k1")
-
-    priv = r.randbytes(32)
-    digest = r.randbytes(32)
-    sig = r.randbytes(64)
-
-    lib.zkp_ecdsa_sign_digest(
-        curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0)
-    )
-
-    exp = bytes2num(priv)
-    sk = ecdsa.SigningKey.from_secret_exponent(exp, curve, hashfunc=hashlib.sha256)
-    vk = sk.get_verifying_key()
-
-    sig_ref = sk.sign_digest_deterministic(
-        digest, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string_canonize
-    )
-    assert binascii.hexlify(sig) == binascii.hexlify(sig_ref)
-
-    assert vk.verify_digest(sig, digest, sigdecode)
-
-
-def test_validate_pubkey(curve, r):
-    p = r.randpoint(curve)
-    assert lib.ecdsa_validate_pubkey(curve.ptr, to_POINT(p))
-
-
-def test_validate_pubkey_direct(point):
-    assert lib.ecdsa_validate_pubkey(point.ptr, to_POINT(point.p))
-
-
-def test_curve25519(r):
-    sec1 = bytes(bytearray(r.randbytes(32)))
-    sec2 = bytes(bytearray(r.randbytes(32)))
-    pub1 = curve25519.Private(sec1).get_public()
-    pub2 = curve25519.Private(sec2).get_public()
-
-    session1 = r.randbytes(32)
-    lib.curve25519_scalarmult(session1, sec2, pub1.public)
-    session2 = r.randbytes(32)
-    lib.curve25519_scalarmult(session2, sec1, pub2.public)
-    assert bytearray(session1) == bytearray(session2)
-
-    shared1 = curve25519.Private(sec2).get_shared_key(pub1, hashfunc=lambda x: x)
-    shared2 = curve25519.Private(sec1).get_shared_key(pub2, hashfunc=lambda x: x)
-    assert shared1 == shared2
-    assert bytearray(session1) == shared1
-    assert bytearray(session2) == shared2
-
-
-def test_curve25519_pubkey(r):
-    sec = bytes(bytearray(r.randbytes(32)))
-    pub = curve25519.Private(sec).get_public()
-    res = r.randbytes(32)
-    lib.curve25519_scalarmult_basepoint(res, sec)
-    assert bytearray(res) == pub.public
-
-
-def test_curve25519_scalarmult_from_gpg(r):
-    sec = binascii.unhexlify(
-        "4a1e76f133afb29dbc7860bcbc16d0e829009cc15c2f81ed26de1179b1d9c938"
-    )
-    pub = binascii.unhexlify(
-        "5d6fc75c016e85b17f54e0128a216d5f9229f25bac1ec85cecab8daf48621b31"
-    )
-    res = r.randbytes(32)
-    lib.curve25519_scalarmult(res, sec[::-1], pub[::-1])
-    expected = "a93dbdb23e5c99da743e203bd391af79f2b83fb8d0fd6ec813371c71f08f2d4d"
-    assert binascii.hexlify(bytearray(res)) == bytes(expected, "ascii")

+ 0 - 150
crypto/tests/test_openssl.c

@@ -1,150 +0,0 @@
-/**
- * Copyright (c) 2013-2014 Tomas Dzetkulic
- * Copyright (c) 2013-2014 Pavol Rusnak
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* OpenSSL's SHA256_CTX/SHA512_CTX conflicts with our own */
-#define SHA256_CTX _openssl_SHA256_CTX
-#define SHA512_CTX _openssl_SHA512_CTX
-#include <openssl/bn.h>
-#include <openssl/ecdsa.h>
-#include <openssl/obj_mac.h>
-#include <openssl/opensslv.h>
-#include <openssl/sha.h>
-#undef SHA256_CTX
-#undef SHA512_CTX
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "ecdsa.h"
-#include "hasher.h"
-#include "rand.h"
-
-#include "nist256p1.h"
-#include "secp256k1.h"
-
-#include "memzero.h"
-
-void openssl_check(unsigned int iterations, int nid, const ecdsa_curve *curve) {
-  uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256],
-      hash[32];
-  struct SHA256state_st sha256;
-  EC_GROUP *ecgroup;
-
-  ecgroup = EC_GROUP_new_by_curve_name(nid);
-
-  for (unsigned int iter = 0; iter < iterations; iter++) {
-    // random message len between 1 and 256
-    int msg_len = (random32() & 0xFF) + 1;
-    // create random message
-    random_buffer(msg, msg_len);
-
-    // new ECDSA key
-    EC_KEY *eckey = EC_KEY_new();
-    EC_KEY_set_group(eckey, ecgroup);
-
-    // generate the key
-    EC_KEY_generate_key(eckey);
-    // copy key to buffer
-    const BIGNUM *K = EC_KEY_get0_private_key(eckey);
-    int bn_off = sizeof(priv_key) - BN_num_bytes(K);
-    memzero(priv_key, bn_off);
-    BN_bn2bin(K, priv_key + bn_off);
-
-    // use our ECDSA signer to sign the message with the key
-    if (ecdsa_sign(curve, HASHER_SHA2, priv_key, msg, msg_len, sig, NULL,
-                   NULL) != 0) {
-      printf("trezor-crypto signing failed\n");
-      return;
-    }
-
-    // generate public key from private key
-    if (ecdsa_get_public_key33(curve, priv_key, pub_key33) != 0) {
-      printf("ecdsa_get_public_key33 failed\n");
-      return;
-    }
-
-    if (ecdsa_get_public_key65(curve, priv_key, pub_key65) != 0) {
-      printf("ecdsa_get_public_key65 failed\n");
-      return;
-    }
-
-    // use our ECDSA verifier to verify the message signature
-    if (ecdsa_verify(curve, HASHER_SHA2, pub_key65, sig, msg, msg_len) != 0) {
-      printf("trezor-crypto verification failed (pub_key_len = 65)\n");
-      return;
-    }
-    if (ecdsa_verify(curve, HASHER_SHA2, pub_key33, sig, msg, msg_len) != 0) {
-      printf("trezor-crypto verification failed (pub_key_len = 33)\n");
-      return;
-    }
-
-    // copy signature to the OpenSSL struct
-    ECDSA_SIG *signature = ECDSA_SIG_new();
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-    BN_bin2bn(sig, 32, signature->r);
-    BN_bin2bn(sig + 32, 32, signature->s);
-#else
-    BIGNUM *R = BN_bin2bn(sig, 32, NULL);
-    BIGNUM *S = BN_bin2bn(sig + 32, 32, NULL);
-    ECDSA_SIG_set0(signature, R, S);
-#endif
-
-    // compute the digest of the message
-    // note: these are OpenSSL functions, not our own
-    SHA256_Init(&sha256);
-    SHA256_Update(&sha256, msg, msg_len);
-    SHA256_Final(hash, &sha256);
-
-    // verify all went well, i.e. we can decrypt our signature with OpenSSL
-    int v = ECDSA_do_verify(hash, 32, signature, eckey);
-    if (v != 1) {
-      printf("OpenSSL verification failed (%d)\n", v);
-      return;
-    }
-
-    ECDSA_SIG_free(signature);
-    EC_KEY_free(eckey);
-    if (((iter + 1) % 100) == 0) printf("Passed ... %d\n", iter + 1);
-  }
-  EC_GROUP_free(ecgroup);
-  printf("All OK\n");
-}
-
-int main(int argc, char *argv[]) {
-  if (argc != 2) {
-    printf("Usage: test_openssl iterations\n");
-    return 1;
-  }
-
-  unsigned int iterations;
-  sscanf(argv[1], "%u", &iterations);
-
-  printf("Testing secp256k1:\n");
-  openssl_check(iterations, NID_secp256k1, &secp256k1);
-
-  printf("Testing nist256p1:\n");
-  openssl_check(iterations, NID_X9_62_prime256v1, &nist256p1);
-
-  return 0;
-}

+ 0 - 231
crypto/tests/test_speed.c

@@ -1,231 +0,0 @@
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include "bip32.h"
-#include "curves.h"
-#include "ecdsa.h"
-#include "ed25519-donna/ed25519.h"
-#include "hasher.h"
-#include "nist256p1.h"
-#include "secp256k1.h"
-
-static uint8_t msg[256];
-
-void prepare_msg(void) {
-  for (size_t i = 0; i < sizeof(msg); i++) {
-    msg[i] = i * 1103515245;
-  }
-}
-
-void bench_sign_secp256k1(int iterations) {
-  uint8_t sig[64], priv[32], pby;
-
-  const ecdsa_curve *curve = &secp256k1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-  }
-}
-
-void bench_sign_nist256p1(int iterations) {
-  uint8_t sig[64], priv[32], pby;
-
-  const ecdsa_curve *curve = &nist256p1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-  }
-}
-
-void bench_sign_ed25519(int iterations) {
-  ed25519_secret_key sk;
-  ed25519_signature sig;
-
-  memcpy(sk,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-
-  for (int i = 0; i < iterations; i++) {
-    ed25519_sign(msg, sizeof(msg), sk, sig);
-  }
-}
-
-void bench_verify_secp256k1_33(int iterations) {
-  uint8_t sig[64], pub[33], priv[32], pby;
-
-  const ecdsa_curve *curve = &secp256k1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  ecdsa_get_public_key33(curve, priv, pub);
-  ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
-  }
-}
-
-void bench_verify_secp256k1_65(int iterations) {
-  uint8_t sig[64], pub[65], priv[32], pby;
-
-  const ecdsa_curve *curve = &secp256k1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  ecdsa_get_public_key65(curve, priv, pub);
-  ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
-  }
-}
-
-void bench_verify_nist256p1_33(int iterations) {
-  uint8_t sig[64], pub[33], priv[32], pby;
-
-  const ecdsa_curve *curve = &nist256p1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  ecdsa_get_public_key33(curve, priv, pub);
-  ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
-  }
-}
-
-void bench_verify_nist256p1_65(int iterations) {
-  uint8_t sig[64], pub[65], priv[32], pby;
-
-  const ecdsa_curve *curve = &nist256p1;
-
-  memcpy(priv,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  ecdsa_get_public_key65(curve, priv, pub);
-  ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
-
-  for (int i = 0; i < iterations; i++) {
-    ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
-  }
-}
-
-void bench_verify_ed25519(int iterations) {
-  ed25519_public_key pk;
-  ed25519_secret_key sk;
-  ed25519_signature sig;
-
-  memcpy(sk,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  ed25519_publickey(sk, pk);
-  ed25519_sign(msg, sizeof(msg), sk, sig);
-
-  for (int i = 0; i < iterations; i++) {
-    ed25519_sign_open(msg, sizeof(msg), pk, sig);
-  }
-}
-
-void bench_multiply_curve25519(int iterations) {
-  uint8_t result[32];
-  uint8_t secret[32];
-  uint8_t basepoint[32];
-
-  memcpy(secret,
-         "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
-         "\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
-         32);
-  memcpy(basepoint,
-         "\x96\x47\xda\xbe\x1e\xea\xaf\x25\x47\x1e\x68\x0b\x4d\x7c\x6f\xd1\x14"
-         "\x38\x76\xbb\x77\x59\xd8\x3d\x0f\xf7\xa2\x49\x08\xfd\xda\xbc",
-         32);
-
-  for (int i = 0; i < iterations; i++) {
-    curve25519_scalarmult(result, secret, basepoint);
-  }
-}
-
-static HDNode root;
-
-void prepare_node(void) {
-  hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root);
-  hdnode_fill_public_key(&root);
-}
-
-void bench_ckd_normal(int iterations) {
-  char addr[MAX_ADDR_SIZE];
-  HDNode node;
-  for (int i = 0; i < iterations; i++) {
-    memcpy(&node, &root, sizeof(HDNode));
-    hdnode_public_ckd(&node, i);
-    hdnode_fill_public_key(&node);
-    ecdsa_get_address(node.public_key, HASHER_SHA2, HASHER_SHA2D, 0, addr,
-                      sizeof(addr));
-  }
-}
-
-void bench_ckd_optimized(int iterations) {
-  char addr[MAX_ADDR_SIZE];
-  curve_point pub;
-  ecdsa_read_pubkey(&secp256k1, root.public_key, &pub);
-  for (int i = 0; i < iterations; i++) {
-    hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0,
-                                        HASHER_SHA2, HASHER_SHA2D, addr,
-                                        sizeof(addr), false);
-  }
-}
-
-void bench(void (*func)(int), const char *name, int iterations) {
-  clock_t t = clock();
-  func(iterations);
-  float speed = iterations / ((float)(clock() - t) / CLOCKS_PER_SEC);
-  printf("%25s: %8.2f ops/s\n", name, speed);
-}
-
-#define BENCH(FUNC, ITER) bench(FUNC, #FUNC, ITER)
-
-int main(void) {
-  prepare_msg();
-
-  BENCH(bench_sign_secp256k1, 500);
-  BENCH(bench_verify_secp256k1_33, 500);
-  BENCH(bench_verify_secp256k1_65, 500);
-
-  BENCH(bench_sign_nist256p1, 500);
-  BENCH(bench_verify_nist256p1_33, 500);
-  BENCH(bench_verify_nist256p1_65, 500);
-
-  BENCH(bench_sign_ed25519, 4000);
-  BENCH(bench_verify_ed25519, 4000);
-
-  BENCH(bench_multiply_curve25519, 4000);
-
-  prepare_node();
-
-  BENCH(bench_ckd_normal, 1000);
-  BENCH(bench_ckd_optimized, 1000);
-
-  return 0;
-}

+ 0 - 748
crypto/tests/test_wycheproof.py

@@ -1,748 +0,0 @@
-#!/usr/bin/env python
-import ctypes
-import json
-import os
-from binascii import hexlify, unhexlify
-
-import pytest
-from pyasn1.codec.ber.decoder import decode as ber_decode
-from pyasn1.codec.der.decoder import decode as der_decode
-from pyasn1.codec.der.encoder import encode as der_encode
-from pyasn1.type import namedtype, univ
-
-
-class EcSignature(univ.Sequence):
-    componentType = namedtype.NamedTypes(
-        namedtype.NamedType("r", univ.Integer()),
-        namedtype.NamedType("s", univ.Integer()),
-    )
-
-
-class EcKeyInfo(univ.Sequence):
-    componentType = namedtype.NamedTypes(
-        namedtype.NamedType("key_type", univ.ObjectIdentifier()),
-        namedtype.NamedType("curve_name", univ.ObjectIdentifier()),
-    )
-
-
-class EcPublicKey(univ.Sequence):
-    componentType = namedtype.NamedTypes(
-        namedtype.NamedType("key_info", EcKeyInfo()),
-        namedtype.NamedType("public_key", univ.BitString()),
-    )
-
-
-class EdKeyInfo(univ.Sequence):
-    componentType = namedtype.NamedTypes(
-        namedtype.NamedType("key_type", univ.ObjectIdentifier())
-    )
-
-
-class EdPublicKey(univ.Sequence):
-    componentType = namedtype.NamedTypes(
-        namedtype.NamedType("key_info", EdKeyInfo()),
-        namedtype.NamedType("public_key", univ.BitString()),
-    )
-
-
-class ParseError(Exception):
-    pass
-
-
-class NotSupported(Exception):
-    pass
-
-
-class DataError(Exception):
-    pass
-
-
-class curve_info(ctypes.Structure):
-    _fields_ = [("bip32_name", ctypes.c_char_p), ("params", ctypes.c_void_p)]
-
-
-def keys_in_dict(dictionary, keys):
-    return keys <= set(dictionary.keys())
-
-
-def parse_eddsa_signature(signature):
-    if len(signature) != 64:
-        raise ParseError("Not a valid EdDSA signature")
-    return signature
-
-
-def parse_ecdh256_privkey(private_key):
-    if private_key < 0 or private_key.bit_length() > 256:
-        raise ParseError("Not a valid 256 bit ECDH private key")
-    return private_key.to_bytes(32, byteorder="big")
-
-
-def parse_signed_hex(string):
-    if len(string) % 2 == 1:
-        string = "0" + string
-    number = int(string, 16)
-    if int(string[0], 16) & 8:
-        return -number
-    else:
-        return number
-
-
-def parse_result(result):
-    if result == "valid":
-        return True
-    elif result == "invalid":
-        return False
-    elif result == "acceptable":
-        return None
-    else:
-        raise DataError()
-
-
-def is_valid_der(data):
-    try:
-        structure, _ = der_decode(data)
-        return data == der_encode(structure)
-    except Exception:
-        return False
-
-
-def parse_ed_pubkey(public_key):
-    try:
-        public_key, _ = ber_decode(public_key, asn1Spec=EdPublicKey())
-    except Exception:
-        raise ParseError("Not a BER encoded Edwards curve public key")
-
-    if not public_key["key_info"]["key_type"] == univ.ObjectIdentifier("1.3.101.112"):
-        raise ParseError("Not a BER encoded Edwards curve public key")
-
-    public_key = bytes(public_key["public_key"].asOctets())
-
-    return public_key
-
-
-def parse_ec_pubkey(public_key):
-    try:
-        public_key, _ = ber_decode(public_key, asn1Spec=EcPublicKey())
-    except Exception:
-        raise ParseError("Not a BER encoded named elliptic curve public key")
-
-    if not public_key["key_info"]["key_type"] == univ.ObjectIdentifier(
-        "1.2.840.10045.2.1"
-    ):
-        raise ParseError("Not a BER encoded named elliptic curve public key")
-    curve_identifier = public_key["key_info"]["curve_name"]
-    curve_name = get_curve_name_by_identifier(curve_identifier)
-
-    if curve_name is None:
-        raise NotSupported(
-            "Unsupported named elliptic curve: {}".format(curve_identifier)
-        )
-
-    try:
-        public_key = bytes(public_key["public_key"].asOctets())
-    except Exception:
-        raise ParseError("Not a BER encoded named elliptic curve public key")
-
-    return curve_name, public_key
-
-
-def parse_ecdsa256_signature(signature):
-    s = signature
-    if not is_valid_der(signature):
-        raise ParseError("Not a valid DER")
-    try:
-        signature, _ = der_decode(signature, asn1Spec=EcSignature())
-    except Exception:
-        raise ParseError("Not a valid DER encoded ECDSA signature")
-    try:
-        r = int(signature["r"]).to_bytes(32, byteorder="big")
-        s = int(signature["s"]).to_bytes(32, byteorder="big")
-        signature = r + s
-    except Exception:
-        raise ParseError("Not a valid DER encoded 256 bit ECDSA signature")
-    return signature
-
-
-def parse_digest(name):
-    if name == "SHA-256":
-        return 0
-    else:
-        raise NotSupported("Unsupported hash function: {}".format(name))
-
-
-def get_curve_by_name(name):
-    lib.get_curve_by_name.restype = ctypes.c_void_p
-    curve = lib.get_curve_by_name(bytes(name, "ascii"))
-    if curve is None:
-        return None
-    curve = ctypes.cast(curve, ctypes.POINTER(curve_info))
-    return ctypes.c_void_p(curve.contents.params)
-
-
-def parse_curve_name(name):
-    if name == "secp256r1":
-        return "nist256p1"
-    elif name == "secp256k1":
-        return "secp256k1"
-    elif name == "curve25519":
-        return "curve25519"
-    else:
-        return None
-
-
-def get_curve_name_by_identifier(identifier):
-    if identifier == univ.ObjectIdentifier("1.3.132.0.10"):
-        return "secp256k1"
-    elif identifier == univ.ObjectIdentifier("1.2.840.10045.3.1.7"):
-        return "nist256p1"
-    else:
-        return None
-
-
-def chacha_poly_encrypt(key, iv, associated_data, plaintext):
-    context = bytes(context_structure_length)
-    tag = bytes(16)
-    ciphertext = bytes(len(plaintext))
-    lib.rfc7539_init(context, key, iv)
-    lib.rfc7539_auth(context, associated_data, len(associated_data))
-    lib.chacha20poly1305_encrypt(context, plaintext, ciphertext, len(plaintext))
-    lib.rfc7539_finish(context, len(associated_data), len(plaintext), tag)
-    return ciphertext, tag
-
-
-def chacha_poly_decrypt(key, iv, associated_data, ciphertext, tag):
-    context = bytes(context_structure_length)
-    computed_tag = bytes(16)
-    plaintext = bytes(len(ciphertext))
-    lib.rfc7539_init(context, key, iv)
-    lib.rfc7539_auth(context, associated_data, len(associated_data))
-    lib.chacha20poly1305_decrypt(context, ciphertext, plaintext, len(ciphertext))
-    lib.rfc7539_finish(context, len(associated_data), len(ciphertext), computed_tag)
-    return plaintext if tag == computed_tag else False
-
-
-def add_pkcs_padding(data):
-    padding_length = 16 - len(data) % 16
-    return data + bytes([padding_length] * padding_length)
-
-
-def remove_pkcs_padding(data):
-    padding_length = data[-1]
-    if not (
-        0 < padding_length <= 16
-        and data[-padding_length:] == bytes([padding_length] * padding_length)
-    ):
-        return False
-    else:
-        return data[:-padding_length]
-
-
-def aes_encrypt_initialise(key, context):
-    if len(key) == (128 / 8):
-        lib.aes_encrypt_key128(key, context)
-    elif len(key) == (192 / 8):
-        lib.aes_encrypt_key192(key, context)
-    elif len(key) == (256 / 8):
-        lib.aes_encrypt_key256(key, context)
-    else:
-        raise NotSupported("Unsupported key length: {}".format(len(key) * 8))
-
-
-def aes_cbc_encrypt(key, iv, plaintext):
-    plaintext = add_pkcs_padding(plaintext)
-    context = bytes(context_structure_length)
-    ciphertext = bytes(len(plaintext))
-    aes_encrypt_initialise(key, context)
-    lib.aes_cbc_encrypt(
-        plaintext, ciphertext, len(plaintext), bytes(bytearray(iv)), context
-    )
-    return ciphertext
-
-
-def aes_decrypt_initialise(key, context):
-    if len(key) == (128 / 8):
-        lib.aes_decrypt_key128(key, context)
-    elif len(key) == (192 / 8):
-        lib.aes_decrypt_key192(key, context)
-    elif len(key) == (256 / 8):
-        lib.aes_decrypt_key256(key, context)
-    else:
-        raise NotSupported("Unsupported AES key length: {}".format(len(key) * 8))
-
-
-def aes_cbc_decrypt(key, iv, ciphertext):
-    context = bytes(context_structure_length)
-    plaintext = bytes(len(ciphertext))
-    aes_decrypt_initialise(key, context)
-    lib.aes_cbc_decrypt(ciphertext, plaintext, len(ciphertext), iv, context)
-    return remove_pkcs_padding(plaintext)
-
-
-def load_json_testvectors(filename):
-    try:
-        result = json.loads(open(os.path.join(testvectors_directory, filename)).read())
-    except Exception:
-        raise DataError()
-    return result
-
-
-def generate_aes(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "AES-CBC-PKCS5":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests"}):
-            raise DataError()
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(test, {"key", "iv", "msg", "ct", "result"}):
-                raise DataError()
-            try:
-                key = unhexlify(test["key"])
-                iv = unhexlify(test["iv"])
-                plaintext = unhexlify(test["msg"])
-                ciphertext = unhexlify(test["ct"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            if len(key) not in [128 / 8, 192 / 8, 256 / 8]:
-                continue
-
-            if result is None:
-                continue
-
-            vectors.append(
-                (
-                    hexlify(key),
-                    hexlify(iv),
-                    hexlify(plaintext),
-                    hexlify(ciphertext),
-                    result,
-                )
-            )
-    return vectors
-
-
-def generate_chacha_poly(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "CHACHA20-POLY1305":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests"}):
-            raise DataError()
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(
-                test, {"key", "iv", "aad", "msg", "ct", "tag", "result"}
-            ):
-                raise DataError()
-            try:
-                key = unhexlify(test["key"])
-                iv = unhexlify(test["iv"])
-                associated_data = unhexlify(test["aad"])
-                plaintext = unhexlify(test["msg"])
-                ciphertext = unhexlify(test["ct"])
-                tag = unhexlify(test["tag"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            if result is None:
-                continue
-
-            vectors.append(
-                (
-                    hexlify(key),
-                    hexlify(iv),
-                    hexlify(associated_data),
-                    hexlify(plaintext),
-                    hexlify(ciphertext),
-                    hexlify(tag),
-                    result,
-                )
-            )
-    return vectors
-
-
-def generate_curve25519_dh(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "XDH":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests", "curve"}):
-            raise DataError()
-
-        try:
-            curve_name = parse_curve_name(test_group["curve"])
-        except Exception:
-            raise DataError()
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(test, {"public", "private", "shared", "result"}):
-                raise DataError()
-
-            try:
-                public_key = unhexlify(test["public"])
-                private_key = unhexlify(test["private"])
-                shared = unhexlify(test["shared"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            if curve_name != "curve25519":
-                continue
-            if result is None:
-                continue
-
-            vectors.append(
-                (hexlify(public_key), hexlify(private_key), hexlify(shared), result)
-            )
-
-    return vectors
-
-
-def generate_ecdh(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "ECDH":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests", "curve"}):
-            raise DataError()
-
-        try:
-            curve_name = parse_curve_name(test_group["curve"])
-        except Exception:
-            raise DataError()
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(test, {"public", "private", "shared", "result"}):
-                raise DataError()
-
-            try:
-                public_key = unhexlify(test["public"])
-                private_key = parse_signed_hex(test["private"])
-                shared = unhexlify(test["shared"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            try:
-                private_key = parse_ecdh256_privkey(private_key)
-            except ParseError:
-                continue
-
-            try:
-                key_curve_name, public_key = parse_ec_pubkey(public_key)
-            except NotSupported:
-                continue
-            except ParseError:
-                continue
-
-            if key_curve_name != curve_name:
-                continue
-            if result is None:
-                continue
-
-            vectors.append(
-                (
-                    curve_name,
-                    hexlify(public_key),
-                    hexlify(private_key),
-                    hexlify(shared),
-                    result,
-                )
-            )
-
-    return vectors
-
-
-def generate_ecdsa(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "ECDSA":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests", "keyDer", "sha"}):
-            raise DataError()
-
-        try:
-            public_key = unhexlify(test_group["keyDer"])
-        except Exception:
-            raise DataError()
-
-        try:
-            curve_name, public_key = parse_ec_pubkey(public_key)
-        except NotSupported:
-            continue
-        except ParseError:
-            continue
-
-        try:
-            hasher = parse_digest(test_group["sha"])
-        except NotSupported:
-            continue
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(test, {"sig", "msg", "result"}):
-                raise DataError()
-
-            try:
-                signature = unhexlify(test["sig"])
-                message = unhexlify(test["msg"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            if result is None:
-                continue
-
-            try:
-                signature = parse_ecdsa256_signature(signature)
-            except ParseError:
-                continue
-
-            vectors.append(
-                (
-                    curve_name,
-                    hexlify(public_key),
-                    hasher,
-                    hexlify(message),
-                    hexlify(signature),
-                    result,
-                )
-            )
-
-    return vectors
-
-
-def generate_eddsa(filename):
-    vectors = []
-
-    data = load_json_testvectors(filename)
-
-    if not keys_in_dict(data, {"algorithm", "testGroups"}):
-        raise DataError()
-
-    if data["algorithm"] != "EDDSA":
-        raise DataError()
-
-    for test_group in data["testGroups"]:
-        if not keys_in_dict(test_group, {"tests", "keyDer"}):
-            raise DataError()
-
-        try:
-            public_key = unhexlify(test_group["keyDer"])
-        except Exception:
-            raise DataError()
-
-        try:
-            public_key = parse_ed_pubkey(public_key)
-        except ParseError:
-            continue
-
-        for test in test_group["tests"]:
-            if not keys_in_dict(test, {"sig", "msg", "result"}):
-                raise DataError()
-
-            try:
-                signature = unhexlify(test["sig"])
-                message = unhexlify(test["msg"])
-                result = parse_result(test["result"])
-            except Exception:
-                raise DataError()
-
-            if result is None:
-                continue
-
-            try:
-                signature = parse_eddsa_signature(signature)
-            except ParseError:
-                continue
-
-            vectors.append(
-                (hexlify(public_key), hexlify(message), hexlify(signature), result)
-            )
-
-    return vectors
-
-
-dir = os.path.abspath(os.path.dirname(__file__))
-lib = ctypes.cdll.LoadLibrary(os.path.join(dir, "libtrezor-crypto.so"))
-if not lib.zkp_context_is_initialized():
-    assert lib.zkp_context_init() == 0
-testvectors_directory = os.path.join(dir, "wycheproof/testvectors")
-context_structure_length = 1024
-
-curve25519_dh_vectors = generate_curve25519_dh("x25519_test.json")
-eddsa_vectors = generate_eddsa("eddsa_test.json")
-ecdsa_vectors = (
-    generate_ecdsa("ecdsa_test.json")
-    + generate_ecdsa("ecdsa_secp256k1_sha256_test.json")
-    + generate_ecdsa("ecdsa_secp256r1_sha256_test.json")
-)
-ecdh_vectors = (
-    generate_ecdh("ecdh_test.json")
-    + generate_ecdh("ecdh_secp256k1_test.json")
-    + generate_ecdh("ecdh_secp256r1_test.json")
-)
-chacha_poly_vectors = generate_chacha_poly("chacha20_poly1305_test.json")
-aes_vectors = generate_aes("aes_cbc_pkcs5_test.json")
-
-
-@pytest.mark.parametrize("public_key, message, signature, result", eddsa_vectors)
-def test_eddsa(public_key, message, signature, result):
-    public_key = unhexlify(public_key)
-    signature = unhexlify(signature)
-    message = unhexlify(message)
-
-    computed_result = (
-        lib.ed25519_sign_open(message, len(message), public_key, signature) == 0
-    )
-    assert result == computed_result
-
-
-@pytest.mark.parametrize(
-    "curve_name, public_key, hasher, message, signature, result", ecdsa_vectors
-)
-def test_ecdsa(curve_name, public_key, hasher, message, signature, result):
-    curve = get_curve_by_name(curve_name)
-    if curve is None:
-        raise NotSupported("Curve not supported: {}".format(curve_name))
-
-    public_key = unhexlify(public_key)
-    signature = unhexlify(signature)
-    message = unhexlify(message)
-
-    computed_result = (
-        lib.ecdsa_verify(curve, hasher, public_key, signature, message, len(message))
-        == 0
-    )
-    assert result == computed_result
-
-
-@pytest.mark.parametrize(
-    "curve_name, public_key, hasher, message, signature, result",
-    filter(lambda v: v[0] == "secp256k1", ecdsa_vectors),
-)
-def test_ecdsa_zkp(curve_name, public_key, hasher, message, signature, result):
-    curve = get_curve_by_name(curve_name)
-    if curve is None:
-        raise NotSupported("Curve not supported: {}".format(curve_name))
-
-    public_key = unhexlify(public_key)
-    signature = unhexlify(signature)
-    message = unhexlify(message)
-
-    computed_result = (
-        lib.zkp_ecdsa_verify(
-            curve, hasher, public_key, signature, message, len(message)
-        )
-        == 0
-    )
-    assert result == computed_result
-
-
-@pytest.mark.parametrize(
-    "public_key, private_key, shared, result", curve25519_dh_vectors
-)
-def test_curve25519_dh(public_key, private_key, shared, result):
-    public_key = unhexlify(public_key)
-    private_key = unhexlify(private_key)
-    shared = unhexlify(shared)
-
-    computed_shared = bytes([0] * 32)
-    lib.curve25519_scalarmult(computed_shared, private_key, public_key)
-    computed_result = shared == computed_shared
-    assert result == computed_result
-
-
-@pytest.mark.parametrize(
-    "curve_name, public_key, private_key, shared, result", ecdh_vectors
-)
-def test_ecdh(curve_name, public_key, private_key, shared, result):
-    curve = get_curve_by_name(curve_name)
-    if curve is None:
-        raise NotSupported("Curve not supported: {}".format(curve_name))
-
-    public_key = unhexlify(public_key)
-    private_key = unhexlify(private_key)
-    shared = unhexlify(shared)
-
-    computed_shared = bytes([0] * 2 * 32)
-    lib.ecdh_multiply(curve, private_key, public_key, computed_shared)
-    computed_shared = computed_shared[1:33]
-    computed_result = shared == computed_shared
-    assert result == computed_result
-
-
-@pytest.mark.parametrize(
-    "key, iv, associated_data, plaintext, ciphertext, tag, result", chacha_poly_vectors
-)
-def test_chacha_poly(key, iv, associated_data, plaintext, ciphertext, tag, result):
-    key = unhexlify(key)
-    iv = unhexlify(iv)
-    associated_data = unhexlify(associated_data)
-    plaintext = unhexlify(plaintext)
-    ciphertext = unhexlify(ciphertext)
-    tag = unhexlify(tag)
-
-    computed_ciphertext, computed_tag = chacha_poly_encrypt(
-        key, iv, associated_data, plaintext
-    )
-    computed_result = ciphertext == computed_ciphertext and tag == computed_tag
-    assert result == computed_result
-
-    computed_plaintext = chacha_poly_decrypt(key, iv, associated_data, ciphertext, tag)
-    computed_result = plaintext == computed_plaintext
-    assert result == computed_result
-
-
-@pytest.mark.parametrize("key, iv, plaintext, ciphertext, result", aes_vectors)
-def test_aes(key, iv, plaintext, ciphertext, result):
-    key = unhexlify(key)
-    iv = unhexlify(iv)
-    plaintext = unhexlify(plaintext)
-    ciphertext = unhexlify(ciphertext)
-
-    computed_ciphertext = aes_cbc_encrypt(key, iv, plaintext)
-    computed_result = ciphertext == computed_ciphertext
-    assert result == computed_result
-
-    computed_plaintext = aes_cbc_decrypt(key, bytes(iv), ciphertext)
-    computed_result = plaintext == computed_plaintext
-    assert result == computed_result

+ 0 - 3
crypto/tools/.gitignore

@@ -1,3 +0,0 @@
-xpubaddrgen
-mktable
-bip39bruteforce

+ 0 - 54
crypto/tools/README.md

@@ -1,54 +0,0 @@
-trezor-crypto tools
-===================
-
-Set of small utilities using the trezor-crypto library.
-
-xpubaddrgen
------------
-
-xpubaddrgen reads job specification from stdin in format:
-
-```
-<jobid> <xpub> <change> <from> <to>
-```
-
-and prints the results to stdout in format:
-
-```
-<jobid> <index> <address>
-```
-
-Example input:
-
-```
-23 xpub6BcjTvRCYD4VvFQ8whztSXhbNyhS56eTd5P3g9Zvd3zPEeUeL5CUqBYX8NSd1b6Thitr8bZcSnesmXZH7KerMcc4tUkenBShYCtQ1L8ebVe 0 0 5
-42 xpub6AT2YrLinU4Be5UWUxMaUz3zTA99CSGvXt1jt2Lgym8PqXbTzmpQ8MHjoLnx8YJiMMUP5iEfR97YQVmgF6B2tAhbCZrXqn65ur526NkZ6ey 1 1000 1005
-```
-
-Example output:
-
-```
-23 0 14vb5Cws75p2i5rmSiF5CKMyezUX4hxSb9
-23 1 1Lf4ciA36dsi1niF6smVcpCiHcpj2skaPq
-23 2 1LraByp7gQAipvHnFS1gTSzixBtYaVyQGp
-23 3 1Hy6n56qZj1EefLVfDAeEpmveNteY9jpiG
-23 4 183Nn4mrUjPizM3xu8C6SrmViaWrk8YyRS
-42 1000 12eAFGAqGUtszc9R7euRqk7DUcQNXvQZSg
-42 1001 1BrLbFCD3MNYedJaz92U9iqy9ukHrtQ1A6
-42 1002 1Jhv33bJy229ThM7HKxUa92cMK5gi7DyPC
-42 1003 13LxbTjQPByisj4F4sZEivUBdnJwigzg6R
-42 1004 1BWBpSWkPwcKxVr2WDyUqQbmvk5SGihcx9
-```
-
-It will print ```<jobid> error``` when there was an error processing job jobid.
-
-It will print ```error``` when it encountered a malformed line.
-
-
-mktable
------------
-
-mktable computes the points of the form `(2*j+1)*16^i*G` and prints them in the format to be included in `secp256k1.c` and `nist256p1.c`.
-These points are used by the fast ECC multiplication.
-
-It is only meant to be run if the `scalar_mult` algorithm changes.

+ 0 - 100
crypto/tools/bip39bruteforce.c

@@ -1,100 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include "bip32.h"
-#include "bip39.h"
-#include "curves.h"
-#include "ecdsa.h"
-#include "secp256k1.h"
-
-char iter[256];
-uint8_t seed[512 / 8];
-char addr[MAX_ADDR_SIZE];
-int count = 0, found = 0;
-HDNode node;
-clock_t start;
-
-#define ACCOUNT_LEGACY 0
-
-// around 280 tries per second
-
-// testing data:
-//
-// mnemonic:   "all all all all all all all all all all all all"
-// address:    legacy: "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL"
-//             segwit: "3L6TyTisPBmrDAj6RoKmDzNnj4eQi54gD2"
-// passphrase: ""
-//
-// mnemonic:   "all all all all all all all all all all all all"
-// address:    legacy: "1N3uJ5AU3FTYQ1ZQgTMtYmgSvMBmQiGVBS"
-//             segwit: "3NcXPfbDP4UHSbuHASALJEBtDeAcWYMMcS"
-// passphrase: "testing"
-
-int main(int argc, char **argv) {
-  if (argc != 2 && argc != 3) {
-    fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n");
-    return 1;
-  }
-  const char *address = argv[1];
-  const char *mnemonic, *item;
-  if (argc == 3) {
-    mnemonic = argv[2];
-    item = "passphrase";
-  } else {
-    mnemonic = NULL;
-    item = "mnemonic";
-  }
-  if (mnemonic && !mnemonic_check(mnemonic)) {
-    fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic);
-    return 2;
-  }
-  printf("Reading %ss from stdin ...\n", item);
-  start = clock();
-  for (;;) {
-    if (fgets(iter, 256, stdin) == NULL) break;
-    int len = strlen(iter);
-    if (len <= 0) {
-      continue;
-    }
-    count++;
-    iter[len - 1] = 0;
-    if (mnemonic) {
-      mnemonic_to_seed(mnemonic, iter, seed, NULL);
-    } else {
-      mnemonic_to_seed(iter, "", seed, NULL);
-    }
-    hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node);
-#if ACCOUNT_LEGACY
-    hdnode_private_ckd_prime(&node, 44);
-#else
-    hdnode_private_ckd_prime(&node, 49);
-#endif
-    hdnode_private_ckd_prime(&node, 0);
-    hdnode_private_ckd_prime(&node, 0);
-    hdnode_private_ckd(&node, 0);
-    hdnode_private_ckd(&node, 0);
-    hdnode_fill_public_key(&node);
-#if ACCOUNT_LEGACY
-    // Legacy address
-    ecdsa_get_address(node.public_key, 0, HASHER_SHA2_RIPEMD, HASHER_SHA2D,
-                      addr, sizeof(addr));
-#else
-    // Segwit-in-P2SH
-    ecdsa_get_address_segwit_p2sh(node.public_key, 5, HASHER_SHA2_RIPEMD,
-                                  HASHER_SHA2D, addr, sizeof(addr));
-#endif
-    if (strcmp(address, addr) == 0) {
-      found = 1;
-      break;
-    }
-  }
-  float dur = (float)(clock() - start) / CLOCKS_PER_SEC;
-  printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur,
-         (float)count / dur);
-  if (found) {
-    printf("Correct %s found! :-)\n\"%s\"\n", item, iter);
-    return 0;
-  }
-  printf("Correct %s not found. :-(\n", item);
-  return 4;
-}

+ 0 - 73
crypto/tools/mktable.c

@@ -1,73 +0,0 @@
-#include <assert.h>
-#include <stdio.h>
-#include "bignum.h"
-#include "bip32.h"
-#include "ecdsa.h"
-#include "rand.h"
-
-/*
- * This program prints the contents of the ecdsa_curve.cp array.
- * The entry cp[i][j] contains the number (2*j+1)*16^i*G,
- * where G is the generator of the specified elliptic curve.
- */
-int main(int argc, char **argv) {
-  int i, j, k;
-  if (argc != 2) {
-    printf("Usage: %s CURVE_NAME\n", argv[0]);
-    return 1;
-  }
-  const char *name = argv[1];
-  const curve_info *info = get_curve_by_name(name);
-  if (info == 0) {
-    printf("Unknown curve '%s'\n", name);
-    return 1;
-  }
-  const ecdsa_curve *curve = info->params;
-  if (curve == 0) {
-    printf("Unknown curve params");
-    return 1;
-  }
-
-  curve_point ng = curve->G;
-  curve_point pow2ig = curve->G;
-  for (i = 0; i < 64; i++) {
-    // invariants:
-    //   pow2ig = 16^i * G
-    //   ng     = pow2ig
-    printf("\t{\n");
-    for (j = 0; j < 8; j++) {
-      // invariants:
-      //   pow2ig = 16^i * G
-      //   ng     = (2*j+1) * 16^i * G
-#ifndef NDEBUG
-      curve_point checkresult;
-      bignum256 a;
-      bn_zero(&a);
-      a.val[(4 * i) / BN_BITS_PER_LIMB] = ((uint32_t)2 * j + 1)
-                                          << ((4 * i) % BN_BITS_PER_LIMB);
-      bn_normalize(&a);
-      point_multiply(curve, &a, &curve->G, &checkresult);
-      assert(point_is_equal(&checkresult, &ng));
-#endif
-      printf("\t\t/* %2d*16^%d*G: */\n\t\t{{{", 2 * j + 1, i);
-      // print x coordinate
-      for (k = 0; k < 9; k++) {
-        printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.x.val[k]);
-      }
-      printf("}},\n\t\t {{");
-      // print y coordinate
-      for (k = 0; k < 9; k++) {
-        printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.y.val[k]);
-      }
-      if (j == 7) {
-        printf("}}}\n\t},\n");
-      } else {
-        printf("}}},\n");
-        point_add(curve, &pow2ig, &ng);
-      }
-      point_add(curve, &pow2ig, &ng);
-    }
-    pow2ig = ng;
-  }
-  return 0;
-}

+ 0 - 18
crypto/tools/nem_test_vectors.erb

@@ -1,18 +0,0 @@
-// test vectors from <%= source_url %>
-START_TEST(<%= test_name %>)
-{
-	static const struct {
-<% fields.each do |(name, type)| -%>
-		<%= if type.nil? then 'const char *' else "#{type} " end %><%= name %>;
-<% end -%>
-	} tests[] = {
-<% data.each do |values| -%>
-		{ <% values.each do |value| %><%= value %>, <% end %>},
-<% end -%>
-	};
-
-	for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
-		// TODO: Implement test
-	}
-}
-END_TEST

+ 0 - 126
crypto/tools/nem_test_vectors.rb

@@ -1,126 +0,0 @@
-#!/usr/bin/env ruby
-require 'highline'
-require 'open-uri'
-
-TEMPLATE_NAME = (Pathname.new(__FILE__).sub_ext '.erb').to_s.freeze
-
-@terminal = HighLine.new($stdin, $stderr)
-
-def github_files
-  require 'octokit'
-
-  @github_files ||= Octokit.contents('NemProject/nem-test-vectors')
-                           .select do |file|
-    file.name.end_with? '.dat'
-  end
-end
-
-def choose_data_file
-  @terminal.choose do |menu|
-    github_files.each do |file|
-      menu.choice(file.name) { file.download_url }
-    end
-
-    menu.prompt = 'Which file?  '
-
-    menu.index = :none
-    menu.select_by = :name
-  end
-end
-
-def load_header(line)
-  line = line.dup
-  abort 'Header is not a comment' unless line.slice!(0) == '#'
-
-  header = line.split(':').each(&:strip!)
-  header.shift if header.first.empty?
-
-  header
-end
-
-def parse_field_answer(answer)
-  if answer.empty?
-    nil
-  elsif /^(?:(?<type>\w+) )?(?<identifier>\w+)$/ =~ answer
-    [identifier, type]
-  else
-    raise NotValidQuestionError
-  end
-end
-
-def ask_fields(header)
-  header.map do |name|
-    @terminal.ask "Field for `#{name}'?  " do |question|
-      question.answer_type = lambda(&method(:parse_field_answer))
-    end
-  end
-end
-
-def load_data_line(line)
-  abort 'Line does not begin with colon' unless line.slice!(0) == ':'
-
-  line.strip!
-  line.chomp!(',')
-
-  values = line.split(':').each(&:strip!)
-  values.pop if values.last.empty?
-
-  values
-end
-
-def load_data(file, count)
-  file.each_line.lazy.reject { |line| line.start_with? '#' }
-      .take(count)
-      .map(&method(:load_data_line))
-      .to_a
-end
-
-def remove_skipped_fields(fields, data)
-  data.each do |values|
-    abort 'Line does not match header' unless values.size == fields.size
-
-    values.reject!.each_with_index { |_, index| fields[index].nil? }
-  end
-
-  fields.compact!
-end
-
-def format_data_fields(fields, data)
-  data.each do |values|
-    fields.each_with_index do |(_, type), index|
-      values[index] = values[index].dump if type.nil?
-    end
-  end
-end
-
-def template(source_url, fields, data)
-  test_name = @terminal.ask('Name for test?  ') do |question|
-    question.validate = /./
-  end
-
-  erb = ERB.new(File.read(TEMPLATE_NAME), nil, '-')
-  erb.filename = TEMPLATE_NAME
-
-  erb.result(binding)
-end
-
-download_url = choose_data_file
-
-source_code = open download_url do |file|
-  line = file.readline
-
-  header = load_header(line)
-  @terminal.say line
-
-  count = @terminal.ask('How many vectors to import?  ', Integer)
-
-  fields = ask_fields(header)
-  data = load_data(file, count)
-
-  remove_skipped_fields(fields, data)
-  format_data_fields(fields, data)
-
-  template(download_url, fields, data)
-end
-
-puts source_code

+ 0 - 48
crypto/tools/xpubaddrgen.c

@@ -1,48 +0,0 @@
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include "bip32.h"
-#include "curves.h"
-#include "ecdsa.h"
-
-#define VERSION_PUBLIC 0x0488b21e
-
-void process_job(uint32_t jobid, const char *xpub, uint32_t change,
-                 uint32_t from, uint32_t to) {
-  HDNode node, child;
-  if (change > 1 || to <= from ||
-      hdnode_deserialize_public(xpub, VERSION_PUBLIC, SECP256K1_NAME, &node,
-                                NULL) != 0) {
-    printf("%d error\n", jobid);
-    return;
-  }
-  hdnode_public_ckd(&node, change);
-  uint32_t i;
-  char address[36];
-  for (i = from; i < to; i++) {
-    memcpy(&child, &node, sizeof(HDNode));
-    hdnode_public_ckd(&child, i);
-    ecdsa_get_address(child.public_key, 0, HASHER_SHA2, HASHER_SHA2D, address,
-                      sizeof(address));
-    printf("%d %d %s\n", jobid, i, address);
-  }
-}
-
-int main(void) {
-  char line[1024], xpub[1024];
-  uint32_t jobid, change, from, to;
-  int r;
-  for (;;) {
-    if (!fgets(line, sizeof(line), stdin)) break;
-    r = sscanf(line, "%u %s %u %u %u\n", &jobid, xpub, &change, &from, &to);
-    if (r < 1) {
-      printf("error\n");
-    } else if (r != 5) {
-      printf("%d error\n", jobid);
-    } else {
-      process_job(jobid, xpub, change, from, to);
-    }
-  }
-  return 0;
-}

+ 0 - 359
crypto/zkp_bip340.c

@@ -1,359 +0,0 @@
-/**
- * Copyright (c) SatoshiLabs
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <string.h>
-
-#include "memzero.h"
-#include "sha2.h"
-#include "zkp_context.h"
-
-#include "vendor/secp256k1-zkp/include/secp256k1.h"
-#include "vendor/secp256k1-zkp/include/secp256k1_extrakeys.h"
-#include "vendor/secp256k1-zkp/include/secp256k1_schnorrsig.h"
-
-#include "zkp_bip340.h"
-
-// Initial hash value H for SHA-256 TapTweak:
-const uint32_t sha256_initial_taptweak_state[8] = {
-    0xd129a2f3UL, 0x701c655dUL, 0x6583b6c3UL, 0xb9419727UL,
-    0x95f4e232UL, 0x94fd54f4UL, 0xa2ae8d85UL, 0x47ca590bUL,
-};
-
-// BIP340 Schnorr public key derivation
-// private_key_bytes has 32 bytes
-// public_key_bytes has 32 bytes
-// returns 0 on success
-int zkp_bip340_get_public_key(const uint8_t *private_key_bytes,
-                              uint8_t *public_key_bytes) {
-  int result = 0;
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = -1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = -1;
-    }
-  }
-
-  secp256k1_pubkey public_key = {0};
-  if (result == 0) {
-    if (secp256k1_ec_pubkey_create(context_writable, &public_key,
-                                   private_key_bytes) != 1) {
-      result = -1;
-    }
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  secp256k1_xonly_pubkey xonly_pubkey = {0};
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_from_pubkey(context_read_only, &xonly_pubkey,
-                                           NULL, &public_key) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&public_key, sizeof(public_key));
-
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_serialize(context_read_only, public_key_bytes,
-                                         &xonly_pubkey) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&xonly_pubkey, sizeof(xonly_pubkey));
-
-  return result;
-}
-
-// BIP340 Schnorr signature signing
-// private_key_bytes has 32 bytes
-// digest has 32 bytes
-// signature_bytes has 64 bytes
-// auxiliary_data has 32 bytes or is NULL (32 zero bytes are used)
-// returns 0 on success
-int zkp_bip340_sign_digest(const uint8_t *private_key_bytes,
-                           const uint8_t *digest, uint8_t *signature_bytes,
-                           uint8_t *auxiliary_data) {
-  int result = 0;
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = -1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = -1;
-    }
-  }
-
-  secp256k1_keypair keypair = {0};
-  if (result == 0) {
-    if (secp256k1_keypair_create(context_writable, &keypair,
-                                 private_key_bytes) != 1) {
-      result = -1;
-    }
-  }
-
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = -1;
-    }
-  }
-
-  if (result == 0) {
-    if (secp256k1_schnorrsig_sign32(context_writable, signature_bytes, digest,
-                                    &keypair, auxiliary_data) != 1) {
-      result = -1;
-    }
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  memzero(&keypair, sizeof(keypair));
-
-  return result;
-}
-
-// BIP340 Schnorr signature verification
-// public_key_bytes has 32 bytes
-// signature_bytes has 64 bytes
-// digest has 32 bytes
-// returns 0 if verification succeeded
-int zkp_bip340_verify_digest(const uint8_t *public_key_bytes,
-                             const uint8_t *signature_bytes,
-                             const uint8_t *digest) {
-  int result = 0;
-
-  secp256k1_xonly_pubkey xonly_pubkey = {0};
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_parse(context_read_only, &xonly_pubkey,
-                                     public_key_bytes) != 1) {
-      result = 1;
-    }
-  }
-
-  if (result == 0) {
-    if (secp256k1_schnorrsig_verify(context_read_only, signature_bytes, digest,
-                                    32, &xonly_pubkey) != 1) {
-      result = 5;
-    }
-  }
-
-  memzero(&xonly_pubkey, sizeof(xonly_pubkey));
-
-  return result;
-}
-
-// BIP340 Schnorr public key verification
-// public_key_bytes has 32 bytes
-// returns 0 if verification succeeded
-int zkp_bip340_verify_publickey(const uint8_t *public_key_bytes) {
-  int result = 0;
-
-  secp256k1_xonly_pubkey xonly_pubkey = {0};
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_parse(context_read_only, &xonly_pubkey,
-                                     public_key_bytes) != 1) {
-      result = 1;
-    }
-  }
-
-  memzero(&xonly_pubkey, sizeof(xonly_pubkey));
-
-  return result;
-}
-
-// BIP340 Schnorr public key tweak
-// internal_public_key has 32 bytes
-// root_hash has 32 bytes or is empty (NULL)
-// output_public_key has 32 bytes
-// returns 0 on success
-int zkp_bip340_tweak_public_key(const uint8_t *internal_public_key,
-                                const uint8_t *root_hash,
-                                uint8_t *output_public_key) {
-  int result = 0;
-
-  uint8_t tweak[SHA256_DIGEST_LENGTH] = {0};
-  if (result == 0) {
-    SHA256_CTX ctx = {0};
-    sha256_Init_ex(&ctx, sha256_initial_taptweak_state, 512);
-    sha256_Update(&ctx, internal_public_key, 32);
-    if (root_hash != NULL) {
-      sha256_Update(&ctx, root_hash, 32);
-    }
-    sha256_Final(&ctx, tweak);
-  }
-
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-
-  secp256k1_xonly_pubkey internal_pubkey = {0};
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_parse(context_read_only, &internal_pubkey,
-                                     internal_public_key) != 1) {
-      result = -1;
-    }
-  }
-
-  secp256k1_pubkey output_pubkey = {0};
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_tweak_add(context_read_only, &output_pubkey,
-                                         &internal_pubkey, tweak) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(tweak, sizeof(tweak));
-  memzero(&internal_pubkey, sizeof(internal_pubkey));
-
-  secp256k1_xonly_pubkey xonly_output_pubkey = {0};
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_from_pubkey(context_read_only,
-                                           &xonly_output_pubkey, NULL,
-                                           &output_pubkey) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&output_pubkey, sizeof(output_pubkey));
-
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_serialize(context_read_only, output_public_key,
-                                         &xonly_output_pubkey) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&xonly_output_pubkey, sizeof(xonly_output_pubkey));
-
-  return result;
-}
-
-// BIP340 Schnorr private key tweak
-// internal_private_key has 32 bytes
-// root_hash has 32 bytes or is empty (NULL)
-// output_private_key has 32 bytes
-// returns 0 on success
-int zkp_bip340_tweak_private_key(const uint8_t *internal_private_key,
-                                 const uint8_t *root_hash,
-                                 uint8_t *output_private_key) {
-  int result = 0;
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = -1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = -1;
-    }
-  }
-
-  secp256k1_keypair keypair = {0};
-  if (secp256k1_keypair_create(context_writable, &keypair,
-                               internal_private_key) != 1) {
-    result = -1;
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-
-  secp256k1_xonly_pubkey internal_xonly_pubkey = {0};
-  if (result == 0) {
-    if (secp256k1_keypair_xonly_pub(context_read_only, &internal_xonly_pubkey,
-                                    NULL, &keypair) != 1) {
-      result = -1;
-    }
-  }
-
-  uint8_t internal_public_key[32] = {0};
-  if (result == 0) {
-    if (secp256k1_xonly_pubkey_serialize(context_read_only, internal_public_key,
-                                         &internal_xonly_pubkey) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&internal_xonly_pubkey, sizeof(internal_xonly_pubkey));
-
-  uint8_t tweak[SHA256_DIGEST_LENGTH] = {0};
-  if (result == 0) {
-    SHA256_CTX ctx = {0};
-    sha256_Init_ex(&ctx, sha256_initial_taptweak_state, 512);
-    sha256_Update(&ctx, internal_public_key, 32);
-    if (root_hash != NULL) {
-      sha256_Update(&ctx, root_hash, 32);
-    }
-    sha256_Final(&ctx, tweak);
-  }
-
-  memzero(&internal_public_key, sizeof(internal_public_key));
-
-  if (result == 0) {
-    if (secp256k1_keypair_xonly_tweak_add(context_read_only, &keypair, tweak) !=
-        1) {
-      result = -1;
-    }
-  }
-
-  memzero(tweak, sizeof(tweak));
-
-  if (result == 0) {
-    if (secp256k1_keypair_sec(context_read_only, output_private_key,
-                              &keypair) != 1) {
-      result = -1;
-    }
-  }
-
-  memzero(&keypair, sizeof(keypair));
-
-  return result;
-}

+ 0 - 22
crypto/zkp_bip340.h

@@ -1,22 +0,0 @@
-#ifndef __ZKP_BIP340_H__
-#define __ZKP_BIP340_H__
-
-#include <stdint.h>
-
-int zkp_bip340_get_public_key(const uint8_t *private_key_bytes,
-                              uint8_t *public_key_bytes);
-int zkp_bip340_sign_digest(const uint8_t *private_key_bytes,
-                           const uint8_t *digest, uint8_t *signature_bytes,
-                           uint8_t *auxiliary_data);
-int zkp_bip340_verify_digest(const uint8_t *public_key_bytes,
-                             const uint8_t *signature_bytes,
-                             const uint8_t *digest);
-int zkp_bip340_verify_publickey(const uint8_t *public_key_bytes);
-int zkp_bip340_tweak_public_key(const uint8_t *internal_public_key,
-                                const uint8_t *root_hash,
-                                uint8_t *output_public_key);
-int zkp_bip340_tweak_private_key(const uint8_t *internal_private_key,
-                                 const uint8_t *root_hash,
-                                 uint8_t *output_private_key);
-
-#endif

+ 0 - 112
crypto/zkp_context.c

@@ -1,112 +0,0 @@
-/**
- * Copyright (c) SatoshiLabs
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdatomic.h>
-#include <stdbool.h>
-
-#include "memzero.h"
-#include "rand.h"
-#include "zkp_context.h"
-
-#include "vendor/secp256k1-zkp/include/secp256k1.h"
-
-static uint8_t context_buffer[SECP256K1_CONTEXT_SIZE];
-static secp256k1_context *context;
-static volatile atomic_flag locked;
-
-// returns 0 on success
-int secp256k1_context_writable_randomize(secp256k1_context *context_writable) {
-  uint8_t seed[32] = {0};
-  random_buffer(seed, sizeof(seed));
-  int returned = secp256k1_context_randomize(context_writable, seed);
-  memzero(seed, sizeof(seed));
-
-  if (returned != 1) {
-    return 1;
-  }
-
-  return 0;
-}
-
-bool zkp_context_is_initialized(void) { return context != NULL; }
-
-// returns 0 on success
-int zkp_context_init(void) {
-  assert(context == NULL);
-
-  const unsigned int context_flags =
-      SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY;
-
-  const size_t context_size =
-      secp256k1_context_preallocated_size(context_flags);
-  // Assert the context is as small as possible
-  assert(context_size == SECP256K1_CONTEXT_SIZE);
-  if (context_size == 0 || context_size > SECP256K1_CONTEXT_SIZE) {
-    return 1;
-  }
-
-  context =
-      secp256k1_context_preallocated_create(context_buffer, context_flags);
-  if (context == NULL) {
-    return 1;
-  }
-
-  secp256k1_context_writable_randomize(context);
-
-  atomic_flag_clear(&locked);
-
-  return 0;
-}
-
-void zkp_context_destroy(void) {
-  assert(context != NULL);
-
-  secp256k1_context_preallocated_destroy(context);
-  memzero(context_buffer, sizeof(context_buffer));
-  atomic_flag_clear(&locked);
-  context = NULL;
-}
-
-const secp256k1_context *zkp_context_get_read_only(void) {
-  assert(context != NULL);
-
-  return context;
-}
-
-// returns NULL if context cannot be acquired
-secp256k1_context *zkp_context_acquire_writable(void) {
-  assert(context != NULL);
-
-  // We don't expect the context to be used by multiple threads
-  if (atomic_flag_test_and_set(&locked)) {
-    return NULL;
-  }
-
-  return context;
-}
-
-void zkp_context_release_writable(void) {
-  assert(context != NULL);
-
-  atomic_flag_clear(&locked);
-}

+ 0 - 16
crypto/zkp_context.h

@@ -1,16 +0,0 @@
-#ifndef __ZKP_CONTEXT_H__
-#define __ZKP_CONTEXT_H__
-
-#include <stdint.h>
-
-#include "vendor/secp256k1-zkp/include/secp256k1_preallocated.h"
-
-int secp256k1_context_writable_randomize(secp256k1_context *context);
-bool zkp_context_is_initialized(void);
-int zkp_context_init(void);
-void zkp_context_destroy(void);
-const secp256k1_context *zkp_context_get_read_only(void);
-secp256k1_context *zkp_context_acquire_writable(void);
-void zkp_context_release_writable(void);
-
-#endif

+ 0 - 382
crypto/zkp_ecdsa.c

@@ -1,382 +0,0 @@
-/**
- * Copyright (c) SatoshiLabs
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include "memzero.h"
-#include "secp256k1.h"
-#include "zkp_context.h"
-
-#include "vendor/secp256k1-zkp/include/secp256k1.h"
-#include "vendor/secp256k1-zkp/include/secp256k1_extrakeys.h"
-#include "vendor/secp256k1-zkp/include/secp256k1_preallocated.h"
-#include "vendor/secp256k1-zkp/include/secp256k1_recovery.h"
-
-#include "zkp_ecdsa.h"
-
-static bool is_zero_digest(const uint8_t *digest) {
-  const uint8_t zeroes[32] = {0};
-  return memcmp(digest, zeroes, 32) == 0;
-}
-
-// ECDSA compressed public key derivation
-// curve has to be &secp256k1
-// private_key_bytes has 32 bytes
-// public_key_bytes has 33 bytes
-// returns 0 on success
-int zkp_ecdsa_get_public_key33(const ecdsa_curve *curve,
-                               const uint8_t *private_key_bytes,
-                               uint8_t *public_key_bytes) {
-  assert(curve == &secp256k1);
-  if (curve != &secp256k1) {
-    return 1;
-  }
-
-  int result = 0;
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = 1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = 1;
-    }
-  }
-
-  secp256k1_pubkey public_key = {0};
-  if (result == 0) {
-    if (secp256k1_ec_pubkey_create(context_writable, &public_key,
-                                   private_key_bytes) != 1) {
-      result = 1;
-    }
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  if (result == 0) {
-    size_t written = 33;
-    const secp256k1_context *context_read_only = zkp_context_get_read_only();
-    int returned = secp256k1_ec_pubkey_serialize(
-        context_read_only, public_key_bytes, &written, &public_key,
-        SECP256K1_EC_COMPRESSED);
-
-    if (returned != 1 || written != 33) {
-      result = 1;
-    }
-  }
-
-  memzero(&public_key, sizeof(public_key));
-  return result;
-}
-
-// ECDSA uncompressed public key derivation
-// curve has to be &secp256k1
-// private_key_bytes has 32 bytes
-// public_key_bytes has 65 bytes
-// returns 0 on success
-int zkp_ecdsa_get_public_key65(const ecdsa_curve *curve,
-                               const uint8_t *private_key_bytes,
-                               uint8_t *public_key_bytes) {
-  assert(curve == &secp256k1);
-  if (curve != &secp256k1) {
-    return 1;
-  }
-
-  int result = 0;
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = 1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = 1;
-    }
-  }
-
-  secp256k1_pubkey public_key = {0};
-  if (result == 0) {
-    if (secp256k1_ec_pubkey_create(context_writable, &public_key,
-                                   private_key_bytes) != 1) {
-      result = 1;
-    }
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  if (result == 0) {
-    size_t written = 65;
-    const secp256k1_context *context_read_only = zkp_context_get_read_only();
-    int returned = secp256k1_ec_pubkey_serialize(
-        context_read_only, public_key_bytes, &written, &public_key,
-        SECP256K1_EC_UNCOMPRESSED);
-
-    if (returned != 1 || written != 65) {
-      result = 1;
-    }
-  }
-
-  memzero(&public_key, sizeof(public_key));
-  return result;
-}
-
-// ECDSA signing
-// curve has to be &secp256k1
-// private_key_bytes has 32 bytes
-// digest has 32 bytes
-// signature_bytes has 64 bytes
-// pby is one byte
-// is_canonical has to be NULL
-// returns 0 on success
-int zkp_ecdsa_sign_digest(
-    const ecdsa_curve *curve, const uint8_t *private_key_bytes,
-    const uint8_t *digest, uint8_t *signature_bytes, uint8_t *pby,
-    int (*is_canonical)(uint8_t by, uint8_t signature_bytes[64])) {
-  assert(curve == &secp256k1);
-  assert(is_canonical == NULL);
-  if (curve != &secp256k1 || is_canonical != NULL) {
-    return 1;
-  }
-
-  int result = 0;
-
-  if (result == 0) {
-    if (is_zero_digest(digest)) {
-      // The probability of the digest being all-zero by chance is
-      // infinitesimal, so this is most likely an indication of a bug.
-      // Furthermore, the signature has no value, because in this case it can be
-      // easily forged for any public key, see zkp_ecdsa_verify_digest().
-      result = 1;
-    }
-  }
-
-  secp256k1_context *context_writable = NULL;
-  if (result == 0) {
-    context_writable = zkp_context_acquire_writable();
-    if (context_writable == NULL) {
-      result = 1;
-    }
-  }
-  if (result == 0) {
-    if (secp256k1_context_writable_randomize(context_writable) != 0) {
-      result = 1;
-    }
-  }
-
-  secp256k1_ecdsa_recoverable_signature recoverable_signature = {0};
-  if (result == 0) {
-    if (secp256k1_ecdsa_sign_recoverable(context_writable,
-                                         &recoverable_signature, digest,
-                                         private_key_bytes, NULL, NULL) != 1) {
-      result = 1;
-    }
-  }
-
-  if (context_writable) {
-    zkp_context_release_writable();
-    context_writable = NULL;
-  }
-
-  if (result == 0) {
-    int recid = 0;
-    const secp256k1_context *context_read_only = zkp_context_get_read_only();
-    if (secp256k1_ecdsa_recoverable_signature_serialize_compact(
-            context_read_only, signature_bytes, &recid,
-            &recoverable_signature) != 1) {
-      result = 1;
-    }
-    if (pby != NULL) {
-      *pby = (uint8_t)recid;
-    }
-  }
-
-  memzero(&recoverable_signature, sizeof(recoverable_signature));
-
-  return result;
-}
-
-// ECDSA public key recovery
-// public_key_bytes has 65 bytes
-// signature_bytes has 64 bytes
-// digest has 32 bytes
-// recid is 0, 1, 2 or 3
-// returns 0 on success
-int zkp_ecdsa_recover_pub_from_sig(const ecdsa_curve *curve,
-                                   uint8_t *public_key_bytes,
-                                   const uint8_t *signature_bytes,
-                                   const uint8_t *digest, int recid) {
-  assert(curve == &secp256k1);
-  if (curve != &secp256k1) {
-    return 1;
-  }
-
-  int result = 0;
-
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-  secp256k1_ecdsa_recoverable_signature recoverable_signature = {0};
-
-  if (result == 0) {
-    if (secp256k1_ecdsa_recoverable_signature_parse_compact(
-            context_read_only, &recoverable_signature, signature_bytes,
-            recid) != 1) {
-      result = 1;
-    }
-  }
-
-  secp256k1_pubkey public_key = {0};
-
-  if (result == 0) {
-    if (secp256k1_ecdsa_recover(context_read_only, &public_key,
-                                &recoverable_signature, digest) != 1) {
-      result = 1;
-    }
-  }
-
-  memzero(&recoverable_signature, sizeof(recoverable_signature));
-
-  if (result == 0) {
-    size_t written = 65;
-    int returned = secp256k1_ec_pubkey_serialize(
-        context_read_only, public_key_bytes, &written, &public_key,
-        SECP256K1_EC_UNCOMPRESSED);
-    if (returned != 1 || written != 65) {
-      result = 1;
-    }
-  }
-
-  memzero(&public_key, sizeof(public_key));
-
-  return result;
-}
-
-// ECDSA verification
-// curve has to be &secp256k1
-// public_key_bytes has 33 or 65 bytes
-// signature_bytes has 64 bytes
-// digest has 32 bytes
-// returns 0 if verification succeeded
-int zkp_ecdsa_verify_digest(const ecdsa_curve *curve,
-                            const uint8_t *public_key_bytes,
-                            const uint8_t *signature_bytes,
-                            const uint8_t *digest) {
-  assert(curve == &secp256k1);
-  if (curve != &secp256k1) {
-    return 1;
-  }
-
-  int result = 0;
-
-  int public_key_length = 0;
-
-  if (result == 0) {
-    if (public_key_bytes[0] == 0x04) {
-      public_key_length = 65;
-    } else if (public_key_bytes[0] == 0x02 || public_key_bytes[0] == 0x03) {
-      public_key_length = 33;
-    } else {
-      result = 1;
-    }
-  }
-
-  if (result == 0) {
-    if (is_zero_digest(digest)) {
-      // The digest was all-zero. The probability of this happening by chance is
-      // infinitesimal, but it could be induced by a fault injection. In this
-      // case the signature (r,s) can be forged by taking r := (t * Q).x mod n
-      // and s := r * t^-1 mod n for any t in [1, n-1]. We fail verification,
-      // because there is no guarantee that the signature was created by the
-      // owner of the private key.
-      result = 3;
-    }
-  }
-
-  const secp256k1_context *context_read_only = zkp_context_get_read_only();
-  secp256k1_pubkey public_key = {0};
-
-  if (result == 0) {
-    if (secp256k1_ec_pubkey_parse(context_read_only, &public_key,
-                                  public_key_bytes, public_key_length) != 1) {
-      result = 1;
-    }
-  }
-
-  secp256k1_ecdsa_signature signature = {0};
-
-  if (result == 0) {
-    if (secp256k1_ecdsa_signature_parse_compact(context_read_only, &signature,
-                                                signature_bytes) != 1) {
-      result = 2;
-    }
-  }
-
-  if (result == 0) {
-    secp256k1_ecdsa_signature_normalize(context_read_only, &signature,
-                                        &signature);
-
-    if (secp256k1_ecdsa_verify(context_read_only, &signature, digest,
-                               &public_key) != 1) {
-      result = 5;
-    }
-  }
-
-  memzero(&public_key, sizeof(public_key));
-  memzero(&signature, sizeof(signature));
-
-  return result;
-}
-
-// ECDSA verification
-// curve has to be &secp256k1
-// public_key_bytes has 33 or 65 bytes
-// signature_bytes has 64 bytes
-// returns 0 if verification succeeded
-int zkp_ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_type,
-                     const uint8_t *public_key_bytes,
-                     const uint8_t *signature_bytes, const uint8_t *message,
-                     uint32_t message_length) {
-  assert(curve == &secp256k1);
-  if (curve != &secp256k1) {
-    return 1;
-  }
-
-  uint8_t hash[32] = {0};
-  hasher_Raw(hasher_type, message, message_length, hash);
-  int result =
-      zkp_ecdsa_verify_digest(curve, public_key_bytes, signature_bytes, hash);
-  memzero(hash, sizeof(hash));
-  return result;
-}

+ 0 - 30
crypto/zkp_ecdsa.h

@@ -1,30 +0,0 @@
-#ifndef __ZKP_ECDSA_H__
-#define __ZKP_ECDSA_H__
-
-#include <stdint.h>
-
-#include "hasher.h"
-
-int zkp_ecdsa_get_public_key33(const ecdsa_curve *curve,
-                               const uint8_t *private_key_bytes,
-                               uint8_t *public_key_bytes);
-int zkp_ecdsa_get_public_key65(const ecdsa_curve *curve,
-                               const uint8_t *private_key_bytes,
-                               uint8_t *public_key_bytes);
-int zkp_ecdsa_sign_digest(const ecdsa_curve *curve,
-                          const uint8_t *private_key_bytes,
-                          const uint8_t *digest, uint8_t *signature_bytes,
-                          uint8_t *pby,
-                          int (*is_canonical)(uint8_t by, uint8_t sig[64]));
-int zkp_ecdsa_recover_pub_from_sig(const ecdsa_curve *curve,
-                                   uint8_t *public_key_bytes,
-                                   const uint8_t *signature_bytes,
-                                   const uint8_t *digest, int recid);
-int zkp_ecdsa_verify_digest(const ecdsa_curve *curve,
-                            const uint8_t *public_key_bytes,
-                            const uint8_t *signature_bytes,
-                            const uint8_t *digest);
-int zkp_ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign,
-                     const uint8_t *pub_key, const uint8_t *sig,
-                     const uint8_t *msg, uint32_t msg_len);
-#endif

+ 3 - 3
views/flipbip39_scene_1.c

@@ -5,10 +5,10 @@
 #include <gui/elements.h>
 #include <dolphin/dolphin.h>
 
-//#include "../crypto/bip32.h"
+#include "../crypto/bip32.h"
 #include "../crypto/bip39.h"
-//#include "../crypto/ecdsa.h"
-//#include "../crypto/curves.h"
+#include "../crypto/ecdsa.h"
+#include "../crypto/curves.h"
 
 struct FlipBip39Scene1 {
     View* view;