From 054edd04ac73fcf9358879f0c49cb241aaf5a7de Mon Sep 17 00:00:00 2001 From: IC Rainbow Date: Mon, 30 Oct 2023 15:31:40 +0200 Subject: [PATCH] WIP: move to cryptonite cbits instead of openssl and haskell-funptrs --- cbits/cryptonite_align.h | 140 +++++++++ cbits/cryptonite_bitfn.h | 253 +++++++++++++++ cbits/cryptonite_chacha.c | 288 ++++++++++++++++++ cbits/cryptonite_chacha.h | 54 ++++ cbits/cryptonite_hash_prefix.c | 90 ++++++ cbits/cryptonite_hash_prefix.h | 65 ++++ cbits/cryptonite_sha512.c | 209 +++++++++++++ cbits/cryptonite_sha512.h | 61 ++++ cbits/sntrup761.c | 7 +- cbits/sntrup761.h | 2 +- cbits/{sxcrandom.c => sntrup_random.c} | 2 +- cbits/{sxcrandom.h => sntrup_random.h} | 0 cbits/sntrup_sha512.c | 13 + cbits/sntrup_sha512.h | 3 + package.yaml | 14 +- simplexmq.cabal | 21 +- .../Crypto/SNTRUP761/Bindings/Defines.hsc | 1 - .../Crypto/SNTRUP761/Bindings/RNG.hs | 14 +- 18 files changed, 1214 insertions(+), 23 deletions(-) create mode 100644 cbits/cryptonite_align.h create mode 100644 cbits/cryptonite_bitfn.h create mode 100644 cbits/cryptonite_chacha.c create mode 100644 cbits/cryptonite_chacha.h create mode 100644 cbits/cryptonite_hash_prefix.c create mode 100644 cbits/cryptonite_hash_prefix.h create mode 100644 cbits/cryptonite_sha512.c create mode 100644 cbits/cryptonite_sha512.h rename cbits/{sxcrandom.c => sntrup_random.c} (81%) rename cbits/{sxcrandom.h => sntrup_random.h} (100%) create mode 100644 cbits/sntrup_sha512.c create mode 100644 cbits/sntrup_sha512.h diff --git a/cbits/cryptonite_align.h b/cbits/cryptonite_align.h new file mode 100644 index 000000000..01e8a36d3 --- /dev/null +++ b/cbits/cryptonite_align.h @@ -0,0 +1,140 @@ +#ifndef CRYPTONITE_ALIGN_H +#define CRYPTONITE_ALIGN_H + +#include "cryptonite_bitfn.h" + +#if (defined(__i386__)) +# define UNALIGNED_ACCESS_OK +#elif defined(__x86_64__) +# define UNALIGNED_ACCESS_OK +#else +# define UNALIGNED_ACCESS_FAULT +#endif + +/* n need to be power of 2. + * IS_ALIGNED(p,8) */ +#define IS_ALIGNED(p,alignment) (((uintptr_t) (p)) & ((alignment)-1)) + +#ifdef WITH_ASSERT_ALIGNMENT +#include +#include +#include +# define ASSERT_ALIGNMENT(up, alignment) \ + do { if (IS_ALIGNED(up, alignment)) \ + { printf("ALIGNMENT-ASSERT-FAILURE: %s:%d: ptr=%p alignment=%d\n", __FILE__, __LINE__, (void *) up, (alignment)); \ + exit(99); \ + }; } while (0) +#else +# define ASSERT_ALIGNMENT(p, n) do {} while (0) +#endif + +#ifdef UNALIGNED_ACCESS_OK +#define need_alignment(p,n) (0) +#else +#define need_alignment(p,n) IS_ALIGNED(p,n) +#endif + +static inline uint32_t load_le32_aligned(const uint8_t *p) +{ + return le32_to_cpu(*((uint32_t *) p)); +} + +static inline void store_le32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) = cpu_to_le32(v); +} + +static inline void xor_le32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) ^= cpu_to_le32(v); +} + +static inline void store_be32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) = cpu_to_be32(v); +} + +static inline void xor_be32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) ^= cpu_to_be32(v); +} + +static inline void store_le64_aligned(uint8_t *dst, const uint64_t v) +{ + *((uint64_t *) dst) = cpu_to_le64(v); +} + +static inline void store_be64_aligned(uint8_t *dst, const uint64_t v) +{ + *((uint64_t *) dst) = cpu_to_be64(v); +} + +static inline void xor_be64_aligned(uint8_t *dst, const uint64_t v) +{ + *((uint64_t *) dst) ^= cpu_to_be64(v); +} + +#ifdef UNALIGNED_ACCESS_OK +#define load_le32(a) load_le32_aligned(a) +#else +static inline uint32_t load_le32(const uint8_t *p) +{ + return ((uint32_t)p[0]) | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); +} +#endif + +#ifdef UNALIGNED_ACCESS_OK +#define store_le32(a, b) store_le32_aligned(a, b) +#define xor_le32(a, b) xor_le32_aligned(a, b) +#else +static inline void store_le32(uint8_t *dst, const uint32_t v) +{ + dst[0] = v; dst[1] = v >> 8; dst[2] = v >> 16; dst[3] = v >> 24; +} +static inline void xor_le32(uint8_t *dst, const uint32_t v) +{ + dst[0] ^= v; dst[1] ^= v >> 8; dst[2] ^= v >> 16; dst[3] ^= v >> 24; +} +#endif + +#ifdef UNALIGNED_ACCESS_OK +#define store_be32(a, b) store_be32_aligned(a, b) +#define xor_be32(a, b) xor_be32_aligned(a, b) +#else +static inline void store_be32(uint8_t *dst, const uint32_t v) +{ + dst[3] = v; dst[2] = v >> 8; dst[1] = v >> 16; dst[0] = v >> 24; +} +static inline void xor_be32(uint8_t *dst, const uint32_t v) +{ + dst[3] ^= v; dst[2] ^= v >> 8; dst[1] ^= v >> 16; dst[0] ^= v >> 24; +} +#endif + +#ifdef UNALIGNED_ACCESS_OK +#define store_le64(a, b) store_le64_aligned(a, b) +#else +static inline void store_le64(uint8_t *dst, const uint64_t v) +{ + dst[0] = v ; dst[1] = v >> 8 ; dst[2] = v >> 16; dst[3] = v >> 24; + dst[4] = v >> 32; dst[5] = v >> 40; dst[6] = v >> 48; dst[7] = v >> 56; +} +#endif + +#ifdef UNALIGNED_ACCESS_OK +#define store_be64(a, b) store_be64_aligned(a, b) +#define xor_be64(a, b) xor_be64_aligned(a, b) +#else +static inline void store_be64(uint8_t *dst, const uint64_t v) +{ + dst[7] = v ; dst[6] = v >> 8 ; dst[5] = v >> 16; dst[4] = v >> 24; + dst[3] = v >> 32; dst[2] = v >> 40; dst[1] = v >> 48; dst[0] = v >> 56; +} +static inline void xor_be64(uint8_t *dst, const uint64_t v) +{ + dst[7] ^= v ; dst[6] ^= v >> 8 ; dst[5] ^= v >> 16; dst[4] ^= v >> 24; + dst[3] ^= v >> 32; dst[2] ^= v >> 40; dst[1] ^= v >> 48; dst[0] ^= v >> 56; +} +#endif + +#endif diff --git a/cbits/cryptonite_bitfn.h b/cbits/cryptonite_bitfn.h new file mode 100644 index 000000000..3a00dd8a4 --- /dev/null +++ b/cbits/cryptonite_bitfn.h @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2006-2014 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BITFN_H +#define BITFN_H +#include + +#ifndef NO_INLINE_ASM +/**********************************************************/ +# if (defined(__i386__)) +# define ARCH_HAS_SWAP32 +static inline uint32_t bitfn_swap32(uint32_t a) +{ + asm ("bswap %0" : "=r" (a) : "0" (a)); + return a; +} +/**********************************************************/ +# elif (defined(__arm__)) +# define ARCH_HAS_SWAP32 +static inline uint32_t bitfn_swap32(uint32_t a) +{ + uint32_t tmp = a; + asm volatile ("eor %1, %0, %0, ror #16\n" + "bic %1, %1, #0xff0000\n" + "mov %0, %0, ror #8\n" + "eor %0, %0, %1, lsr #8\n" + : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp)); + return a; +} +/**********************************************************/ +# elif defined(__x86_64__) +# define ARCH_HAS_SWAP32 +# define ARCH_HAS_SWAP64 +static inline uint32_t bitfn_swap32(uint32_t a) +{ + asm ("bswap %0" : "=r" (a) : "0" (a)); + return a; +} + +static inline uint64_t bitfn_swap64(uint64_t a) +{ + asm ("bswap %0" : "=r" (a) : "0" (a)); + return a; +} + +# endif +#endif /* NO_INLINE_ASM */ +/**********************************************************/ + +#ifndef ARCH_HAS_ROL32 +static inline uint32_t rol32(uint32_t word, uint32_t shift) +{ + return (word << shift) | (word >> (32 - shift)); +} +#endif + +#ifndef ARCH_HAS_ROR32 +static inline uint32_t ror32(uint32_t word, uint32_t shift) +{ + return (word >> shift) | (word << (32 - shift)); +} +#endif + +#ifndef ARCH_HAS_ROL64 +static inline uint64_t rol64(uint64_t word, uint32_t shift) +{ + return (word << shift) | (word >> (64 - shift)); +} +#endif + +#ifndef ARCH_HAS_ROR64 +static inline uint64_t ror64(uint64_t word, uint32_t shift) +{ + return (word >> shift) | (word << (64 - shift)); +} +#endif + +#ifndef ARCH_HAS_SWAP32 +static inline uint32_t bitfn_swap32(uint32_t a) +{ + return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24); +} +#endif + +#ifndef ARCH_HAS_ARRAY_SWAP32 +static inline void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb) +{ + while (nb--) + *d++ = bitfn_swap32(*s++); +} +#endif + +#ifndef ARCH_HAS_SWAP64 +static inline uint64_t bitfn_swap64(uint64_t a) +{ + return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) | + (((uint64_t) bitfn_swap32((uint32_t) a)) << 32); +} +#endif + +#ifndef ARCH_HAS_ARRAY_SWAP64 +static inline void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb) +{ + while (nb--) + *d++ = bitfn_swap64(*s++); +} +#endif + +#ifndef ARCH_HAS_MEMORY_ZERO +static inline void memory_zero(void *ptr, uint32_t len) +{ + uint32_t *ptr32 = ptr; + uint8_t *ptr8; + int i; + + for (i = 0; i < len / 4; i++) + *ptr32++ = 0; + if (len % 4) { + ptr8 = (uint8_t *) ptr32; + for (i = len % 4; i >= 0; i--) + ptr8[i] = 0; + } +} +#endif + +#ifndef ARCH_HAS_ARRAY_COPY32 +static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb) +{ + while (nb--) *d++ = *s++; +} +#endif + +#ifndef ARCH_HAS_ARRAY_XOR32 +static inline void array_xor32(uint32_t *d, uint32_t *s, uint32_t nb) +{ + while (nb--) *d++ ^= *s++; +} +#endif + +#ifndef ARCH_HAS_ARRAY_COPY64 +static inline void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb) +{ + while (nb--) *d++ = *s++; +} +#endif + +#ifdef __GNUC__ +#define bitfn_ntz(n) __builtin_ctz(n) +#else +#error "define ntz for your platform" +#endif + +#ifdef __MINGW32__ + # define LITTLE_ENDIAN 1234 + # define BYTE_ORDER LITTLE_ENDIAN +#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) + # include +#elif defined(__OpenBSD__) || defined(__SVR4) + # include +#elif defined(__APPLE__) + # include +#elif defined( BSD ) && ( BSD >= 199103 ) + # include +#elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ ) + # define LITTLE_ENDIAN 1234 + # define BYTE_ORDER LITTLE_ENDIAN +#elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ ) + # define BIG_ENDIAN 1234 + # define BYTE_ORDER BIG_ENDIAN +#elif defined( _AIX ) + # include +#else + # include +#endif +/* big endian to cpu */ +#if LITTLE_ENDIAN == BYTE_ORDER + +# define be32_to_cpu(a) bitfn_swap32(a) +# define cpu_to_be32(a) bitfn_swap32(a) +# define le32_to_cpu(a) (a) +# define cpu_to_le32(a) (a) +# define be64_to_cpu(a) bitfn_swap64(a) +# define cpu_to_be64(a) bitfn_swap64(a) +# define le64_to_cpu(a) (a) +# define cpu_to_le64(a) (a) + +# define cpu_to_le32_array(d, s, l) array_copy32(d, s, l) +# define le32_to_cpu_array(d, s, l) array_copy32(d, s, l) +# define cpu_to_be32_array(d, s, l) array_swap32(d, s, l) +# define be32_to_cpu_array(d, s, l) array_swap32(d, s, l) + +# define cpu_to_le64_array(d, s, l) array_copy64(d, s, l) +# define le64_to_cpu_array(d, s, l) array_copy64(d, s, l) +# define cpu_to_be64_array(d, s, l) array_swap64(d, s, l) +# define be64_to_cpu_array(d, s, l) array_swap64(d, s, l) + +# define ror32_be(a, s) rol32(a, s) +# define rol32_be(a, s) ror32(a, s) + +# define ARCH_IS_LITTLE_ENDIAN + +#elif BIG_ENDIAN == BYTE_ORDER + +# define be32_to_cpu(a) (a) +# define cpu_to_be32(a) (a) +# define be64_to_cpu(a) (a) +# define cpu_to_be64(a) (a) +# define le64_to_cpu(a) bitfn_swap64(a) +# define cpu_to_le64(a) bitfn_swap64(a) +# define le32_to_cpu(a) bitfn_swap32(a) +# define cpu_to_le32(a) bitfn_swap32(a) + +# define cpu_to_le32_array(d, s, l) array_swap32(d, s, l) +# define le32_to_cpu_array(d, s, l) array_swap32(d, s, l) +# define cpu_to_be32_array(d, s, l) array_copy32(d, s, l) +# define be32_to_cpu_array(d, s, l) array_copy32(d, s, l) + +# define cpu_to_le64_array(d, s, l) array_swap64(d, s, l) +# define le64_to_cpu_array(d, s, l) array_swap64(d, s, l) +# define cpu_to_be64_array(d, s, l) array_copy64(d, s, l) +# define be64_to_cpu_array(d, s, l) array_copy64(d, s, l) + +# define ror32_be(a, s) ror32(a, s) +# define rol32_be(a, s) rol32(a, s) + +# define ARCH_IS_BIG_ENDIAN + +#else +# error "endian not supported" +#endif + +#endif /* !BITFN_H */ diff --git a/cbits/cryptonite_chacha.c b/cbits/cryptonite_chacha.c new file mode 100644 index 000000000..bfc5d873d --- /dev/null +++ b/cbits/cryptonite_chacha.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2014-2015 Vincent Hanquez + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "cryptonite_chacha.h" +#include "cryptonite_bitfn.h" +#include "cryptonite_align.h" +#include + +#define QR(a,b,c,d) \ + a += b; d = rol32(d ^ a,16); \ + c += d; b = rol32(b ^ c,12); \ + a += b; d = rol32(d ^ a, 8); \ + c += d; b = rol32(b ^ c, 7); + +#define ALIGNED64(PTR) \ + (((uintptr_t)(const void *)(PTR)) % 8 == 0) + +static const uint8_t sigma[16] = "expand 32-byte k"; +static const uint8_t tau[16] = "expand 16-byte k"; + +static void chacha_core(int rounds, block *out, const cryptonite_chacha_state *in) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + int i; + + x0 = in->d[0]; x1 = in->d[1]; x2 = in->d[2]; x3 = in->d[3]; + x4 = in->d[4]; x5 = in->d[5]; x6 = in->d[6]; x7 = in->d[7]; + x8 = in->d[8]; x9 = in->d[9]; x10 = in->d[10]; x11 = in->d[11]; + x12 = in->d[12]; x13 = in->d[13]; x14 = in->d[14]; x15 = in->d[15]; + + for (i = rounds; i > 0; i -= 2) { + QR(x0, x4, x8, x12); + QR(x1, x5, x9, x13); + QR(x2, x6, x10, x14); + QR(x3, x7, x11, x15); + + QR(x0, x5, x10, x15); + QR(x1, x6, x11, x12); + QR(x2, x7, x8, x13); + QR(x3, x4, x9, x14); + } + + x0 += in->d[0]; x1 += in->d[1]; x2 += in->d[2]; x3 += in->d[3]; + x4 += in->d[4]; x5 += in->d[5]; x6 += in->d[6]; x7 += in->d[7]; + x8 += in->d[8]; x9 += in->d[9]; x10 += in->d[10]; x11 += in->d[11]; + x12 += in->d[12]; x13 += in->d[13]; x14 += in->d[14]; x15 += in->d[15]; + + out->d[0] = cpu_to_le32(x0); + out->d[1] = cpu_to_le32(x1); + out->d[2] = cpu_to_le32(x2); + out->d[3] = cpu_to_le32(x3); + out->d[4] = cpu_to_le32(x4); + out->d[5] = cpu_to_le32(x5); + out->d[6] = cpu_to_le32(x6); + out->d[7] = cpu_to_le32(x7); + out->d[8] = cpu_to_le32(x8); + out->d[9] = cpu_to_le32(x9); + out->d[10] = cpu_to_le32(x10); + out->d[11] = cpu_to_le32(x11); + out->d[12] = cpu_to_le32(x12); + out->d[13] = cpu_to_le32(x13); + out->d[14] = cpu_to_le32(x14); + out->d[15] = cpu_to_le32(x15); +} + +/* only 2 valids values are 256 (32) and 128 (16) */ +void cryptonite_chacha_init_core(cryptonite_chacha_state *st, + uint32_t keylen, const uint8_t *key, + uint32_t ivlen, const uint8_t *iv) +{ + const uint8_t *constants = (keylen == 32) ? sigma : tau; + + ASSERT_ALIGNMENT(constants, 4); + + st->d[0] = load_le32_aligned(constants + 0); + st->d[1] = load_le32_aligned(constants + 4); + st->d[2] = load_le32_aligned(constants + 8); + st->d[3] = load_le32_aligned(constants + 12); + + st->d[4] = load_le32(key + 0); + st->d[5] = load_le32(key + 4); + st->d[6] = load_le32(key + 8); + st->d[7] = load_le32(key + 12); + /* we repeat the key on 128 bits */ + if (keylen == 32) + key += 16; + st->d[8] = load_le32(key + 0); + st->d[9] = load_le32(key + 4); + st->d[10] = load_le32(key + 8); + st->d[11] = load_le32(key + 12); + st->d[12] = 0; + switch (ivlen) { + case 8: + st->d[13] = 0; + st->d[14] = load_le32(iv + 0); + st->d[15] = load_le32(iv + 4); + break; + case 12: + st->d[13] = load_le32(iv + 0); + st->d[14] = load_le32(iv + 4); + st->d[15] = load_le32(iv + 8); + default: + return; + } +} + +void cryptonite_chacha_init(cryptonite_chacha_context *ctx, uint8_t nb_rounds, + uint32_t keylen, const uint8_t *key, + uint32_t ivlen, const uint8_t *iv) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->nb_rounds = nb_rounds; + cryptonite_chacha_init_core(&ctx->st, keylen, key, ivlen, iv); +} + +void cryptonite_chacha_combine(uint8_t *dst, cryptonite_chacha_context *ctx, const uint8_t *src, uint32_t bytes) +{ + block out; + cryptonite_chacha_state *st; + int i; + + if (!bytes) + return; + + /* xor the previous buffer first (if any) */ + if (ctx->prev_len > 0) { + int to_copy = (ctx->prev_len < bytes) ? ctx->prev_len : bytes; + for (i = 0; i < to_copy; i++) + dst[i] = src[i] ^ ctx->prev[ctx->prev_ofs+i]; + memset(ctx->prev + ctx->prev_ofs, 0, to_copy); + ctx->prev_len -= to_copy; + ctx->prev_ofs += to_copy; + src += to_copy; + dst += to_copy; + bytes -= to_copy; + } + + if (bytes == 0) + return; + + st = &ctx->st; + + /* xor new 64-bytes chunks and store the left over if any */ + for (; bytes >= 64; bytes -= 64, src += 64, dst += 64) { + /* generate new chunk and update state */ + chacha_core(ctx->nb_rounds, &out, st); + st->d[12] += 1; + if (st->d[12] == 0) + st->d[13] += 1; + + for (i = 0; i < 64; ++i) + dst[i] = src[i] ^ out.b[i]; + } + + if (bytes > 0) { + /* generate new chunk and update state */ + chacha_core(ctx->nb_rounds, &out, st); + st->d[12] += 1; + if (st->d[12] == 0) + st->d[13] += 1; + + /* xor as much as needed */ + for (i = 0; i < bytes; i++) + dst[i] = src[i] ^ out.b[i]; + + /* copy the left over in the buffer */ + ctx->prev_len = 64 - bytes; + ctx->prev_ofs = i; + for (; i < 64; i++) { + ctx->prev[i] = out.b[i]; + } + } +} + +void cryptonite_chacha_generate(uint8_t *dst, cryptonite_chacha_context *ctx, uint32_t bytes) +{ + cryptonite_chacha_state *st; + block out; + int i; + + if (!bytes) + return; + + /* xor the previous buffer first (if any) */ + if (ctx->prev_len > 0) { + int to_copy = (ctx->prev_len < bytes) ? ctx->prev_len : bytes; + for (i = 0; i < to_copy; i++) + dst[i] = ctx->prev[ctx->prev_ofs+i]; + memset(ctx->prev + ctx->prev_ofs, 0, to_copy); + ctx->prev_len -= to_copy; + ctx->prev_ofs += to_copy; + dst += to_copy; + bytes -= to_copy; + } + + if (bytes == 0) + return; + + st = &ctx->st; + + if (ALIGNED64(dst)) { + /* xor new 64-bytes chunks and store the left over if any */ + for (; bytes >= 64; bytes -= 64, dst += 64) { + /* generate new chunk and update state */ + chacha_core(ctx->nb_rounds, (block *) dst, st); + st->d[12] += 1; + if (st->d[12] == 0) + st->d[13] += 1; + } + } else { + /* xor new 64-bytes chunks and store the left over if any */ + for (; bytes >= 64; bytes -= 64, dst += 64) { + /* generate new chunk and update state */ + chacha_core(ctx->nb_rounds, &out, st); + st->d[12] += 1; + if (st->d[12] == 0) + st->d[13] += 1; + + for (i = 0; i < 64; ++i) + dst[i] = out.b[i]; + } + } + + if (bytes > 0) { + /* generate new chunk and update state */ + chacha_core(ctx->nb_rounds, &out, st); + st->d[12] += 1; + if (st->d[12] == 0) + st->d[13] += 1; + + /* xor as much as needed */ + for (i = 0; i < bytes; i++) + dst[i] = out.b[i]; + + /* copy the left over in the buffer */ + ctx->prev_len = 64 - bytes; + ctx->prev_ofs = i; + for (; i < 64; i++) + ctx->prev[i] = out.b[i]; + } +} + +void cryptonite_chacha_random(uint32_t rounds, uint8_t *dst, cryptonite_chacha_state *st, uint32_t bytes) +{ + block out; + + if (!bytes) + return; + for (; bytes >= 16; bytes -= 16, dst += 16) { + chacha_core(rounds, &out, st); + memcpy(dst, out.b + 40, 16); + cryptonite_chacha_init_core(st, 32, out.b, 8, out.b + 32); + } + if (bytes) { + chacha_core(rounds, &out, st); + memcpy(dst, out.b + 40, bytes); + cryptonite_chacha_init_core(st, 32, out.b, 8, out.b + 32); + } +} diff --git a/cbits/cryptonite_chacha.h b/cbits/cryptonite_chacha.h new file mode 100644 index 000000000..95ee29eff --- /dev/null +++ b/cbits/cryptonite_chacha.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Vincent Hanquez + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef CRYPTONITE_CHACHA +#define CRYPTONITE_CHACHA + +typedef union { + uint64_t q[8]; + uint32_t d[16]; + uint8_t b[64]; +} block; + +typedef block cryptonite_chacha_state; + +typedef struct { + cryptonite_chacha_state st; + uint8_t prev[64]; + uint8_t prev_ofs; + uint8_t prev_len; + uint8_t nb_rounds; +} cryptonite_chacha_context; + +void cryptonite_chacha_init_core(cryptonite_chacha_state *st, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv); +void cryptonite_chacha_init(cryptonite_chacha_context *ctx, uint8_t nb_rounds, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv); +void cryptonite_chacha_combine(uint8_t *dst, cryptonite_chacha_context *st, const uint8_t *src, uint32_t bytes); +void cryptonite_chacha_generate(uint8_t *dst, cryptonite_chacha_context *st, uint32_t bytes); + +#endif diff --git a/cbits/cryptonite_hash_prefix.c b/cbits/cryptonite_hash_prefix.c new file mode 100644 index 000000000..b487708cb --- /dev/null +++ b/cbits/cryptonite_hash_prefix.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2020 Olivier Chéron + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void CRYPTONITE_HASHED(finalize_prefix)(struct HASHED_LOWER(ctx) *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out) +{ + uint64_t bits[HASHED(BITS_ELEMS)]; + uint8_t *p = (uint8_t *) &bits; + uint32_t index, padidx, padlen, pos, out_mask; + static const uint32_t cut_off = HASHED(BLOCK_SIZE) - sizeof(bits); + + /* Make sure n <= len */ + n += (len - n) & constant_time_lt(len, n); + + /* Initial index, based on current context state */ + index = CRYPTONITE_HASHED(get_index)(ctx); + + /* Final size after n bytes */ + CRYPTONITE_HASHED(incr_sz)(ctx, bits, n); + + /* Padding index and length */ + padidx = CRYPTONITE_HASHED(get_index)(ctx); + padlen = HASHED(BLOCK_SIZE) + cut_off - padidx; + padlen -= HASHED(BLOCK_SIZE) & constant_time_lt(padidx, cut_off); + + /* Initialize buffers because we will XOR into them */ + memset(ctx->buf + index, 0, HASHED(BLOCK_SIZE) - index); + memset(out, 0, HASHED(DIGEST_SIZE)); + pos = 0; + + /* Iterate based on the full buffer length, regardless of n, and include + * the maximum overhead with padding and size bytes + */ + while (pos < len + HASHED(BLOCK_SIZE) + sizeof(bits)) { + uint8_t b; + + /* Take as many bytes from the input buffer as possible */ + if (pos < len) + b = *(data++) & (uint8_t) constant_time_lt(pos, n); + else + b = 0; + + /* First padding byte */ + b |= 0x80 & (uint8_t) constant_time_eq(pos, n); + + /* Size bytes are always at the end of a block */ + if (index >= cut_off) + b |= p[index - cut_off] & (uint8_t) constant_time_ge(pos, n + padlen); + + /* Store this byte into the buffer */ + ctx->buf[index++] ^= b; + pos++; + + /* Process a full block, at a boundary which is independent from n */ + if (index >= HASHED(BLOCK_SIZE)) { + index = 0; + HASHED_LOWER(do_chunk)(ctx, (void *) ctx->buf); + memset(ctx->buf, 0, HASHED(BLOCK_SIZE)); + + /* Try to store the result: this is a no-op except when we reach the + * actual size based on n, more iterations may continue after that + * when len is really larger + */ + out_mask = constant_time_eq(pos, n + padlen + sizeof(bits)); + CRYPTONITE_HASHED(select_digest)(ctx, out, out_mask); + } + } +} diff --git a/cbits/cryptonite_hash_prefix.h b/cbits/cryptonite_hash_prefix.h new file mode 100644 index 000000000..3eed4e09f --- /dev/null +++ b/cbits/cryptonite_hash_prefix.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 Olivier Chéron + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTONITE_HASH_PREFIX_H +#define CRYPTONITE_HASH_PREFIX_H + +#include + +static inline uint32_t constant_time_msb(uint32_t a) +{ + return 0 - (a >> 31); +} + +static inline uint32_t constant_time_lt(uint32_t a, uint32_t b) +{ + return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static inline uint32_t constant_time_ge(uint32_t a, uint32_t b) +{ + return ~constant_time_lt(a, b); +} + +static inline uint32_t constant_time_is_zero(uint32_t a) +{ + return constant_time_msb(~a & (a - 1)); +} + +static inline uint32_t constant_time_eq(uint32_t a, uint32_t b) +{ + return constant_time_is_zero(a ^ b); +} + +static inline uint64_t constant_time_msb_64(uint64_t a) +{ + return 0 - (a >> 63); +} + +static inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) +{ + return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +#endif diff --git a/cbits/cryptonite_sha512.c b/cbits/cryptonite_sha512.c new file mode 100644 index 000000000..7c6ae5569 --- /dev/null +++ b/cbits/cryptonite_sha512.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_align.h" +#include "cryptonite_sha512.h" + +void sxc_cryptonite_sha512_init(struct sha512_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x6a09e667f3bcc908ULL; + ctx->h[1] = 0xbb67ae8584caa73bULL; + ctx->h[2] = 0x3c6ef372fe94f82bULL; + ctx->h[3] = 0xa54ff53a5f1d36f1ULL; + ctx->h[4] = 0x510e527fade682d1ULL; + ctx->h[5] = 0x9b05688c2b3e6c1fULL; + ctx->h[6] = 0x1f83d9abfb41bd6bULL; + ctx->h[7] = 0x5be0cd19137e2179ULL; +} + +/* 232 times the cube root of the first 64 primes 2..311 */ +static const uint64_t k[] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +#define e0(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39)) +#define e1(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6)) + +static void sha512_do_chunk(struct sha512_ctx *ctx, uint64_t *buf) +{ + uint64_t a, b, c, d, e, f, g, h, t1, t2; + int i; + uint64_t w[80]; + + cpu_to_be64_array(w, buf, 16); + + for (i = 16; i < 80; i++) + w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16]; + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + +#define R(a, b, c, d, e, f, g, h, k, w) \ + t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; \ + t2 = e0(a) + ((a & b) | (c & (a | b))); \ + d += t1; \ + h = t1 + t2 + + for (i = 0; i < 80; i += 8) { + R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]); + R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]); + R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]); + R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]); + R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]); + R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]); + R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]); + R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]); + } + +#undef R + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; +} + +void sxc_cryptonite_sha512_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len) +{ + unsigned int index, to_fill; + + /* check for partial buffer */ + index = (unsigned int) (ctx->sz[0] & 0x7f); + to_fill = 128 - index; + + ctx->sz[0] += len; + if (ctx->sz[0] < len) + ctx->sz[1]++; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + sha512_do_chunk(ctx, (uint64_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + if (need_alignment(data, 8)) { + uint64_t tramp[16]; + ASSERT_ALIGNMENT(tramp, 8); + for (; len >= 128; len -= 128, data += 128) { + memcpy(tramp, data, 128); + sha512_do_chunk(ctx, tramp); + } + } else { + /* process as much 128-block as possible */ + for (; len >= 128; len -= 128, data += 128) + sha512_do_chunk(ctx, (uint64_t *) data); + } + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void sxc_cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[128] = { 0x80, }; + uint32_t i, index, padlen; + uint64_t bits[2]; + + /* cpu -> big endian */ + bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61)); + bits[1] = cpu_to_be64((ctx->sz[0] << 3)); + + /* pad out to 56 */ + index = (unsigned int) (ctx->sz[0] & 0x7f); + padlen = (index < 112) ? (112 - index) : ((128 + 112) - index); + cryptonite_sha512_update(ctx, padding, padlen); + + /* append length */ + cryptonite_sha512_update(ctx, (uint8_t *) bits, sizeof(bits)); + + /* store to digest */ + for (i = 0; i < 8; i++) + store_be64(out+8*i, ctx->h[i]); +} + +#define HASHED(m) SHA512_##m +#define HASHED_LOWER(m) sha512_##m +#define CRYPTONITE_HASHED(m) sxc_cryptonite_sha512_##m +#define SHA512_BLOCK_SIZE 128 +#define SHA512_BITS_ELEMS 2 + +#include + +static inline uint32_t sxc_cryptonite_sha512_get_index(const struct sha512_ctx *ctx) +{ + return (uint32_t) (ctx->sz[0] & 0x7f); +} + +static inline void sxc_cryptonite_sha512_incr_sz(struct sha512_ctx *ctx, uint64_t *bits, uint32_t n) +{ + ctx->sz[0] += n; + ctx->sz[1] += 1 & constant_time_lt_64(ctx->sz[0], n); + bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61)); + bits[1] = cpu_to_be64((ctx->sz[0] << 3)); +} + +static inline void sxc_cryptonite_sha512_select_digest(const struct sha512_ctx *ctx, uint8_t *out, uint32_t out_mask) +{ + uint32_t i; + uint64_t out_mask_64 = out_mask; + out_mask_64 |= out_mask_64 << 32; + for (i = 0; i < 8; i++) + xor_be64(out+8*i, ctx->h[i] & out_mask_64); +} + +#include diff --git a/cbits/cryptonite_sha512.h b/cbits/cryptonite_sha512.h new file mode 100644 index 000000000..53893c02e --- /dev/null +++ b/cbits/cryptonite_sha512.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SHA512_H +#define CRYPTOHASH_SHA512_H + +#include + +# define SHA512_BLOCK_SIZE 128 + +struct sha512_ctx +{ + uint64_t sz[2]; + uint8_t buf[SHA512_BLOCK_SIZE]; + uint64_t h[8]; +}; + +#define sha384_ctx sha512_ctx + +#define SHA384_DIGEST_SIZE 48 +#define SHA384_CTX_SIZE sizeof(struct sha384_ctx) + +#define SHA512_DIGEST_SIZE 64 +#define SHA512_CTX_SIZE sizeof(struct sha512_ctx) + +void cryptonite_sha384_init(struct sha384_ctx *ctx); +void cryptonite_sha384_update(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len); +void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out); +void cryptonite_sha384_finalize_prefix(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); + +void cryptonite_sha512_init(struct sha512_ctx *ctx); +void cryptonite_sha512_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len); +void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out); +void cryptonite_sha512_finalize_prefix(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); + +/* only multiples of 8 are supported as valid t values */ +void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen); +void cryptonite_sha512t_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len); +void cryptonite_sha512t_finalize(struct sha512_ctx *ctx, uint32_t hashlen, uint8_t *out); + +#endif diff --git a/cbits/sntrup761.c b/cbits/sntrup761.c index d697fd37c..120217b6c 100644 --- a/cbits/sntrup761.c +++ b/cbits/sntrup761.c @@ -6,9 +6,10 @@ * - Christine van Vredendaal */ -#include +// #include #include "sntrup761.h" -#include "sxcrandom.h" +#include "sntrup_sha512.h" +#include "sntrup_random.h" /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */ #define int32_MINMAX(a,b) \ @@ -676,7 +677,7 @@ Hash_prefix (unsigned char *out, int b, const unsigned char *in, int inlen) x[0] = b; for (i = 0; i < inlen; ++i) x[i + 1] = in[i]; - SHA512 (x, inlen + 1, h); + crypto_hash_sha512 (h, x, inlen + 1); for (i = 0; i < 32; ++i) out[i] = h[i]; } diff --git a/cbits/sntrup761.h b/cbits/sntrup761.h index 81d056e9d..1838da258 100644 --- a/cbits/sntrup761.h +++ b/cbits/sntrup761.h @@ -11,7 +11,7 @@ #include #include -#include "sxcrandom.h" +#include "sntrup_random.h" #define SNTRUP761_SECRETKEY_SIZE 1763 #define SNTRUP761_PUBLICKEY_SIZE 1158 diff --git a/cbits/sxcrandom.c b/cbits/sntrup_random.c similarity index 81% rename from cbits/sxcrandom.c rename to cbits/sntrup_random.c index 75859b9a3..379e74b2c 100644 --- a/cbits/sxcrandom.c +++ b/cbits/sntrup_random.c @@ -1,5 +1,5 @@ #include -#include "sxcrandom.h" +#include "sntrup_random.h" void sxcrandom_dummy (void *ctx, size_t length, uint8_t *dst) { memset(dst, 0x00, length); diff --git a/cbits/sxcrandom.h b/cbits/sntrup_random.h similarity index 100% rename from cbits/sxcrandom.h rename to cbits/sntrup_random.h diff --git a/cbits/sntrup_sha512.c b/cbits/sntrup_sha512.c new file mode 100644 index 000000000..1f63ea53e --- /dev/null +++ b/cbits/sntrup_sha512.c @@ -0,0 +1,13 @@ +// #include +#include "cryptonite_sha512.h" +#include "sntrup_sha512.h" + +void crypto_hash_sha512 (unsigned char *out, + const unsigned char *in, + unsigned long long inlen) +{ + struct sha512_ctx ctx; + cryptonite_sha512_init(&ctx); + cryptonite_sha512_update(&ctx, (const uint8_t *) in, (uint32_t) inlen); + cryptonite_sha512_finalize(&ctx, (uint8_t *) out); +} diff --git a/cbits/sntrup_sha512.h b/cbits/sntrup_sha512.h new file mode 100644 index 000000000..af16f5888 --- /dev/null +++ b/cbits/sntrup_sha512.h @@ -0,0 +1,3 @@ +void crypto_hash_sha512 (unsigned char *out, + const unsigned char *in, + unsigned long long inlen); diff --git a/package.yaml b/package.yaml index 1f63379b9..a148b6be1 100644 --- a/package.yaml +++ b/package.yaml @@ -20,9 +20,8 @@ category: Chat, Network, Web, System, Cryptography extra-source-files: - README.md - CHANGELOG.md - # - cbits/sha512.h - - cbits/sntrup761.h - - cbits/sxcrandom.h + - cbits/*.h + - cbits/*.c dependencies: - aeson == 2.2.* @@ -91,11 +90,14 @@ when: library: source-dirs: src c-sources: - # - cbits/sha512.c + # - cbits/cryptonite_hash_prefix.c # gets included in sha512 + - cbits/cryptonite_chacha.c + - cbits/cryptonite_sha512.c + - cbits/sntrup_random.c + - cbits/sntrup_sha512.c - cbits/sntrup761.c - - cbits/sxcrandom.c include-dirs: cbits - extra-libraries: crypto + # extra-libraries: crypto # not used for sha512 executables: smp-server: diff --git a/simplexmq.cabal b/simplexmq.cabal index c2c0af78b..492f8a4b0 100644 --- a/simplexmq.cabal +++ b/simplexmq.cabal @@ -26,8 +26,20 @@ build-type: Simple extra-source-files: README.md CHANGELOG.md + cbits/cryptonite_align.h + cbits/cryptonite_bitfn.h + cbits/cryptonite_chacha.h + cbits/cryptonite_hash_prefix.h + cbits/cryptonite_sha512.h cbits/sntrup761.h - cbits/sxcrandom.h + cbits/sntrup_random.h + cbits/sntrup_sha512.h + cbits/cryptonite_chacha.c + cbits/cryptonite_hash_prefix.c + cbits/cryptonite_sha512.c + cbits/sntrup761.c + cbits/sntrup_random.c + cbits/sntrup_sha512.c flag swift description: Enable swift JSON format @@ -155,10 +167,11 @@ library include-dirs: cbits c-sources: + cbits/cryptonite_chacha.c + cbits/cryptonite_sha512.c + cbits/sntrup_random.c + cbits/sntrup_sha512.c cbits/sntrup761.c - cbits/sxcrandom.c - extra-libraries: - crypto build-depends: aeson ==2.2.* , ansi-terminal >=0.10 && <0.12 diff --git a/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/Defines.hsc b/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/Defines.hsc index 06a4ea9c2..a7ba2a09b 100644 --- a/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/Defines.hsc +++ b/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/Defines.hsc @@ -3,7 +3,6 @@ module Simplex.Messaging.Crypto.SNTRUP761.Bindings.Defines where import Foreign.C #include "sntrup761.h" -#include "sxcrandom.h" c_SNTRUP761_SECRETKEY_SIZE :: Int c_SNTRUP761_SECRETKEY_SIZE = #{const SNTRUP761_SECRETKEY_SIZE} diff --git a/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/RNG.hs b/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/RNG.hs index ce4964945..287289d99 100644 --- a/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/RNG.hs +++ b/src/Simplex/Messaging/Crypto/SNTRUP761/Bindings/RNG.hs @@ -2,7 +2,7 @@ module Simplex.Messaging.Crypto.SNTRUP761.Bindings.RNG ( RNG (..), - dummyRNG, + -- dummyRNG, withHaskellRNG, startHaskellRNG, stopHaskellRNG, @@ -24,9 +24,6 @@ data RNG = RNG rngFunc :: FunPtr RNGFunc } -dummyRNG :: RNG -dummyRNG = RNG {rngContext = nullPtr, rngFunc = randomDummy} - withHaskellRNG :: (RNG -> IO c) -> IO c withHaskellRNG = bracket startHaskellRNG stopHaskellRNG @@ -48,8 +45,11 @@ type RNGContext = Ptr RNG -- typedef void random_func (void *ctx, size_t length, uint8_t *dst); type RNGFunc = Ptr RNGContext -> CSize -> Ptr Word8 -> IO () -foreign import ccall "&sxcrandom_dummy" - randomDummy :: FunPtr RNGFunc - foreign import ccall "wrapper" mkRNGFunc :: RNGFunc -> IO (FunPtr RNGFunc) + +-- dummyRNG :: RNG +-- dummyRNG = RNG {rngContext = nullPtr, rngFunc = randomDummy} + +-- foreign import ccall "&sxcrandom_dummy" +-- randomDummy :: FunPtr RNGFunc