From 01d5de8fca77a55ddd9bc79db3078c9f2ccdbab1 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Fri, 17 Aug 2018 00:30:04 +0000 Subject: [PATCH] Add xform-conforming auth_hash wrapper for Poly-1305 The wrapper is a thin shim around libsodium's Poly-1305 implementation. For now, we just use the C algorithm and do not attempt to build the SSE-optimized variant for x86 processors. The algorithm support has not yet been plumbed through cryptodev, or added to cryptosoft. --- sys/conf/files | 15 ++++++ sys/modules/crypto/Makefile | 22 ++++++++ sys/opencrypto/cryptodev.h | 6 ++- sys/opencrypto/xform_auth.h | 1 + sys/opencrypto/xform_poly1305.c | 91 +++++++++++++++++++++++++++++++++ sys/opencrypto/xform_poly1305.h | 16 ++++++ 6 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 sys/opencrypto/xform_poly1305.c create mode 100644 sys/opencrypto/xform_poly1305.h diff --git a/sys/conf/files b/sys/conf/files index 8d1780ad3e6f..51d5a1516669 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -4819,6 +4819,21 @@ opencrypto/gfmult.c optional crypto | ipsec | ipsec_support opencrypto/rmd160.c optional crypto | ipsec | ipsec_support opencrypto/skipjack.c optional crypto | ipsec | ipsec_support opencrypto/xform.c optional crypto | ipsec | ipsec_support +opencrypto/xform_poly1305.c optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium" +contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \ + optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium" +contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c \ + optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium" +contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c \ + optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium" +crypto/libsodium/randombytes.c optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium" +crypto/libsodium/utils.c optional crypto \ + compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium" rpc/auth_none.c optional krpc | nfslockd | nfscl | nfsd rpc/auth_unix.c optional krpc | nfslockd | nfscl | nfsd rpc/authunix_prot.c optional krpc | nfslockd | nfscl | nfsd diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile index d324a6994306..0e66e4c3827a 100644 --- a/sys/modules/crypto/Makefile +++ b/sys/modules/crypto/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +LIBSODIUM=${SRCTOP}/sys/contrib/libsodium/src/libsodium + .PATH: ${SRCTOP}/sys/opencrypto .PATH: ${SRCTOP}/sys/crypto .PATH: ${SRCTOP}/sys/crypto/blowfish @@ -12,6 +14,10 @@ .PATH: ${SRCTOP}/sys/crypto/blake2 .PATH: ${SRCTOP}/sys/crypto/chacha20 .PATH: ${SRCTOP}/sys/contrib/libb2 +.PATH: ${LIBSODIUM}/crypto_onetimeauth/poly1305 +.PATH: ${LIBSODIUM}/crypto_onetimeauth/poly1305/donna +.PATH: ${LIBSODIUM}/crypto_verify/sodium +.PATH: ${SRCTOP}/sys/crypto/libsodium KMOD = crypto SRCS = crypto.c cryptodev_if.c @@ -44,6 +50,22 @@ CWARNFLAGS.blake2b-ref.c += -Wno-cast-qual -Wno-unused-function CWARNFLAGS.blake2s-ref.c += -Wno-cast-qual -Wno-unused-function SRCS += chacha.c SRCS += chacha-sw.c + +LIBSODIUM_INC=${LIBSODIUM}/include +LIBSODIUM_COMPAT=${SRCTOP}/sys/crypto/libsodium +SRCS += xform_poly1305.c +CFLAGS.xform_poly1305.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT} +SRCS += onetimeauth_poly1305.c +CFLAGS.onetimeauth_poly1305.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT} +SRCS += poly1305_donna.c +CFLAGS.poly1305_donna.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT} +SRCS += verify.c +CFLAGS.verify.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT} +SRCS += randombytes.c +CFLAGS.randombytes.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT} +SRCS += utils.c +CFLAGS.utils.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT} + SRCS += opt_param.h cryptodev_if.h bus_if.h device_if.h SRCS += opt_ddb.h diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h index 8ad1868a13da..b3f81563d9ab 100644 --- a/sys/opencrypto/cryptodev.h +++ b/sys/opencrypto/cryptodev.h @@ -85,6 +85,7 @@ #define MD5_KPDK_HASH_LEN 16 #define SHA1_KPDK_HASH_LEN 20 #define AES_GMAC_HASH_LEN 16 +#define POLY1305_HASH_LEN 16 /* Maximum hash algorithm result length */ #define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */ @@ -107,6 +108,8 @@ #define AES_192_GMAC_KEY_LEN 24 #define AES_256_GMAC_KEY_LEN 32 +#define POLY1305_KEY_LEN 32 + /* Encryption algorithm block sizes */ #define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */ #define DES_BLOCK_LEN 8 @@ -195,7 +198,8 @@ #define CRYPTO_SHA2_256 35 #define CRYPTO_SHA2_384 36 #define CRYPTO_SHA2_512 37 -#define CRYPTO_ALGORITHM_MAX 37 /* Keep updated - see below */ +#define CRYPTO_POLY1305 38 +#define CRYPTO_ALGORITHM_MAX 38 /* Keep updated - see below */ #define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \ (x) <= CRYPTO_ALGORITHM_MAX) diff --git a/sys/opencrypto/xform_auth.h b/sys/opencrypto/xform_auth.h index bdd492bd117e..061838686117 100644 --- a/sys/opencrypto/xform_auth.h +++ b/sys/opencrypto/xform_auth.h @@ -83,6 +83,7 @@ extern struct auth_hash auth_hash_nist_gmac_aes_192; extern struct auth_hash auth_hash_nist_gmac_aes_256; extern struct auth_hash auth_hash_blake2b; extern struct auth_hash auth_hash_blake2s; +extern struct auth_hash auth_hash_poly1305; union authctx { MD5_CTX md5ctx; diff --git a/sys/opencrypto/xform_poly1305.c b/sys/opencrypto/xform_poly1305.c new file mode 100644 index 000000000000..79c2d0505a32 --- /dev/null +++ b/sys/opencrypto/xform_poly1305.c @@ -0,0 +1,91 @@ +/* This file is in the public domain. */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include + +struct poly1305_xform_ctx { + struct crypto_onetimeauth_poly1305_state state; +}; +CTASSERT(sizeof(union authctx) >= sizeof(struct poly1305_xform_ctx)); + +CTASSERT(POLY1305_KEY_LEN == crypto_onetimeauth_poly1305_KEYBYTES); +CTASSERT(POLY1305_HASH_LEN == crypto_onetimeauth_poly1305_BYTES); + +void +Poly1305_Init(struct poly1305_xform_ctx *polyctx) +{ + /* Nop */ +} + +void +Poly1305_Setkey(struct poly1305_xform_ctx *polyctx, + const uint8_t key[__min_size(POLY1305_KEY_LEN)], size_t klen) +{ + int rc; + + if (klen != POLY1305_KEY_LEN) + panic("%s: Bogus keylen: %u bytes", __func__, (unsigned)klen); + + rc = crypto_onetimeauth_poly1305_init(&polyctx->state, key); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); +} + +static void +xform_Poly1305_Setkey(void *ctx, const uint8_t *key, uint16_t klen) +{ + Poly1305_Setkey(ctx, key, klen); +} + +int +Poly1305_Update(struct poly1305_xform_ctx *polyctx, const void *data, + size_t len) +{ + int rc; + + rc = crypto_onetimeauth_poly1305_update(&polyctx->state, data, len); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); + return (0); +} + +static int +xform_Poly1305_Update(void *ctx, const uint8_t *data, uint16_t len) +{ + return (Poly1305_Update(ctx, data, len)); +} + +void +Poly1305_Final(uint8_t digest[__min_size(POLY1305_HASH_LEN)], + struct poly1305_xform_ctx *polyctx) +{ + int rc; + + rc = crypto_onetimeauth_poly1305_final(&polyctx->state, digest); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); +} + +static void +xform_Poly1305_Final(uint8_t *digest, void *ctx) +{ + Poly1305_Final(digest, ctx); +} + +struct auth_hash auth_hash_poly1305 = { + .type = CRYPTO_POLY1305, + .name = "Poly-1305", + .keysize = POLY1305_KEY_LEN, + .hashsize = POLY1305_HASH_LEN, + .ctxsize = sizeof(struct poly1305_xform_ctx), + .blocksize = crypto_onetimeauth_poly1305_BYTES, + .Init = (void *)Poly1305_Init, + .Setkey = xform_Poly1305_Setkey, + .Update = xform_Poly1305_Update, + .Final = xform_Poly1305_Final, +}; diff --git a/sys/opencrypto/xform_poly1305.h b/sys/opencrypto/xform_poly1305.h new file mode 100644 index 000000000000..7364ecdef117 --- /dev/null +++ b/sys/opencrypto/xform_poly1305.h @@ -0,0 +1,16 @@ +/* This file is in the public domain. */ +/* $FreeBSD$ */ +#pragma once + +#include + +struct poly1305_xform_ctx; + +void Poly1305_Init(struct poly1305_xform_ctx *); + +void Poly1305_Setkey(struct poly1305_xform_ctx *, + const uint8_t [__min_size(32)], size_t); + +int Poly1305_Update(struct poly1305_xform_ctx *, const void *, size_t); + +void Poly1305_Final(uint8_t [__min_size(16)], struct poly1305_xform_ctx *);