Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -659,6 +659,8 @@ 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/chacha.c optional crypto | ipsec | ipsec_support +crypto/chacha20/chacha-sw.c optional crypto | ipsec | ipsec_support 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 Index: sys/crypto/chacha20/chacha-sw.c =================================================================== --- /dev/null +++ sys/crypto/chacha20/chacha-sw.c @@ -0,0 +1,78 @@ +/* This file is in the public domain. */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +static int +chacha20_xform_setkey(u_int8_t **sched, u_int8_t *key, int len) +{ + struct chacha_ctx *ctx; + + if (len != CHACHA_MINKEYLEN || len != 32) + return (EINVAL); + + ctx = malloc(sizeof(*ctx), M_CRYPTO_DATA, M_NOWAIT | M_ZERO); + *sched = (void *)ctx; + if (ctx == NULL) + return (ENOMEM); + + chacha_keysetup(ctx, key, len * 8); + return (0); +} + +static void +chacha20_xform_reinit(caddr_t key, u_int8_t *iv) +{ + struct chacha_ctx *ctx; + + ctx = (void *)key; + chacha_ivsetup(ctx, iv, NULL); +} + +static void +chacha20_xform_zerokey(u_int8_t **sched) +{ + struct chacha_ctx *ctx; + + ctx = (void *)*sched; + explicit_bzero(ctx, sizeof(*ctx)); + free(ctx, M_CRYPTO_DATA); + *sched = NULL; +} + +static void +chacha20_xform_crypt(caddr_t cctx, u_int8_t *bytes) +{ + struct chacha_ctx *ctx; + + ctx = (void *)cctx; + chacha_encrypt_bytes(ctx, bytes, bytes, 1); +} + +#ifdef NOTYET +static void +chacha20_xform_crypt_multi(caddr_t cctx, u_int8_t *bytes, size_t len) +{ + struct chacha_ctx *ctx; + + ctx = (void *)cctx; + chacha_encrypt_bytes(ctx, bytes, bytes, len); +} +#endif /* NOTYET */ + +struct enc_xform enc_xform_chacha20 = { + .type = CRYPTO_CHACHA20, + .name = "chacha20", + .blocksize = 1, + .ivsize = 8, + .minkey = CHACHA_MINKEYLEN, + .maxkey = 32, + .encrypt = chacha20_xform_crypt, + .decrypt = chacha20_xform_crypt, + .setkey = chacha20_xform_setkey, + .zerokey = chacha20_xform_zerokey, + .reinit = chacha20_xform_reinit, +}; Index: sys/modules/crypto/Makefile =================================================================== --- sys/modules/crypto/Makefile +++ sys/modules/crypto/Makefile @@ -10,6 +10,7 @@ .PATH: ${SRCTOP}/sys/crypto/siphash .PATH: ${SRCTOP}/sys/crypto/skein .PATH: ${SRCTOP}/sys/crypto/blake2 +.PATH: ${SRCTOP}/sys/crypto/chacha20 .PATH: ${SRCTOP}/sys/contrib/libb2 KMOD = crypto @@ -41,6 +42,8 @@ CFLAGS.blake2-sw.c += -I${SRCTOP}/sys/crypto/blake2 CWARNFLAGS.blake2b-ref.c += ${NO_WCAST_QUAL} CWARNFLAGS.blake2s-ref.c += ${NO_WCAST_QUAL} +SRCS += chacha.c +SRCS += chacha-sw.c SRCS += opt_param.h cryptodev_if.h bus_if.h device_if.h SRCS += opt_ddb.h Index: sys/opencrypto/cryptodev.h =================================================================== --- sys/opencrypto/cryptodev.h +++ sys/opencrypto/cryptodev.h @@ -180,7 +180,8 @@ #define CRYPTO_AES_256_NIST_GMAC 28 /* auth side */ #define CRYPTO_BLAKE2B 29 /* Blake2b hash */ #define CRYPTO_BLAKE2S 30 /* Blake2s hash */ -#define CRYPTO_ALGORITHM_MAX 30 /* Keep updated - see below */ +#define CRYPTO_CHACHA20 31 /* Chacha20 stream cipher */ +#define CRYPTO_ALGORITHM_MAX 31 /* Keep updated - see below */ #define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \ (x) <= CRYPTO_ALGORITHM_MAX) Index: sys/opencrypto/cryptodev.c =================================================================== --- sys/opencrypto/cryptodev.c +++ sys/opencrypto/cryptodev.c @@ -443,6 +443,9 @@ case CRYPTO_AES_NIST_GCM_16: txform = &enc_xform_aes_nist_gcm; break; + case CRYPTO_CHACHA20: + txform = &enc_xform_chacha20; + break; default: CRYPTDEB("invalid cipher"); Index: sys/opencrypto/cryptosoft.c =================================================================== --- sys/opencrypto/cryptosoft.c +++ sys/opencrypto/cryptosoft.c @@ -810,6 +810,9 @@ case CRYPTO_NULL_CBC: txf = &enc_xform_null; goto enccommon; + case CRYPTO_CHACHA20: + txf = &enc_xform_chacha20; + goto enccommon; enccommon: if (cri->cri_key != NULL) { error = txf->setkey(&((*swd)->sw_kschedule), @@ -1036,6 +1039,7 @@ case CRYPTO_AES_NIST_GMAC: case CRYPTO_CAMELLIA_CBC: case CRYPTO_NULL_CBC: + case CRYPTO_CHACHA20: txf = swd->sw_exf; if (swd->sw_kschedule) @@ -1165,6 +1169,7 @@ case CRYPTO_AES_XTS: case CRYPTO_AES_ICM: case CRYPTO_CAMELLIA_CBC: + case CRYPTO_CHACHA20: if ((crp->crp_etype = swcr_encdec(crd, sw, crp->crp_buf, crp->crp_flags)) != 0) goto done; @@ -1278,6 +1283,7 @@ REGISTER(CRYPTO_DEFLATE_COMP); REGISTER(CRYPTO_BLAKE2B); REGISTER(CRYPTO_BLAKE2S); + REGISTER(CRYPTO_CHACHA20); #undef REGISTER return 0; Index: sys/opencrypto/xform_enc.h =================================================================== --- sys/opencrypto/xform_enc.h +++ sys/opencrypto/xform_enc.h @@ -51,7 +51,7 @@ struct enc_xform { int type; char *name; - u_int16_t blocksize; + u_int16_t blocksize; /* Required input block size -- 1 for stream ciphers. */ u_int16_t ivsize; u_int16_t minkey, maxkey; void (*encrypt) (caddr_t, u_int8_t *); @@ -75,6 +75,7 @@ extern struct enc_xform enc_xform_aes_xts; extern struct enc_xform enc_xform_arc4; extern struct enc_xform enc_xform_camellia; +extern struct enc_xform enc_xform_chacha20; struct aes_icm_ctx { u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)];