commit 9d1251e9dec600e08da7dbe7484aeb82967d3ef2
parent 775be9d89cf59673aa13238258f1021a91e96d7a
Author: William Casarin <jb55@jb55.com>
Date: Fri, 14 Jan 2022 15:01:17 -0800
act_one_initiator wip
Diffstat:
M | .gitignore | | | 4 | +++- |
M | Makefile | | | 17 | ++++++++++++----- |
A | compiler.h | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | config.h | | | 13 | +++++++++++++ |
A | configurator.c | | | 1111 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | deps/rotate-bits/package.json | | | 13 | ------------- |
D | deps/rotate-bits/rotate-bits.h | | | 46 | ---------------------------------------------- |
D | deps/sha256/package.json | | | 15 | --------------- |
D | deps/sha256/sha256.c | | | 221 | ------------------------------------------------------------------------------- |
D | deps/sha256/sha256.h | | | 24 | ------------------------ |
A | endian.h | | | 360 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | handshake.h | | | 6 | +++--- |
A | hkdf.c | | | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | hkdf.h | | | 22 | ++++++++++++++++++++++ |
A | hmac.c | | | 258 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | hmac.h | | | 116 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | lnsocket.c | | | 193 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | netln.c | | | 81 | ------------------------------------------------------------------------------- |
A | sha256.c | | | 303 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | sha256.h | | | 155 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | sha512.c | | | 261 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | sha512.h | | | 138 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
22 files changed, 3103 insertions(+), 409 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,5 +1,7 @@
.build-result
.buildcmd
/.direnv
-/netln
/tags
+*.o
+/configurator
+/lnsocket
diff --git a/Makefile b/Makefile
@@ -1,14 +1,21 @@
CFLAGS=-Wall -g -Og -Ideps/secp256k1/include -Ideps/libsodium/src/libsodium/include -Ideps
-
LDFLAGS=
ARS=deps/secp256k1/.libs/libsecp256k1.a deps/libsodium/src/libsodium/.libs/libsodium.a
+OBJS=sha256.o hkdf.o hmac.o sha512.o
+DEPS=$(ARS) $(OBJS) config.h
+
+all: lnsocket
+
+config.h: configurator
+ ./configurator > $@
-all: netln
+configurator: configurator.c
+ $(CC) $< -o $@
deps/secp256k1/src/libsecp256k1-config.h: deps/secp256k1/configure
- ./configure
+ ./configure --enable-module-ecdh
deps/secp256k1/configure:
cd deps/secp256k1; \
@@ -27,14 +34,14 @@ deps/libsodium/src/libsodium/.libs/libsodium.a: deps/libsodium/configure
cd deps/libsodium/src/libsodium; \
make -j2 libsodium.la
-netln: netln.c $(ARS)
+lnsocket: lnsocket.c $(DEPS)
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
tags: fake
find . -name '*.c' -or -name '*.h' | xargs ctags
clean: fake
- rm -f netln
+ rm -f lnsocket $(DEPS) deps/secp256k1/src/libsecp256k1-config.h
cd deps/secp256k1; \
make clean
cd deps/libsodium; \
diff --git a/compiler.h b/compiler.h
@@ -0,0 +1,57 @@
+
+#ifndef COMPILER_H
+#define COMPILER_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+#if HAVE_UNALIGNED_ACCESS
+#define alignment_ok(p, n) 1
+#else
+#define alignment_ok(p, n) ((size_t)(p) % (n) == 0)
+#endif
+
+#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); }
+
+#endif /* COMPILER_H */
diff --git a/config.h b/config.h
@@ -0,0 +1,13 @@
+/* Generated by CCAN configurator */
+#ifndef CCAN_CONFIG_H
+#define CCAN_CONFIG_H
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* Always use GNU extensions. */
+#endif
+#define CCAN_COMPILER "cc"
+#define CCAN_CFLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition"
+#define CCAN_OUTPUT_EXE_CFLAG "-o"
+
+#define HAVE_CCAN 1
+#define HAVE_UNALIGNED_ACCESS 1
+#endif /* CCAN_CONFIG_H */
diff --git a/configurator.c b/configurator.c
@@ -0,0 +1,1111 @@
+/* Simple tool to create config.h.
+ * Would be much easier with ccan modules, but deliberately standalone.
+ *
+ * Copyright 2011 Rusty Russell <rusty@rustcorp.com.au>. MIT license.
+ *
+ * c12r_err, c12r_errx functions copied from ccan/err/err.c
+ * Copyright Rusty Russell <rusty@rustcorp.com.au>. CC0 (Public domain) License.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#define _POSIX_C_SOURCE 200809L /* For pclose, popen, strdup */
+
+#define EXIT_BAD_USAGE 1
+#define EXIT_TROUBLE_RUNNING 2
+#define EXIT_BAD_TEST 3
+#define EXIT_BAD_INPUT 4
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef _MSC_VER
+#define popen _popen
+#define pclose _pclose
+#endif
+
+#ifdef _MSC_VER
+#define DEFAULT_COMPILER "cl"
+/* Note: Dash options avoid POSIX path conversion when used under msys bash
+ * and are therefore preferred to slash (e.g. -nologo over /nologo)
+ * Note: Disable Warning 4200 "nonstandard extension used : zero-sized array
+ * in struct/union" for flexible array members.
+ */
+#define DEFAULT_FLAGS "-nologo -Zi -W4 -wd4200 " \
+ "-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS"
+#define DEFAULT_OUTPUT_EXE_FLAG "-Fe:"
+#else
+#define DEFAULT_COMPILER "cc"
+#define DEFAULT_FLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition"
+#define DEFAULT_OUTPUT_EXE_FLAG "-o"
+#endif
+
+#define OUTPUT_FILE "configurator.out"
+#define INPUT_FILE "configuratortest.c"
+
+#ifdef _WIN32
+#define DIR_SEP "\\"
+#else
+#define DIR_SEP "/"
+#endif
+
+static const char *progname = "";
+static int verbose;
+static bool like_a_libtool = false;
+
+struct test {
+ const char *name;
+ const char *desc;
+ /*
+ * Template style flags (pick one):
+ * OUTSIDE_MAIN:
+ * - put a simple boilerplate main below it.
+ * DEFINES_FUNC:
+ * - defines a static function called func; adds ref to avoid warnings
+ * INSIDE_MAIN:
+ * - put this inside main().
+ * DEFINES_EVERYTHING:
+ * - don't add any boilerplate at all.
+ *
+ * Execution flags:
+ * EXECUTE:
+ * - a runtime test; must compile, exit 0 means flag is set.
+ * MAY_NOT_COMPILE:
+ * - Only useful with EXECUTE: don't get upset if it doesn't compile.
+ * <nothing>:
+ * - a compile test, if it compiles must run and exit 0.
+ */
+ const char *style;
+ const char *depends;
+ const char *link;
+ const char *fragment;
+ const char *flags;
+ const char *overrides; /* On success, force this to '1' */
+ bool done;
+ bool answer;
+};
+
+/* Terminated by a NULL name */
+static struct test *tests;
+
+static const struct test base_tests[] = {
+ { "HAVE_UNALIGNED_ACCESS", "unaligned access to int",
+ "DEFINES_EVERYTHING|EXECUTE", NULL, NULL,
+ "#include <string.h>\n"
+ "int main(int argc, char *argv[]) {\n"
+ " (void)argc;\n"
+ " char pad[sizeof(int *) * 1];\n"
+ " memcpy(pad, argv[0], sizeof(pad));\n"
+ " int *x = (int *)pad, *y = (int *)(pad + 1);\n"
+ " return *x == *y;\n"
+ "}\n" },
+
+ /*
+ { "HAVE_32BIT_OFF_T", "off_t is 32 bits",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL,
+ "#include <sys/types.h>\n"
+ "int main(void) {\n"
+ " return sizeof(off_t) == 4 ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_ALIGNOF", "__alignof__ support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __alignof__(double) > 0 ? 0 : 1;" },
+ { "HAVE_ASPRINTF", "asprintf() declaration",
+ "DEFINES_FUNC", NULL, NULL,
+ "#ifndef _GNU_SOURCE\n"
+ "#define _GNU_SOURCE\n"
+ "#endif\n"
+ "#include <stdio.h>\n"
+ "static char *func(int x) {"
+ " char *p;\n"
+ " if (asprintf(&p, \"%u\", x) == -1) \n"
+ " p = NULL;\n"
+ " return p;\n"
+ "}" },
+ { "HAVE_ATTRIBUTE_COLD", "__attribute__((cold)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static int __attribute__((cold)) func(int x) { return x; }" },
+ { "HAVE_ATTRIBUTE_CONST", "__attribute__((const)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static int __attribute__((const)) func(int x) { return x; }" },
+ { "HAVE_ATTRIBUTE_DEPRECATED", "__attribute__((deprecated)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static int __attribute__((deprecated)) func(int x) { return x; }" },
+ { "HAVE_ATTRIBUTE_NONNULL", "__attribute__((nonnull)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static char *__attribute__((nonnull)) func(char *p) { return p; }" },
+ { "HAVE_ATTRIBUTE_RETURNS_NONNULL", "__attribute__((returns_nonnull)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static const char *__attribute__((returns_nonnull)) func(void) { return \"hi\"; }" },
+ { "HAVE_ATTRIBUTE_SENTINEL", "__attribute__((sentinel)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static int __attribute__((sentinel)) func(int i, ...) { return i; }" },
+ { "HAVE_ATTRIBUTE_PURE", "__attribute__((pure)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static int __attribute__((pure)) func(int x) { return x; }" },
+ { "HAVE_ATTRIBUTE_MAY_ALIAS", "__attribute__((may_alias)) support",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "typedef short __attribute__((__may_alias__)) short_a;" },
+ { "HAVE_ATTRIBUTE_NORETURN", "__attribute__((noreturn)) support",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <stdlib.h>\n"
+ "static void __attribute__((noreturn)) func(int x) { exit(x); }" },
+ { "HAVE_ATTRIBUTE_PRINTF", "__attribute__ format printf support",
+ "DEFINES_FUNC", NULL, NULL,
+ "static void __attribute__((format(__printf__, 1, 2))) func(const char *fmt, ...) { (void)fmt; }" },
+ { "HAVE_ATTRIBUTE_UNUSED", "__attribute__((unused)) support",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "static int __attribute__((unused)) func(int x) { return x; }" },
+ { "HAVE_ATTRIBUTE_USED", "__attribute__((used)) support",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "static int __attribute__((used)) func(int x) { return x; }" },
+ { "HAVE_BACKTRACE", "backtrace() in <execinfo.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <execinfo.h>\n"
+ "static int func(int x) {"
+ " void *bt[10];\n"
+ " return backtrace(bt, 10) < x;\n"
+ "}" },
+ { "HAVE_BIG_ENDIAN", "big endian",
+ "INSIDE_MAIN|EXECUTE", NULL, NULL,
+ "union { int i; char c[sizeof(int)]; } u;\n"
+ "u.i = 0x01020304;\n"
+ "return u.c[0] == 0x01 && u.c[1] == 0x02 && u.c[2] == 0x03 && u.c[3] == 0x04 ? 0 : 1;" },
+ { "HAVE_BSWAP_64", "bswap64 in byteswap.h",
+ "DEFINES_FUNC", "HAVE_BYTESWAP_H", NULL,
+ "#include <byteswap.h>\n"
+ "static int func(int x) { return bswap_64(x); }" },
+ { "HAVE_BUILTIN_CHOOSE_EXPR", "__builtin_choose_expr support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_choose_expr(1, 0, \"garbage\");" },
+ { "HAVE_BUILTIN_CLZ", "__builtin_clz support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_clz(1) == (sizeof(int)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CLZL", "__builtin_clzl support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_clzl(1) == (sizeof(long)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CLZLL", "__builtin_clzll support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_clzll(1) == (sizeof(long long)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CTZ", "__builtin_ctz support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ctz(1 << (sizeof(int)*8 - 1)) == (sizeof(int)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CTZL", "__builtin_ctzl support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ctzl(1UL << (sizeof(long)*8 - 1)) == (sizeof(long)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CTZLL", "__builtin_ctzll support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ctzll(1ULL << (sizeof(long long)*8 - 1)) == (sizeof(long long)*8 - 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_CONSTANT_P", "__builtin_constant_p support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_constant_p(1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_EXPECT", "__builtin_expect support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_expect(argc == 1, 1) ? 0 : 1;" },
+ { "HAVE_BUILTIN_FFS", "__builtin_ffs support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ffs(0) == 0 ? 0 : 1;" },
+ { "HAVE_BUILTIN_FFSL", "__builtin_ffsl support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ffsl(0L) == 0 ? 0 : 1;" },
+ { "HAVE_BUILTIN_FFSLL", "__builtin_ffsll support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_ffsll(0LL) == 0 ? 0 : 1;" },
+ { "HAVE_BUILTIN_POPCOUNT", "__builtin_popcount support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_popcount(255) == 8 ? 0 : 1;" },
+ { "HAVE_BUILTIN_POPCOUNTL", "__builtin_popcountl support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_popcountl(255L) == 8 ? 0 : 1;" },
+ { "HAVE_BUILTIN_POPCOUNTLL", "__builtin_popcountll support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_popcountll(255LL) == 8 ? 0 : 1;" },
+ { "HAVE_BUILTIN_TYPES_COMPATIBLE_P", "__builtin_types_compatible_p support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return __builtin_types_compatible_p(char *, int) ? 1 : 0;" },
+ { "HAVE_ICCARM_INTRINSICS", "<intrinsics.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <intrinsics.h>\n"
+ "int func(int v) {\n"
+ " return __CLZ(__RBIT(v));\n"
+ "}" },
+ { "HAVE_BYTESWAP_H", "<byteswap.h>",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "#include <byteswap.h>\n" },
+ { "HAVE_CLOCK_GETTIME", "clock_gettime() declaration",
+ "DEFINES_FUNC", "HAVE_STRUCT_TIMESPEC", NULL,
+ "#include <time.h>\n"
+ "static struct timespec func(void) {\n"
+ " struct timespec ts;\n"
+ " clock_gettime(CLOCK_REALTIME, &ts);\n"
+ " return ts;\n"
+ "}\n" },
+ { "HAVE_CLOCK_GETTIME_IN_LIBRT", "clock_gettime() in librt",
+ "DEFINES_FUNC",
+ "HAVE_STRUCT_TIMESPEC !HAVE_CLOCK_GETTIME",
+ "-lrt",
+ "#include <time.h>\n"
+ "static struct timespec func(void) {\n"
+ " struct timespec ts;\n"
+ " clock_gettime(CLOCK_REALTIME, &ts);\n"
+ " return ts;\n"
+ "}\n",
+ "HAVE_CLOCK_GETTIME" },
+ { "HAVE_COMPOUND_LITERALS", "compound literal support",
+ "INSIDE_MAIN", NULL, NULL,
+ "int *foo = (int[]) { 1, 2, 3, 4 };\n"
+ "return foo[0] ? 0 : 1;" },
+ { "HAVE_FCHDIR", "fchdir support",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL,
+ "#include <sys/types.h>\n"
+ "#include <sys/stat.h>\n"
+ "#include <fcntl.h>\n"
+ "#include <unistd.h>\n"
+ "int main(void) {\n"
+ " int fd = open(\"..\", O_RDONLY);\n"
+ " return fchdir(fd) == 0 ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_ERR_H", "<err.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <err.h>\n"
+ "static void func(int arg) {\n"
+ " if (arg == 0)\n"
+ " err(1, \"err %u\", arg);\n"
+ " if (arg == 1)\n"
+ " errx(1, \"err %u\", arg);\n"
+ " if (arg == 3)\n"
+ " warn(\"warn %u\", arg);\n"
+ " if (arg == 4)\n"
+ " warnx(\"warn %u\", arg);\n"
+ "}\n" },
+ { "HAVE_FILE_OFFSET_BITS", "_FILE_OFFSET_BITS to get 64-bit offsets",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE",
+ "HAVE_32BIT_OFF_T", NULL,
+ "#define _FILE_OFFSET_BITS 64\n"
+ "#include <sys/types.h>\n"
+ "int main(void) {\n"
+ " return sizeof(off_t) == 8 ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_FOR_LOOP_DECLARATION", "for loop declaration support",
+ "INSIDE_MAIN", NULL, NULL,
+ "int ret = 1;\n"
+ "for (int i = 0; i < argc; i++) { ret = 0; };\n"
+ "return ret;" },
+ { "HAVE_FLEXIBLE_ARRAY_MEMBER", "flexible array member support",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "struct foo { unsigned int x; int arr[]; };" },
+ { "HAVE_GETPAGESIZE", "getpagesize() in <unistd.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <unistd.h>\n"
+ "static int func(void) { return getpagesize(); }" },
+ { "HAVE_ISBLANK", "isblank() in <ctype.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#ifndef _GNU_SOURCE\n"
+ "#define _GNU_SOURCE\n"
+ "#endif\n"
+ "#include <ctype.h>\n"
+ "static int func(void) { return isblank(' '); }" },
+ { "HAVE_LITTLE_ENDIAN", "little endian",
+ "INSIDE_MAIN|EXECUTE", NULL, NULL,
+ "union { int i; char c[sizeof(int)]; } u;\n"
+ "u.i = 0x01020304;\n"
+ "return u.c[0] == 0x04 && u.c[1] == 0x03 && u.c[2] == 0x02 && u.c[3] == 0x01 ? 0 : 1;" },
+ { "HAVE_MEMMEM", "memmem in <string.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#ifndef _GNU_SOURCE\n"
+ "#define _GNU_SOURCE\n"
+ "#endif\n"
+ "#include <string.h>\n"
+ "static void *func(void *h, size_t hl, void *n, size_t nl) {\n"
+ "return memmem(h, hl, n, nl);"
+ "}\n", },
+ { "HAVE_MEMRCHR", "memrchr in <string.h>",
+ "DEFINES_FUNC", NULL, NULL,
+ "#ifndef _GNU_SOURCE\n"
+ "#define _GNU_SOURCE\n"
+ "#endif\n"
+ "#include <string.h>\n"
+ "static void *func(void *s, int c, size_t n) {\n"
+ "return memrchr(s, c, n);"
+ "}\n", },
+ { "HAVE_MMAP", "mmap() declaration",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <sys/mman.h>\n"
+ "static void *func(int fd) {\n"
+ " return mmap(0, 65536, PROT_READ, MAP_SHARED, fd, 0);\n"
+ "}" },
+ { "HAVE_PROC_SELF_MAPS", "/proc/self/maps exists",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL,
+ "#include <sys/types.h>\n"
+ "#include <sys/stat.h>\n"
+ "#include <fcntl.h>\n"
+ "int main(void) {\n"
+ " return open(\"/proc/self/maps\", O_RDONLY) != -1 ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_QSORT_R_PRIVATE_LAST", "qsort_r cmp takes trailing arg",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL,
+ "#ifndef _GNU_SOURCE\n"
+ "#define _GNU_SOURCE\n"
+ "#endif\n"
+ "#include <stdlib.h>\n"
+ "static int cmp(const void *lp, const void *rp, void *priv) {\n"
+ " *(unsigned int *)priv = 1;\n"
+ " return *(const int *)lp - *(const int *)rp; }\n"
+ "int main(void) {\n"
+ " int array[] = { 9, 2, 5 };\n"
+ " unsigned int called = 0;\n"
+ " qsort_r(array, 3, sizeof(int), cmp, &called);\n"
+ " return called && array[0] == 2 && array[1] == 5 && array[2] == 9 ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_STRUCT_TIMESPEC", "struct timespec declaration",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <time.h>\n"
+ "static void func(void) {\n"
+ " struct timespec ts;\n"
+ " ts.tv_sec = ts.tv_nsec = 1;\n"
+ "}\n" },
+ { "HAVE_SECTION_START_STOP", "__attribute__((section)) and __start/__stop",
+ "DEFINES_FUNC", NULL, NULL,
+ "static void *__attribute__((__section__(\"mysec\"))) p = &p;\n"
+ "static int func(void) {\n"
+ " extern void *__start_mysec[], *__stop_mysec[];\n"
+ " return __stop_mysec - __start_mysec;\n"
+ "}\n" },
+ { "HAVE_STACK_GROWS_UPWARDS", "stack grows upwards",
+ "DEFINES_EVERYTHING|EXECUTE", NULL, NULL,
+ "#include <stddef.h>\n"
+ "static ptrdiff_t nest(const void *base, unsigned int i)\n"
+ "{\n"
+ " if (i == 0)\n"
+ " return (const char *)&i - (const char *)base;\n"
+ " return nest(base, i-1);\n"
+ "}\n"
+ "int main(int argc, char *argv[]) {\n"
+ " (void)argv;\n"
+ " return (nest(&argc, argc) > 0) ? 0 : 1;\n"
+ "}\n" },
+ { "HAVE_STATEMENT_EXPR", "statement expression support",
+ "INSIDE_MAIN", NULL, NULL,
+ "return ({ int x = argc; x == argc ? 0 : 1; });" },
+ { "HAVE_SYS_FILIO_H", "<sys/filio.h>",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "#include <sys/filio.h>\n" },
+ { "HAVE_SYS_TERMIOS_H", "<sys/termios.h>",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "#include <sys/termios.h>\n" },
+ { "HAVE_SYS_UNISTD_H", "<sys/unistd.h>",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "#include <sys/unistd.h>\n" },
+ { "HAVE_TYPEOF", "__typeof__ support",
+ "INSIDE_MAIN", NULL, NULL,
+ "__typeof__(argc) i; i = argc; return i == argc ? 0 : 1;" },
+ { "HAVE_UTIME", "utime() declaration",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <sys/types.h>\n"
+ "#include <utime.h>\n"
+ "static int func(const char *filename) {\n"
+ " struct utimbuf times = { 0 };\n"
+ " return utime(filename, ×);\n"
+ "}" },
+ { "HAVE_WARN_UNUSED_RESULT", "__attribute__((warn_unused_result))",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <sys/types.h>\n"
+ "#include <utime.h>\n"
+ "static __attribute__((warn_unused_result)) int func(int i) {\n"
+ " return i + 1;\n"
+ "}" },
+ { "HAVE_OPENMP", "#pragma omp and -fopenmp support",
+ "INSIDE_MAIN|EXECUTE|MAY_NOT_COMPILE", NULL, NULL,
+ "int i;\n"
+ "#pragma omp parallel for\n"
+ "for(i = 0; i < 0; i++) {};\n"
+ "return 0;\n",
+ "-Werror -fopenmp" },
+ { "HAVE_VALGRIND_MEMCHECK_H", "<valgrind/memcheck.h>",
+ "OUTSIDE_MAIN", NULL, NULL,
+ "#include <valgrind/memcheck.h>\n" },
+ { "HAVE_UCONTEXT", "working <ucontext.h",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE",
+ NULL, NULL,
+ "#include <ucontext.h>\n"
+ "static int x = 0;\n"
+ "static char stack[2048];\n"
+ "static ucontext_t a, b;\n"
+ "static void fn(void) {\n"
+ " x |= 2;\n"
+ " setcontext(&b);\n"
+ " x |= 4;\n"
+ "}\n"
+ "int main(void) {\n"
+ " x |= 1;\n"
+ " getcontext(&a);\n"
+ " a.uc_stack.ss_sp = stack;\n"
+ " a.uc_stack.ss_size = sizeof(stack);\n"
+ " makecontext(&a, fn, 0);\n"
+ " swapcontext(&b, &a);\n"
+ " return (x == 3) ? 0 : 1;\n"
+ "}\n"
+ },
+ { "HAVE_POINTER_SAFE_MAKECONTEXT", "passing pointers via makecontext()",
+ "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE",
+ "HAVE_UCONTEXT", NULL,
+ "#include <stddef.h>\n"
+ "#include <ucontext.h>\n"
+ "static int worked = 0;\n"
+ "static char stack[1024];\n"
+ "static ucontext_t a, b;\n"
+ "static void fn(void *p, void *q) {\n"
+ " void *cp = &worked;\n"
+ " void *cq = (void *)(~((ptrdiff_t)cp));\n"
+ " if ((p == cp) && (q == cq))\n"
+ " worked = 1;\n"
+ " setcontext(&b);\n"
+ "}\n"
+ "int main(void) {\n"
+ " void *ap = &worked;\n"
+ " void *aq = (void *)(~((ptrdiff_t)ap));\n"
+ " getcontext(&a);\n"
+ " a.uc_stack.ss_sp = stack;\n"
+ " a.uc_stack.ss_size = sizeof(stack);\n"
+ " makecontext(&a, (void (*)(void))fn, 2, ap, aq);\n"
+ " swapcontext(&b, &a);\n"
+ " return worked ? 0 : 1;\n"
+ "}\n"
+ },
+ { "HAVE_BUILTIN_CPU_SUPPORTS", "__builtin_cpu_supports()",
+ "DEFINES_FUNC", NULL, NULL,
+ "#include <stdbool.h>\n"
+ "static bool func(void) {\n"
+ " return __builtin_cpu_supports(\"mmx\");\n"
+ "}"
+ },
+ { "HAVE_CLOSEFROM", "closefrom() offered by system",
+ "DEFINES_EVERYTHING", NULL, NULL,
+ "#include <stdlib.h>\n"
+ "#include <unistd.h>\n"
+ "int main(void) {\n"
+ " closefrom(STDERR_FILENO + 1);\n"
+ " return 0;\n"
+ "}\n"
+ },
+ { "HAVE_F_CLOSEM", "F_CLOSEM defined for fctnl.",
+ "DEFINES_EVERYTHING", NULL, NULL,
+ "#include <fcntl.h>\n"
+ "#include <unistd.h>\n"
+ "int main(void) {\n"
+ " int res = fcntl(STDERR_FILENO + 1, F_CLOSEM, 0);\n"
+ " return res < 0;\n"
+ "}\n"
+ },
+ { "HAVE_NR_CLOSE_RANGE", "close_range syscall available as __NR_close_range.",
+ "DEFINES_EVERYTHING", NULL, NULL,
+ "#include <limits.h>\n"
+ "#include <sys/syscall.h>\n"
+ "#include <unistd.h>\n"
+ "int main(void) {\n"
+ " int res = syscall(__NR_close_range, STDERR_FILENO + 1, INT_MAX, 0);\n"
+ " return res < 0;\n"
+ "}\n"
+ },
+ { "HAVE_F_MAXFD", "F_MAXFD defined for fcntl.",
+ "DEFINES_EVERYTHING", NULL, NULL,
+ "#include <fcntl.h>\n"
+ "#include <unistd.h>\n"
+ "int main(void) {\n"
+ " int res = fcntl(0, F_MAXFD);\n"
+ " return res < 0;\n"
+ "}\n"
+ },
+ */
+};
+
+static void c12r_err(int eval, const char *fmt, ...)
+{
+ int err_errno = errno;
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, ": %s\n", strerror(err_errno));
+ exit(eval);
+}
+
+static void c12r_errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ exit(eval);
+}
+
+static void start_test(const char *what, const char *why)
+{
+ if (like_a_libtool) {
+ printf("%s%s... ", what, why);
+ fflush(stdout);
+ }
+}
+
+static void end_test(bool result)
+{
+ if (like_a_libtool)
+ printf("%s\n", result ? "yes" : "no");
+}
+
+static size_t fcopy(FILE *fsrc, FILE *fdst)
+{
+ char buffer[BUFSIZ];
+ size_t rsize, wsize;
+ size_t copied = 0;
+
+ while ((rsize = fread(buffer, 1, BUFSIZ, fsrc)) > 0) {
+ wsize = fwrite(buffer, 1, rsize, fdst);
+ copied += wsize;
+ if (wsize != rsize)
+ break;
+ }
+
+ return copied;
+}
+
+static char *grab_stream(FILE *file)
+{
+ size_t max, ret, size = 0;
+ char *buffer;
+
+ max = BUFSIZ;
+ buffer = malloc(max);
+ while ((ret = fread(buffer+size, 1, max - size, file)) == max - size) {
+ size += ret;
+ buffer = realloc(buffer, max *= 2);
+ }
+ size += ret;
+ if (ferror(file))
+ c12r_err(EXIT_TROUBLE_RUNNING, "reading from command");
+ buffer[size] = '\0';
+ return buffer;
+}
+
+static char *run(const char *cmd, int *exitstatus)
+{
+ static const char redir[] = " 2>&1";
+ size_t cmdlen;
+ char *cmdredir;
+ FILE *cmdout;
+ char *ret;
+
+ cmdlen = strlen(cmd);
+ cmdredir = malloc(cmdlen + sizeof(redir));
+ memcpy(cmdredir, cmd, cmdlen);
+ memcpy(cmdredir + cmdlen, redir, sizeof(redir));
+
+ cmdout = popen(cmdredir, "r");
+ if (!cmdout)
+ c12r_err(EXIT_TROUBLE_RUNNING, "popen \"%s\"", cmdredir);
+
+ free(cmdredir);
+
+ ret = grab_stream(cmdout);
+ *exitstatus = pclose(cmdout);
+ return ret;
+}
+
+static char *connect_args(const char *argv[], const char *outflag,
+ const char *files)
+{
+ unsigned int i;
+ char *ret;
+ size_t len = strlen(outflag) + strlen(files) + 1;
+
+ for (i = 1; argv[i]; i++)
+ len += 1 + strlen(argv[i]);
+
+ ret = malloc(len);
+ len = 0;
+ for (i = 1; argv[i]; i++) {
+ strcpy(ret + len, argv[i]);
+ len += strlen(argv[i]);
+ if (argv[i+1] || *outflag)
+ ret[len++] = ' ';
+ }
+ strcpy(ret + len, outflag);
+ len += strlen(outflag);
+ strcpy(ret + len, files);
+ return ret;
+}
+
+static struct test *find_test(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; tests[i].name; i++) {
+ if (strcmp(tests[i].name, name) == 0)
+ return &tests[i];
+ }
+ c12r_errx(EXIT_BAD_TEST, "Unknown test %s", name);
+ abort();
+}
+
+#define PRE_BOILERPLATE "/* Test program generated by configurator. */\n"
+#define MAIN_START_BOILERPLATE \
+ "int main(int argc, char *argv[]) {\n" \
+ " (void)argc;\n" \
+ " (void)argv;\n"
+#define USE_FUNC_BOILERPLATE "(void)func;\n"
+#define MAIN_BODY_BOILERPLATE "return 0;\n"
+#define MAIN_END_BOILERPLATE "}\n"
+
+static bool run_test(const char *cmd, const char *wrapper, struct test *test)
+{
+ char *output, *newcmd;
+ FILE *outf;
+ int status;
+
+ if (test->done)
+ return test->answer;
+
+ if (test->depends) {
+ size_t len;
+ const char *deps = test->depends;
+ char *dep;
+
+ /* Space-separated dependencies, could be ! for inverse. */
+ while ((len = strcspn(deps, " ")) != 0) {
+ bool positive = true;
+ if (deps[len]) {
+ dep = strdup(deps);
+ dep[len] = '\0';
+ } else {
+ dep = (char *)deps;
+ }
+
+ if (dep[0] == '!') {
+ dep++;
+ positive = false;
+ }
+ if (run_test(cmd, wrapper, find_test(dep)) != positive) {
+ test->answer = false;
+ test->done = true;
+ return test->answer;
+ }
+ if (deps[len])
+ free(dep);
+
+ deps += len;
+ deps += strspn(deps, " ");
+ }
+ }
+
+ outf = fopen(INPUT_FILE, verbose > 1 ? "w+" : "w");
+ if (!outf)
+ c12r_err(EXIT_TROUBLE_RUNNING, "creating %s", INPUT_FILE);
+
+ fprintf(outf, "%s", PRE_BOILERPLATE);
+
+ if (strstr(test->style, "INSIDE_MAIN")) {
+ fprintf(outf, "%s", MAIN_START_BOILERPLATE);
+ fprintf(outf, "%s", test->fragment);
+ fprintf(outf, "%s", MAIN_END_BOILERPLATE);
+ } else if (strstr(test->style, "OUTSIDE_MAIN")) {
+ fprintf(outf, "%s", test->fragment);
+ fprintf(outf, "%s", MAIN_START_BOILERPLATE);
+ fprintf(outf, "%s", MAIN_BODY_BOILERPLATE);
+ fprintf(outf, "%s", MAIN_END_BOILERPLATE);
+ } else if (strstr(test->style, "DEFINES_FUNC")) {
+ fprintf(outf, "%s", test->fragment);
+ fprintf(outf, "%s", MAIN_START_BOILERPLATE);
+ fprintf(outf, "%s", USE_FUNC_BOILERPLATE);
+ fprintf(outf, "%s", MAIN_BODY_BOILERPLATE);
+ fprintf(outf, "%s", MAIN_END_BOILERPLATE);
+ } else if (strstr(test->style, "DEFINES_EVERYTHING")) {
+ fprintf(outf, "%s", test->fragment);
+ } else
+ c12r_errx(EXIT_BAD_TEST, "Unknown style for test %s: %s",
+ test->name, test->style);
+
+ if (verbose > 1) {
+ fseek(outf, 0, SEEK_SET);
+ fcopy(outf, stdout);
+ }
+
+ fclose(outf);
+
+ newcmd = strdup(cmd);
+
+ if (test->flags) {
+ newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ")
+ + strlen(test->flags) + 1);
+ strcat(newcmd, " ");
+ strcat(newcmd, test->flags);
+ if (verbose > 1)
+ printf("Extra flags line: %s", newcmd);
+ }
+
+ if (test->link) {
+ newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ")
+ + strlen(test->link) + 1);
+ strcat(newcmd, " ");
+ strcat(newcmd, test->link);
+ if (verbose > 1)
+ printf("Extra link line: %s", newcmd);
+ }
+
+ start_test("checking for ", test->desc);
+ output = run(newcmd, &status);
+
+ free(newcmd);
+
+ if (status != 0 || strstr(output, "warning")) {
+ if (verbose)
+ printf("Compile %s for %s, status %i: %s\n",
+ status ? "fail" : "warning",
+ test->name, status, output);
+ if (strstr(test->style, "EXECUTE")
+ && !strstr(test->style, "MAY_NOT_COMPILE"))
+ c12r_errx(EXIT_BAD_TEST,
+ "Test for %s did not compile:\n%s",
+ test->name, output);
+ test->answer = false;
+ free(output);
+ } else {
+ /* Compile succeeded. */
+ free(output);
+ /* We run INSIDE_MAIN tests for sanity checking. */
+ if (strstr(test->style, "EXECUTE")
+ || strstr(test->style, "INSIDE_MAIN")) {
+ char *cmd = malloc(strlen(wrapper) + strlen(" ." DIR_SEP OUTPUT_FILE) + 1);
+
+ strcpy(cmd, wrapper);
+ strcat(cmd, " ." DIR_SEP OUTPUT_FILE);
+ output = run(cmd, &status);
+ free(cmd);
+ if (!strstr(test->style, "EXECUTE") && status != 0)
+ c12r_errx(EXIT_BAD_TEST,
+ "Test for %s failed with %i:\n%s",
+ test->name, status, output);
+ if (verbose && status)
+ printf("%s exited %i\n", test->name, status);
+ free(output);
+ }
+ test->answer = (status == 0);
+ }
+ test->done = true;
+ end_test(test->answer);
+
+ if (test->answer && test->overrides) {
+ struct test *override = find_test(test->overrides);
+ override->done = true;
+ override->answer = true;
+ }
+ return test->answer;
+}
+
+static char *any_field(char **fieldname)
+{
+ char buf[1000];
+ for (;;) {
+ char *p, *eq;
+
+ if (!fgets(buf, sizeof(buf), stdin))
+ return NULL;
+
+ p = buf;
+ /* Ignore whitespace, lines starting with # */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (*p == '#' || *p == '\n')
+ continue;
+
+ eq = strchr(p, '=');
+ if (!eq)
+ c12r_errx(EXIT_BAD_INPUT, "no = in line: %s", p);
+ *eq = '\0';
+ *fieldname = strdup(p);
+ p = eq + 1;
+ if (strlen(p) && p[strlen(p)-1] == '\n')
+ p[strlen(p)-1] = '\0';
+ return strdup(p);
+ }
+}
+
+static char *read_field(const char *name, bool compulsory)
+{
+ char *fieldname, *value;
+
+ value = any_field(&fieldname);
+ if (!value) {
+ if (!compulsory)
+ return NULL;
+ c12r_errx(EXIT_BAD_INPUT, "Could not read field %s", name);
+ }
+ if (strcmp(fieldname, name) != 0)
+ c12r_errx(EXIT_BAD_INPUT,
+ "Expected field %s not %s", name, fieldname);
+ return value;
+}
+
+/* Test descriptions from stdin:
+ * Lines starting with # or whitespace-only are ignored.
+ *
+ * First three non-ignored lines must be:
+ * var=<varname>
+ * desc=<description-for-autotools-style>
+ * style=OUTSIDE_MAIN DEFINES_FUNC INSIDE_MAIN DEFINES_EVERYTHING EXECUTE MAY_NOT_COMPILE
+ *
+ * Followed by optional lines:
+ * depends=<space-separated-testnames, ! to invert>
+ * link=<extra args for link line>
+ * flags=<extra args for compile line>
+ * overrides=<testname-to-force>
+ *
+ * Finally a code line, either:
+ * code=<oneline> OR
+ * code=
+ * <lines of code>
+ * <end-comment>
+ *
+ * And <end-comment> looks like this next comment: */
+/*END*/
+static bool read_test(struct test *test)
+{
+ char *field, *value;
+ char buf[1000];
+
+ memset(test, 0, sizeof(*test));
+ test->name = read_field("var", false);
+ if (!test->name)
+ return false;
+ test->desc = read_field("desc", true);
+ test->style = read_field("style", true);
+ /* Read any optional fields. */
+ while ((value = any_field(&field)) != NULL) {
+ if (strcmp(field, "depends") == 0)
+ test->depends = value;
+ else if (strcmp(field, "link") == 0)
+ test->link = value;
+ else if (strcmp(field, "flags") == 0)
+ test->flags = value;
+ else if (strcmp(field, "overrides") == 0)
+ test->overrides = value;
+ else if (strcmp(field, "code") == 0)
+ break;
+ else
+ c12r_errx(EXIT_BAD_INPUT, "Unknown field %s in %s",
+ field, test->name);
+ }
+ if (!value)
+ c12r_errx(EXIT_BAD_INPUT, "Missing code in %s", test->name);
+
+ if (strlen(value) == 0) {
+ /* Multiline program, read to END comment */
+ while (fgets(buf, sizeof(buf), stdin) != 0) {
+ size_t n;
+ if (strncmp(buf, "/*END*/", 7) == 0)
+ break;
+ n = strlen(value);
+ value = realloc(value, n + strlen(buf) + 1);
+ strcpy(value + n, buf);
+ n += strlen(buf);
+ }
+ }
+ test->fragment = value;
+ return true;
+}
+
+static void read_tests(size_t num_tests)
+{
+ while (read_test(tests + num_tests)) {
+ num_tests++;
+ tests = realloc(tests, (num_tests + 1) * sizeof(tests[0]));
+ tests[num_tests].name = NULL;
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ char *cmd;
+ unsigned int i;
+ const char *default_args[]
+ = { "", DEFAULT_COMPILER, DEFAULT_FLAGS, NULL };
+ const char *outflag = DEFAULT_OUTPUT_EXE_FLAG;
+ const char *configurator_cc = NULL;
+ const char *wrapper = "";
+ const char *orig_cc;
+ const char *varfile = NULL;
+ const char *headerfile = NULL;
+ bool extra_tests = false;
+ FILE *outf;
+
+ if (argc > 0)
+ progname = argv[0];
+
+ while (argc > 1) {
+ if (strcmp(argv[1], "--help") == 0) {
+ printf("Usage: configurator [-v] [--var-file=<filename>] [-O<outflag>] [--configurator-cc=<compiler-for-tests>] [--wrapper=<wrapper-for-tests>] [--autotools-style] [--extra-tests] [<compiler> <flags>...]\n"
+ " <compiler> <flags> will have \"<outflag> <outfile> <infile.c>\" appended\n"
+ "Default: %s %s %s\n",
+ DEFAULT_COMPILER, DEFAULT_FLAGS,
+ DEFAULT_OUTPUT_EXE_FLAG);
+ exit(0);
+ }
+ if (strncmp(argv[1], "-O", 2) == 0) {
+ argc--;
+ argv++;
+ outflag = argv[1] + 2;
+ if (!*outflag) {
+ fprintf(stderr,
+ "%s: option requires an argument -- O\n",
+ argv[0]);
+ exit(EXIT_BAD_USAGE);
+ }
+ } else if (strcmp(argv[1], "-v") == 0) {
+ argc--;
+ argv++;
+ verbose++;
+ } else if (strcmp(argv[1], "-vv") == 0) {
+ argc--;
+ argv++;
+ verbose += 2;
+ } else if (strncmp(argv[1], "--configurator-cc=", 18) == 0) {
+ configurator_cc = argv[1] + 18;
+ argc--;
+ argv++;
+ } else if (strncmp(argv[1], "--wrapper=", 10) == 0) {
+ wrapper = argv[1] + 10;
+ argc--;
+ argv++;
+ } else if (strncmp(argv[1], "--var-file=", 11) == 0) {
+ varfile = argv[1] + 11;
+ argc--;
+ argv++;
+ } else if (strcmp(argv[1], "--autotools-style") == 0) {
+ like_a_libtool = true;
+ argc--;
+ argv++;
+ } else if (strncmp(argv[1], "--header-file=", 14) == 0) {
+ headerfile = argv[1] + 14;
+ argc--;
+ argv++;
+ } else if (strcmp(argv[1], "--extra-tests") == 0) {
+ extra_tests = true;
+ argc--;
+ argv++;
+ } else if (strcmp(argv[1], "--") == 0) {
+ break;
+ } else if (argv[1][0] == '-') {
+ c12r_errx(EXIT_BAD_USAGE, "Unknown option %s", argv[1]);
+ } else {
+ break;
+ }
+ }
+
+ if (argc == 1)
+ argv = default_args;
+
+ /* Copy with NULL entry at end */
+ tests = calloc(sizeof(base_tests)/sizeof(base_tests[0]) + 1,
+ sizeof(base_tests[0]));
+ memcpy(tests, base_tests, sizeof(base_tests));
+
+ if (extra_tests)
+ read_tests(sizeof(base_tests)/sizeof(base_tests[0]));
+
+ orig_cc = argv[1];
+ if (configurator_cc)
+ argv[1] = configurator_cc;
+
+ cmd = connect_args(argv, outflag, OUTPUT_FILE " " INPUT_FILE);
+ if (like_a_libtool) {
+ start_test("Making autoconf users comfortable", "");
+ sleep(1);
+ end_test(1);
+ }
+ for (i = 0; tests[i].name; i++)
+ run_test(cmd, wrapper, &tests[i]);
+ free(cmd);
+
+ remove(OUTPUT_FILE);
+ remove(INPUT_FILE);
+
+ if (varfile) {
+ FILE *vars;
+
+ if (strcmp(varfile, "-") == 0)
+ vars = stdout;
+ else {
+ start_test("Writing variables to ", varfile);
+ vars = fopen(varfile, "a");
+ if (!vars)
+ c12r_err(EXIT_TROUBLE_RUNNING,
+ "Could not open %s", varfile);
+ }
+ for (i = 0; tests[i].name; i++)
+ fprintf(vars, "%s=%u\n", tests[i].name, tests[i].answer);
+ if (vars != stdout) {
+ if (fclose(vars) != 0)
+ c12r_err(EXIT_TROUBLE_RUNNING,
+ "Closing %s", varfile);
+ end_test(1);
+ }
+ }
+
+ if (headerfile) {
+ start_test("Writing header to ", headerfile);
+ outf = fopen(headerfile, "w");
+ if (!outf)
+ c12r_err(EXIT_TROUBLE_RUNNING,
+ "Could not open %s", headerfile);
+ } else
+ outf = stdout;
+
+ fprintf(outf, "/* Generated by CCAN configurator */\n"
+ "#ifndef CCAN_CONFIG_H\n"
+ "#define CCAN_CONFIG_H\n");
+ fprintf(outf, "#ifndef _GNU_SOURCE\n");
+ fprintf(outf, "#define _GNU_SOURCE /* Always use GNU extensions. */\n");
+ fprintf(outf, "#endif\n");
+ fprintf(outf, "#define CCAN_COMPILER \"%s\"\n", orig_cc);
+ cmd = connect_args(argv + 1, "", "");
+ fprintf(outf, "#define CCAN_CFLAGS \"%s\"\n", cmd);
+ free(cmd);
+ fprintf(outf, "#define CCAN_OUTPUT_EXE_CFLAG \"%s\"\n\n", outflag);
+ /* This one implies "#include <ccan/..." works, eg. for tdb2.h */
+ fprintf(outf, "#define HAVE_CCAN 1\n");
+ for (i = 0; tests[i].name; i++)
+ fprintf(outf, "#define %s %u\n", tests[i].name, tests[i].answer);
+ fprintf(outf, "#endif /* CCAN_CONFIG_H */\n");
+
+ if (headerfile) {
+ if (fclose(outf) != 0)
+ c12r_err(EXIT_TROUBLE_RUNNING, "Closing %s", headerfile);
+ end_test(1);
+ }
+
+ return 0;
+}
diff --git a/deps/rotate-bits/package.json b/deps/rotate-bits/package.json
@@ -1,13 +0,0 @@
-{
- "name": "rotate-bits",
- "version": "0.1.1",
- "repo": "jb55/rotate-bits.h",
- "description": "rotate bits",
- "keywords": ["rotl", "rotr"],
- "src": ["rotate-bits.h"],
- "license": "Public Domain",
- "development": {
- "thlorenz/tap.c": "*"
- }
-}
-
diff --git a/deps/rotate-bits/rotate-bits.h b/deps/rotate-bits/rotate-bits.h
@@ -1,46 +0,0 @@
-
-
-#ifndef __ROTATE_DEFS_H
-#define __ROTATE_DEFS_H
-
-#ifdef _MSC_VER
-
-#include <stdlib.h>
-
-#define ROTL32(v, n) _rotl((v), (n))
-#define ROTL64(v, n) _rotl64((v), (n))
-
-#define ROTR32(v, n) _rotr((v), (n))
-#define ROTR64(v, n) _rotr64((v), (n))
-
-#else
-
-#include <stdint.h>
-
-#define U8V(v) ((uint8_t)(v) & 0xFFU)
-#define U16V(v) ((uint16_t)(v) & 0xFFFFU)
-#define U32V(v) ((uint32_t)(v) & 0xFFFFFFFFU)
-#define U64V(v) ((uint64_t)(v) & 0xFFFFFFFFFFFFFFFFU)
-
-#define ROTL32(v, n) \
- (U32V((uint32_t)(v) << (n)) | ((uint32_t)(v) >> (32 - (n))))
-
-// tests fail if we don't have this cast...
-#define ROTL64(v, n) \
- (U64V((uint64_t)(v) << (n)) | ((uint64_t)(v) >> (64 - (n))))
-
-#define ROTR32(v, n) ROTL32(v, 32 - (n))
-#define ROTR64(v, n) ROTL64(v, 64 - (n))
-
-#endif
-
-#define ROTL8(v, n) \
- (U8V((uint8_t)(v) << (n)) | ((uint8_t)(v) >> (8 - (n))))
-
-#define ROTL16(v, n) \
- (U16V((uint16_t)(v) << (n)) | ((uint16_t)(v) >> (16 - (n))))
-
-#define ROTR8(v, n) ROTL8(v, 8 - (n))
-#define ROTR16(v, n) ROTL16(v, 16 - (n))
-
-#endif
diff --git a/deps/sha256/package.json b/deps/sha256/package.json
@@ -1,15 +0,0 @@
-{
- "name": "sha256",
- "version": "0.0.2",
- "repo": "jb55/sha256.c",
- "description": "sha256 in c",
- "keywords": ["sha256", "sha2"],
- "src": ["sha256.c", "sha256.h"],
- "dependencies": {
- "jb55/rotate-bits.h": "0.1.1"
- },
- "development": {
- "thlorenz/tap.c": "*"
- }
-}
-
diff --git a/deps/sha256/sha256.c b/deps/sha256/sha256.c
@@ -1,221 +0,0 @@
-/* Crypto/Sha256.c -- SHA-256 Hash
-2010-06-11 : Igor Pavlov : Public domain
-This code is based on public domain code from Wei Dai's Crypto++ library. */
-
-#include "rotate-bits/rotate-bits.h"
-#include "sha256.h"
-
-/* define it for speed optimization */
-#define _SHA256_UNROLL
-#define _SHA256_UNROLL2
-
-void
-sha256_init(struct sha256 *p)
-{
- p->state[0] = 0x6a09e667;
- p->state[1] = 0xbb67ae85;
- p->state[2] = 0x3c6ef372;
- p->state[3] = 0xa54ff53a;
- p->state[4] = 0x510e527f;
- p->state[5] = 0x9b05688c;
- p->state[6] = 0x1f83d9ab;
- p->state[7] = 0x5be0cd19;
- p->count = 0;
-}
-
-#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x, 22))
-#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x, 25))
-#define s0(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ (x >> 3))
-#define s1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ (x >> 10))
-
-#define blk0(i) (W[i] = data[i])
-#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
-
-#define Ch(x,y,z) (z^(x&(y^z)))
-#define Maj(x,y,z) ((x&y)|(z&(x|y)))
-
-#define a(i) T[(0-(i))&7]
-#define b(i) T[(1-(i))&7]
-#define c(i) T[(2-(i))&7]
-#define d(i) T[(3-(i))&7]
-#define e(i) T[(4-(i))&7]
-#define f(i) T[(5-(i))&7]
-#define g(i) T[(6-(i))&7]
-#define h(i) T[(7-(i))&7]
-
-
-#ifdef _SHA256_UNROLL2
-
-#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
- d += h; h += S0(a) + Maj(a, b, c)
-
-#define RX_8(i) \
- R(a,b,c,d,e,f,g,h, i); \
- R(h,a,b,c,d,e,f,g, (i+1)); \
- R(g,h,a,b,c,d,e,f, (i+2)); \
- R(f,g,h,a,b,c,d,e, (i+3)); \
- R(e,f,g,h,a,b,c,d, (i+4)); \
- R(d,e,f,g,h,a,b,c, (i+5)); \
- R(c,d,e,f,g,h,a,b, (i+6)); \
- R(b,c,d,e,f,g,h,a, (i+7))
-
-#else
-
-#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
- d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
-
-#ifdef _SHA256_UNROLL
-
-#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
-
-#endif
-
-#endif
-
-static const uint32_t K[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-static void
-struct sha256ransform(uint32_t *state, const uint32_t *data)
-{
- uint32_t W[16];
- unsigned j;
- #ifdef _SHA256_UNROLL2
- uint32_t a,b,c,d,e,f,g,h;
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- f = state[5];
- g = state[6];
- h = state[7];
- #else
- uint32_t T[8];
- for (j = 0; j < 8; j++)
- T[j] = state[j];
- #endif
-
- for (j = 0; j < 64; j += 16)
- {
- #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
- RX_8(0); RX_8(8);
- #else
- unsigned i;
- for (i = 0; i < 16; i++) { R(i); }
- #endif
- }
-
- #ifdef _SHA256_UNROLL2
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- state[5] += f;
- state[6] += g;
- state[7] += h;
- #else
- for (j = 0; j < 8; j++)
- state[j] += T[j];
- #endif
-
- /* Wipe variables */
- /* memset(W, 0, sizeof(W)); */
- /* memset(T, 0, sizeof(T)); */
-}
-
-#undef S0
-#undef S1
-#undef s0
-#undef s1
-
-static void
-sha256_write_byte_block(struct sha256 *p)
-{
- uint32_t data32[16];
- unsigned i;
- for (i = 0; i < 16; i++)
- data32[i] =
- ((uint32_t)(p->buffer[i * 4 ]) << 24) +
- ((uint32_t)(p->buffer[i * 4 + 1]) << 16) +
- ((uint32_t)(p->buffer[i * 4 + 2]) << 8) +
- ((uint32_t)(p->buffer[i * 4 + 3]));
- struct sha256ransform(p->state, data32);
-}
-
-
-void
-sha256_hash(unsigned char *buf, const unsigned char *data, size_t size)
-{
- struct sha256 hash;
- sha256_init(&hash);
- sha256_update(&hash, data, size);
- sha256_final(&hash, buf);
-}
-
-
-void
-sha256_update(struct sha256 *p, const unsigned char *data, size_t size)
-{
- uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
- while (size > 0)
- {
- p->buffer[curBufferPos++] = *data++;
- p->count++;
- size--;
- if (curBufferPos == 64)
- {
- curBufferPos = 0;
- sha256_write_byte_block(p);
- }
- }
-}
-
-
-void
-sha256_final(struct sha256 *p, unsigned char *digest)
-{
- uint64_t lenInBits = (p->count << 3);
- uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
- unsigned i;
- p->buffer[curBufferPos++] = 0x80;
- while (curBufferPos != (64 - 8))
- {
- curBufferPos &= 0x3F;
- if (curBufferPos == 0)
- sha256_write_byte_block(p);
- p->buffer[curBufferPos++] = 0;
- }
- for (i = 0; i < 8; i++)
- {
- p->buffer[curBufferPos++] = (unsigned char)(lenInBits >> 56);
- lenInBits <<= 8;
- }
- sha256_write_byte_block(p);
-
- for (i = 0; i < 8; i++)
- {
- *digest++ = (unsigned char)(p->state[i] >> 24);
- *digest++ = (unsigned char)(p->state[i] >> 16);
- *digest++ = (unsigned char)(p->state[i] >> 8);
- *digest++ = (unsigned char)(p->state[i]);
- }
- sha256_init(p);
-}
diff --git a/deps/sha256/sha256.h b/deps/sha256/sha256.h
@@ -1,24 +0,0 @@
-/* Sha256.h -- SHA-256 Hash
-2010-06-11 : Igor Pavlov : Public domain */
-
-#ifndef __CRYPTO_SHA256_H
-#define __CRYPTO_SHA256_H
-
-#include <stdlib.h>
-#include <stdint.h>
-
-#define SHA256_DIGEST_SIZE 32
-
-struct sha256
-{
- uint32_t state[8];
- uint64_t count;
- unsigned char buffer[64];
-};
-
-void sha256_init(struct sha256 *p);
-void sha256_update(struct sha256 *p, const unsigned char *data, size_t size);
-void sha256_final(struct sha256 *p, unsigned char *digest);
-void sha256_hash(unsigned char *buf, const unsigned char *data, size_t size);
-
-#endif
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/handshake.h b/handshake.h
@@ -3,10 +3,10 @@
#define LNLINK_HANDSHAKE_H
#include "types.h"
+#include "sha256.h"
#include <sodium/crypto_aead_chacha20poly1305.h>
#include <secp256k1_extrakeys.h>
-#include <sha256/sha256.h>
#define PUBKEY_CMPR_LEN 33
@@ -20,7 +20,7 @@ struct secret {
};
struct pubkey {
- u8 data[64];
+ secp256k1_pubkey pubkey;
};
struct privkey {
@@ -99,7 +99,7 @@ struct handshake {
struct secret temp_k;
struct sha256 h;
struct keypair e;
- struct secret *ss;
+ struct secret ss;
/* Used between the Acts */
struct pubkey re;
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,258 @@
+
+#include <string.h>
+#include "hmac.h"
+
+#define IPAD 0x3636363636363636ULL
+#define OPAD 0x5C5C5C5C5C5C5C5CULL
+
+#define BLOCK_256_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t))
+#define BLOCK_512_U64S (HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t))
+
+static inline void xor_block_256(uint64_t block[BLOCK_256_U64S], uint64_t pad)
+{
+ size_t i;
+
+ for (i = 0; i < BLOCK_256_U64S; i++)
+ block[i] ^= pad;
+}
+
+
+static inline void xor_block_512(uint64_t block[BLOCK_512_U64S], uint64_t pad)
+{
+ size_t i;
+
+ for (i = 0; i < BLOCK_512_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_256(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_256(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_512(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_512(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/lnsocket.c b/lnsocket.c
@@ -0,0 +1,193 @@
+
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <secp256k1.h>
+#include <secp256k1_ecdh.h>
+#include <sodium/crypto_aead_chacha20poly1305.h>
+#include <sodium/randombytes.h>
+
+#include "sha256.h"
+#include "hkdf.h"
+#include "handshake.h"
+
+#define array_len(x) (sizeof(x)/sizeof(x[0]))
+
+struct lnsocket {
+ const char *errors[8];
+ int socket;
+ int num_errors;
+ secp256k1_context *secp_ctx;
+};
+
+
+static struct keypair generate_key(secp256k1_context *ctx)
+{
+ struct keypair k;
+
+ do {
+ randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data));
+ } while (!secp256k1_ec_pubkey_create(ctx, &k.pub.pubkey,
+ k.priv.secret.data));
+ return k;
+}
+
+
+static void push_error(struct lnsocket *lnsocket, const char *err)
+{
+ if (lnsocket->num_errors >= array_len(lnsocket->errors)) {
+ // TODO: push out old errors instead
+ return;
+ }
+
+ lnsocket->errors[lnsocket->num_errors++] = err;
+}
+
+static void lnsocket_init(struct lnsocket *lnsocket)
+{
+ memset(lnsocket, 0, sizeof(*lnsocket));
+
+ lnsocket->secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
+ SECP256K1_CONTEXT_SIGN);
+}
+
+/* h = SHA-256(h || data) */
+static void sha_mix_in(struct sha256 *h, const void *data, size_t len)
+{
+ struct sha256_ctx shactx;
+
+ sha256_init(&shactx);
+ sha256_update(&shactx, h->u.u8, sizeof(*h));
+ sha256_update(&shactx, data, len);
+ sha256_done(&shactx, h);
+}
+
+/* h = SHA-256(h || pub.serializeCompressed()) */
+static void sha_mix_in_key(secp256k1_context *ctx, struct sha256 *h,
+ const struct pubkey *key)
+{
+ u8 der[PUBKEY_CMPR_LEN];
+ size_t len = sizeof(der);
+
+ secp256k1_ec_pubkey_serialize(ctx, der, &len, &key->pubkey,
+ SECP256K1_EC_COMPRESSED);
+ assert(len == sizeof(der));
+ sha_mix_in(h, der, sizeof(der));
+}
+
+static int handshake_failed(struct lnsocket *ln, struct handshake *h)
+{
+ push_error(ln, "handshake failed");
+ return 0;
+}
+
+/* out1, out2 = HKDF(in1, in2)` */
+static void hkdf_two_keys(struct secret *out1, struct secret *out2,
+ const struct secret *in1,
+ const void *in2, size_t in2_size)
+{
+ /* BOLT #8:
+ *
+ * * `HKDF(salt,ikm)`: a function defined in `RFC 5869`<sup>[3](#reference-3)</sup>,
+ * evaluated with a zero-length `info` field
+ * * All invocations of `HKDF` implicitly return 64 bytes
+ * of cryptographic randomness using the extract-and-expand
+ * component of the `HKDF`.
+ */
+ struct secret okm[2];
+
+ hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, in2_size,
+ NULL, 0);
+ *out1 = okm[0];
+ *out2 = okm[1];
+}
+
+int act_one_initiator(struct lnsocket *ln, struct handshake *h)
+{
+ h->e = generate_key(ln->secp_ctx);
+
+ /* BOLT #8:
+ *
+ * 2. `h = SHA-256(h || e.pub.serializeCompressed())`
+ * * The newly generated ephemeral key is accumulated into the
+ * running handshake digest.
+ */
+ sha_mix_in_key(ln->secp_ctx, &h->h, &h->e.pub);
+
+ /* BOLT #8:
+ *
+ * 3. `es = ECDH(e.priv, rs)`
+ * * The initiator performs an ECDH between its newly generated ephemeral
+ * key and the remote node's static public key.
+ */
+ if (!secp256k1_ecdh(ln->secp_ctx, h->ss.data,
+ &h->their_id.pubkey, h->e.priv.secret.data,
+ NULL, NULL))
+ return handshake_failed(ln, h);
+
+ /* BOLT #8:
+ *
+ * 4. `ck, temp_k1 = HKDF(ck, es)`
+ * * A new temporary encryption key is generated, which is
+ * used to generate the authenticating MAC.
+ */
+ hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
+
+ return 1;
+}
+
+int connect_node(struct lnsocket *ln, const struct pubkey pubkey, const char *host)
+{
+ int ret;
+ struct addrinfo *addrs = NULL;
+ struct handshake h;
+
+ h.their_id = pubkey;
+
+ if ((ret = getaddrinfo(host, "9735", NULL, &addrs)) || !addrs) {
+ push_error(ln, gai_strerror(ret));
+ return 0;
+ }
+
+ if (!(ln->socket = socket(AF_INET, SOCK_STREAM, 0))) {
+ push_error(ln, "creating socket failed");
+ return 0;
+ }
+
+ if (connect(ln->socket, addrs->ai_addr, addrs->ai_addrlen) == -1) {
+ push_error(ln, strerror(errno));
+ return 0;
+ }
+
+ return act_one_initiator(ln, &h);
+}
+
+static struct pubkey nodeid = {
+ .pubkey = {
+ .data = {
+ 0x03, 0xf3, 0xc1, 0x08, 0xcc, 0xd5, 0x36, 0xb8, 0x52, 0x68, 0x41, 0xf0,
+ 0xa5, 0xc5, 0x82, 0x12, 0xbb, 0x9e, 0x65, 0x84, 0xa1, 0xeb, 0x49, 0x30,
+ 0x80, 0xe7, 0xc1, 0xcc, 0x34, 0xf8, 0x2d, 0xad, 0x71 } }
+};
+
+int main(int argc, const char *argv[])
+{
+ struct lnsocket ln;
+ lnsocket_init(&ln);
+
+ if (!connect_node(&ln, nodeid, "24.84.152.187")) {
+ printf("connection failed: %s\n", ln.errors[0]);
+ return 1;
+ }
+
+ printf("connected!\n");
+
+ return 0;
+}
diff --git a/netln.c b/netln.c
@@ -1,81 +0,0 @@
-
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "handshake.h"
-
-#define array_len(x) (sizeof(x)/sizeof(x[0]))
-
-struct netln {
- const char *errors[8];
- int num_errors;
-};
-
-static void push_error(struct netln *netln, const char *err)
-{
- if (netln->num_errors >= array_len(netln->errors)) {
- // TODO: push out old errors instead
- return;
- }
-
- netln->errors[netln->num_errors++] = err;
-}
-
-static void netln_init(struct netln *netln)
-{
- memset(netln, 0, sizeof(*netln));
-}
-
-int connect_node(struct netln *netln, unsigned char *pubkey, const char *host)
-{
- int fd, ret;
- struct addrinfo *addrs = NULL;
-
- if ((ret = getaddrinfo(host, "9735", NULL, &addrs)) || !addrs) {
- push_error(netln, gai_strerror(ret));
- return 0;
- }
-
- if (!(fd = socket(AF_INET, SOCK_STREAM, 0))) {
- push_error(netln, "creating socket failed");
- return 0;
- }
-
- if (connect(fd, addrs->ai_addr, addrs->ai_addrlen) == -1) {
- push_error(netln, strerror(errno));
- return 0;
- }
-
- return 1;
-}
-
-void act_one_initiator(int fd)
-{
-
-}
-
-static unsigned char nodeid[] = {
- 0x03, 0xf3, 0xc1, 0x08, 0xcc, 0xd5, 0x36, 0xb8, 0x52, 0x68, 0x41, 0xf0,
- 0xa5, 0xc5, 0x82, 0x12, 0xbb, 0x9e, 0x65, 0x84, 0xa1, 0xeb, 0x49, 0x30,
- 0x80, 0xe7, 0xc1, 0xcc, 0x34, 0xf8, 0x2d, 0xad, 0x71 };
-
-int main(int argc, const char *argv[])
-{
- struct netln netln;
- netln_init(&netln);
-
- if (!connect_node(&netln, nodeid, "24.84.152.187")) {
- printf("connection failed: %s\n", netln.errors[0]);
- return 1;
- }
-
- printf("connected!\n");
-
- return 0;
-}
diff --git a/sha256.c b/sha256.c
@@ -0,0 +1,303 @@
+
+/* 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));
+}
+
+
diff --git a/sha256.h b/sha256.h
@@ -0,0 +1,155 @@
+
+#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);
+
+#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 */