From 61590291a8be2f70a88cc0d5411f19d6093824e2 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Thu, 29 Mar 2018 04:02:50 +0000 Subject: [PATCH] opencrypto: Integrate Chacha20 algorithm into OCF Mostly this is a thin shim around existing code to integrate with enc_xform and cryptosoft (+ cryptodev). Expand the cryptodev buffer used to match that of Chacha20's native block size as a performance enhancement for chacha20_xform_crypt_multi. --- sys/conf/files | 2 + sys/crypto/chacha20/chacha-sw.c | 78 +++++++++++++++++++++++++++++++++ sys/modules/crypto/Makefile | 3 ++ sys/opencrypto/cryptodev.c | 3 ++ sys/opencrypto/cryptodev.h | 6 ++- sys/opencrypto/cryptosoft.c | 6 +++ sys/opencrypto/xform_enc.h | 3 +- 7 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 sys/crypto/chacha20/chacha-sw.c diff --git a/sys/conf/files b/sys/conf/files index 48fd509b70a9..0a0b6ac831cb 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -662,6 +662,8 @@ crypto/blowfish/bf_ecb.c optional ipsec | ipsec_support 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 diff --git a/sys/crypto/chacha20/chacha-sw.c b/sys/crypto/chacha20/chacha-sw.c new file mode 100644 index 000000000000..e874d48c606e --- /dev/null +++ b/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 + 8, iv); +} + +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); +} + +static void +chacha20_xform_crypt_multi(void *vctx, uint8_t *bytes, size_t len) +{ + struct chacha_ctx *ctx; + + ctx = vctx; + chacha_encrypt_bytes(ctx, bytes, bytes, len); +} + +struct enc_xform enc_xform_chacha20 = { + .type = CRYPTO_CHACHA20, + .name = "chacha20", + .blocksize = 1, + .ivsize = CHACHA_NONCELEN + CHACHA_CTRLEN, + .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, + .encrypt_multi = chacha20_xform_crypt_multi, + .decrypt_multi = chacha20_xform_crypt_multi, +}; diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile index 492fce95bda1..0f7087ad3af9 100644 --- a/sys/modules/crypto/Makefile +++ b/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.blake2s-ref.c += -I${SRCTOP}/sys/crypto/blake2 -DSUFFIX=_ref 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 diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index 58e15212cdb7..984344492271 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -443,6 +443,9 @@ cryptof_ioctl( 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"); diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h index eea1a00c50b8..654225410fe9 100644 --- a/sys/opencrypto/cryptodev.h +++ b/sys/opencrypto/cryptodev.h @@ -112,7 +112,8 @@ #define AES_ICM_BLOCK_LEN 1 #define ARC4_BLOCK_LEN 1 #define CAMELLIA_BLOCK_LEN 16 -#define EALG_MAX_BLOCK_LEN AES_BLOCK_LEN /* Keep this updated */ +#define CHACHA20_NATIVE_BLOCK_LEN 64 +#define EALG_MAX_BLOCK_LEN CHACHA20_NATIVE_BLOCK_LEN /* Keep this updated */ /* IV Lengths */ @@ -180,7 +181,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) diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c index 6974015200de..f85f63e92a7c 100644 --- a/sys/opencrypto/cryptosoft.c +++ b/sys/opencrypto/cryptosoft.c @@ -830,6 +830,9 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) 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), @@ -1056,6 +1059,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) case CRYPTO_AES_NIST_GMAC: case CRYPTO_CAMELLIA_CBC: case CRYPTO_NULL_CBC: + case CRYPTO_CHACHA20: txf = swd->sw_exf; if (swd->sw_kschedule) @@ -1185,6 +1189,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint) 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; @@ -1298,6 +1303,7 @@ swcr_attach(device_t dev) REGISTER(CRYPTO_DEFLATE_COMP); REGISTER(CRYPTO_BLAKE2B); REGISTER(CRYPTO_BLAKE2S); + REGISTER(CRYPTO_CHACHA20); #undef REGISTER return 0; diff --git a/sys/opencrypto/xform_enc.h b/sys/opencrypto/xform_enc.h index dc49c7f4c4ee..545e0ec25497 100644 --- a/sys/opencrypto/xform_enc.h +++ b/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 *); @@ -83,6 +83,7 @@ extern struct enc_xform enc_xform_aes_nist_gmac; 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)];