clightning-dumpkeys

dump clightning output descriptors
git clone git://jb55.com/clightning-dumpkeys
Log | Files | Refs | README | LICENSE

commit 94e6f571e969a5fc40ee9fb3808615ee191b851c
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 24 May 2019 13:26:33 -0700

initial commit

Diffstat:
A.dir-locals.el | 7+++++++
A.gitignore | 3+++
AMakefile | 31+++++++++++++++++++++++++++++++
Abase58.c | 301+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abase58.h | 31+++++++++++++++++++++++++++++++
Abip32.c | 762+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abip32.h | 252+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acheck.c | 11+++++++++++
Aclightning-dumpkeys.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acompiler.c | 12++++++++++++
Acompiler.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aec.c | 30++++++++++++++++++++++++++++++
Aec.h | 34++++++++++++++++++++++++++++++++++
Aendian.h | 360+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahash.c | 28++++++++++++++++++++++++++++
Ahash.h | 13+++++++++++++
Ahkdf.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahkdf.h | 22++++++++++++++++++++++
Ahmac.c | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahmac.h | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aripemd160.c | 404+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aripemd160.h | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asha256.c | 321+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asha256.h | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asha512.c | 261+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asha512.h | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ashort_types.h | 21+++++++++++++++++++++
27 files changed, 4025 insertions(+), 0 deletions(-)

diff --git a/.dir-locals.el b/.dir-locals.el @@ -0,0 +1,7 @@ +((c-mode . ((c-file-style . "linux") + (indent-tabs-mode . t) + (show-trailing-whitespace . t) + (c-basic-offset . 8) + (tab-width . 8) + )) + ) diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +*.o +/clightning-dumpkeys +/check diff --git a/Makefile b/Makefile @@ -0,0 +1,31 @@ + +BIN = clightning-dumpkeys +PREFIX ?= /usr/local + +LDFLAGS = -lsecp256k1 +CFLAGS = $(DEFS) -Og -g -I src -Wall -Werror -Wextra -std=c99 + +OBJS = sha256.o +OBJS += sha512.o +OBJS += ripemd160.o +OBJS += hmac.o +OBJS += hkdf.o +OBJS += bip32.o +OBJS += compiler.o +OBJS += ec.o +OBJS += hash.o +OBJS += base58.o + +SRCS=$(OBJS:.o=.c) + +all: $(BIN) + +$(BIN): clightning-dumpkeys.o $(OBJS) + $(CC) $(LDFLAGS) $(CFLAGS) $^ -o $@ + +clean: + rm -f $(OBJS) clightning-dumpkeys.o check.o $(BIN) check + +check: check.o $(OBJS) + $(CC) $(LDFLAGS) $^ -o $@ + ./check diff --git a/base58.c b/base58.c @@ -0,0 +1,301 @@ + +#include "base58.h" +#include "sha256.h" +#include "endian.h" +#include "short_types.h" +#include "compiler.h" + +#include <strings.h> + +/* Temporary stack buffer sizes */ +#define BIGNUM_WORDS 128u +#define BIGNUM_BYTES (BIGNUM_WORDS * sizeof(uint32_t)) +#define BASE58_ALL_DEFINED_FLAGS (BASE58_FLAG_CHECKSUM) + +static const unsigned char base58_to_byte[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* .1234567 */ + 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89...... */ + + 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, /* .ABCDEFG */ + 0x11, 0x00, 0x12, 0x13, 0x14, 0x15, 0x16, 0x00, /* H.JKLMN. */ + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, /* PQRSTUVW */ + 0x1F, 0x20, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ..... */ + + 0x00, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* .abcdefg */ + 0x29, 0x2A, 0x2B, 0x2C, 0x00, 0x2D, 0x2E, 0x2F, /* hijk.mno */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* pqrstuvx */ + 0x38, 0x39, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, /* xyz..... */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ +}; + +static const char byte_to_base58[58] = { + '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y','z' +}; + +/* Returns non-zero on error. If 0 is returned then: + * *len <= input value - OK, bytes_out contains data. + * *len > input value - Failed and bytes_out untouched. + */ +static int base58_decode(const char *base58, size_t base58_len, + unsigned char *bytes_out, size_t *len) +{ + uint32_t bn_buf[BIGNUM_WORDS]; + uint32_t *bn = bn_buf, *top_word, *bn_p; + size_t bn_words = 0, ones, cp_len, i; + unsigned char *cp; + int ret = WALLY_EINVAL; + + if (!base58 || !base58_len) + return WALLY_EINVAL; /* Empty string can't be decoded or represented */ + + /* Process leading '1's */ + for (ones = 0; ones < base58_len && base58[ones] == '1'; ++ones) + ; /* no-op*/ + + if (!(base58_len -= ones)) { + if (bytes_out && ones <= *len) + memset(bytes_out, 0, ones); + *len = ones; + return WALLY_OK; /* String of all '1's */ + } + base58 += ones; /* Skip over leading '1's */ + + /* Take 6 bits to store each 58 bit number, rounded up to the next byte, + * then round that up to a uint32_t word boundary. */ + bn_words = ((base58_len * 6 + 7) / 8 + 3) / 4; + + /* Allocate our bignum buffer if it won't fit on the stack */ + if (bn_words > BIGNUM_WORDS) + if (!(bn = malloc(bn_words * sizeof(*bn)))) { + ret = WALLY_ENOMEM; + goto cleanup; + } + + /* Iterate through the characters adding them to our bignum. We keep + * track of the current top word to avoid iterating over words that + * we know are zero. */ + top_word = bn + bn_words - 1; + *top_word = 0; + + for (i = 0; i < base58_len; ++i) { + unsigned char byte = base58_to_byte[((unsigned char *)base58)[i]]; + if (!byte--) + goto cleanup; /* Invalid char */ + + for (bn_p = bn + bn_words - 1; bn_p >= top_word; --bn_p) { + uint64_t mult = *bn_p * 58ull + byte; + *bn_p = mult & 0xffffffff; + byte = (mult >> 32) & 0xff; + if (byte && bn_p == top_word) { + *--top_word = byte; /* Increase bignum size */ + break; + } + } + } + + /* We have our bignum stored from top_word to bn + bn_words - 1. Convert + * its words to big-endian so we can simply memcpy it to bytes_out. */ + for (bn_p = top_word; bn_p < bn + bn_words; ++bn_p) + *bn_p = cpu_to_be32(*bn_p); /* No-op on big-endian machines */ + + for (cp = (unsigned char *)top_word; !*cp; ++cp) + ; /* Skip leading zero bytes in our bignum */ + + /* Copy the result if it fits, cleanup and return */ + cp_len = (unsigned char *)(bn + bn_words) - cp; + + if (bytes_out && ones + cp_len <= *len) { + memset(bytes_out, 0, ones); + memcpy(bytes_out + ones, cp, cp_len); + } + + *len = ones + cp_len; + ret = WALLY_OK; + +cleanup: + wally_clear(bn, bn_words * sizeof(*bn)); + if (bn != bn_buf) + free(bn); + return ret; +} + +uint32_t base58_get_checksum(const unsigned char *bytes, size_t bytes_len) +{ + struct sha256 sha; + uint32_t checksum; + + sha256d(bytes, bytes_len, (unsigned char *)&sha, sizeof(sha)); + checksum = sha.u.u32[0]; + wally_clear(&sha, sizeof(sha)); + return checksum; +} + + +int wally_base58_from_bytes(const unsigned char *bytes, size_t bytes_len, + uint32_t flags, char **output) +{ + uint32_t checksum, *cs_p = NULL; + unsigned char bn_buf[BIGNUM_BYTES]; + unsigned char *bn = bn_buf, *top_byte, *bn_p; + size_t bn_bytes = 0, zeros, i, orig_len = bytes_len; + int ret = WALLY_EINVAL; + + if (output) + *output = NULL; + + if (!bytes || !bytes_len || (flags & ~BASE58_ALL_DEFINED_FLAGS) || !output) + goto cleanup; /* Invalid argument */ + + if (flags & BASE58_FLAG_CHECKSUM) { + checksum = base58_get_checksum(bytes, bytes_len); + cs_p = &checksum; + bytes_len += 4; + } + +#define b(n) (n < orig_len ? bytes[n] : ((unsigned char *)cs_p)[n - orig_len]) + + /* Process leading zeros */ + for (zeros = 0; zeros < bytes_len && !b(zeros); ++zeros) + ; /* no-op*/ + + if (zeros == bytes_len) { + if (!(*output = malloc(zeros + 1))) { + ret = WALLY_ENOMEM; + goto cleanup; + } + + memset(*output, '1', zeros); + (*output)[zeros] = '\0'; + return WALLY_OK; /* All 0's */ + } + + bn_bytes = (bytes_len - zeros) * 138 / 100 + 1; /* log(256)/log(58) rounded up */ + + /* Allocate our bignum buffer if it won't fit on the stack */ + if (bn_bytes > BIGNUM_BYTES) + if (!(bn = malloc(bn_bytes))) { + ret = WALLY_ENOMEM; + goto cleanup; + } + + top_byte = bn + bn_bytes - 1; + *top_byte = 0; + + for (i = zeros; i < bytes_len; ++i) { + uint32_t carry = b(i); + for (bn_p = bn + bn_bytes - 1; bn_p >= top_byte; --bn_p) { + carry = *bn_p * 256 + carry; + *bn_p = carry % 58; + carry = carry / 58; + if (carry && bn_p == top_byte) + *--top_byte = 0; /* Increase bignum size */ + } + } + + while (!*top_byte && top_byte < bn + bn_bytes - 1) + ++top_byte; /* Skip leading zero bytes in our bignum */ + + /* Copy the result */ + bn_bytes = bn + bn_bytes - top_byte; + + if (!(*output = malloc(zeros + bn_bytes + 1))) { + ret = WALLY_ENOMEM; + goto cleanup; + } + + memset(*output, '1', zeros); + for (i = 0; i < bn_bytes; ++i) + (*output)[zeros + i] = byte_to_base58[top_byte[i]]; + (*output)[zeros + bn_bytes] = '\0'; + + ret = WALLY_OK; + +cleanup: + wally_clear(bn, bn_bytes); + if (bn != bn_buf) + free(bn); + return ret; +#undef b +} + + +int wally_base58_get_length(const char *str_in, size_t *written) +{ + return base58_decode(str_in, strlen(str_in), NULL, written); +} + +int wally_base58_to_bytes(const char *str_in, uint32_t flags, + unsigned char *bytes_out, size_t len, + size_t *written) +{ + size_t offset; + uint32_t checksum; + int ret; + + if (written) + *written = 0; + + if (!str_in || flags & ~BASE58_ALL_DEFINED_FLAGS || + !bytes_out || !len || !written) + return WALLY_EINVAL; + + if (flags & BASE58_FLAG_CHECKSUM && len <= BASE58_CHECKSUM_LEN) + return WALLY_EINVAL; /* No room for checksum */ + + *written = len; + ret = base58_decode(str_in, strlen(str_in), bytes_out, written); + if (!ret && *written > len) + return WALLY_OK; /* not enough space, return required amount */ + + if (!ret && (flags & BASE58_FLAG_CHECKSUM)) { + if (*written <= BASE58_CHECKSUM_LEN) { + wally_clear(bytes_out, len); + return WALLY_EINVAL; /* Input not long enough to contain a checksum */ + } + + offset = *written - BASE58_CHECKSUM_LEN; + checksum = base58_get_checksum(bytes_out, offset); + + if (memcmp(bytes_out + offset, &checksum, sizeof(checksum))) { + wally_clear(bytes_out, len); + return WALLY_EINVAL; /* Checksum mismatch */ + } + + wally_clear(bytes_out + offset, BASE58_CHECKSUM_LEN); + *written -= BASE58_CHECKSUM_LEN; + } + return ret; +} diff --git a/base58.h b/base58.h @@ -0,0 +1,31 @@ + +#ifndef LIBWALLY_BASE58_H +#define LIBWALLY_BASE58_H + +#include <stdint.h> +#include <stdlib.h> + +/** + * Calculate the base58 checksum of a block of binary data. + * + * @bytes: Binary data to calculate the checksum for. + * @len: The length of @bytes in bytes. + */ +uint32_t base58_get_checksum( + const unsigned char *bytes, + size_t len); + +int wally_base58_from_bytes(const unsigned char *bytes, size_t bytes_len, + uint32_t flags, char **output); + +int wally_base58_to_bytes( + const char *str_in, + uint32_t flags, + unsigned char *bytes_out, + size_t len, + size_t *written); + +#define BASE58_FLAG_CHECKSUM 0x1 +#define BASE58_CHECKSUM_LEN 4 + +#endif /* LIBWALLY_BASE58_H */ diff --git a/bip32.c b/bip32.c @@ -0,0 +1,762 @@ + +#include "hmac.h" +#include "ripemd160.h" +#include "sha512.h" +#include "endian.h" +#include "compiler.h" +#include "bip32.h" +#include "ec.h" +#include "hash.h" +#include "base58.h" +#include "short_types.h" + +#include <stdbool.h> +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#define EC_PRIVATE_KEY_LEN 32 +#define BIP32_ALL_DEFINED_FLAGS (BIP32_FLAG_KEY_PRIVATE | BIP32_FLAG_KEY_PUBLIC | BIP32_FLAG_SKIP_HASH) + +static const unsigned char SEED[] = { + 'B', 'i', 't', 'c', 'o', 'i', 'n', ' ', 's', 'e', 'e', 'd' +}; + +/* LCOV_EXCL_START */ +/* Check assumptions we expect to hold true */ +void assert_bip32_assumptions(void) +{ +#define key_off(member) offsetof(struct ext_key, member) +#define key_size(member) sizeof(((struct ext_key *)0)->member) + + /* Our ripend buffers must be uint32_t aligned and the correct size */ + BUILD_ASSERT(key_off(parent160) % sizeof(uint32_t) == 0); + BUILD_ASSERT(key_off(hash160) % sizeof(uint32_t) == 0); + BUILD_ASSERT(key_size(parent160) == sizeof(struct ripemd160)); + BUILD_ASSERT(key_size(hash160) == sizeof(struct ripemd160)); + BUILD_ASSERT(key_size(priv_key) == EC_PRIVATE_KEY_LEN + 1); + + /* Our keys following the parity byte must be uint64_t aligned */ + BUILD_ASSERT((key_off(priv_key) + 1) % sizeof(uint64_t) == 0); + BUILD_ASSERT((key_off(pub_key) + 1) % sizeof(uint64_t) == 0); + + /* child_num must be contigous after priv_key */ + BUILD_ASSERT((key_off(priv_key) + key_size(priv_key)) == key_off(child_num)); + + /* We use priv_key[0] to determine if this extended key is public or + * private, If priv_key[0] is BIP32_FLAG_KEY_PRIVATE then this key is private + * with a computed public key present. If set to BIP32_FLAG_KEY_PUBLIC then + * this is a public key with no private key (A BIP32 'neutered' key). + * + * For this to work BIP32_FLAG_KEY_PRIVATE must be zero so the whole 33 byte + * private key is valid when serialized, and BIP32_FLAG_KEY_PUBLIC cannot be + * 2 or 3 as they are valid parity bytes for public keys. + */ + BUILD_ASSERT(BIP32_FLAG_KEY_PRIVATE == 0); + BUILD_ASSERT(BIP32_FLAG_KEY_PUBLIC != BIP32_FLAG_KEY_PRIVATE && + BIP32_FLAG_KEY_PUBLIC != 2u && + BIP32_FLAG_KEY_PUBLIC != 3u); +} +/* LCOV_EXCL_STOP */ + +static bool mem_is_zero(const void *mem, size_t len) +{ + size_t i; + for (i = 0; i < len; ++i) + if (((const unsigned char *)mem)[i]) + return false; + return true; +} + +static bool child_is_hardened(uint32_t child_num) +{ + return child_num >= BIP32_INITIAL_HARDENED_CHILD; +} + +static bool version_is_valid(uint32_t ver, uint32_t flags) +{ + if (ver == BIP32_VER_MAIN_PRIVATE || ver == BIP32_VER_TEST_PRIVATE) + return true; + + return flags == BIP32_FLAG_KEY_PUBLIC && + (ver == BIP32_VER_MAIN_PUBLIC || ver == BIP32_VER_TEST_PUBLIC); +} + +static bool version_is_mainnet(uint32_t ver) +{ + return ver == BIP32_VER_MAIN_PRIVATE || ver == BIP32_VER_MAIN_PUBLIC; +} + +static bool key_is_private(const struct ext_key *hdkey) +{ + return hdkey->priv_key[0] == BIP32_FLAG_KEY_PRIVATE; +} + +static void key_strip_private_key(struct ext_key *key_out) +{ + key_out->priv_key[0] = BIP32_FLAG_KEY_PUBLIC; + memclear(key_out->priv_key + 1, sizeof(key_out->priv_key) - 1); +} + +/* Compute a public key from a private key */ +static int key_compute_pub_key(const secp256k1_context *ctx, + struct ext_key *key_out) +{ + return wally_ec_public_key_from_private_key(ctx, + key_out->priv_key + 1, + EC_PRIVATE_KEY_LEN, + key_out->pub_key, + sizeof(key_out->pub_key)); +} + +static void key_compute_hash160(struct ext_key *key_out) +{ + wally_hash160(key_out->pub_key, sizeof(key_out->pub_key), + key_out->hash160, sizeof(key_out->hash160)); +} + +int bip32_key_free(const struct ext_key *hdkey) +{ + if (!hdkey) + return WALLY_EINVAL; + memclear((void *)hdkey, sizeof(*hdkey)); + free((void *)hdkey); + return WALLY_OK; +} + +static bool is_valid_seed_len(size_t len) { + return len == BIP32_ENTROPY_LEN_512 || len == BIP32_ENTROPY_LEN_256 || + len == BIP32_ENTROPY_LEN_128; +} + +int bip32_key_from_seed( + const secp256k1_context *ctx, + const unsigned char *bytes, size_t bytes_len, + uint32_t version, uint32_t flags, + struct ext_key *key_out) +{ + struct hmac_sha512 hmac; + + if (!bytes || !is_valid_seed_len(bytes_len) || + !version_is_valid(version, BIP32_FLAG_KEY_PRIVATE) || + (flags & ~BIP32_FLAG_SKIP_HASH) || !key_out) + { + return WALLY_EINVAL; + } + + memclear(key_out, sizeof(*key_out)); + key_out->version = version; + + /* Generate private key and chain code */ + hmac_sha512(&hmac, SEED, sizeof(SEED), bytes, bytes_len); + + /* Check that the generated private key is valid */ + if (!secp256k1_ec_seckey_verify(ctx, hmac.sha.u.u8)) { + memclear(&hmac, sizeof(hmac)); + return WALLY_ERROR; /* Invalid private key */ + } + + /* Copy the private key and set its prefix */ + key_out->priv_key[0] = BIP32_FLAG_KEY_PRIVATE; + memcpy(key_out->priv_key + 1, hmac.sha.u.u8, sizeof(hmac) / 2); + if (key_compute_pub_key(ctx, key_out) != WALLY_OK) { + memclear(&hmac, sizeof(hmac)); + memclear(key_out, sizeof(*key_out)); + printf("\n"); + return WALLY_EINVAL; + } + + /* Copy the chain code */ + memcpy(key_out->chain_code, hmac.sha.u.u8 + sizeof(hmac.sha) / 2, + sizeof(hmac.sha) / 2); + + key_out->depth = 0; /* Master key, depth 0 */ + key_out->child_num = 0; + if (!(flags & BIP32_FLAG_SKIP_HASH)) + key_compute_hash160(key_out); + memclear(&hmac, sizeof(hmac)); + return WALLY_OK; +} + +#define ALLOC_KEY() \ + if (!output) \ + return WALLY_EINVAL; \ + *output = malloc(sizeof(struct ext_key)); \ + if (!*output) \ + return WALLY_ENOMEM; \ + memclear((void *)*output, sizeof(struct ext_key)) + +int bip32_key_from_seed_alloc(const secp256k1_context *ctx, + const unsigned char *bytes, size_t bytes_len, + uint32_t version, uint32_t flags, + struct ext_key **output) +{ + int ret; + + ALLOC_KEY(); + ret = bip32_key_from_seed(ctx, bytes, bytes_len, version, flags, *output); + if (ret != WALLY_OK) { + free((void *)*output); + *output = NULL; + } + return ret; +} + +static unsigned char *copy_out(unsigned char *dest, + const void *src, size_t len) +{ + memcpy(dest, src, len); + return dest + len; +} + +static bool key_is_valid(const struct ext_key *hdkey) +{ + bool is_private = key_is_private(hdkey); + bool is_master = !hdkey->depth; + int8_t ver_flags = is_private ? BIP32_FLAG_KEY_PRIVATE : BIP32_FLAG_KEY_PUBLIC; + + if (!version_is_valid(hdkey->version, ver_flags)) { + return false; + } + + if (mem_is_zero(hdkey->chain_code, sizeof(hdkey->chain_code)) || + (hdkey->pub_key[0] != 0x2 && hdkey->pub_key[0] != 0x3) || + mem_is_zero(hdkey->pub_key + 1, sizeof(hdkey->pub_key) - 1)) + return false; + + if (hdkey->priv_key[0] != BIP32_FLAG_KEY_PUBLIC && + hdkey->priv_key[0] != BIP32_FLAG_KEY_PRIVATE) + return false; + + if (is_private && + mem_is_zero(hdkey->priv_key + 1, sizeof(hdkey->priv_key) - 1)) + return false; + + if (is_master && + !mem_is_zero(hdkey->parent160, sizeof(hdkey->parent160))) + return false; + + return true; +} + +int bip32_key_serialize(const struct ext_key *hdkey, uint32_t flags, + unsigned char *bytes_out, size_t len) +{ + const bool serialize_private = !(flags & BIP32_FLAG_KEY_PUBLIC); + unsigned char *out = bytes_out; + uint32_t tmp32; + beint32_t tmp32_be; + + if (flags & ~BIP32_FLAG_KEY_PUBLIC) + return WALLY_EINVAL; /* Only this flag makes sense here */ + + /* Validate our arguments and then the input key */ + if (!hdkey || + (serialize_private && !key_is_private(hdkey)) || + !key_is_valid(hdkey) || + !bytes_out || len != BIP32_SERIALIZED_LEN) + return WALLY_EINVAL; + + + tmp32 = hdkey->version; + if (!serialize_private) { + /* Change version if serializing the public part of a private key */ + if (tmp32 == BIP32_VER_MAIN_PRIVATE) + tmp32 = BIP32_VER_MAIN_PUBLIC; + else if (tmp32 == BIP32_VER_TEST_PRIVATE) + tmp32 = BIP32_VER_TEST_PUBLIC; + } + tmp32_be = cpu_to_be32(tmp32); + out = copy_out(out, &tmp32_be, sizeof(tmp32_be)); + + *out++ = hdkey->depth; + + /* Save the first 32 bits of the parent key (aka fingerprint) only */ + out = copy_out(out, hdkey->parent160, sizeof(uint32_t)); + + + tmp32_be = cpu_to_be32(hdkey->child_num); + out = copy_out(out, &tmp32_be, sizeof(tmp32_be)); + + out = copy_out(out, hdkey->chain_code, sizeof(hdkey->chain_code)); + + if (serialize_private) + copy_out(out, hdkey->priv_key, sizeof(hdkey->priv_key)); + else + copy_out(out, hdkey->pub_key, sizeof(hdkey->pub_key)); + + return WALLY_OK; +} + +static const unsigned char *copy_in(void *dest, + const unsigned char *src, size_t len) +{ + memcpy(dest, src, len); + return src + len; +} + +/* Wipe a key and return failure for the caller to propigate */ +static int wipe_key_fail(struct ext_key *key_out) +{ + memclear(key_out, sizeof(*key_out)); + return WALLY_EINVAL; +} + +int bip32_key_unserialize(const secp256k1_context *ctx, + const unsigned char *bytes, size_t bytes_len, + struct ext_key *key_out) +{ + if (!bytes || bytes_len != BIP32_SERIALIZED_LEN || !key_out) + return WALLY_EINVAL; + + memclear(key_out, sizeof(*key_out)); + + bytes = copy_in(&key_out->version, bytes, sizeof(key_out->version)); + key_out->version = be32_to_cpu(key_out->version); + if (!version_is_valid(key_out->version, BIP32_FLAG_KEY_PUBLIC)) + return wipe_key_fail(key_out); + + bytes = copy_in(&key_out->depth, bytes, sizeof(key_out->depth)); + + /* We only have a partial fingerprint available. Copy it, but the + * user will need to call bip32_key_set_parent() (FIXME: Implement) + * later if they want it to be fully populated. + */ + bytes = copy_in(key_out->parent160, bytes, sizeof(uint32_t)); + bytes = copy_in(&key_out->child_num, bytes, sizeof(key_out->child_num)); + key_out->child_num = be32_to_cpu(key_out->child_num); + bytes = copy_in(key_out->chain_code, bytes, sizeof(key_out->chain_code)); + + if (bytes[0] == BIP32_FLAG_KEY_PRIVATE) { + if (key_out->version == BIP32_VER_MAIN_PUBLIC || + key_out->version == BIP32_VER_TEST_PUBLIC) + return wipe_key_fail(key_out); /* Private key data in public key */ + + copy_in(key_out->priv_key, bytes, sizeof(key_out->priv_key)); + if (key_compute_pub_key(ctx, key_out) != WALLY_OK) + return wipe_key_fail(key_out); + } else { + if (key_out->version == BIP32_VER_MAIN_PRIVATE || + key_out->version == BIP32_VER_TEST_PRIVATE) + return wipe_key_fail(key_out); /* Public key data in private key */ + + copy_in(key_out->pub_key, bytes, sizeof(key_out->pub_key)); + key_strip_private_key(key_out); + } + + key_compute_hash160(key_out); + return WALLY_OK; +} + +int bip32_key_unserialize_alloc( + const secp256k1_context *ctx, + const unsigned char *bytes, + size_t bytes_len, struct ext_key **output) +{ + int ret; + + ALLOC_KEY(); + ret = bip32_key_unserialize(ctx, bytes, bytes_len, *output); + if (ret) { + free(*output); + *output = 0; + } + return ret; +} + +/* BIP32: Child Key Derivations + * + * The spec doesn't have a simple table of derivations, its: + * + * Parent Child Hardened Status Path In Spec + * private private no OK m/n Y + * private private yes OK m/nH Y + * private public no OK - N + * private public yes OK - N + * public private no FAIL (N/A) (N/A) + * public private yes FAIL (N/A) (N/A) + * public public no OK M/n N + * public public yes FAIL M/nH (N/A) + * + * The spec path nomenclature only expresses derivations where the parent + * and desired child type match. For private->public the derivation is + * described in terms of private-private and public->public, but there are + * no test vectors or paths describing these values to validate against. + * Further, there are no public-public vectors in the BIP32 spec either. + */ +int bip32_key_from_parent(const secp256k1_context *ctx, + const struct ext_key *hdkey, + uint32_t child_num, uint32_t flags, + struct ext_key *key_out) +{ + struct hmac_sha512 hmac; + const bool we_are_private = hdkey && key_is_private(hdkey); + const bool derive_private = !(flags & BIP32_FLAG_KEY_PUBLIC); + const bool hardened = child_is_hardened(child_num); + + if (flags & ~BIP32_ALL_DEFINED_FLAGS) + return WALLY_EINVAL; /* These flags are not defined yet */ + + if (!hdkey || !key_out) + return WALLY_EINVAL; + + if (!we_are_private && (derive_private || hardened)) + return wipe_key_fail(key_out); /* Unsupported derivation */ + + if (hdkey->depth == 0xff) + return wipe_key_fail(key_out); /* Maximum depth reached */ + + /* + * Private parent -> private child: + * CKDpriv((kpar, cpar), i) -> (ki, ci) + * + * Private parent -> public child: + * N(CKDpriv((kpar, cpar), i) -> (ki, ci)) + * As we always calculate the public key, we can derive a public + * child by deriving a private one and stripping its private key. + * + * Public parent -> non hardened public child + * CKDpub((Kpar, cpar), i) -> (Ki, ci) + */ + + /* NB: We use the key_outs' priv_key+child_num to hold 'Data' here */ + if (hardened) { + /* Hardened: Data = 0x00 || ser256(kpar) || ser32(i)) */ + memcpy(key_out->priv_key, hdkey->priv_key, sizeof(hdkey->priv_key)); + } else { + /* Non Hardened Private: Data = serP(point(kpar)) || ser32(i) + * Non Hardened Public : Data = serP(kpar) || ser32(i) + * point(kpar) when par is private is the public key. + */ + memcpy(key_out->priv_key, hdkey->pub_key, sizeof(hdkey->pub_key)); + } + + /* This is the '|| ser32(i)' part of the above */ + key_out->child_num = cpu_to_be32(child_num); + + /* I = HMAC-SHA512(Key = cpar, Data) */ + hmac_sha512(&hmac, hdkey->chain_code, sizeof(hdkey->chain_code), + key_out->priv_key, + sizeof(key_out->priv_key) + sizeof(key_out->child_num)); + + /* Split I into two 32-byte sequences, IL and IR + * The returned chain code ci is IR (i.e. the 2nd half of our hmac sha512) + */ + memcpy(key_out->chain_code, hmac.sha.u.u8 + sizeof(hmac.sha) / 2, + sizeof(key_out->chain_code)); + + if (we_are_private) { + /* The returned child key ki is parse256(IL) + kpar (mod n) + * In case parse256(IL) ≥ n or ki = 0, the resulting key is invalid + * (NOTE: privkey_tweak_add checks both conditions) + */ + memcpy(key_out->priv_key, hdkey->priv_key, sizeof(hdkey->priv_key)); + if (!secp256k1_ec_privkey_tweak_add(ctx, key_out->priv_key + 1, + hmac.sha.u.u8)) { + memclear(&hmac.sha, sizeof(hmac.sha)); + return wipe_key_fail(key_out); /* Out of bounds FIXME: Iterate to the next? */ + } + + if (key_compute_pub_key(ctx, key_out) != WALLY_OK) { + memclear(&hmac.sha, sizeof(hmac.sha)); + return wipe_key_fail(key_out); + } + } else { + /* The returned child key ki is point(parse256(IL) + kpar) + * In case parse256(IL) ≥ n or Ki is the point at infinity, the + * resulting key is invalid (NOTE: pubkey_tweak_add checks both + * conditions) + */ + secp256k1_pubkey pub_key; + size_t len = sizeof(key_out->pub_key); + + /* FIXME: Out of bounds on pubkey_tweak_add */ + if (!secp256k1_ec_pubkey_parse(ctx, &pub_key, hdkey->pub_key, + sizeof(hdkey->pub_key)) || + + !secp256k1_ec_privkey_tweak_add(ctx, pub_key.data, + hmac.sha.u.u8) || + + !secp256k1_ec_pubkey_serialize(ctx, key_out->pub_key, + &len, &pub_key, + SECP256K1_EC_COMPRESSED) || + len != sizeof(key_out->pub_key)) { + memclear(&hmac.sha, sizeof(hmac.sha)); + return wipe_key_fail(key_out); + } + } + + if (derive_private) { + if (version_is_mainnet(hdkey->version)) + key_out->version = BIP32_VER_MAIN_PRIVATE; + else + key_out->version = BIP32_VER_TEST_PRIVATE; + + } else { + if (version_is_mainnet(hdkey->version)) + key_out->version = BIP32_VER_MAIN_PUBLIC; + else + key_out->version = BIP32_VER_TEST_PUBLIC; + + key_strip_private_key(key_out); + } + + key_out->depth = hdkey->depth + 1; + key_out->child_num = child_num; + if (flags & BIP32_FLAG_SKIP_HASH) { + memclear_2(&key_out->parent160, sizeof(key_out->parent160), + &key_out->hash160, sizeof(key_out->hash160)); + } + else { + memcpy(key_out->parent160, hdkey->hash160, sizeof(hdkey->hash160)); + key_compute_hash160(key_out); + } + memclear(&hmac.sha, sizeof(hmac.sha)); + return WALLY_OK; +} + +int bip32_key_from_parent_alloc( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + uint32_t child_num, uint32_t flags, + struct ext_key **output) +{ + int ret; + + ALLOC_KEY(); + ret = bip32_key_from_parent(ctx, hdkey, child_num, flags, *output); + if (ret) { + free(*output); + *output = 0; + } + return ret; +} + +int bip32_key_from_parent_path( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + const uint32_t *child_path, size_t child_path_len, + uint32_t flags, struct ext_key *key_out) +{ + /* Optimization: We can skip hash calculations for internal nodes */ + uint32_t derivation_flags = flags | BIP32_FLAG_SKIP_HASH; + struct ext_key tmp[2]; + size_t i, tmp_idx = 0; + int ret = WALLY_OK; + + if (flags & ~BIP32_ALL_DEFINED_FLAGS) + return WALLY_EINVAL; /* These flags are not defined yet */ + + if (!hdkey || !child_path || !child_path_len || !key_out) + return WALLY_EINVAL; + + for (i = 0; i < child_path_len; ++i) { + struct ext_key *derived = &tmp[tmp_idx]; + + if (i + 2 >= child_path_len) + derivation_flags = flags; /* Use callers flags for the final derivations */ + + ret = bip32_key_from_parent(ctx, hdkey, child_path[i], + derivation_flags, derived); + + if (ret != WALLY_OK) + break; + + hdkey = derived; /* Derived becomes next parent */ + tmp_idx = !tmp_idx; /* Use free slot in tmp for next derived */ + } + + if (ret == WALLY_OK) + memcpy(key_out, hdkey, sizeof(*key_out)); + + memclear(tmp, sizeof(tmp)); + return ret; +} + +int bip32_key_from_parent_path_alloc( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + const uint32_t *child_path, size_t child_path_len, + uint32_t flags, + struct ext_key **output) +{ + int ret; + + ALLOC_KEY(); + ret = bip32_key_from_parent_path(ctx, hdkey, child_path, + child_path_len, flags, *output); + if (ret) { + free(*output); + *output = 0; + } + return ret; +} + +int bip32_key_init_alloc( + const secp256k1_context *ctx, + uint32_t version, uint32_t depth, uint32_t child_num, + const unsigned char *chain_code, size_t chain_code_len, + const unsigned char *pub_key, size_t pub_key_len, + const unsigned char *priv_key, size_t priv_key_len, + const unsigned char *hash160, size_t hash160_len, + const unsigned char *parent160, size_t parent160_len, + struct ext_key **output) +{ + struct ext_key *key_out; + + if (!output) + return WALLY_EINVAL; + *output = NULL; + + switch (version) { + case BIP32_VER_MAIN_PRIVATE: + case BIP32_VER_TEST_PRIVATE: + if (!priv_key || priv_key_len != key_size(priv_key) - 1) + return WALLY_EINVAL; + break; + case BIP32_VER_MAIN_PUBLIC: + case BIP32_VER_TEST_PUBLIC: + if (!pub_key || pub_key_len != key_size(pub_key)) + return WALLY_EINVAL; + break; + } + + if (!chain_code || chain_code_len != key_size(chain_code)) + return WALLY_EINVAL; + + if ((priv_key && priv_key_len != key_size(priv_key) - 1) || (!priv_key && priv_key_len) || + (pub_key && pub_key_len != key_size(pub_key)) || (!pub_key && pub_key_len) || + (hash160 && hash160_len != key_size(hash160)) || (!hash160 && hash160_len) || + (parent160 && parent160_len != key_size(parent160))) + return WALLY_EINVAL; + + ALLOC_KEY(); + + key_out = *output; + key_out->version = version; + key_out->depth = depth; + key_out->child_num = child_num; + + memcpy(key_out->chain_code, chain_code, key_size(chain_code)); + if (priv_key && version != BIP32_VER_MAIN_PUBLIC && version != BIP32_VER_TEST_PUBLIC) + memcpy(key_out->priv_key + 1, priv_key, key_size(priv_key) - 1); + else + key_out->priv_key[0] = BIP32_FLAG_KEY_PUBLIC; + if (pub_key) + memcpy(key_out->pub_key, pub_key, key_size(pub_key)); + else if (version == BIP32_VER_MAIN_PRIVATE || version == BIP32_VER_TEST_PRIVATE) { + /* Compute the public key if not given */ + int ret = key_compute_pub_key(ctx, key_out); + if (ret != WALLY_OK) { + memclear(key_out, sizeof(*key_out)); + free(key_out); + *output = 0; + return ret; + } + } + if (hash160) + memcpy(key_out->hash160, hash160, key_size(hash160)); + else + key_compute_hash160(key_out); + if (parent160) + memcpy(key_out->parent160, parent160, key_size(parent160)); + + return WALLY_OK; +} + +int bip32_key_to_base58(const struct ext_key *hdkey, + uint32_t flags, + char **output) +{ + int ret; + unsigned char bytes[BIP32_SERIALIZED_LEN]; + + if ((ret = bip32_key_serialize(hdkey, flags, bytes, sizeof(bytes)))) + return ret; + + ret = wally_base58_from_bytes(bytes, BIP32_SERIALIZED_LEN, + BASE58_FLAG_CHECKSUM, output); + + memclear(bytes, sizeof(bytes)); + return ret; +} + +int bip32_key_from_base58( + const secp256k1_context *ctx, + const char *base58, + struct ext_key *output) +{ + int ret; + unsigned char bytes[BIP32_SERIALIZED_LEN + BASE58_CHECKSUM_LEN]; + size_t written; + + if ((ret = wally_base58_to_bytes(base58, BASE58_FLAG_CHECKSUM, bytes, sizeof(bytes), &written))) + return ret; + + if (written != BIP32_SERIALIZED_LEN) + ret = WALLY_EINVAL; + else + ret = bip32_key_unserialize(ctx, bytes, + BIP32_SERIALIZED_LEN, output); + + memclear(bytes, sizeof(bytes)); + return ret; +} + +int bip32_key_from_base58_alloc( + const secp256k1_context *ctx, + const char *base58, struct ext_key **output) +{ + int ret; + + ALLOC_KEY(); + ret = bip32_key_from_base58(ctx, base58, *output); + if (ret) { + free(*output); + *output = 0; + } + return ret; +} + +#if defined (SWIG_JAVA_BUILD) || defined (SWIG_PYTHON_BUILD) || defined (SWIG_JAVASCRIPT_BUILD) + +/* Getters for ext_key values */ + +static int getb_impl(const struct ext_key *hdkey, + const unsigned char *src, size_t src_len, + unsigned char *bytes_out, size_t len) +{ + if (!hdkey || !bytes_out || len != src_len) + return WALLY_EINVAL; + memcpy(bytes_out, src, len); + return WALLY_OK; +} + +#define GET_B(name) \ + int bip32_key_get_ ## name(const struct ext_key *hdkey, unsigned char *bytes_out, size_t len) { \ + return getb_impl(hdkey, hdkey->name, sizeof(hdkey->name), bytes_out, len); \ + } + +GET_B(chain_code) +GET_B(parent160) +GET_B(hash160) +GET_B(pub_key) + +int bip32_key_get_priv_key(const struct ext_key *hdkey, unsigned char *bytes_out, size_t len) { + return getb_impl(hdkey, hdkey->priv_key + 1, sizeof(hdkey->priv_key) - 1, bytes_out, len); +} + + +#define GET_I(name) \ + int bip32_key_get_ ## name(const struct ext_key *hdkey, size_t *written) { \ + if (written) *written = 0; \ + if (!hdkey || !written) return WALLY_EINVAL; \ + *written = hdkey->name; \ + return WALLY_OK; \ + } + +GET_I(depth) +GET_I(child_num) +GET_I(version) + +#endif /* SWIG_JAVA_BUILD/SWIG_PYTHON_BUILD */ diff --git a/bip32.h b/bip32.h @@ -0,0 +1,252 @@ + +#ifndef LIBWALLY_CORE_BIP32_H +#define LIBWALLY_CORE_BIP32_H + +#include <stdint.h> +#include "secp256k1.h" + +/** The required lengths of entropy for `bip32_key_from_seed` */ +#define BIP32_ENTROPY_LEN_128 16 +#define BIP32_ENTROPY_LEN_256 32 +#define BIP32_ENTROPY_LEN_512 64 + +/** Length of an ext_key serialized using BIP32 format */ +#define BIP32_SERIALIZED_LEN 78 + +/** Child number of the first hardened child */ +#define BIP32_INITIAL_HARDENED_CHILD 0x80000000 + +/** Indicate that we want to derive a private key in `bip32_key_from_parent` */ +#define BIP32_FLAG_KEY_PRIVATE 0x0 +/** Indicate that we want to derive a public key in `bip32_key_from_parent` */ +#define BIP32_FLAG_KEY_PUBLIC 0x1 +/** Indicate that we want to skip hash calculation when deriving a key in `bip32_key_from_parent` */ +#define BIP32_FLAG_SKIP_HASH 0x2 + +/** Version codes for extended keys */ +#define BIP32_VER_MAIN_PUBLIC 0x0488B21E +#define BIP32_VER_MAIN_PRIVATE 0x0488ADE4 +#define BIP32_VER_TEST_PUBLIC 0x043587CF +#define BIP32_VER_TEST_PRIVATE 0x04358394 + +/** An extended key */ +struct ext_key { + /** The chain code for this key */ + unsigned char chain_code[32]; + /** The Hash160 of this keys parent */ + unsigned char parent160[20]; + /** The depth of this key */ + uint8_t depth; + unsigned char pad1[10]; + /** The private key with prefix byte 0 */ + unsigned char priv_key[33]; + /** The child number of the parent key that this key represents */ + uint32_t child_num; + /** The Hash160 of this key */ + unsigned char hash160[20]; + /** The version code for this key indicating main/testnet and private/public */ + uint32_t version; + unsigned char pad2[3]; + /** The public key with prefix byte 0x2 or 0x3 */ + unsigned char pub_key[33]; +}; + +/** + * Free a key allocated by `bip32_key_from_seed_alloc` + * or `bip32_key_unserialize_alloc`. + * + * :param hdkey: Key to free. + */ +int bip32_key_free(const struct ext_key *hdkey); + +/** + */ + +int bip32_key_init_alloc( + const secp256k1_context *ctx, + uint32_t version, uint32_t depth, uint32_t child_num, + const unsigned char *chain_code, size_t chain_code_len, + const unsigned char *pub_key, size_t pub_key_len, + const unsigned char *priv_key, size_t priv_key_len, + const unsigned char *hash160, size_t hash160_len, + const unsigned char *parent160, size_t parent160_len, + struct ext_key **output + ); + + +/** + * Create a new master extended key from entropy. + * + * This creates a new master key, i.e. the root of a new HD tree. + * The entropy passed in may produce an invalid key. If this happens, + * WALLY_ERROR will be returned and the caller should retry with + * new entropy. + * + * :param bytes: Entropy to use. + * :param bytes_len: Size of ``bytes`` in bytes. Must be one of ``BIP32_ENTROPY_LEN_128``, + *| ``BIP32_ENTROPY_LEN_256`` or ``BIP32_ENTROPY_LEN_512``. + * :param version: Either ``BIP32_VER_MAIN_PRIVATE`` or ``BIP32_VER_TEST_PRIVATE``, + *| indicating mainnet or testnet/regtest respectively. + * :param flags: Either ``BIP32_FLAG_SKIP_HASH`` to skip hash160 calculation, or 0. + * :param output: Destination for the resulting master extended key. + */ +int bip32_key_from_seed( + const secp256k1_context *ctx, + const unsigned char *bytes, + size_t bytes_len, + uint32_t version, + uint32_t flags, + struct ext_key *output); + +/** + * As per `bip32_key_from_seed`, but allocates the key. + * + * .. note:: The returned key should be freed with `bip32_key_free`. + */ +int bip32_key_from_seed_alloc( + const secp256k1_context *ctx, + const unsigned char *bytes, + size_t bytes_len, + uint32_t version, + uint32_t flags, + struct ext_key **output); + +/** + * Serialize an extended key to memory using BIP32 format. + * + * :param hdkey: The extended key to serialize. + * :param flags: BIP32_FLAG_KEY_ Flags indicating which key to serialize. You can not + *| serialize a private extended key from a public extended key. + * :param bytes_out: Destination for the serialized key. + * :param len: Size of ``bytes_out`` in bytes. Must be ``BIP32_SERIALIZED_LEN``. + */ +int bip32_key_serialize( + const struct ext_key *hdkey, + uint32_t flags, + unsigned char *bytes_out, + size_t len); + + +/** + * Un-serialize an extended key from memory. + * + * :param bytes: Storage holding the serialized key. + * :param bytes_len: Size of ``bytes`` in bytes. Must be ``BIP32_SERIALIZED_LEN``. + * :param output: Destination for the resulting extended key. + */ +int bip32_key_unserialize( + const secp256k1_context *ctx, + const unsigned char *bytes, + size_t bytes_len, + struct ext_key *output); + +/** + * As per `bip32_key_unserialize`, but allocates the key. + * + * .. note:: The returned key should be freed with `bip32_key_free`. + */ +int bip32_key_unserialize_alloc( + const secp256k1_context *ctx, + const unsigned char *bytes, + size_t bytes_len, + struct ext_key **output); + +/** + * Create a new child extended key from a parent extended key. + * + * :param hdkey: The parent extended key. + * :param child_num: The child number to create. Numbers greater + *| than or equal to ``BIP32_INITIAL_HARDENED_CHILD`` represent + *| hardened keys that cannot be created from public parent + *| extended keys. + * :param flags: BIP32_FLAG_KEY_ Flags indicating the type of derivation wanted. + *| You can not derive a private child extended key from a public + *| parent extended key. + * :param output: Destination for the resulting child extended key. + */ +int bip32_key_from_parent( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + uint32_t child_num, + uint32_t flags, + struct ext_key *output); + +/** + * As per `bip32_key_from_parent`, but allocates the key. + * + * .. note:: The returned key should be freed with `bip32_key_free`. + */ +int bip32_key_from_parent_alloc( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + uint32_t child_num, + uint32_t flags, + struct ext_key **output); + +/** + * Create a new child extended key from a parent extended key and a path. + * + * :param hdkey: The parent extended key. + * :param child_path: The path of child numbers to create. + * :param child_path_len: The number of child numbers in ``child_path``. + * :param flags: BIP32_KEY_ Flags indicating the type of derivation wanted. + * :param output: Destination for the resulting child extended key. + */ +int bip32_key_from_parent_path( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + const uint32_t *child_path, + size_t child_path_len, + uint32_t flags, + struct ext_key *output); + +/** + * As per `bip32_key_from_parent_path`, but allocates the key. + * + * .. note:: The returned key should be freed with `bip32_key_free`. + */ +int bip32_key_from_parent_path_alloc( + const secp256k1_context *ctx, + const struct ext_key *hdkey, + const uint32_t *child_path, + size_t child_path_len, + uint32_t flags, + struct ext_key **output); + +/** + * Convert an extended key to base58. + * + * :param hdkey: The extended key. + * :param flags: BIP32_FLAG_KEY_ Flags indicating which key to serialize. You can not + *| serialize a private extended key from a public extended key. + * :param output: Destination for the resulting key in bas58. + */ +int bip32_key_to_base58( + const struct ext_key *hdkey, + uint32_t flags, + char **output); + +/** + * Convert a base58 encoded extended key to an extended key. + * + * :param wif: The extended key in base58. + * :param output: Destination for the resulting extended key. + */ + +int bip32_key_from_base58( + const secp256k1_context *ctx, + const char *base58, + struct ext_key *output); + +/** + * As per `bip32_key_from_base58`, but allocates the key. + * + * .. note:: The returned key should be freed with `bip32_key_free`. + */ +int bip32_key_from_base58_alloc( + const secp256k1_context *ctx, + const char *base58, struct ext_key **output); + +void assert_bip32_assumptions(void); + +#endif /* LIBWALLY_CORE_BIP32_H */ diff --git a/check.c b/check.c @@ -0,0 +1,11 @@ + +#include "bip32.h" +#include <stdio.h> + +int main() +{ + printf("asserting bip32 assumptions\n"); + assert_bip32_assumptions(); + printf("ok!\n"); + return 0; +} diff --git a/clightning-dumpkeys.c b/clightning-dumpkeys.c @@ -0,0 +1,160 @@ + +#include "short_types.h" +#include "hkdf.h" +#include "compiler.h" +#include "secp256k1.h" +#include "bip32.h" + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> + +#define BIP32_ENTROPY_LEN_256 32 + + +#define fatal(fmt, ...) do { fprintf(stderr, fmt "\n", __VA_ARGS__); exit(1); } while (0) +#define fatal1(...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0) + +/* General 256-bit secret, which must be private. Used in various places. */ +struct secret { + u8 data[32]; +}; + +static struct { + struct secret hsm_secret; + struct ext_key bip32; +} secretstuff; + +struct bip32_key_version { + u32 bip32_pubkey_version; + u32 bip32_privkey_version; +}; + + + +/* Version codes for BIP32 extended keys in libwally-core. + * It's not suitable to add this struct into client struct, + * so set it static.*/ +static struct bip32_key_version bip32_key_version; + +bool read_all(int fd, void *data, size_t size) +{ + while (size) { + ssize_t done; + + done = read(fd, data, size); + if (done < 0 && errno == EINTR) + continue; + if (done <= 0) + return false; + data = (char *)data + done; + size -= done; + } + + return true; +} + + + +static void populate_secretstuff(void) +{ + u8 bip32_seed[BIP32_ENTROPY_LEN_256]; + u32 salt = 0; + struct ext_key master_extkey, child_extkey; + const u32 flags = SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN; + secp256k1_context *ctx = secp256k1_context_create(flags); + + bip32_key_version = (struct bip32_key_version) { + .bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, + .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE + }; + + assert(bip32_key_version.bip32_pubkey_version == BIP32_VER_MAIN_PUBLIC + || bip32_key_version.bip32_pubkey_version == BIP32_VER_TEST_PUBLIC); + + assert(bip32_key_version.bip32_privkey_version == BIP32_VER_MAIN_PRIVATE + || bip32_key_version.bip32_privkey_version == BIP32_VER_TEST_PRIVATE); + + /* Fill in the BIP32 tree for bitcoin addresses. */ + /* In libwally-core, the version BIP32_VER_TEST_PRIVATE is for testnet/regtest, + * and BIP32_VER_MAIN_PRIVATE is for mainnet. For litecoin, we also set it like + * bitcoin else.*/ + do { + hkdf_sha256(bip32_seed, sizeof(bip32_seed), + &salt, sizeof(salt), + &secretstuff.hsm_secret, + sizeof(secretstuff.hsm_secret), + "bip32 seed", strlen("bip32 seed")); + salt++; + } while (bip32_key_from_seed(ctx, bip32_seed, sizeof(bip32_seed), + bip32_key_version.bip32_privkey_version, + 0, &master_extkey) != WALLY_OK); + + /* BIP 32: + * + * The default wallet layout + * + * An HDW is organized as several 'accounts'. Accounts are numbered, + * the default account ("") being number 0. Clients are not required + * to support more than one account - if not, they only use the + * default account. + * + * Each account is composed of two keypair chains: an internal and an + * external one. The external keychain is used to generate new public + * addresses, while the internal keychain is used for all other + * operations (change addresses, generation addresses, ..., anything + * that doesn't need to be communicated). Clients that do not support + * separate keychains for these should use the external one for + * everything. + * + * - m/iH/0/k corresponds to the k'th keypair of the external chain of + * account number i of the HDW derived from master m. + */ + /* Hence child 0, then child 0 again to get extkey to derive from. */ + if (bip32_key_from_parent(ctx, &master_extkey, 0, + BIP32_FLAG_KEY_PRIVATE, + &child_extkey) != WALLY_OK) + /*~ status_failed() is a helper which exits and sends lightningd + * a message about what happened. For hsmd, that's fatal to + * lightningd. */ + fatal1("Can't derive child bip32 key"); + + if (bip32_key_from_parent(ctx, &child_extkey, 0, + BIP32_FLAG_KEY_PRIVATE, + &secretstuff.bip32) != WALLY_OK) + fatal1("Can't derive private bip32 key"); +} + +static void load_hsm(const char *secretfile) +{ + int fd = open(secretfile ? secretfile : "hsm_secret", O_RDONLY); + if (fd < 0) + fatal("opening: %s", strerror(errno)); + if (!read_all(fd, &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret))) + fatal("reading: %s", strerror(errno)); + close(fd); + + populate_secretstuff(); +} + +void usage() +{ + fprintf(stderr, "usage: clightning-dumpkeys <hsmd_secretfile>\n"); + exit(42); +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) + usage(); + + const char *secretfile = argv[1]; + + assert_bip32_assumptions(); + load_hsm(secretfile); + + return 0; +} diff --git a/compiler.c b/compiler.c @@ -0,0 +1,12 @@ + +#include <stdlib.h> +#include "compiler.h" + +bool alignment_ok(const void *p, size_t n) +{ +#if HAVE_UNALIGNED_ACCESS + return true; +#else + return ((size_t)p % n == 0); +#endif +} diff --git a/compiler.h b/compiler.h @@ -0,0 +1,55 @@ + +#ifndef COMPILER_H +#define COMPILER_H + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +bool alignment_ok(const void *p, size_t n); + +#define UNUSED __attribute__((__unused__)) + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include <stddef.h> + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define memclear(mem, size) memset(mem, 0, size) +#define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); } +#define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); } +#define wally_clear memclear +#define wally_clear_2 memclear_2 +#define wally_clear_3 memclear_3 + +#endif /* COMPILER_H */ diff --git a/ec.c b/ec.c @@ -0,0 +1,30 @@ +/* from wally_core */ + +#include "ec.h" +#include <stdbool.h> +#include "short_types.h" +#include "compiler.h" + +int wally_ec_public_key_from_private_key( + const secp256k1_context *ctx, + const unsigned char *priv_key, size_t priv_key_len, + unsigned char *bytes_out, size_t len) +{ + secp256k1_pubkey pub; + size_t len_in_out = EC_PUBLIC_KEY_LEN; + bool ok; + + if (!ctx) + return WALLY_ENOMEM; + + ok = priv_key && priv_key_len == EC_PRIVATE_KEY_LEN && + bytes_out && len == EC_PUBLIC_KEY_LEN && + secp256k1_ec_pubkey_create(ctx, &pub, priv_key) && + secp256k1_ec_pubkey_serialize(ctx, bytes_out, &len_in_out, &pub, SECP256K1_EC_COMPRESSED) && + len_in_out == EC_PUBLIC_KEY_LEN; + + if (!ok && bytes_out) + memclear(bytes_out, len); + memclear(&pub, sizeof(pub)); + return ok ? WALLY_OK : WALLY_EINVAL; +} diff --git a/ec.h b/ec.h @@ -0,0 +1,34 @@ + +#ifndef EC_H +#define EC_H + +#include <stdlib.h> +#include "secp256k1.h" + +/** The length of a private key used for EC signing */ +#define EC_PRIVATE_KEY_LEN 32 +/** The length of a public key used for EC signing */ +#define EC_PUBLIC_KEY_LEN 33 +/** The length of an uncompressed public key */ +#define EC_PUBLIC_KEY_UNCOMPRESSED_LEN 65 +/** The length of a message hash to EC sign */ +#define EC_MESSAGE_HASH_LEN 32 +/** The length of a compact signature produced by EC signing */ +#define EC_SIGNATURE_LEN 64 +/** The maximum encoded length of a DER encoded signature */ +#define EC_SIGNATURE_DER_MAX_LEN 72 +/** The maximum encoded length of a DER encoded signature created with EC_FLAG_GRIND_R */ +#define EC_SIGNATURE_DER_MAX_LOW_R_LEN 71 + +/** Indicates that a signature using ECDSA/secp256k1 is required */ +#define EC_FLAG_ECDSA 0x1 +/** Indicates that a signature using EC-Schnorr-SHA256 is required */ +#define EC_FLAG_SCHNORR 0x2 +/** Indicates that the signature nonce should be incremented until the signature is low-R */ +#define EC_FLAG_GRIND_R 0x4 + +int wally_ec_public_key_from_private_key( + const secp256k1_context *ctx, const unsigned char *priv_key, + size_t priv_key_len, unsigned char *bytes_out, size_t len); + +#endif /* EC_H */ diff --git a/endian.h b/endian.h @@ -0,0 +1,360 @@ +/* CC0 (Public domain) */ +#ifndef CCAN_ENDIAN_H +#define CCAN_ENDIAN_H +#include <stdint.h> + +/** + * BSWAP_16 - reverse bytes in a constant uint16_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_16(0x1234)]; + * }; + */ +#define BSWAP_16(val) \ + ((((uint16_t)(val) & 0x00ff) << 8) \ + | (((uint16_t)(val) & 0xff00) >> 8)) + +/** + * BSWAP_32 - reverse bytes in a constant uint32_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_32(0xff000000)]; + * }; + */ +#define BSWAP_32(val) \ + ((((uint32_t)(val) & 0x000000ff) << 24) \ + | (((uint32_t)(val) & 0x0000ff00) << 8) \ + | (((uint32_t)(val) & 0x00ff0000) >> 8) \ + | (((uint32_t)(val) & 0xff000000) >> 24)) + +/** + * BSWAP_64 - reverse bytes in a constant uint64_t value. + * @val: constantvalue whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_64(0xff00000000000000ULL)]; + * }; + */ +#define BSWAP_64(val) \ + ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ + | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ + | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ + | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ + | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ + | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ + | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ + | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) + +#if HAVE_BYTESWAP_H +#include <byteswap.h> +#else +/** + * bswap_16 - reverse bytes in a uint16_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 4 as two bytes reversed" + * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); + */ +static inline uint16_t bswap_16(uint16_t val) +{ + return BSWAP_16(val); +} + +/** + * bswap_32 - reverse bytes in a uint32_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 262144 as four bytes reversed" + * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); + */ +static inline uint32_t bswap_32(uint32_t val) +{ + return BSWAP_32(val); +} +#endif /* !HAVE_BYTESWAP_H */ + +#if !HAVE_BSWAP_64 +/** + * bswap_64 - reverse bytes in a uint64_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 1125899906842624 as eight bytes reversed" + * printf("1024 is %llu as eight bytes reversed\n", + * (unsigned long long)bswap_64(1024)); + */ +static inline uint64_t bswap_64(uint64_t val) +{ + return BSWAP_64(val); +} +#endif + +/* Needed for Glibc like endiness check */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +/* Sanity check the defines. We don't handle weird endianness. */ +#if HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN +#error "Can't compile for both big and little endian." +#elif HAVE_LITTLE_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif __BYTE_ORDER != __LITTLE_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" +#endif +#elif HAVE_BIG_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#elif __BYTE_ORDER != __BIG_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" +#endif +#endif + + +#ifdef __CHECKER__ +/* sparse needs forcing to remove bitwise attribute from ccan/short_types */ +#define ENDIAN_CAST __attribute__((force)) +#define ENDIAN_TYPE __attribute__((bitwise)) +#else +#define ENDIAN_CAST +#define ENDIAN_TYPE +#endif + +typedef uint64_t ENDIAN_TYPE leint64_t; +typedef uint64_t ENDIAN_TYPE beint64_t; +typedef uint32_t ENDIAN_TYPE leint32_t; +typedef uint32_t ENDIAN_TYPE beint32_t; +typedef uint16_t ENDIAN_TYPE leint16_t; +typedef uint16_t ENDIAN_TYPE beint16_t; + +#if HAVE_LITTLE_ENDIAN +/** + * CPU_TO_LE64 - convert a constant uint64_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) + +/** + * CPU_TO_LE32 - convert a constant uint32_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) + +/** + * CPU_TO_LE16 - convert a constant uint16_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) + +/** + * LE64_TO_CPU - convert a little-endian uint64_t constant + * @le_val: little-endian constant to convert + */ +#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * LE32_TO_CPU - convert a little-endian uint32_t constant + * @le_val: little-endian constant to convert + */ +#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * LE16_TO_CPU - convert a little-endian uint16_t constant + * @le_val: little-endian constant to convert + */ +#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_BIG_ENDIAN */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) +#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_BIG_ENDIAN */ + +#if HAVE_BIG_ENDIAN +/** + * CPU_TO_BE64 - convert a constant uint64_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) + +/** + * CPU_TO_BE32 - convert a constant uint32_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) + +/** + * CPU_TO_BE16 - convert a constant uint16_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) + +/** + * BE64_TO_CPU - convert a big-endian uint64_t constant + * @le_val: big-endian constant to convert + */ +#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * BE32_TO_CPU - convert a big-endian uint32_t constant + * @le_val: big-endian constant to convert + */ +#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * BE16_TO_CPU - convert a big-endian uint16_t constant + * @le_val: big-endian constant to convert + */ +#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_LITTLE_ENDIAN */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) +#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_LITTE_ENDIAN */ + + +/** + * cpu_to_le64 - convert a uint64_t value to little-endian + * @native: value to convert + */ +static inline leint64_t cpu_to_le64(uint64_t native) +{ + return CPU_TO_LE64(native); +} + +/** + * cpu_to_le32 - convert a uint32_t value to little-endian + * @native: value to convert + */ +static inline leint32_t cpu_to_le32(uint32_t native) +{ + return CPU_TO_LE32(native); +} + +/** + * cpu_to_le16 - convert a uint16_t value to little-endian + * @native: value to convert + */ +static inline leint16_t cpu_to_le16(uint16_t native) +{ + return CPU_TO_LE16(native); +} + +/** + * le64_to_cpu - convert a little-endian uint64_t value + * @le_val: little-endian value to convert + */ +static inline uint64_t le64_to_cpu(leint64_t le_val) +{ + return LE64_TO_CPU(le_val); +} + +/** + * le32_to_cpu - convert a little-endian uint32_t value + * @le_val: little-endian value to convert + */ +static inline uint32_t le32_to_cpu(leint32_t le_val) +{ + return LE32_TO_CPU(le_val); +} + +/** + * le16_to_cpu - convert a little-endian uint16_t value + * @le_val: little-endian value to convert + */ +static inline uint16_t le16_to_cpu(leint16_t le_val) +{ + return LE16_TO_CPU(le_val); +} + +/** + * cpu_to_be64 - convert a uint64_t value to big endian. + * @native: value to convert + */ +static inline beint64_t cpu_to_be64(uint64_t native) +{ + return CPU_TO_BE64(native); +} + +/** + * cpu_to_be32 - convert a uint32_t value to big endian. + * @native: value to convert + */ +static inline beint32_t cpu_to_be32(uint32_t native) +{ + return CPU_TO_BE32(native); +} + +/** + * cpu_to_be16 - convert a uint16_t value to big endian. + * @native: value to convert + */ +static inline beint16_t cpu_to_be16(uint16_t native) +{ + return CPU_TO_BE16(native); +} + +/** + * be64_to_cpu - convert a big-endian uint64_t value + * @be_val: big-endian value to convert + */ +static inline uint64_t be64_to_cpu(beint64_t be_val) +{ + return BE64_TO_CPU(be_val); +} + +/** + * be32_to_cpu - convert a big-endian uint32_t value + * @be_val: big-endian value to convert + */ +static inline uint32_t be32_to_cpu(beint32_t be_val) +{ + return BE32_TO_CPU(be_val); +} + +/** + * be16_to_cpu - convert a big-endian uint16_t value + * @be_val: big-endian value to convert + */ +static inline uint16_t be16_to_cpu(beint16_t be_val) +{ + return BE16_TO_CPU(be_val); +} + +/* Whichever they include first, they get these definitions. */ +#ifdef CCAN_SHORT_TYPES_H +/** + * be64/be32/be16 - 64/32/16 bit big-endian representation. + */ +typedef beint64_t be64; +typedef beint32_t be32; +typedef beint16_t be16; + +/** + * le64/le32/le16 - 64/32/16 bit little-endian representation. + */ +typedef leint64_t le64; +typedef leint32_t le32; +typedef leint16_t le16; +#endif +#endif /* CCAN_ENDIAN_H */ diff --git a/hash.c b/hash.c @@ -0,0 +1,28 @@ + +#include "ripemd160.h" +#include "sha256.h" +#include "compiler.h" +#include "hash.h" + +int wally_hash160(const unsigned char *bytes, size_t bytes_len, + unsigned char *bytes_out, size_t len) +{ + struct sha256 sha; + struct ripemd160 ripemd; + bool aligned = alignment_ok(bytes_out, sizeof(ripemd.u.u32)); + + if (!bytes || !bytes_out || len != HASH160_LEN) + return 0; + + BUILD_ASSERT(sizeof(ripemd) == HASH160_LEN); + + sha256(&sha, bytes, bytes_len); + ripemd160(aligned ? (struct ripemd160 *)bytes_out : &ripemd, &sha, sizeof(sha)); + if (!aligned) { + memcpy(bytes_out, &ripemd, sizeof(ripemd)); + memclear(&ripemd, sizeof(ripemd)); + } + memclear(&sha, sizeof(sha)); + return 1; +} + diff --git a/hash.h b/hash.h @@ -0,0 +1,13 @@ + +#ifndef HASH_H +#define HASH_H + +#include <stdlib.h> + +/** Output length for `wally_hash160` */ +#define HASH160_LEN 20 + +int wally_hash160(const unsigned char *bytes, size_t bytes_len, + unsigned char *bytes_out, size_t len); + +#endif /* HASH_H */ diff --git a/hkdf.c b/hkdf.c @@ -0,0 +1,98 @@ + +/* MIT (BSD) license - see LICENSE file for details */ +#include "hmac.h" +#include "sha256.h" +#include <assert.h> +#include <string.h> + +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize) +{ + struct hmac_sha256 prk, t; + struct hmac_sha256_ctx ctx; + unsigned char c; + + assert(okm_size < 255 * sizeof(t)); + + /* RFC 5869: + * + * 2.2. Step 1: Extract + * + * HKDF-Extract(salt, IKM) -> PRK + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * salt optional salt value (a non-secret random value); + * if not provided, it is set to a string of HashLen zeros. + * IKM input keying material + * + * Output: + * PRK a pseudorandom key (of HashLen octets) + * + * The output PRK is calculated as follows: + * + * PRK = HMAC-Hash(salt, IKM) + */ + hmac_sha256(&prk, s, ssize, k, ksize); + + /* + * 2.3. Step 2: Expand + * + * HKDF-Expand(PRK, info, L) -> OKM + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * PRK a pseudorandom key of at least HashLen octets + * (usually, the output from the extract step) + * info optional context and application specific information + * (can be a zero-length string) + * L length of output keying material in octets + * (<= 255*HashLen) + * + * Output: + * OKM output keying material (of L octets) + * + * The output OKM is calculated as follows: + * + * N = ceil(L/HashLen) + * T = T(1) | T(2) | T(3) | ... | T(N) + * OKM = first L octets of T + * + * where: + * T(0) = empty string (zero length) + * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + * ... + * + * (where the constant concatenated to the end of each T(n) is a + * single octet.) + */ + c = 1; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + + while (okm_size > sizeof(t)) { + memcpy(okm, &t, sizeof(t)); + okm = (char *)okm + sizeof(t); + okm_size -= sizeof(t); + + c++; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, &t, sizeof(t)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + } + memcpy(okm, &t, okm_size); +} diff --git a/hkdf.h b/hkdf.h @@ -0,0 +1,22 @@ + +#ifndef CCAN_CRYPTO_HKDF_SHA256_H +#define CCAN_CRYPTO_HKDF_SHA256_H +/* BSD-MIT - see LICENSE file for details */ +#include <stdlib.h> + +/** + * hkdf_sha256 - generate a derived key + * @okm: where to output the key + * @okm_size: the number of bytes pointed to by @okm (must be less than 255*32) + * @s: salt + * @ssize: the number of bytes pointed to by @s + * @k: pointer to input key + * @ksize: the number of bytes pointed to by @k + * @info: pointer to info + * @isize: the number of bytes pointed to by @info + */ +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize); +#endif /* CCAN_CRYPTO_HKDF_SHA256_H */ diff --git a/hmac.c b/hmac.c @@ -0,0 +1,248 @@ + +#include <string.h> +#include "hmac.h" + +#define IPAD 0x3636363636363636ULL +#define OPAD 0x5C5C5C5C5C5C5C5CULL + +#define BLOCK_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)) + +static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad) +{ + size_t i; + + for (i = 0; i < BLOCK_U64S; i++) + block[i] ^= pad; +} + +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha256 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA256_BLOCKSIZE) { + sha256(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha512 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA512_BLOCKSIZE) { + sha512(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA512_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, k_ipad, HMAC_SHA512_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size) +{ + /* This is the appending-text part of this: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_update(&ctx->sha, p, size); +} + + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, const void *p, size_t size) +{ + sha512_update(&ctx->sha, p, size); +} + + +void hmac_sha256_done(struct hmac_sha256_ctx *ctx, + struct hmac_sha256 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha256_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha256_done(&ctx->sha, &hmac->sha); +} + + +void hmac_sha512_done(struct hmac_sha512_ctx *ctx, + struct hmac_sha512 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha512_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha512_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha512_done(&ctx->sha, &hmac->sha); +} + +#if 1 +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha256_ctx ctx; + + hmac_sha256_init(&ctx, k, ksize); + hmac_sha256_update(&ctx, d, dsize); + hmac_sha256_done(&ctx, hmac); +} + + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha512_ctx ctx; + + hmac_sha512_init(&ctx, k, ksize); + hmac_sha512_update(&ctx, d, dsize); + hmac_sha512_done(&ctx, hmac); +} + + +#else +/* Direct mapping from MD5 example in RFC2104 */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *key, size_t key_len, + const void *text, size_t text_len) +{ + struct sha256_ctx context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + *//* start out by storing key in pads */ + unsigned char tk[32]; + int i; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + struct sha256_ctx tctx; + + sha256_init(&tctx); + sha256_update(&tctx, key, key_len); + sha256_done(&tctx, tk); + + key = tk; + key_len = 32; + } + bzero( k_ipad, sizeof k_ipad); + bzero( k_opad, sizeof k_opad); + bcopy( key, k_ipad, key_len); + bcopy( key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + sha256_init(&context); /* init context for 1st + * pass */ + sha256_update(&context, k_ipad, 64); /* start with inner pad */ + sha256_update(&context, text, text_len); /* then text of datagram */ + sha256_done(&context, &hmac->sha); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + sha256_init(&context); /* init context for 2nd + * pass */ + sha256_update(&context, k_opad, 64); /* start with outer pad */ + sha256_update(&context, &hmac->sha, 32); /* then results of 1st + * hash */ + sha256_done(&context, &hmac->sha); /* finish up 2nd pass */ +} +#endif diff --git a/hmac.h b/hmac.h @@ -0,0 +1,116 @@ + +#ifndef CCAN_CRYPTO_HMAC_SHA256_H +#define CCAN_CRYPTO_HMAC_SHA256_H +/* BSD-MIT */ +#include <stdint.h> +#include <stdlib.h> +#include "sha256.h" +#include "sha512.h" + +/* Number of bytes per block. */ +#define HMAC_SHA256_BLOCKSIZE 64 +#define HMAC_SHA512_BLOCKSIZE 128 + +/** + * struct hmac_sha256 - structure representing a completed HMAC. + */ +struct hmac_sha256 { + struct sha256 sha; +}; + + +struct hmac_sha512 { + struct sha512 sha; +}; + +/** + * hmac_sha256 - return hmac of an object with a key. + * @hmac: the hmac to fill in + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * @d: pointer to memory, + * @dsize: the number of bytes pointed to by @d + */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +/** + * struct hmac_sha256_ctx - structure to store running context for hmac_sha256 + */ +struct hmac_sha256_ctx { + struct sha256_ctx sha; + uint64_t k_opad[HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)]; +}; + + +struct hmac_sha512_ctx { + struct sha512_ctx sha; + uint64_t k_opad[HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)]; +}; + +/** + * hmac_sha256_init - initialize an HMAC_SHA256 context. + * @ctx: the hmac_sha256_ctx to initialize + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * + * This must be called before hmac_sha256_update or hmac_sha256_done. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hmac_all(const char *key, + * const char **arr, struct hmac_sha256 *hash) + * { + * size_t i; + * struct hmac_sha256_ctx ctx; + * + * hmac_sha256_init(&ctx, key, strlen(key)); + * for (i = 0; arr[i]; i++) + * hmac_sha256_update(&ctx, arr[i], strlen(arr[i])); + * hmac_sha256_done(&ctx, hash); + * } + */ +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize); + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize); + + +/** + * hmac_sha256_update - include some memory in the hash. + * @ctx: the hmac_sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * hmac_sha256_done(). + */ +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, + const void *p, size_t size); + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, + const void *p, size_t size); + +/** + * hmac_sha256_done - finish HMAC_SHA256 and return the hash + * @ctx: the hmac_sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void hmac_sha256_done(struct hmac_sha256_ctx *hmac_sha256, + struct hmac_sha256 *res); + +void hmac_sha512_done(struct hmac_sha512_ctx *hmac_sha256, + struct hmac_sha512 *res); + +#endif /* CCAN_CRYPTO_HMAC_SHA256_H */ diff --git a/ripemd160.c b/ripemd160.c @@ -0,0 +1,404 @@ +/* MIT (BSD) license - see LICENSE file for details */ +/* RIPEMD core code translated from the Bitcoin project's C++: + * + * src/crypto/ripemd160.cpp commit f914f1a746d7f91951c1da262a4a749dd3ebfa71 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "ripemd160.h" +#include "endian.h" +#include "compiler.h" +#include <stdbool.h> +#include <assert.h> +#include <string.h> + +static void invalidate_ripemd160(struct ripemd160_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL + ctx->c.num = -1U; +#else + ctx->bytes = -1ULL; +#endif +} + +static void check_ripemd160(struct ripemd160_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL + assert(ctx->c.num != -1U); +#else + assert(ctx->bytes != -1ULL); +#endif +} + +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL +void ripemd160_init(struct ripemd160_ctx *ctx) +{ + RIPEMD160_Init(&ctx->c); +} + +void ripemd160_update(struct ripemd160_ctx *ctx, const void *p, size_t size) +{ + check_ripemd160(ctx); + RIPEMD160_Update(&ctx->c, p, size); +} + +void ripemd160_done(struct ripemd160_ctx *ctx, struct ripemd160 *res) +{ + RIPEMD160_Final(res->u.u8, &ctx->c); + invalidate_ripemd160(ctx); +} +#else +inline static uint32_t f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } +inline static uint32_t f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } +inline static uint32_t f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; } +inline static uint32_t f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); } +inline static uint32_t f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); } + +/** Initialize RIPEMD-160 state. */ +inline static void Initialize(uint32_t* s) +{ + s[0] = 0x67452301ul; + s[1] = 0xEFCDAB89ul; + s[2] = 0x98BADCFEul; + s[3] = 0x10325476ul; + s[4] = 0xC3D2E1F0ul; +} + +inline static uint32_t rol(uint32_t x, int i) { return (x << i) | (x >> (32 - i)); } + +inline static void Round(uint32_t *a, uint32_t b UNUSED, uint32_t *c, uint32_t d UNUSED, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) +{ + *a = rol(*a + f + x + k, r) + e; + *c = rol(*c, 10); +} + +inline static void R11(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, *c, d), x, 0, r); } +inline static void R21(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, *c, d), x, 0x5A827999ul, r); } +inline static void R31(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, *c, d), x, 0x6ED9EBA1ul, r); } +inline static void R41(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, *c, d), x, 0x8F1BBCDCul, r); } +inline static void R51(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, *c, d), x, 0xA953FD4Eul, r); } + +inline static void R12(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, *c, d), x, 0x50A28BE6ul, r); } +inline static void R22(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, *c, d), x, 0x5C4DD124ul, r); } +inline static void R32(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, *c, d), x, 0x6D703EF3ul, r); } +inline static void R42(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, *c, d), x, 0x7A6D76E9ul, r); } +inline static void R52(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, *c, d), x, 0, r); } + +/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */ +static void Transform(uint32_t *s, const uint32_t *chunk) +{ + uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4]; + uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1; + uint32_t w0 = le32_to_cpu(chunk[0]), w1 = le32_to_cpu(chunk[1]), w2 = le32_to_cpu(chunk[2]), w3 = le32_to_cpu(chunk[3]); + uint32_t w4 = le32_to_cpu(chunk[4]), w5 = le32_to_cpu(chunk[5]), w6 = le32_to_cpu(chunk[6]), w7 = le32_to_cpu(chunk[7]); + uint32_t w8 = le32_to_cpu(chunk[8]), w9 = le32_to_cpu(chunk[9]), w10 = le32_to_cpu(chunk[10]), w11 = le32_to_cpu(chunk[11]); + uint32_t w12 = le32_to_cpu(chunk[12]), w13 = le32_to_cpu(chunk[13]), w14 = le32_to_cpu(chunk[14]), w15 = le32_to_cpu(chunk[15]); + uint32_t t; + + R11(&a1, b1, &c1, d1, e1, w0, 11); + R12(&a2, b2, &c2, d2, e2, w5, 8); + R11(&e1, a1, &b1, c1, d1, w1, 14); + R12(&e2, a2, &b2, c2, d2, w14, 9); + R11(&d1, e1, &a1, b1, c1, w2, 15); + R12(&d2, e2, &a2, b2, c2, w7, 9); + R11(&c1, d1, &e1, a1, b1, w3, 12); + R12(&c2, d2, &e2, a2, b2, w0, 11); + R11(&b1, c1, &d1, e1, a1, w4, 5); + R12(&b2, c2, &d2, e2, a2, w9, 13); + R11(&a1, b1, &c1, d1, e1, w5, 8); + R12(&a2, b2, &c2, d2, e2, w2, 15); + R11(&e1, a1, &b1, c1, d1, w6, 7); + R12(&e2, a2, &b2, c2, d2, w11, 15); + R11(&d1, e1, &a1, b1, c1, w7, 9); + R12(&d2, e2, &a2, b2, c2, w4, 5); + R11(&c1, d1, &e1, a1, b1, w8, 11); + R12(&c2, d2, &e2, a2, b2, w13, 7); + R11(&b1, c1, &d1, e1, a1, w9, 13); + R12(&b2, c2, &d2, e2, a2, w6, 7); + R11(&a1, b1, &c1, d1, e1, w10, 14); + R12(&a2, b2, &c2, d2, e2, w15, 8); + R11(&e1, a1, &b1, c1, d1, w11, 15); + R12(&e2, a2, &b2, c2, d2, w8, 11); + R11(&d1, e1, &a1, b1, c1, w12, 6); + R12(&d2, e2, &a2, b2, c2, w1, 14); + R11(&c1, d1, &e1, a1, b1, w13, 7); + R12(&c2, d2, &e2, a2, b2, w10, 14); + R11(&b1, c1, &d1, e1, a1, w14, 9); + R12(&b2, c2, &d2, e2, a2, w3, 12); + R11(&a1, b1, &c1, d1, e1, w15, 8); + R12(&a2, b2, &c2, d2, e2, w12, 6); + + R21(&e1, a1, &b1, c1, d1, w7, 7); + R22(&e2, a2, &b2, c2, d2, w6, 9); + R21(&d1, e1, &a1, b1, c1, w4, 6); + R22(&d2, e2, &a2, b2, c2, w11, 13); + R21(&c1, d1, &e1, a1, b1, w13, 8); + R22(&c2, d2, &e2, a2, b2, w3, 15); + R21(&b1, c1, &d1, e1, a1, w1, 13); + R22(&b2, c2, &d2, e2, a2, w7, 7); + R21(&a1, b1, &c1, d1, e1, w10, 11); + R22(&a2, b2, &c2, d2, e2, w0, 12); + R21(&e1, a1, &b1, c1, d1, w6, 9); + R22(&e2, a2, &b2, c2, d2, w13, 8); + R21(&d1, e1, &a1, b1, c1, w15, 7); + R22(&d2, e2, &a2, b2, c2, w5, 9); + R21(&c1, d1, &e1, a1, b1, w3, 15); + R22(&c2, d2, &e2, a2, b2, w10, 11); + R21(&b1, c1, &d1, e1, a1, w12, 7); + R22(&b2, c2, &d2, e2, a2, w14, 7); + R21(&a1, b1, &c1, d1, e1, w0, 12); + R22(&a2, b2, &c2, d2, e2, w15, 7); + R21(&e1, a1, &b1, c1, d1, w9, 15); + R22(&e2, a2, &b2, c2, d2, w8, 12); + R21(&d1, e1, &a1, b1, c1, w5, 9); + R22(&d2, e2, &a2, b2, c2, w12, 7); + R21(&c1, d1, &e1, a1, b1, w2, 11); + R22(&c2, d2, &e2, a2, b2, w4, 6); + R21(&b1, c1, &d1, e1, a1, w14, 7); + R22(&b2, c2, &d2, e2, a2, w9, 15); + R21(&a1, b1, &c1, d1, e1, w11, 13); + R22(&a2, b2, &c2, d2, e2, w1, 13); + R21(&e1, a1, &b1, c1, d1, w8, 12); + R22(&e2, a2, &b2, c2, d2, w2, 11); + + R31(&d1, e1, &a1, b1, c1, w3, 11); + R32(&d2, e2, &a2, b2, c2, w15, 9); + R31(&c1, d1, &e1, a1, b1, w10, 13); + R32(&c2, d2, &e2, a2, b2, w5, 7); + R31(&b1, c1, &d1, e1, a1, w14, 6); + R32(&b2, c2, &d2, e2, a2, w1, 15); + R31(&a1, b1, &c1, d1, e1, w4, 7); + R32(&a2, b2, &c2, d2, e2, w3, 11); + R31(&e1, a1, &b1, c1, d1, w9, 14); + R32(&e2, a2, &b2, c2, d2, w7, 8); + R31(&d1, e1, &a1, b1, c1, w15, 9); + R32(&d2, e2, &a2, b2, c2, w14, 6); + R31(&c1, d1, &e1, a1, b1, w8, 13); + R32(&c2, d2, &e2, a2, b2, w6, 6); + R31(&b1, c1, &d1, e1, a1, w1, 15); + R32(&b2, c2, &d2, e2, a2, w9, 14); + R31(&a1, b1, &c1, d1, e1, w2, 14); + R32(&a2, b2, &c2, d2, e2, w11, 12); + R31(&e1, a1, &b1, c1, d1, w7, 8); + R32(&e2, a2, &b2, c2, d2, w8, 13); + R31(&d1, e1, &a1, b1, c1, w0, 13); + R32(&d2, e2, &a2, b2, c2, w12, 5); + R31(&c1, d1, &e1, a1, b1, w6, 6); + R32(&c2, d2, &e2, a2, b2, w2, 14); + R31(&b1, c1, &d1, e1, a1, w13, 5); + R32(&b2, c2, &d2, e2, a2, w10, 13); + R31(&a1, b1, &c1, d1, e1, w11, 12); + R32(&a2, b2, &c2, d2, e2, w0, 13); + R31(&e1, a1, &b1, c1, d1, w5, 7); + R32(&e2, a2, &b2, c2, d2, w4, 7); + R31(&d1, e1, &a1, b1, c1, w12, 5); + R32(&d2, e2, &a2, b2, c2, w13, 5); + + R41(&c1, d1, &e1, a1, b1, w1, 11); + R42(&c2, d2, &e2, a2, b2, w8, 15); + R41(&b1, c1, &d1, e1, a1, w9, 12); + R42(&b2, c2, &d2, e2, a2, w6, 5); + R41(&a1, b1, &c1, d1, e1, w11, 14); + R42(&a2, b2, &c2, d2, e2, w4, 8); + R41(&e1, a1, &b1, c1, d1, w10, 15); + R42(&e2, a2, &b2, c2, d2, w1, 11); + R41(&d1, e1, &a1, b1, c1, w0, 14); + R42(&d2, e2, &a2, b2, c2, w3, 14); + R41(&c1, d1, &e1, a1, b1, w8, 15); + R42(&c2, d2, &e2, a2, b2, w11, 14); + R41(&b1, c1, &d1, e1, a1, w12, 9); + R42(&b2, c2, &d2, e2, a2, w15, 6); + R41(&a1, b1, &c1, d1, e1, w4, 8); + R42(&a2, b2, &c2, d2, e2, w0, 14); + R41(&e1, a1, &b1, c1, d1, w13, 9); + R42(&e2, a2, &b2, c2, d2, w5, 6); + R41(&d1, e1, &a1, b1, c1, w3, 14); + R42(&d2, e2, &a2, b2, c2, w12, 9); + R41(&c1, d1, &e1, a1, b1, w7, 5); + R42(&c2, d2, &e2, a2, b2, w2, 12); + R41(&b1, c1, &d1, e1, a1, w15, 6); + R42(&b2, c2, &d2, e2, a2, w13, 9); + R41(&a1, b1, &c1, d1, e1, w14, 8); + R42(&a2, b2, &c2, d2, e2, w9, 12); + R41(&e1, a1, &b1, c1, d1, w5, 6); + R42(&e2, a2, &b2, c2, d2, w7, 5); + R41(&d1, e1, &a1, b1, c1, w6, 5); + R42(&d2, e2, &a2, b2, c2, w10, 15); + R41(&c1, d1, &e1, a1, b1, w2, 12); + R42(&c2, d2, &e2, a2, b2, w14, 8); + + R51(&b1, c1, &d1, e1, a1, w4, 9); + R52(&b2, c2, &d2, e2, a2, w12, 8); + R51(&a1, b1, &c1, d1, e1, w0, 15); + R52(&a2, b2, &c2, d2, e2, w15, 5); + R51(&e1, a1, &b1, c1, d1, w5, 5); + R52(&e2, a2, &b2, c2, d2, w10, 12); + R51(&d1, e1, &a1, b1, c1, w9, 11); + R52(&d2, e2, &a2, b2, c2, w4, 9); + R51(&c1, d1, &e1, a1, b1, w7, 6); + R52(&c2, d2, &e2, a2, b2, w1, 12); + R51(&b1, c1, &d1, e1, a1, w12, 8); + R52(&b2, c2, &d2, e2, a2, w5, 5); + R51(&a1, b1, &c1, d1, e1, w2, 13); + R52(&a2, b2, &c2, d2, e2, w8, 14); + R51(&e1, a1, &b1, c1, d1, w10, 12); + R52(&e2, a2, &b2, c2, d2, w7, 6); + R51(&d1, e1, &a1, b1, c1, w14, 5); + R52(&d2, e2, &a2, b2, c2, w6, 8); + R51(&c1, d1, &e1, a1, b1, w1, 12); + R52(&c2, d2, &e2, a2, b2, w2, 13); + R51(&b1, c1, &d1, e1, a1, w3, 13); + R52(&b2, c2, &d2, e2, a2, w13, 6); + R51(&a1, b1, &c1, d1, e1, w8, 14); + R52(&a2, b2, &c2, d2, e2, w14, 5); + R51(&e1, a1, &b1, c1, d1, w11, 11); + R52(&e2, a2, &b2, c2, d2, w0, 15); + R51(&d1, e1, &a1, b1, c1, w6, 8); + R52(&d2, e2, &a2, b2, c2, w3, 13); + R51(&c1, d1, &e1, a1, b1, w15, 5); + R52(&c2, d2, &e2, a2, b2, w9, 11); + R51(&b1, c1, &d1, e1, a1, w13, 6); + R52(&b2, c2, &d2, e2, a2, w11, 11); + + t = s[0]; + s[0] = s[1] + c1 + d2; + s[1] = s[2] + d1 + e2; + s[2] = s[3] + e1 + a2; + s[3] = s[4] + a1 + b2; + s[4] = t + b1 + c2; +} + +static void add(struct ripemd160_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 64; + + if (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize); + ctx->bytes += 64 - bufsize; + data += 64 - bufsize; + len -= 64 - bufsize; + Transform(ctx->s, ctx->buf.u32); + bufsize = 0; + } + + while (len >= 64) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint32_t))) + Transform(ctx->s, (const uint32_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u32); + } + ctx->bytes += 64; + data += 64; + len -= 64; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void ripemd160_init(struct ripemd160_ctx *ctx) +{ + struct ripemd160_ctx init = RIPEMD160_INIT; + *ctx = init; +} + +void ripemd160_update(struct ripemd160_ctx *ctx, const void *p, size_t size) +{ + check_ripemd160(ctx); + add(ctx, p, size); +} + +void ripemd160_done(struct ripemd160_ctx *ctx, struct ripemd160 *res) +{ + static const unsigned char pad[64] = {0x80}; + uint64_t sizedesc; + size_t i; + + sizedesc = cpu_to_le64(ctx->bytes << 3); + /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */ + add(ctx, pad, 1 + ((119 - (ctx->bytes % 64)) % 64)); + /* Add number of bits of data (big endian) */ + add(ctx, &sizedesc, 8); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u32[i] = cpu_to_le32(ctx->s[i]); + invalidate_ripemd160(ctx); +} +#endif + +void ripemd160(struct ripemd160 *ripemd, const void *p, size_t size) +{ + struct ripemd160_ctx ctx; + + ripemd160_init(&ctx); + ripemd160_update(&ctx, p, size); + ripemd160_done(&ctx, ripemd); + memset(&ctx, 0, sizeof(ctx)); +} + +void ripemd160_u8(struct ripemd160_ctx *ctx, uint8_t v) +{ + ripemd160_update(ctx, &v, sizeof(v)); +} + +void ripemd160_u16(struct ripemd160_ctx *ctx, uint16_t v) +{ + ripemd160_update(ctx, &v, sizeof(v)); +} + +void ripemd160_u32(struct ripemd160_ctx *ctx, uint32_t v) +{ + ripemd160_update(ctx, &v, sizeof(v)); +} + +void ripemd160_u64(struct ripemd160_ctx *ctx, uint64_t v) +{ + ripemd160_update(ctx, &v, sizeof(v)); +} + +/* Add as little-endian */ +void ripemd160_le16(struct ripemd160_ctx *ctx, uint16_t v) +{ + leint16_t lev = cpu_to_le16(v); + ripemd160_update(ctx, &lev, sizeof(lev)); +} + +void ripemd160_le32(struct ripemd160_ctx *ctx, uint32_t v) +{ + leint32_t lev = cpu_to_le32(v); + ripemd160_update(ctx, &lev, sizeof(lev)); +} + +void ripemd160_le64(struct ripemd160_ctx *ctx, uint64_t v) +{ + leint64_t lev = cpu_to_le64(v); + ripemd160_update(ctx, &lev, sizeof(lev)); +} + +/* Add as big-endian */ +void ripemd160_be16(struct ripemd160_ctx *ctx, uint16_t v) +{ + beint16_t bev = cpu_to_be16(v); + ripemd160_update(ctx, &bev, sizeof(bev)); +} + +void ripemd160_be32(struct ripemd160_ctx *ctx, uint32_t v) +{ + beint32_t bev = cpu_to_be32(v); + ripemd160_update(ctx, &bev, sizeof(bev)); +} + +void ripemd160_be64(struct ripemd160_ctx *ctx, uint64_t v) +{ + beint64_t bev = cpu_to_be64(v); + ripemd160_update(ctx, &bev, sizeof(bev)); +} + + diff --git a/ripemd160.h b/ripemd160.h @@ -0,0 +1,148 @@ + +#ifndef CCAN_CRYPTO_RIPEMD160_H +#define CCAN_CRYPTO_RIPEMD160_H +/* BSD-MIT - see LICENSE file for details */ +#include <stdint.h> +#include <stdlib.h> + +/* Uncomment this to use openssl's RIPEMD160 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_RIPEMD160_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL +#include <openssl/ripemd.h> +#endif + +/** + * struct ripemd160 - structure representing a completed RIPEMD160. + * @u.u8: an unsigned char array. + * @u.u32: a 32-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct ripemd160 { + union { + /* Array of chars */ + unsigned char u8[20]; + /* Array of uint32_t */ + uint32_t u32[5]; + } u; +}; + +/** + * ripemd160 - return ripemd160 of an object. + * @ripemd160: the ripemd160 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is RIPEMD160 hashed into @ripemd160. This is + * equivalent to ripemd160_init(), ripemd160_update() then ripemd160_done(). + */ +void ripemd160(struct ripemd160 *ripemd, const void *p, size_t size); + +/** + * struct ripemd160_ctx - structure to store running context for ripemd160 + */ +struct ripemd160_ctx { +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL + RIPEMD160_CTX c; +#else + uint32_t s[5]; + uint64_t bytes; + union { + uint32_t u32[16]; + unsigned char u8[64]; + } buf; +#endif +}; + +/** + * ripemd160_init - initialize an RIPEMD160 context. + * @ctx: the ripemd160_ctx to initialize + * + * This must be called before ripemd160_update or ripemd160_done, or + * alternately you can assign RIPEMD160_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct ripemd160 *hash) + * { + * size_t i; + * struct ripemd160_ctx ctx; + * + * ripemd160_init(&ctx); + * for (i = 0; arr[i]; i++) + * ripemd160_update(&ctx, arr[i], strlen(arr[i])); + * ripemd160_done(&ctx, hash); + * } + */ +void ripemd160_init(struct ripemd160_ctx *ctx); + +/** + * RIPEMD160_INIT - initializer for an RIPEMD160 context. + * + * This can be used to staticly initialize an RIPEMD160 context (instead + * of ripemd160_init()). + * + * Example: + * static void hash_all(const char **arr, struct ripemd160 *hash) + * { + * size_t i; + * struct ripemd160_ctx ctx = RIPEMD160_INIT; + * + * for (i = 0; arr[i]; i++) + * ripemd160_update(&ctx, arr[i], strlen(arr[i])); + * ripemd160_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_RIPEMD160_USE_OPENSSL +#define RIPEMD160_INIT \ + { { 0x67452301ul, 0xEFCDAB89ul, 0x98BADCFEul, 0x10325476ul, \ + 0xC3D2E1F0ul, \ + 0x0, 0x0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0 } } +#else +#define RIPEMD160_INIT \ + { { 0x67452301ul, 0xEFCDAB89ul, 0x98BADCFEul, 0x10325476ul, \ + 0xC3D2E1F0ul }, 0, {{ 0 }} } +#endif + +/** + * ripemd160_update - include some memory in the hash. + * @ctx: the ripemd160_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * ripemd160_done(). + */ +void ripemd160_update(struct ripemd160_ctx *ctx, const void *p, size_t size); + +/** + * ripemd160_done - finish RIPEMD160 and return the hash + * @ctx: the ripemd160_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void ripemd160_done(struct ripemd160_ctx *ripemd160, struct ripemd160 *res); + +/* Add various types to an RIPEMD160 hash */ +void ripemd160_u8(struct ripemd160_ctx *ctx, uint8_t v); +void ripemd160_u16(struct ripemd160_ctx *ctx, uint16_t v); +void ripemd160_u32(struct ripemd160_ctx *ctx, uint32_t v); +void ripemd160_u64(struct ripemd160_ctx *ctx, uint64_t v); + +/* Add as little-endian */ +void ripemd160_le16(struct ripemd160_ctx *ctx, uint16_t v); +void ripemd160_le32(struct ripemd160_ctx *ctx, uint32_t v); +void ripemd160_le64(struct ripemd160_ctx *ctx, uint64_t v); + +/* Add as big-endian */ +void ripemd160_be16(struct ripemd160_ctx *ctx, uint16_t v); +void ripemd160_be32(struct ripemd160_ctx *ctx, uint32_t v); +void ripemd160_be64(struct ripemd160_ctx *ctx, uint64_t v); +#endif /* CCAN_CRYPTO_RIPEMD160_H */ diff --git a/sha256.c b/sha256.c @@ -0,0 +1,321 @@ + +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA256 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha256.cpp commit 417532c8acb93c36c2b6fd052b7c11b6a2906aa2 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha256.h" +#include "endian.h" +#include "compiler.h" +#include <stdbool.h> +#include <assert.h> +#include <string.h> + +static void invalidate_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +void sha256_init(struct sha256_ctx *ctx) +{ + SHA256_Init(&ctx->c); +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + SHA256_Update(&ctx->c, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + SHA256_Final(res->u.u8, &ctx->c); + invalidate_sha256(ctx); +} +#else +static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint32_t Sigma0(uint32_t x) +{ + return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); +} +static uint32_t Sigma1(uint32_t x) +{ + return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); +} +static uint32_t sigma0(uint32_t x) +{ + return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); +} +static uint32_t sigma1(uint32_t x) +{ + return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); +} + +/** One round of SHA-256. */ +static void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g, uint32_t *h, uint32_t k, uint32_t w) +{ + uint32_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +static void Transform(uint32_t *s, const uint32_t *chunk) +{ + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98, w0 = be32_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x71374491, w1 = be32_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcf, w2 = be32_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba5, w3 = be32_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25b, w4 = be32_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1, w5 = be32_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4, w6 = be32_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5, w7 = be32_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98, w8 = be32_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b01, w9 = be32_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be, w10 = be32_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3, w11 = be32_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74, w12 = be32_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe, w13 = be32_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a7, w14 = be32_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174, w15 = be32_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + + +static void add(struct sha256_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 64; + + if (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize); + ctx->bytes += 64 - bufsize; + data += 64 - bufsize; + len -= 64 - bufsize; + Transform(ctx->s, ctx->buf.u32); + bufsize = 0; + } + + while (len >= 64) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint32_t))) + Transform(ctx->s, (const uint32_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u32); + } + ctx->bytes += 64; + data += 64; + len -= 64; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha256_init(struct sha256_ctx *ctx) +{ + struct sha256_ctx init = SHA256_INIT; + *ctx = init; +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + add(ctx, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + static const unsigned char pad[64] = {0x80}; + uint64_t sizedesc; + size_t i; + + sizedesc = cpu_to_be64((uint64_t)ctx->bytes << 3); + /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */ + add(ctx, pad, 1 + ((128 - 8 - (ctx->bytes % 64) - 1) % 64)); + /* Add number of bits of data (big endian) */ + add(ctx, &sizedesc, 8); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u32[i] = cpu_to_be32(ctx->s[i]); + invalidate_sha256(ctx); +} +#endif + +void sha256(struct sha256 *sha, const void *p, size_t size) +{ + struct sha256_ctx ctx; + + sha256_init(&ctx); + sha256_update(&ctx, p, size); + sha256_done(&ctx, sha); +} + +void sha256_u8(struct sha256_ctx *ctx, uint8_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u16(struct sha256_ctx *ctx, uint16_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u32(struct sha256_ctx *ctx, uint32_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u64(struct sha256_ctx *ctx, uint64_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v) +{ + leint16_t lev = cpu_to_le16(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le32(struct sha256_ctx *ctx, uint32_t v) +{ + leint32_t lev = cpu_to_le32(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le64(struct sha256_ctx *ctx, uint64_t v) +{ + leint64_t lev = cpu_to_le64(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v) +{ + beint16_t bev = cpu_to_be16(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be32(struct sha256_ctx *ctx, uint32_t v) +{ + beint32_t bev = cpu_to_be32(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be64(struct sha256_ctx *ctx, uint64_t v) +{ + beint64_t bev = cpu_to_be64(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + + +int sha256d(const unsigned char *bytes, size_t bytes_len, + unsigned char *bytes_out, size_t len) +{ + struct sha256 sha_1, sha_2; + bool aligned = alignment_ok(bytes_out, sizeof(sha_1.u.u32)); + + if (!bytes || !bytes_out || len != SHA256_LEN) + return 0; + + sha256(&sha_1, bytes, bytes_len); + sha256(aligned ? (struct sha256 *)bytes_out : &sha_2, &sha_1, sizeof(sha_1)); + if (!aligned) { + memcpy(bytes_out, &sha_2, sizeof(sha_2)); + wally_clear(&sha_2, sizeof(sha_2)); + } + wally_clear(&sha_1, sizeof(sha_1)); + return 1; +} diff --git a/sha256.h b/sha256.h @@ -0,0 +1,158 @@ + +#ifndef CCAN_CRYPTO_SHA256_H +#define CCAN_CRYPTO_SHA256_H + + +/** Output length for `wally_sha256` */ +#define SHA256_LEN 32 + + +/* BSD-MIT - see LICENSE file for details */ +/* #include "config.h" */ +#include <stdint.h> +#include <stdlib.h> + +/* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#include <openssl/sha.h> +#endif + +/** + * struct sha256 - structure representing a completed SHA256. + * @u.u8: an unsigned char array. + * @u.u32: a 32-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha256 { + union { + uint32_t u32[8]; + unsigned char u8[32]; + } u; +}; + +/** + * sha256 - return sha256 of an object. + * @sha256: the sha256 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA256 hashed into @sha256. This is + * equivalent to sha256_init(), sha256_update() then sha256_done(). + */ +void sha256(struct sha256 *sha, const void *p, size_t size); + +/** + * struct sha256_ctx - structure to store running context for sha256 + */ +struct sha256_ctx { +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + SHA256_CTX c; +#else + uint32_t s[8]; + union { + uint32_t u32[16]; + unsigned char u8[64]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha256_init - initialize an SHA256 context. + * @ctx: the sha256_ctx to initialize + * + * This must be called before sha256_update or sha256_done, or + * alternately you can assign SHA256_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx; + * + * sha256_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +void sha256_init(struct sha256_ctx *ctx); + +/** + * SHA256_INIT - initializer for an SHA256 context. + * + * This can be used to statically initialize an SHA256 context (instead + * of sha256_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx = SHA256_INIT; + * + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#define SHA256_INIT \ + { { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + 0x0, 0x0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0x0, 0x20 } } +#else +#define SHA256_INIT \ + { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + { { 0 } }, 0 } +#endif + +/** + * sha256_update - include some memory in the hash. + * @ctx: the sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha256_done(). + */ +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size); + +/** + * sha256_done - finish SHA256 and return the hash + * @ctx: the sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha256_done(struct sha256_ctx *sha256, struct sha256 *res); + +/* Add various types to an SHA256 hash */ +void sha256_u8(struct sha256_ctx *ctx, uint8_t v); +void sha256_u16(struct sha256_ctx *ctx, uint16_t v); +void sha256_u32(struct sha256_ctx *ctx, uint32_t v); +void sha256_u64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v); +void sha256_le32(struct sha256_ctx *ctx, uint32_t v); +void sha256_le64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v); +void sha256_be32(struct sha256_ctx *ctx, uint32_t v); +void sha256_be64(struct sha256_ctx *ctx, uint64_t v); + +int sha256d(const unsigned char *bytes, size_t bytes_len, + unsigned char *bytes_out, size_t len); + +#endif /* CCAN_CRYPTO_SHA256_H */ diff --git a/sha512.c b/sha512.c @@ -0,0 +1,261 @@ + +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA512 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha512.cpp commit f914f1a746d7f91951c1da262a4a749dd3ebfa71 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha512.h" +#include "endian.h" +#include "compiler.h" +#include <stdbool.h> +#include <assert.h> +#include <string.h> + +static void invalidate_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +void sha512_init(struct sha512_ctx *ctx) +{ + SHA512_Init(&ctx->c); +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + SHA512_Update(&ctx->c, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + SHA512_Final(res->u.u8, &ctx->c); + invalidate_sha512(ctx); +} +#else +static uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint64_t Sigma0(uint64_t x) +{ + return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); +} +static uint64_t Sigma1(uint64_t x) +{ + return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); +} +static uint64_t sigma0(uint64_t x) +{ + return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); +} +static uint64_t sigma1(uint64_t x) +{ + return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); +} + +/** One round of SHA-512. */ +static void Round(uint64_t a, uint64_t b, uint64_t c, uint64_t *d, uint64_t e, uint64_t f, uint64_t g, uint64_t *h, uint64_t k, uint64_t w) +{ + uint64_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint64_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-512 transformation, processing a 128-byte chunk. */ +static void Transform(uint64_t *s, const uint64_t *chunk) +{ + uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98d728ae22ull, w0 = be64_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x7137449123ef65cdull, w1 = be64_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcfec4d3b2full, w2 = be64_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba58189dbbcull, w3 = be64_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25bf348b538ull, w4 = be64_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1b605d019ull, w5 = be64_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4af194f9bull, w6 = be64_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5da6d8118ull, w7 = be64_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98a3030242ull, w8 = be64_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b0145706fbeull, w9 = be64_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be4ee4b28cull, w10 = be64_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3d5ffb4e2ull, w11 = be64_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74f27b896full, w12 = be64_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe3b1696b1ull, w13 = be64_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a725c71235ull, w14 = be64_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174cf692694ull, w15 = be64_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void add(struct sha512_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 128; + + if (bufsize + len >= 128) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 128 - bufsize); + ctx->bytes += 128 - bufsize; + data += 128 - bufsize; + len -= 128 - bufsize; + Transform(ctx->s, ctx->buf.u64); + bufsize = 0; + } + + while (len >= 128) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint64_t))) + Transform(ctx->s, (const uint64_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u64); + } + ctx->bytes += 128; + data += 128; + len -= 128; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha512_init(struct sha512_ctx *ctx) +{ + struct sha512_ctx init = SHA512_INIT; + *ctx = init; +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + add(ctx, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + static const unsigned char pad[128] = { 0x80 }; + uint64_t sizedesc[2] = { 0, 0 }; + size_t i; + + sizedesc[1] = cpu_to_be64((uint64_t)ctx->bytes << 3); + + /* Add '1' bit to terminate, then all 0 bits, up to next block - 16. */ + add(ctx, pad, 1 + ((256 - 16 - (ctx->bytes % 128) - 1) % 128)); + /* Add number of bits of data (big endian) */ + add(ctx, sizedesc, sizeof(sizedesc)); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u64[i] = cpu_to_be64(ctx->s[i]); + invalidate_sha512(ctx); +} +#endif /* CCAN_CRYPTO_SHA512_USE_OPENSSL */ + +void sha512(struct sha512 *sha, const void *p, size_t size) +{ + struct sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, p, size); + sha512_done(&ctx, sha); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/sha512.h b/sha512.h @@ -0,0 +1,138 @@ + +#ifndef CCAN_CRYPTO_SHA512_H +#define CCAN_CRYPTO_SHA512_H +/* BSD-MIT - see LICENSE file for details */ +#include <stdint.h> +#include <stdlib.h> + +/** Output length for `wally_sha512` */ +#define SHA512_LEN 64 + +/* Uncomment this to use openssl's SHA512 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA512_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +#include <openssl/sha.h> +#endif + +/** + * struct sha512 - structure representing a completed SHA512. + * @u.u8: an unsigned char array. + * @u.u64: a 64-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha512 { + union { + uint64_t u64[8]; + unsigned char u8[64]; + } u; +}; + +/** + * sha512 - return sha512 of an object. + * @sha512: the sha512 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA512 hashed into @sha512. This is + * equivalent to sha512_init(), sha512_update() then sha512_done(). + */ +void sha512(struct sha512 *sha, const void *p, size_t size); + +/** + * struct sha512_ctx - structure to store running context for sha512 + */ +struct sha512_ctx { +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + SHA512_CTX c; +#else + uint64_t s[8]; + union { + uint64_t u64[16]; + unsigned char u8[128]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha512_init - initialize an SHA512 context. + * @ctx: the sha512_ctx to initialize + * + * This must be called before sha512_update or sha512_done, or + * alternately you can assign SHA512_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx; + * + * sha512_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +void sha512_init(struct sha512_ctx *ctx); + +/** + * SHA512_INIT - initializer for an SHA512 context. + * + * This can be used to statically initialize an SHA512 context (instead + * of sha512_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx = SHA512_INIT; + * + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + { { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + 0, 0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0, 0x40 } } +#else +#define SHA512_INIT \ + { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + { { 0 } }, 0 } +#endif + +/** + * sha512_update - include some memory in the hash. + * @ctx: the sha512_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha512_done(). + */ +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size); + +/** + * sha512_done - finish SHA512 and return the hash + * @ctx: the sha512_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha512_done(struct sha512_ctx *sha512, struct sha512 *res); + +#endif /* CCAN_CRYPTO_SHA512_H */ diff --git a/short_types.h b/short_types.h @@ -0,0 +1,21 @@ + +#ifndef DK_SHORT_TYPES_H +#define DK_SHORT_TYPES_H + +#include <stdint.h> + +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint8_t u8; +typedef int8_t s8; + +#define WALLY_OK 0 /** Success */ +#define WALLY_ERROR -1 /** General error */ +#define WALLY_EINVAL -2 /** Invalid argument */ +#define WALLY_ENOMEM -3 /** malloc() failed */ + +#endif /* DK_SHORT_TYPES_H */