Date: Sat, 15 Apr 2017 20:51:53 +0000 (UTC) From: =?UTF-8?Q?Dag-Erling_Sm=c3=b8rgrav?= <des@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r316982 - in head/sys: conf crypto/chacha20 modules modules/chacha20 Message-ID: <201704152051.v3FKpr38020502@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: des Date: Sat Apr 15 20:51:53 2017 New Revision: 316982 URL: https://svnweb.freebsd.org/changeset/base/316982 Log: 3BSD-licensed implementation of the chacha20 stream cipher, intended for use by the upcoming arc4random replacement. Added: head/sys/crypto/chacha20/ head/sys/crypto/chacha20/chacha20.c (contents, props changed) head/sys/crypto/chacha20/chacha20.h (contents, props changed) head/sys/modules/chacha20/ head/sys/modules/chacha20/Makefile (contents, props changed) Modified: head/sys/conf/files head/sys/modules/Makefile Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Sat Apr 15 20:37:34 2017 (r316981) +++ head/sys/conf/files Sat Apr 15 20:51:53 2017 (r316982) @@ -591,6 +591,7 @@ crypto/blowfish/bf_ecb.c optional ipsec crypto/blowfish/bf_skey.c optional crypto | ipsec | ipsec_support crypto/camellia/camellia.c optional crypto | ipsec | ipsec_support crypto/camellia/camellia-api.c optional crypto | ipsec | ipsec_support +crypto/chacha20/chacha20.c optional chacha20 crypto/des/des_ecb.c optional crypto | ipsec | ipsec_support | netsmb crypto/des/des_setkey.c optional crypto | ipsec | ipsec_support | netsmb crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi Added: head/sys/crypto/chacha20/chacha20.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/crypto/chacha20/chacha20.c Sat Apr 15 20:51:53 2017 (r316982) @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2017 Dag-Erling Smørgrav + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#ifdef _KERNEL +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/libkern.h> +#include <sys/module.h> +#include <sys/syslog.h> +#include <sys/systm.h> +#else +#include <stdint.h> +#include <string.h> +#endif + +#include <sys/endian.h> + + +#include <crypto/chacha20/chacha20.h> + +#define rol32(x, n) \ + ((x) << ((n) & 0x1f) | (x) >> (-(n) & 0x1f)) + +#define CHACHA_QR(x, a, b, c, d) \ + do { \ + x[a] = x[a] + x[b]; x[d] = rol32(x[d] ^ x[a], 16); \ + x[c] = x[c] + x[d]; x[b] = rol32(x[b] ^ x[c], 12); \ + x[a] = x[a] + x[b]; x[d] = rol32(x[d] ^ x[a], 8); \ + x[c] = x[c] + x[d]; x[b] = rol32(x[b] ^ x[c], 7); \ + } while (0) + +static const char magic128[] = "expand 16-byte k"; +static const char magic256[] = "expand 32-byte k"; + +/* + * Fill the state array with 16 bytes of magic and 32 bytes of key, + * repeating the key if necessary. The 8-byte stream position and the + * 8-byte nonce are initialized to all-zeroes. + */ +void +chacha20_init(chacha20_ctx *ctx, const uint8_t *key, size_t keylen) +{ + + memset(ctx, 0, sizeof *ctx); + if (keylen == 32) { + /* magic */ + ctx->state[ 0] = le32dec(magic256 + 0); + ctx->state[ 1] = le32dec(magic256 + 4); + ctx->state[ 2] = le32dec(magic256 + 8); + ctx->state[ 3] = le32dec(magic256 + 12); + /* first half of key */ + ctx->state[ 4] = le32dec(key + 0); + ctx->state[ 5] = le32dec(key + 4); + ctx->state[ 6] = le32dec(key + 8); + ctx->state[ 7] = le32dec(key + 12); + /* second half of key */ + ctx->state[ 8] = le32dec(key + 16); + ctx->state[ 9] = le32dec(key + 20); + ctx->state[10] = le32dec(key + 24); + ctx->state[11] = le32dec(key + 28); + } else { + /* magic */ + ctx->state[ 0] = le32dec(magic128 + 0); + ctx->state[ 1] = le32dec(magic128 + 4); + ctx->state[ 2] = le32dec(magic128 + 8); + ctx->state[ 3] = le32dec(magic128 + 12); + /* first half of key */ + ctx->state[ 4] = le32dec(key + 0); + ctx->state[ 5] = le32dec(key + 4); + ctx->state[ 6] = le32dec(key + 8); + ctx->state[ 7] = le32dec(key + 12); + /* repeat first half of key */ + ctx->state[ 8] = le32dec(key + 0); + ctx->state[ 9] = le32dec(key + 4); + ctx->state[10] = le32dec(key + 8); + ctx->state[11] = le32dec(key + 12); + } +} + +/* + * Reset the stream position and load a new nonce. + */ +void +chacha20_reset(chacha20_ctx *ctx, const uint8_t *nonce) +{ + + /* reset stream counter */ + ctx->state[12] = 0; + ctx->state[13] = 0; + /* copy nonce */ + ctx->state[14] = le32dec(nonce + 0); + ctx->state[15] = le32dec(nonce + 4); +} + +/* + * Encryption: generate a block of keystream, xor it with the plaintext to + * produce the ciphertext, and increment the stream position. If vpt is + * NULL, simply copy the requested keystream to the output buffer. + */ +size_t +chacha20_encrypt(chacha20_ctx *ctx, const void *vpt, uint8_t *ct, size_t len) +{ + const uint8_t *pt = vpt; + uint64_t ctr; + uint32_t mix[16]; + uint8_t ks[64]; + unsigned int b, i; + + len -= len % sizeof ks; + for (b = 0; b < len; b += sizeof ks) { + memcpy(mix, ctx->state, sizeof mix); + for (i = 0; i < 20; i += 2) { + CHACHA_QR(mix, 0, 4, 8, 12); + CHACHA_QR(mix, 1, 5, 9, 13); + CHACHA_QR(mix, 2, 6, 10, 14); + CHACHA_QR(mix, 3, 7, 11, 15); + CHACHA_QR(mix, 0, 5, 10, 15); + CHACHA_QR(mix, 1, 6, 11, 12); + CHACHA_QR(mix, 2, 7, 8, 13); + CHACHA_QR(mix, 3, 4, 9, 14); + } + for (i = 0; i < 16; ++i) + le32enc(ks + i * 4, ctx->state[i] + mix[i]); + if (pt == NULL) { + memcpy(ct, ks, sizeof ks); + ct += sizeof ks; + } else { + for (i = 0; i < 64 && i < len; ++i) + *ct++ = *pt++ ^ ks[i]; + } + ctr = le64dec(ctx->state + 12); + le64enc(ctx->state + 12, ++ctr); + } + return (len); +} + +/* + * Decryption: identical to encryption. + */ +size_t +chacha20_decrypt(chacha20_ctx *ctx, const uint8_t *ct, void *vpt, size_t len) +{ + + return (chacha20_encrypt(ctx, ct, vpt, len)); +} + +/* + * Wipe our state. + */ +void +chacha20_finish(chacha20_ctx *ctx) +{ + + memset(ctx, 0, sizeof *ctx); +} + +#ifdef _KERNEL + +static int +chacha20_modevent(module_t mod, int evtype, void *unused) +{ + + switch (evtype) { + case MOD_LOAD: + return (0); + case MOD_UNLOAD: + return (0); + default: + return (EOPNOTSUPP); + } +} + +static moduledata_t chacha20_mod = { + "chacha20", + chacha20_modevent, + 0 +}; + +DECLARE_MODULE(chacha20, chacha20_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); +MODULE_VERSION(chacha20, 1); +#endif Added: head/sys/crypto/chacha20/chacha20.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/crypto/chacha20/chacha20.h Sat Apr 15 20:51:53 2017 (r316982) @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2017 Dag-Erling Smørgrav + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef SYS_CRYPTO_CHACHA20_H_INCLUDED +#define SYS_CRYPTO_CHACHA20_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t state[16]; +} chacha20_ctx; + +void chacha20_init(chacha20_ctx *, const uint8_t *, size_t); +void chacha20_reset(chacha20_ctx *, const uint8_t *); +size_t chacha20_encrypt(chacha20_ctx *, const void *, uint8_t *, size_t); +size_t chacha20_decrypt(chacha20_ctx *, const uint8_t *, void *, size_t); +void chacha20_finish(chacha20_ctx *); + +#ifdef __cplusplus +} +#endif + +#endif Modified: head/sys/modules/Makefile ============================================================================== --- head/sys/modules/Makefile Sat Apr 15 20:37:34 2017 (r316981) +++ head/sys/modules/Makefile Sat Apr 15 20:51:53 2017 (r316982) @@ -73,6 +73,7 @@ SUBDIR= \ cd9660_iconv \ ${_ce} \ ${_cfi} \ + chacha20 \ ${_chromebook_platform} \ ${_ciss} \ cloudabi \ Added: head/sys/modules/chacha20/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/modules/chacha20/Makefile Sat Apr 15 20:51:53 2017 (r316982) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/crypto/chacha20 + +KMOD= chacha20 +SRCS= chacha20.c + +.include <bsd.kmod.mk>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704152051.v3FKpr38020502>