Module Name: src Committed By: riastradh Date: Sat Jul 25 22:46:35 UTC 2020
Modified Files: src/sys/conf: files Added Files: src/sys/crypto/chacha: chacha.h chacha_impl.c chacha_impl.h chacha_ref.c chacha_ref.h chacha_selftest.c files.chacha Log Message: New ChaCha API in kernel. This will enable us to adopt MD vectorized implementations of ChaCha. To generate a diff of this commit: cvs rdiff -u -r1.1272 -r1.1273 src/sys/conf/files cvs rdiff -u -r0 -r1.1 src/sys/crypto/chacha/chacha.h \ src/sys/crypto/chacha/chacha_impl.c src/sys/crypto/chacha/chacha_impl.h \ src/sys/crypto/chacha/chacha_ref.c src/sys/crypto/chacha/chacha_ref.h \ src/sys/crypto/chacha/chacha_selftest.c \ src/sys/crypto/chacha/files.chacha Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/conf/files diff -u src/sys/conf/files:1.1272 src/sys/conf/files:1.1273 --- src/sys/conf/files:1.1272 Sat Jul 25 22:26:23 2020 +++ src/sys/conf/files Sat Jul 25 22:46:34 2020 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.1272 2020/07/25 22:26:23 riastradh Exp $ +# $NetBSD: files,v 1.1273 2020/07/25 22:46:34 riastradh Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20171118 @@ -202,6 +202,7 @@ defflag opt_machdep.h MACHDEP # Individual crypto transforms include "crypto/adiantum/files.adiantum" include "crypto/aes/files.aes" +include "crypto/chacha/files.chacha" include "crypto/des/files.des" include "crypto/blowfish/files.blowfish" include "crypto/cast128/files.cast128" Added files: Index: src/sys/crypto/chacha/chacha.h diff -u /dev/null src/sys/crypto/chacha/chacha.h:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha.h Sat Jul 25 22:46:34 2020 @@ -0,0 +1,85 @@ +/* $NetBSD: chacha.h,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _SYS_CRYPTO_CHACHA_CHACHA_H +#define _SYS_CRYPTO_CHACHA_CHACHA_H + +#include <sys/types.h> + +#define CHACHA_KEYBYTES 32 + +#define CHACHA_CORE_KEYBYTES CHACHA_KEYBYTES +#define CHACHA_CORE_INBYTES 16 +#define CHACHA_CORE_CONSTBYTES 16 +#define CHACHA_CORE_OUTBYTES 64 + +#define HCHACHA_KEYBYTES CHACHA_KEYBYTES +#define HCHACHA_INBYTES 16 +#define HCHACHA_CONSTBYTES 16 +#define HCHACHA_OUTBYTES 32 + +#define CHACHA_STREAM_KEYBYTES CHACHA_KEYBYTES +#define CHACHA_STREAM_NONCEBYTES 12 + +#define XCHACHA_STREAM_KEYBYTES CHACHA_KEYBYTES +#define XCHACHA_STREAM_NONCEBYTES 24 + +extern const uint8_t chacha_const32[16]; + +void chacha_core(uint8_t[restrict static CHACHA_CORE_OUTBYTES], + const uint8_t[static CHACHA_CORE_INBYTES], + const uint8_t[static CHACHA_CORE_KEYBYTES], + const uint8_t[static CHACHA_CORE_CONSTBYTES], + unsigned); +void hchacha(uint8_t[restrict static HCHACHA_OUTBYTES], + const uint8_t[static HCHACHA_INBYTES], + const uint8_t[static HCHACHA_KEYBYTES], + const uint8_t[static HCHACHA_CONSTBYTES], + unsigned); +void chacha_stream(uint8_t *restrict, size_t, + uint32_t, + const uint8_t[static CHACHA_STREAM_NONCEBYTES], + const uint8_t[static CHACHA_STREAM_KEYBYTES], + unsigned); +void chacha_stream_xor(uint8_t *, const uint8_t *, size_t, + uint32_t, + const uint8_t[static CHACHA_STREAM_NONCEBYTES], + const uint8_t[static CHACHA_STREAM_KEYBYTES], + unsigned); +void xchacha_stream(uint8_t *restrict, size_t, + uint32_t, + const uint8_t[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t[static XCHACHA_STREAM_KEYBYTES], + unsigned); +void xchacha_stream_xor(uint8_t *, const uint8_t *, size_t, + uint32_t, + const uint8_t[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t[static XCHACHA_STREAM_KEYBYTES], + unsigned); + +#endif /* _SYS_CRYPTO_CHACHA_CHACHA_H */ Index: src/sys/crypto/chacha/chacha_impl.c diff -u /dev/null src/sys/crypto/chacha/chacha_impl.c:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha_impl.c Sat Jul 25 22:46:34 2020 @@ -0,0 +1,206 @@ +/* $NetBSD: chacha_impl.c,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/types.h> +#include <sys/cdefs.h> +#include <sys/errno.h> +#include <sys/module.h> +#include <sys/once.h> +#include <sys/sysctl.h> + +#include <lib/libkern/libkern.h> + +#include "chacha.h" +#include "chacha_ref.h" + +static const struct chacha_impl *chacha_md_impl __read_mostly; +static const struct chacha_impl *chacha_impl __read_mostly; + +static int +sysctl_hw_chacha_impl(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + + KASSERTMSG(chacha_impl != NULL, + "sysctl ran before ChaCha implementation was selected"); + + node = *rnode; + node.sysctl_data = __UNCONST(chacha_impl->ci_name); + node.sysctl_size = strlen(chacha_impl->ci_name) + 1; + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +SYSCTL_SETUP(sysctl_hw_chacha_setup, "sysctl hw.chacha_impl setup") +{ + + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING, "chacha_impl", + SYSCTL_DESCR("Selected ChaCha implementation"), + sysctl_hw_chacha_impl, 0, NULL, 0, + CTL_HW, CTL_CREATE, CTL_EOL); +} + +static int +chacha_select(void) +{ + + KASSERT(chacha_impl == NULL); + + if (chacha_md_impl) { + if (chacha_selftest(chacha_md_impl)) + aprint_error("chacha: self-test failed: %s\n", + chacha_md_impl->ci_name); + else + chacha_impl = chacha_md_impl; + } + if (chacha_impl == NULL) { + if (chacha_selftest(&chacha_ref_impl)) + aprint_error("chacha: self-test failed: %s\n", + chacha_ref_impl.ci_name); + else + chacha_impl = &chacha_ref_impl; + } + if (chacha_impl == NULL) + panic("ChaCha self-tests failed"); + + aprint_verbose("chacha: %s\n", chacha_impl->ci_name); + return 0; +} + +MODULE(MODULE_CLASS_MISC, chacha, NULL); + +static int +chacha_modcmd(modcmd_t cmd, void *opaque) +{ + + switch (cmd) { + case MODULE_CMD_INIT: + return chacha_select(); + case MODULE_CMD_FINI: + return 0; + default: + return ENOTTY; + } +} + +static void +chacha_guarantee_selected(void) +{ +#if 0 + static once_t once; + int error; + + error = RUN_ONCE(&once, chacha_select); + KASSERT(error == 0); +#endif +} + +void +chacha_md_init(const struct chacha_impl *impl) +{ + + KASSERT(cold); + KASSERTMSG(chacha_impl == NULL, + "ChaCha implementation `%s' already chosen, can't offer `%s'", + chacha_impl->ci_name, impl->ci_name); + KASSERTMSG(chacha_md_impl == NULL, + "ChaCha implementation `%s' already offered, can't offer `%s'", + chacha_md_impl->ci_name, impl->ci_name); + + chacha_md_impl = impl; +} + +void +chacha_core(uint8_t out[restrict static CHACHA_CORE_OUTBYTES], + const uint8_t in[static CHACHA_CORE_INBYTES], + const uint8_t k[static CHACHA_CORE_KEYBYTES], + const uint8_t c[static CHACHA_CORE_CONSTBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_chacha_core)(out, in, k, c, nr); +} + +void +hchacha(uint8_t out[restrict static HCHACHA_OUTBYTES], + const uint8_t in[static HCHACHA_INBYTES], + const uint8_t k[static HCHACHA_KEYBYTES], + const uint8_t c[static HCHACHA_CONSTBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_hchacha)(out, in, k, c, nr); +} + +void +chacha_stream(uint8_t *restrict s, size_t nbytes, uint32_t blkno, + const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES], + const uint8_t key[static CHACHA_STREAM_KEYBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_chacha_stream)(s, nbytes, blkno, nonce, key, nr); +} + +void +chacha_stream_xor(uint8_t *c, const uint8_t *p, size_t nbytes, uint32_t blkno, + const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES], + const uint8_t key[static CHACHA_STREAM_KEYBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_chacha_stream_xor)(c, p, nbytes, blkno, nonce, key, + nr); +} + +void +xchacha_stream(uint8_t *restrict s, size_t nbytes, uint32_t blkno, + const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t key[static XCHACHA_STREAM_KEYBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_xchacha_stream)(s, nbytes, blkno, nonce, key, nr); +} + +void +xchacha_stream_xor(uint8_t *c, const uint8_t *p, size_t nbytes, uint32_t blkno, + const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t key[static XCHACHA_STREAM_KEYBYTES], + unsigned nr) +{ + + chacha_guarantee_selected(); + (*chacha_impl->ci_xchacha_stream_xor)(c, p, nbytes, blkno, nonce, key, + nr); +} Index: src/sys/crypto/chacha/chacha_impl.h diff -u /dev/null src/sys/crypto/chacha/chacha_impl.h:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha_impl.h Sat Jul 25 22:46:34 2020 @@ -0,0 +1,83 @@ +/* $NetBSD: chacha_impl.h,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _SYS_CRYPTO_CHACHA_CHACHA_IMPL_H +#define _SYS_CRYPTO_CHACHA_CHACHA_IMPL_H + +#ifdef _KERNEL +#include <sys/types.h> +#include <sys/systm.h> +#else +#include <stdint.h> +#include <string.h> +#endif + +#include <crypto/chacha/chacha.h> + +struct chacha_impl { + const char *ci_name; + int (*ci_probe)(void); + void (*ci_chacha_core)(uint8_t[restrict static CHACHA_CORE_OUTBYTES], + const uint8_t[static CHACHA_CORE_INBYTES], + const uint8_t[static CHACHA_CORE_KEYBYTES], + const uint8_t[static CHACHA_CORE_CONSTBYTES], + unsigned); + void (*ci_hchacha)(uint8_t[restrict static HCHACHA_OUTBYTES], + const uint8_t[static HCHACHA_INBYTES], + const uint8_t[static HCHACHA_KEYBYTES], + const uint8_t[static HCHACHA_CONSTBYTES], + unsigned); + void (*ci_chacha_stream)(uint8_t *restrict, size_t, + uint32_t, + const uint8_t[static CHACHA_STREAM_NONCEBYTES], + const uint8_t[static CHACHA_STREAM_KEYBYTES], + unsigned); + void (*ci_chacha_stream_xor)(uint8_t *, const uint8_t *, + size_t, + uint32_t, + const uint8_t[static CHACHA_STREAM_NONCEBYTES], + const uint8_t[static CHACHA_STREAM_KEYBYTES], + unsigned); + void (*ci_xchacha_stream)(uint8_t *restrict, size_t, + uint32_t, + const uint8_t[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t[static XCHACHA_STREAM_KEYBYTES], + unsigned); + void (*ci_xchacha_stream_xor)(uint8_t *, const uint8_t *, + size_t, + uint32_t, + const uint8_t[static XCHACHA_STREAM_NONCEBYTES], + const uint8_t[static XCHACHA_STREAM_KEYBYTES], + unsigned); +}; + +int chacha_selftest(const struct chacha_impl *); + +void chacha_md_init(const struct chacha_impl *); + +#endif /* _SYS_CRYPTO_CHACHA_CHACHA_IMPL_H */ Index: src/sys/crypto/chacha/chacha_ref.c diff -u /dev/null src/sys/crypto/chacha/chacha_ref.c:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha_ref.c Sat Jul 25 22:46:34 2020 @@ -0,0 +1,466 @@ +/* $NetBSD: chacha_ref.c,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * ChaCha pseudorandom function family and stream cipher portable C + * implementation. Derived from the specification, + * + * Daniel J. Bernstein, `ChaCha, a variant of Salsa20', Workshop + * Record of the State of the Art in Stream Ciphers -- SASC 2008. + * https://cr.yp.to/papers.html#chacha + * + * which in turn builds on the specification of Salsa20 available at + * <https://cr.yp.to/snuffle.html>. The particular parametrization of + * the stream cipher, with a 32-bit block counter and 96-bit nonce, is + * described in + * + * Y. Nir and A. Langley, `ChaCha20 and Poly1305 for IETF + * Protocols', IETF RFC 8439, June 2018. + * https://tools.ietf.org/html/rfc8439 + */ + +#include "chacha_ref.h" + +static uint32_t +rol32(uint32_t u, unsigned c) +{ + + return (u << c) | (u >> (32 - c)); +} + +#define CHACHA_QUARTERROUND(a, b, c, d) do \ +{ \ + (a) += (b); (d) ^= (a); (d) = rol32((d), 16); \ + (c) += (d); (b) ^= (c); (b) = rol32((b), 12); \ + (a) += (b); (d) ^= (a); (d) = rol32((d), 8); \ + (c) += (d); (b) ^= (c); (b) = rol32((b), 7); \ +} while (/*CONSTCOND*/0) + +const uint8_t chacha_const32[16] = "expand 32-byte k"; + +static void +chacha_core_ref(uint8_t out[restrict static 64], const uint8_t in[static 16], + const uint8_t k[static 32], const uint8_t c[static 16], unsigned nr) +{ + uint32_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15; + uint32_t y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + + x0 = y0 = le32dec(c + 0); + x1 = y1 = le32dec(c + 4); + x2 = y2 = le32dec(c + 8); + x3 = y3 = le32dec(c + 12); + x4 = y4 = le32dec(k + 0); + x5 = y5 = le32dec(k + 4); + x6 = y6 = le32dec(k + 8); + x7 = y7 = le32dec(k + 12); + x8 = y8 = le32dec(k + 16); + x9 = y9 = le32dec(k + 20); + x10 = y10 = le32dec(k + 24); + x11 = y11 = le32dec(k + 28); + x12 = y12 = le32dec(in + 0); + x13 = y13 = le32dec(in + 4); + x14 = y14 = le32dec(in + 8); + x15 = y15 = le32dec(in + 12); + + for (; nr > 0; nr -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + + le32enc(out + 0, x0 + y0); + le32enc(out + 4, x1 + y1); + le32enc(out + 8, x2 + y2); + le32enc(out + 12, x3 + y3); + le32enc(out + 16, x4 + y4); + le32enc(out + 20, x5 + y5); + le32enc(out + 24, x6 + y6); + le32enc(out + 28, x7 + y7); + le32enc(out + 32, x8 + y8); + le32enc(out + 36, x9 + y9); + le32enc(out + 40, x10 + y10); + le32enc(out + 44, x11 + y11); + le32enc(out + 48, x12 + y12); + le32enc(out + 52, x13 + y13); + le32enc(out + 56, x14 + y14); + le32enc(out + 60, x15 + y15); +} + +/* ChaCha stream cipher (IETF style, 96-bit nonce and 32-bit block counter) */ + +static void +chacha_stream_ref(uint8_t *restrict s, size_t nbytes, + uint32_t blkno, + const uint8_t nonce[static 12], + const uint8_t k[static 32], + unsigned nr) +{ + const uint8_t *c = chacha_const32; + uint32_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15; + uint32_t y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + unsigned i; + + x0 = le32dec(c + 0); + x1 = le32dec(c + 4); + x2 = le32dec(c + 8); + x3 = le32dec(c + 12); + x4 = le32dec(k + 0); + x5 = le32dec(k + 4); + x6 = le32dec(k + 8); + x7 = le32dec(k + 12); + x8 = le32dec(k + 16); + x9 = le32dec(k + 20); + x10 = le32dec(k + 24); + x11 = le32dec(k + 28); + /* x12 = blkno */ + x13 = le32dec(nonce + 0); + x14 = le32dec(nonce + 4); + x15 = le32dec(nonce + 8); + + for (; nbytes >= 64; nbytes -= 64, s += 64, blkno++) { + y0 = x0; + y1 = x1; + y2 = x2; + y3 = x3; + y4 = x4; + y5 = x5; + y6 = x6; + y7 = x7; + y8 = x8; + y9 = x9; + y10 = x10; + y11 = x11; + y12 = x12 = blkno; + y13 = x13; + y14 = x14; + y15 = x15; + for (i = nr; i > 0; i -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + le32enc(s + 0, x0 + y0); + le32enc(s + 4, x1 + y1); + le32enc(s + 8, x2 + y2); + le32enc(s + 12, x3 + y3); + le32enc(s + 16, x4 + y4); + le32enc(s + 20, x5 + y5); + le32enc(s + 24, x6 + y6); + le32enc(s + 28, x7 + y7); + le32enc(s + 32, x8 + y8); + le32enc(s + 36, x9 + y9); + le32enc(s + 40, x10 + y10); + le32enc(s + 44, x11 + y11); + le32enc(s + 48, x12 + y12); + le32enc(s + 52, x13 + y13); + le32enc(s + 56, x14 + y14); + le32enc(s + 60, x15 + y15); + } + + if (nbytes) { + uint8_t buf[64]; + + y0 = x0; + y1 = x1; + y2 = x2; + y3 = x3; + y4 = x4; + y5 = x5; + y6 = x6; + y7 = x7; + y8 = x8; + y9 = x9; + y10 = x10; + y11 = x11; + y12 = x12 = blkno; + y13 = x13; + y14 = x14; + y15 = x15; + for (i = nr; i > 0; i -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + le32enc(buf + 0, x0 + y0); + le32enc(buf + 4, x1 + y1); + le32enc(buf + 8, x2 + y2); + le32enc(buf + 12, x3 + y3); + le32enc(buf + 16, x4 + y4); + le32enc(buf + 20, x5 + y5); + le32enc(buf + 24, x6 + y6); + le32enc(buf + 28, x7 + y7); + le32enc(buf + 32, x8 + y8); + le32enc(buf + 36, x9 + y9); + le32enc(buf + 40, x10 + y10); + le32enc(buf + 44, x11 + y11); + le32enc(buf + 48, x12 + y12); + le32enc(buf + 52, x13 + y13); + le32enc(buf + 56, x14 + y14); + le32enc(buf + 60, x15 + y15); + memcpy(s, buf, nbytes); + } +} + +static void +chacha_stream_xor_ref(uint8_t *s, const uint8_t *p, size_t nbytes, + uint32_t blkno, + const uint8_t nonce[static 12], + const uint8_t k[static 32], + unsigned nr) +{ + const uint8_t *c = chacha_const32; + uint32_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15; + uint32_t y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + unsigned i; + + x0 = le32dec(c + 0); + x1 = le32dec(c + 4); + x2 = le32dec(c + 8); + x3 = le32dec(c + 12); + x4 = le32dec(k + 0); + x5 = le32dec(k + 4); + x6 = le32dec(k + 8); + x7 = le32dec(k + 12); + x8 = le32dec(k + 16); + x9 = le32dec(k + 20); + x10 = le32dec(k + 24); + x11 = le32dec(k + 28); + /* x12 = blkno */ + x13 = le32dec(nonce + 0); + x14 = le32dec(nonce + 4); + x15 = le32dec(nonce + 8); + + for (; nbytes >= 64; nbytes -= 64, s += 64, p += 64, blkno++) { + y0 = x0; + y1 = x1; + y2 = x2; + y3 = x3; + y4 = x4; + y5 = x5; + y6 = x6; + y7 = x7; + y8 = x8; + y9 = x9; + y10 = x10; + y11 = x11; + y12 = x12 = blkno; + y13 = x13; + y14 = x14; + y15 = x15; + for (i = nr; i > 0; i -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + le32enc(s + 0, (x0 + y0) ^ le32dec(p + 0)); + le32enc(s + 4, (x1 + y1) ^ le32dec(p + 4)); + le32enc(s + 8, (x2 + y2) ^ le32dec(p + 8)); + le32enc(s + 12, (x3 + y3) ^ le32dec(p + 12)); + le32enc(s + 16, (x4 + y4) ^ le32dec(p + 16)); + le32enc(s + 20, (x5 + y5) ^ le32dec(p + 20)); + le32enc(s + 24, (x6 + y6) ^ le32dec(p + 24)); + le32enc(s + 28, (x7 + y7) ^ le32dec(p + 28)); + le32enc(s + 32, (x8 + y8) ^ le32dec(p + 32)); + le32enc(s + 36, (x9 + y9) ^ le32dec(p + 36)); + le32enc(s + 40, (x10 + y10) ^ le32dec(p + 40)); + le32enc(s + 44, (x11 + y11) ^ le32dec(p + 44)); + le32enc(s + 48, (x12 + y12) ^ le32dec(p + 48)); + le32enc(s + 52, (x13 + y13) ^ le32dec(p + 52)); + le32enc(s + 56, (x14 + y14) ^ le32dec(p + 56)); + le32enc(s + 60, (x15 + y15) ^ le32dec(p + 60)); + } + + if (nbytes) { + uint8_t buf[64]; + + y0 = x0; + y1 = x1; + y2 = x2; + y3 = x3; + y4 = x4; + y5 = x5; + y6 = x6; + y7 = x7; + y8 = x8; + y9 = x9; + y10 = x10; + y11 = x11; + y12 = x12 = blkno; + y13 = x13; + y14 = x14; + y15 = x15; + for (i = nr; i > 0; i -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + le32enc(buf + 0, x0 + y0); + le32enc(buf + 4, x1 + y1); + le32enc(buf + 8, x2 + y2); + le32enc(buf + 12, x3 + y3); + le32enc(buf + 16, x4 + y4); + le32enc(buf + 20, x5 + y5); + le32enc(buf + 24, x6 + y6); + le32enc(buf + 28, x7 + y7); + le32enc(buf + 32, x8 + y8); + le32enc(buf + 36, x9 + y9); + le32enc(buf + 40, x10 + y10); + le32enc(buf + 44, x11 + y11); + le32enc(buf + 48, x12 + y12); + le32enc(buf + 52, x13 + y13); + le32enc(buf + 56, x14 + y14); + le32enc(buf + 60, x15 + y15); + for (i = 0; i < nbytes - nbytes%4; i += 4) + le32enc(s + i, le32dec(p + i) ^ le32dec(buf + i)); + for (; i < nbytes; i++) + s[i] = p[i] ^ buf[i]; + } +} + +/* HChaCha */ + +static void +hchacha_ref(uint8_t out[restrict static 32], const uint8_t in[static 16], + const uint8_t k[static 32], const uint8_t c[static 16], unsigned nr) +{ + uint32_t y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + + y0 = le32dec(c + 0); + y1 = le32dec(c + 4); + y2 = le32dec(c + 8); + y3 = le32dec(c + 12); + y4 = le32dec(k + 0); + y5 = le32dec(k + 4); + y6 = le32dec(k + 8); + y7 = le32dec(k + 12); + y8 = le32dec(k + 16); + y9 = le32dec(k + 20); + y10 = le32dec(k + 24); + y11 = le32dec(k + 28); + y12 = le32dec(in + 0); + y13 = le32dec(in + 4); + y14 = le32dec(in + 8); + y15 = le32dec(in + 12); + + for (; nr > 0; nr -= 2) { + CHACHA_QUARTERROUND( y0, y4, y8,y12); + CHACHA_QUARTERROUND( y1, y5, y9,y13); + CHACHA_QUARTERROUND( y2, y6,y10,y14); + CHACHA_QUARTERROUND( y3, y7,y11,y15); + CHACHA_QUARTERROUND( y0, y5,y10,y15); + CHACHA_QUARTERROUND( y1, y6,y11,y12); + CHACHA_QUARTERROUND( y2, y7, y8,y13); + CHACHA_QUARTERROUND( y3, y4, y9,y14); + } + + le32enc(out + 0, y0); + le32enc(out + 4, y1); + le32enc(out + 8, y2); + le32enc(out + 12, y3); + le32enc(out + 16, y12); + le32enc(out + 20, y13); + le32enc(out + 24, y14); + le32enc(out + 28, y15); +} + +/* XChaCha stream cipher */ + +/* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03 */ + +static void +xchacha_stream_ref(uint8_t *restrict s, size_t nbytes, uint32_t blkno, + const uint8_t nonce[static 24], const uint8_t k[static 32], unsigned nr) +{ + uint8_t subkey[32]; + uint8_t subnonce[12]; + + hchacha_ref(subkey, nonce/*[0:16)*/, k, chacha_const32, nr); + memset(subnonce, 0, 4); + memcpy(subnonce + 4, nonce + 16, 8); + chacha_stream_ref(s, nbytes, blkno, subnonce, subkey, nr); +} + +static void +xchacha_stream_xor_ref(uint8_t *restrict c, const uint8_t *p, size_t nbytes, + uint32_t blkno, + const uint8_t nonce[static 24], + const uint8_t k[static 32], + unsigned nr) +{ + uint8_t subkey[32]; + uint8_t subnonce[12]; + + hchacha_ref(subkey, nonce/*[0:16)*/, k, chacha_const32, nr); + memset(subnonce, 0, 4); + memcpy(subnonce + 4, nonce + 16, 8); + chacha_stream_xor_ref(c, p, nbytes, blkno, subnonce, subkey, nr); +} + +static int +chacha_probe_ref(void) +{ + + /* The reference implementation is always available. */ + return 0; +} + +const struct chacha_impl chacha_ref_impl = { + .ci_name = "Portable C ChaCha", + .ci_probe = chacha_probe_ref, + .ci_chacha_core = chacha_core_ref, + .ci_hchacha = hchacha_ref, + .ci_chacha_stream = chacha_stream_ref, + .ci_chacha_stream_xor = chacha_stream_xor_ref, + .ci_xchacha_stream = xchacha_stream_ref, + .ci_xchacha_stream_xor = xchacha_stream_xor_ref, +}; Index: src/sys/crypto/chacha/chacha_ref.h diff -u /dev/null src/sys/crypto/chacha/chacha_ref.h:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha_ref.h Sat Jul 25 22:46:34 2020 @@ -0,0 +1,36 @@ +/* $NetBSD: chacha_ref.h,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _SYS_CRYPTO_CHACHA_REF_H +#define _SYS_CRYPTO_CHACHA_REF_H + +#include "chacha_impl.h" + +extern const struct chacha_impl chacha_ref_impl; + +#endif /* _SYS_CRYPTO_CHACHA_REF_H */ Index: src/sys/crypto/chacha/chacha_selftest.c diff -u /dev/null src/sys/crypto/chacha/chacha_selftest.c:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/chacha_selftest.c Sat Jul 25 22:46:34 2020 @@ -0,0 +1,464 @@ +/* $NetBSD: chacha_selftest.c,v 1.1 2020/07/25 22:46:34 riastradh Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "chacha_impl.h" + +#ifdef _KERNEL + +#include <lib/libkern/libkern.h> + +#else + +#include <stdio.h> +#include <string.h> + +static void +hexdump(int (*prf)(const char *, ...) __printflike(1,2), const char *prefix, + const void *buf, size_t len) +{ + const uint8_t *p = buf; + size_t i; + + (*prf)("%s (%zu bytes @ %p)\n", prefix, len, buf); + for (i = 0; i < len; i++) { + if (i % 16 == 8) + (*prf)(" "); + else + (*prf)(" "); + (*prf)("%02hhx", p[i]); + if ((i + 1) % 16 == 0) + (*prf)("\n"); + } + if (i % 16) + (*prf)("\n"); +} + +#endif + +/* https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-00 */ +static int +chacha_core_selftest(const struct chacha_impl *ci) +{ + /* TC1, 32-byte key, rounds=12, keystream block 1 */ + static const uint8_t zero[32]; + static const uint8_t expected0[64] = { + 0x9b,0xf4,0x9a,0x6a, 0x07,0x55,0xf9,0x53, + 0x81,0x1f,0xce,0x12, 0x5f,0x26,0x83,0xd5, + 0x04,0x29,0xc3,0xbb, 0x49,0xe0,0x74,0x14, + 0x7e,0x00,0x89,0xa5, 0x2e,0xae,0x15,0x5f, + 0x05,0x64,0xf8,0x79, 0xd2,0x7a,0xe3,0xc0, + 0x2c,0xe8,0x28,0x34, 0xac,0xfa,0x8c,0x79, + 0x3a,0x62,0x9f,0x2c, 0xa0,0xde,0x69,0x19, + 0x61,0x0b,0xe8,0x2f, 0x41,0x13,0x26,0xbe, + }; + /* TC7, 32-byte key, rounds=12, keystream block 2 */ + static const uint8_t k1[32] = { + 0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77, + 0x88,0x99,0xaa,0xbb, 0xcc,0xdd,0xee,0xff, + 0xff,0xee,0xdd,0xcc, 0xbb,0xaa,0x99,0x88, + 0x77,0x66,0x55,0x44, 0x33,0x22,0x11,0x00, + }; + static const uint8_t in1[16] = { + 0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x0f,0x1e,0x2d,0x3c, 0x4b,0x59,0x68,0x77, + }; + static const uint8_t expected1[64] = { + 0xcd,0x9a,0x2a,0xa9, 0xea,0x93,0xc2,0x67, + 0x5e,0x82,0x88,0x14, 0x08,0xde,0x85,0x2c, + 0x62,0xfa,0x74,0x6a, 0x30,0xe5,0x2b,0x45, + 0xa2,0x69,0x62,0xcf, 0x43,0x51,0xe3,0x04, + 0xd3,0x13,0x20,0xbb, 0xd6,0xaa,0x6c,0xc8, + 0xf3,0x26,0x37,0xf9, 0x59,0x34,0xe4,0xc1, + 0x45,0xef,0xd5,0x62, 0x31,0xef,0x31,0x61, + 0x03,0x28,0x36,0xf4, 0x96,0x71,0x83,0x3e, + }; + uint8_t out[64]; + int result = 0; + + (*ci->ci_chacha_core)(out, zero, zero, chacha_const32, 12); + if (memcmp(out, expected0, 64)) { + hexdump(printf, "chacha core 1", out, sizeof out); + result = -1; + } + + (*ci->ci_chacha_core)(out, in1, k1, chacha_const32, 12); + if (memcmp(out, expected1, 64)) { + hexdump(printf, "chacha core 2", out, sizeof out); + result = -1; + } + + return result; +} + +static int +hchacha_selftest(const struct chacha_impl *ci) +{ + /* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, ยง2.2.1 */ + static const uint8_t k[32] = { + 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f, + }; + static const uint8_t in[16] = { + 0x00,0x00,0x00,0x09, 0x00,0x00,0x00,0x4a, + 0x00,0x00,0x00,0x00, 0x31,0x41,0x59,0x27, + }; + static const uint8_t expected[32] = { + 0x82,0x41,0x3b,0x42, 0x27,0xb2,0x7b,0xfe, + 0xd3,0x0e,0x42,0x50, 0x8a,0x87,0x7d,0x73, + 0xa0,0xf9,0xe4,0xd5, 0x8a,0x74,0xa8,0x53, + 0xc1,0x2e,0xc4,0x13, 0x26,0xd3,0xec,0xdc, + }; + uint8_t out[32]; + int result = 0; + + (*ci->ci_hchacha)(out, in, k, chacha_const32, 20); + if (memcmp(out, expected, 32)) { + hexdump(printf, "hchacha", out, sizeof out); + result = -1; + } + + return result; +} + +static int +chacha_stream_selftest(const struct chacha_impl *ci) +{ + + /* XXX */ + return 0; +} + +static int +xchacha_stream_selftest(const struct chacha_impl *ci) +{ + /* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, A.2.1 */ + static const uint8_t k[32] = { + 0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97, + 0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f, + }; + static const uint8_t nonce[24] = { + 0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, + 0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x58, + }; + static const uint8_t p[608] = { + 0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c, + 0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f, + 0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64, + 0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73, + 0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e, + 0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74, + 0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74, + 0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20, + 0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64, + 0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e, + 0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c, + 0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e, + 0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61, + 0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65, + 0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66, + 0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61, + 0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65, + 0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c, + 0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72, + 0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61, + 0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65, + 0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78, + 0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68, + 0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c, + 0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e, + 0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65, + 0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72, + 0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73, + 0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77, + 0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76, + 0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f, + 0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63, + 0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e, + 0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20, + 0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74, + 0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63, + 0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20, + 0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e, + + 0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c, + 0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f, + 0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64, + 0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73, + 0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e, + 0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74, + 0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74, + 0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20, + 0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64, + 0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e, + 0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c, + 0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e, + 0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61, + 0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65, + 0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66, + 0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61, + 0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65, + 0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c, + 0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72, + 0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61, + 0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65, + 0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78, + 0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68, + 0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c, + 0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e, + 0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65, + 0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72, + 0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73, + 0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77, + 0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76, + 0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f, + 0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63, + 0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e, + 0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20, + 0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74, + 0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63, + 0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20, + 0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e, + }; + static const uint8_t expected[608] = { + 0x45,0x59,0xab,0xba, 0x4e,0x48,0xc1,0x61, + 0x02,0xe8,0xbb,0x2c, 0x05,0xe6,0x94,0x7f, + 0x50,0xa7,0x86,0xde, 0x16,0x2f,0x9b,0x0b, + 0x7e,0x59,0x2a,0x9b, 0x53,0xd0,0xd4,0xe9, + 0x8d,0x8d,0x64,0x10, 0xd5,0x40,0xa1,0xa6, + 0x37,0x5b,0x26,0xd8, 0x0d,0xac,0xe4,0xfa, + 0xb5,0x23,0x84,0xc7, 0x31,0xac,0xbf,0x16, + 0xa5,0x92,0x3c,0x0c, 0x48,0xd3,0x57,0x5d, + 0x4d,0x0d,0x2c,0x67, 0x3b,0x66,0x6f,0xaa, + 0x73,0x10,0x61,0x27, 0x77,0x01,0x09,0x3a, + 0x6b,0xf7,0xa1,0x58, 0xa8,0x86,0x42,0x92, + 0xa4,0x1c,0x48,0xe3, 0xa9,0xb4,0xc0,0xda, + 0xec,0xe0,0xf8,0xd9, 0x8d,0x0d,0x7e,0x05, + 0xb3,0x7a,0x30,0x7b, 0xbb,0x66,0x33,0x31, + 0x64,0xec,0x9e,0x1b, 0x24,0xea,0x0d,0x6c, + 0x3f,0xfd,0xdc,0xec, 0x4f,0x68,0xe7,0x44, + 0x30,0x56,0x19,0x3a, 0x03,0xc8,0x10,0xe1, + 0x13,0x44,0xca,0x06, 0xd8,0xed,0x8a,0x2b, + 0xfb,0x1e,0x8d,0x48, 0xcf,0xa6,0xbc,0x0e, + 0xb4,0xe2,0x46,0x4b, 0x74,0x81,0x42,0x40, + 0x7c,0x9f,0x43,0x1a, 0xee,0x76,0x99,0x60, + 0xe1,0x5b,0xa8,0xb9, 0x68,0x90,0x46,0x6e, + 0xf2,0x45,0x75,0x99, 0x85,0x23,0x85,0xc6, + 0x61,0xf7,0x52,0xce, 0x20,0xf9,0xda,0x0c, + 0x09,0xab,0x6b,0x19, 0xdf,0x74,0xe7,0x6a, + 0x95,0x96,0x74,0x46, 0xf8,0xd0,0xfd,0x41, + 0x5e,0x7b,0xee,0x2a, 0x12,0xa1,0x14,0xc2, + 0x0e,0xb5,0x29,0x2a, 0xe7,0xa3,0x49,0xae, + 0x57,0x78,0x20,0xd5, 0x52,0x0a,0x1f,0x3f, + 0xb6,0x2a,0x17,0xce, 0x6a,0x7e,0x68,0xfa, + 0x7c,0x79,0x11,0x1d, 0x88,0x60,0x92,0x0b, + 0xc0,0x48,0xef,0x43, 0xfe,0x84,0x48,0x6c, + 0xcb,0x87,0xc2,0x5f, 0x0a,0xe0,0x45,0xf0, + 0xcc,0xe1,0xe7,0x98, 0x9a,0x9a,0xa2,0x20, + 0xa2,0x8b,0xdd,0x48, 0x27,0xe7,0x51,0xa2, + 0x4a,0x6d,0x5c,0x62, 0xd7,0x90,0xa6,0x63, + 0x93,0xb9,0x31,0x11, 0xc1,0xa5,0x5d,0xd7, + 0x42,0x1a,0x10,0x18, 0x49,0x74,0xc7,0xc5, + + 0x08,0x38,0x2d,0x64, 0x35,0x8d,0x21,0x77, + 0x2e,0xb9,0x73,0xa8, 0x8f,0xb6,0x2b,0xf8, + 0xce,0xfa,0xb4,0xca, 0x6f,0x0c,0x26,0xbb, + 0x7f,0xd6,0x6d,0xb2, 0xa0,0xbe,0xb0,0x5a, + 0x1a,0x6e,0x39,0xcb, 0xd5,0xda,0xf2,0xfc, + 0x0b,0x74,0x31,0x3d, 0x2e,0xcd,0x5f,0x94, + 0xc2,0x9f,0x30,0xdb, 0x11,0x5e,0x41,0x53, + 0x8c,0x6d,0x30,0xba, 0x97,0xa0,0xc5,0x07, + 0x70,0x78,0x02,0x5a, 0xc1,0x69,0x70,0x8f, + 0x22,0x85,0xcb,0x98, 0xbc,0x6a,0x51,0xfb, + 0xc6,0xa7,0xc3,0x3d, 0x76,0xe4,0x93,0x9a, + 0x21,0xe2,0xc6,0x12, 0xe1,0x3a,0xcc,0xfb, + 0x6f,0xa6,0x57,0xc0, 0x09,0x8c,0x6f,0xf3, + 0x8d,0x83,0x21,0x1b, 0x71,0xa9,0xc1,0x93, + 0x88,0x35,0xfc,0x18, 0x1f,0x94,0xa2,0x57, + 0x3a,0x4e,0xd0,0xc0, 0xbc,0x92,0xa7,0x9c, + 0x52,0x8a,0x82,0x9d, 0x44,0x75,0x7b,0xa0, + 0xcf,0x3d,0x2d,0xbf, 0xf9,0x6f,0x71,0x56, + 0x38,0xb0,0x63,0x5e, 0x55,0xcd,0x28,0x12, + 0xc5,0xea,0x52,0xf4, 0xdc,0xf7,0xdc,0x3d, + 0xd8,0x96,0x09,0xe8, 0x2a,0xcc,0x00,0x16, + 0x88,0x77,0x82,0x10, 0xed,0x7d,0xd8,0x8b, + 0xf5,0xd3,0xe1,0xfc, 0x49,0x66,0x36,0x8d, + 0x55,0xd2,0x33,0xb8, 0x6d,0xff,0xe3,0xd3, + 0x55,0x80,0x0e,0xd8, 0x95,0x32,0x32,0x55, + 0x83,0xe7,0x58,0x6f, 0xec,0xc3,0x8c,0xf8, + 0x52,0x16,0xdc,0x0d, 0x29,0x02,0xe5,0x27, + 0x35,0xc2,0xbb,0xe2, 0xe2,0x3b,0xf5,0x19, + 0xcd,0x44,0x83,0xe8, 0x21,0x55,0xd0,0x10, + 0x15,0x68,0x8e,0x46, 0xa3,0x2f,0xa5,0x7c, + 0xa8,0x2c,0xc6,0x8f, 0x14,0xcd,0xb3,0x79, + 0x92,0x32,0x71,0xac, 0xd9,0xaf,0x9c,0x4d, + 0x00,0x88,0xd1,0x42, 0xd5,0x23,0xfa,0xe6, + 0x7f,0x38,0xa2,0x56, 0x99,0xbe,0x6f,0xcf, + 0xe0,0xaa,0x44,0x11, 0x8a,0xc8,0x3a,0x99, + 0x48,0x6d,0x33,0x0e, 0x94,0xf2,0xb9,0x87, + 0xed,0x4f,0x6a,0x9c, 0x33,0x93,0x6d,0xe4, + 0x92,0x76,0xab,0xfa, 0xce,0x5b,0x17,0x14, + }; + uint8_t c[608]; + unsigned i; + int result = 0; + + /* + * 608 = 96 (mod 256) + * 607 = 95 (mod 256), = 7 (mod 8) + * 543 = 31 (mod 256), = 7 (mod 8) + * 511 = 255 (mod 256), = 7 (mod 8) + * + * This exercises several branches when there are special cases + * for integral numbers of 4-byte words, integral numbers of + * 64-byte blocks, and integral numbers of 256-byte chunks. + */ + + (*ci->ci_xchacha_stream)(c, 608, 0, nonce, k, 20); + for (i = 0; i < 608; i++) + c[i] ^= p[i]; + if (memcmp(c, expected, 608)) { + for (i = 0; i < 608; i++) + c[i] ^= p[i]; + hexdump(printf, "xchacha_stream", c, 608); + for (i = 0; i < 608; i++) + c[i] = expected[i] ^ p[i]; + hexdump(printf, "expected", c, 608); + result = -1; + } + + (*ci->ci_xchacha_stream)(c, 607, 0, nonce, k, 20); + for (i = 0; i < 607; i++) + c[i] ^= p[i]; + if (memcmp(c, expected, 607)) { + for (i = 0; i < 607; i++) + c[i] ^= p[i]; + hexdump(printf, "xchacha_stream", c, 607); + for (i = 0; i < 607; i++) + c[i] = expected[i] ^ p[i]; + hexdump(printf, "expected", c, 607); + result = -1; + } + + (*ci->ci_xchacha_stream)(c, 543, 0, nonce, k, 20); + for (i = 0; i < 543; i++) + c[i] ^= p[i]; + if (memcmp(c, expected, 543)) { + for (i = 0; i < 543; i++) + c[i] ^= p[i]; + hexdump(printf, "xchacha_stream", c, 543); + for (i = 0; i < 543; i++) + c[i] = expected[i] ^ p[i]; + hexdump(printf, "expected", c, 543); + result = -1; + } + + (*ci->ci_xchacha_stream)(c, 511, 0, nonce, k, 20); + for (i = 0; i < 511; i++) + c[i] ^= p[i]; + if (memcmp(c, expected, 511)) { + for (i = 0; i < 511; i++) + c[i] ^= p[i]; + hexdump(printf, "xchacha_stream", c, 511); + for (i = 0; i < 511; i++) + c[i] = expected[i] ^ p[i]; + hexdump(printf, "expected", c, 511); + result = -1; + } + + (*ci->ci_xchacha_stream)(c, 63, 0, nonce, k, 20); + for (i = 0; i < 63; i++) + c[i] ^= p[i]; + if (memcmp(c, expected, 63)) { + for (i = 0; i < 63; i++) + c[i] ^= p[i]; + hexdump(printf, "xchacha_stream", c, 63); + for (i = 0; i < 63; i++) + c[i] = expected[i] ^ p[i]; + hexdump(printf, "expected", c, 63); + result = -1; + } + + (*ci->ci_xchacha_stream_xor)(c, p, 608, 0, nonce, k, 20); + if (memcmp(c, expected, 608)) { + hexdump(printf, "xchacha_stream_xor", c, 608); + hexdump(printf, "expected", expected, 608); + result = -1; + } + + memset(c, 0, sizeof c); + (*ci->ci_xchacha_stream_xor)(c, p, 607, 0, nonce, k, 20); + if (memcmp(c, expected, 607)) { + hexdump(printf, "xchacha_stream_xor", c, 607); + hexdump(printf, "expected", expected, 607); + result = -1; + } + + memset(c, 0, sizeof c); + (*ci->ci_xchacha_stream_xor)(c, p, 543, 0, nonce, k, 20); + if (memcmp(c, expected, 543)) { + hexdump(printf, "xchacha_stream_xor", c, 543); + hexdump(printf, "expected", expected, 543); + result = -1; + } + + memset(c, 0, sizeof c); + (*ci->ci_xchacha_stream_xor)(c, p, 511, 0, nonce, k, 20); + if (memcmp(c, expected, 511)) { + hexdump(printf, "xchacha_stream_xor", c, 511); + hexdump(printf, "expected", expected, 511); + result = -1; + } + + memset(c, 0, sizeof c); + (*ci->ci_xchacha_stream_xor)(c, p, 63, 0, nonce, k, 20); + if (memcmp(c, expected, 63)) { + hexdump(printf, "xchacha_stream_xor", c, 63); + hexdump(printf, "expected", expected, 63); + result = -1; + } + + return result; +} + +int +chacha_selftest(const struct chacha_impl *ci) +{ + int result = 0; + + result |= chacha_core_selftest(ci); + result |= chacha_stream_selftest(ci); + result |= hchacha_selftest(ci); + result |= xchacha_stream_selftest(ci); + + return result; +} Index: src/sys/crypto/chacha/files.chacha diff -u /dev/null src/sys/crypto/chacha/files.chacha:1.1 --- /dev/null Sat Jul 25 22:46:35 2020 +++ src/sys/crypto/chacha/files.chacha Sat Jul 25 22:46:35 2020 @@ -0,0 +1,7 @@ +# $NetBSD: files.chacha,v 1.1 2020/07/25 22:46:35 riastradh Exp $ + +define chacha + +file crypto/chacha/chacha_impl.c chacha +file crypto/chacha/chacha_ref.c chacha +file crypto/chacha/chacha_selftest.c chacha