Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150514621
D27837.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D27837.diff
View Options
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4925,7 +4925,8 @@
opencrypto/rmd160.c optional crypto | ipsec | ipsec_support
opencrypto/xform.c optional crypto | ipsec | ipsec_support
opencrypto/xform_cbc_mac.c optional crypto
-opencrypto/xform_chacha20_poly1305.c optional crypto
+opencrypto/xform_chacha20_poly1305.c optional crypto \
+ compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
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 \
diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile
--- a/sys/modules/crypto/Makefile
+++ b/sys/modules/crypto/Makefile
@@ -15,6 +15,8 @@
.PATH: ${SRCTOP}/sys/contrib/libb2
.PATH: ${LIBSODIUM}/crypto_onetimeauth/poly1305
.PATH: ${LIBSODIUM}/crypto_onetimeauth/poly1305/donna
+.PATH: ${LIBSODIUM}/crypto_stream/chacha20
+.PATH: ${LIBSODIUM}/crypto_stream/chacha20/ref
.PATH: ${LIBSODIUM}/crypto_verify/sodium
.PATH: ${SRCTOP}/sys/crypto/libsodium
@@ -55,8 +57,14 @@
LIBSODIUM_INC=${LIBSODIUM}/include
LIBSODIUM_COMPAT=${SRCTOP}/sys/crypto/libsodium
+SRCS += xform_chacha20_poly1305.c
+CFLAGS.xform_chacha20_poly1305.c+= -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
SRCS += xform_poly1305.c
CFLAGS.xform_poly1305.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
+SRCS += stream_chacha20.c
+CFLAGS.stream_chacha20.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT}
+SRCS += chacha20_ref.c
+CFLAGS.chacha20_ref.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT}
SRCS += onetimeauth_poly1305.c
CFLAGS.onetimeauth_poly1305.c += -I${LIBSODIUM_INC}/sodium -I${LIBSODIUM_COMPAT}
SRCS += poly1305_donna.c
@@ -67,7 +75,6 @@
CFLAGS.randombytes.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
SRCS += utils.c
CFLAGS.utils.c += -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
-SRCS += xform_chacha20_poly1305.c
SRCS += opt_param.h cryptodev_if.h bus_if.h device_if.h
SRCS += opt_compat.h
diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
--- a/sys/opencrypto/cryptosoft.c
+++ b/sys/opencrypto/cryptosoft.c
@@ -867,6 +867,168 @@
return (error);
}
+static int
+swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp)
+{
+ const struct crypto_session_params *csp;
+ uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
+ u_char *blk = (u_char *)blkbuf;
+ u_char tag[POLY1305_HASH_LEN];
+ struct crypto_buffer_cursor cc_in, cc_out;
+ const u_char *inblk;
+ u_char *outblk;
+ uint64_t *blkp;
+ union authctx ctx;
+ struct swcr_auth *swa;
+ struct swcr_encdec *swe;
+ struct auth_hash *axf;
+ struct enc_xform *exf;
+ int blksz, error, r, resid;
+
+ swa = &ses->swcr_auth;
+ axf = swa->sw_axf;
+
+ swe = &ses->swcr_encdec;
+ exf = swe->sw_exf;
+ blksz = exf->native_blocksize;
+ KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__));
+
+ if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
+ return (EINVAL);
+
+ csp = crypto_get_params(crp->crp_session);
+
+ /* Generate Poly1305 key. */
+ if (crp->crp_cipher_key != NULL)
+ axf->Setkey(&ctx, crp->crp_cipher_key, csp->csp_cipher_klen);
+ else
+ axf->Setkey(&ctx, csp->csp_cipher_key, csp->csp_cipher_klen);
+ axf->Reinit(&ctx, crp->crp_iv, csp->csp_ivlen);
+
+ /* Supply MAC with AAD */
+ if (crp->crp_aad != NULL)
+ axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
+ else
+ crypto_apply(crp, crp->crp_aad_start,
+ crp->crp_aad_length, axf->Update, &ctx);
+ if (crp->crp_aad_length % 16 != 0) {
+ /* padding1 */
+ memset(blk, 0, 16);
+ axf->Update(&ctx, blk, 16 - crp->crp_aad_length % 16);
+ }
+
+ if (crp->crp_cipher_key != NULL)
+ exf->setkey(swe->sw_kschedule, crp->crp_cipher_key,
+ csp->csp_cipher_klen);
+ exf->reinit(swe->sw_kschedule, crp->crp_iv);
+
+ /* Do encryption with MAC */
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+ if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
+ crypto_cursor_init(&cc_out, &crp->crp_obuf);
+ crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
+ } else
+ cc_out = cc_in;
+ for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
+ if (crypto_cursor_seglen(&cc_in) < blksz) {
+ crypto_cursor_copydata(&cc_in, blksz, blk);
+ inblk = blk;
+ } else {
+ inblk = crypto_cursor_segbase(&cc_in);
+ crypto_cursor_advance(&cc_in, blksz);
+ }
+ if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
+ if (crypto_cursor_seglen(&cc_out) < blksz)
+ outblk = blk;
+ else
+ outblk = crypto_cursor_segbase(&cc_out);
+ exf->encrypt(swe->sw_kschedule, inblk, outblk);
+ axf->Update(&ctx, outblk, blksz);
+ if (outblk == blk)
+ crypto_cursor_copyback(&cc_out, blksz, blk);
+ else
+ crypto_cursor_advance(&cc_out, blksz);
+ } else {
+ axf->Update(&ctx, inblk, blksz);
+ }
+ }
+ if (resid > 0) {
+ crypto_cursor_copydata(&cc_in, resid, blk);
+ if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
+ exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
+ crypto_cursor_copyback(&cc_out, resid, blk);
+ }
+ axf->Update(&ctx, blk, resid);
+ if (resid % 16 != 0) {
+ /* padding2 */
+ memset(blk, 0, 16);
+ axf->Update(&ctx, blk, 16 - resid % 16);
+ }
+ }
+
+ /* lengths */
+ blkp = (uint64_t *)blk;
+ blkp[0] = htole64(crp->crp_aad_length);
+ blkp[1] = htole64(crp->crp_payload_length);
+ axf->Update(&ctx, blk, sizeof(uint64_t) * 2);
+
+ /* Finalize MAC */
+ axf->Final(tag, &ctx);
+
+ /* Validate tag */
+ error = 0;
+ if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
+ u_char tag2[POLY1305_HASH_LEN];
+
+ crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
+
+ r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
+ explicit_bzero(tag2, sizeof(tag2));
+ if (r != 0) {
+ error = EBADMSG;
+ goto out;
+ }
+
+ /* tag matches, decrypt data */
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+ for (resid = crp->crp_payload_length; resid > blksz;
+ resid -= blksz) {
+ if (crypto_cursor_seglen(&cc_in) < blksz) {
+ crypto_cursor_copydata(&cc_in, blksz, blk);
+ inblk = blk;
+ } else {
+ inblk = crypto_cursor_segbase(&cc_in);
+ crypto_cursor_advance(&cc_in, blksz);
+ }
+ if (crypto_cursor_seglen(&cc_out) < blksz)
+ outblk = blk;
+ else
+ outblk = crypto_cursor_segbase(&cc_out);
+ exf->decrypt(swe->sw_kschedule, inblk, outblk);
+ if (outblk == blk)
+ crypto_cursor_copyback(&cc_out, blksz, blk);
+ else
+ crypto_cursor_advance(&cc_out, blksz);
+ }
+ if (resid > 0) {
+ crypto_cursor_copydata(&cc_in, resid, blk);
+ exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
+ crypto_cursor_copyback(&cc_out, resid, blk);
+ }
+ } else {
+ /* Inject the authentication data */
+ crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
+ }
+
+out:
+ explicit_bzero(blkbuf, sizeof(blkbuf));
+ explicit_bzero(tag, sizeof(tag));
+ explicit_bzero(&ctx, sizeof(ctx));
+ return (error);
+}
+
/*
* Apply a cipher and a digest to perform EtA.
*/
@@ -1171,6 +1333,33 @@
return (swcr_setup_cipher(ses, csp));
}
+static int
+swcr_setup_chacha20_poly1305(struct swcr_session *ses,
+ const struct crypto_session_params *csp)
+{
+ struct swcr_auth *swa;
+ struct auth_hash *axf;
+
+ if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN)
+ return (EINVAL);
+
+ /* First, setup the auth side. */
+ swa = &ses->swcr_auth;
+ axf = &auth_hash_chacha20_poly1305;
+ swa->sw_axf = axf;
+ if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
+ return (EINVAL);
+ if (csp->csp_auth_mlen == 0)
+ swa->sw_mlen = axf->hashsize;
+ else
+ swa->sw_mlen = csp->csp_auth_mlen;
+
+ /* The auth state is regenerated for each nonce. */
+
+ /* Second, setup the cipher side. */
+ return (swcr_setup_cipher(ses, csp));
+}
+
static bool
swcr_auth_supported(const struct crypto_session_params *csp)
{
@@ -1258,6 +1447,7 @@
switch (csp->csp_cipher_alg) {
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ case CRYPTO_CHACHA20_POLY1305:
return (EINVAL);
default:
if (!swcr_cipher_supported(csp))
@@ -1273,6 +1463,7 @@
switch (csp->csp_cipher_alg) {
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ case CRYPTO_CHACHA20_POLY1305:
break;
default:
return (EINVAL);
@@ -1283,6 +1474,7 @@
switch (csp->csp_cipher_alg) {
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ case CRYPTO_CHACHA20_POLY1305:
return (EINVAL);
}
switch (csp->csp_auth_alg) {
@@ -1343,6 +1535,7 @@
#ifdef INVARIANTS
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ case CRYPTO_CHACHA20_POLY1305:
panic("bad cipher algo");
#endif
default:
@@ -1366,6 +1559,11 @@
if (error == 0)
ses->swcr_process = swcr_ccm;
break;
+ case CRYPTO_CHACHA20_POLY1305:
+ error = swcr_setup_chacha20_poly1305(ses, csp);
+ if (error == 0)
+ ses->swcr_process = swcr_chacha20_poly1305;
+ break;
#ifdef INVARIANTS
default:
panic("bad aead algo");
@@ -1377,6 +1575,7 @@
switch (csp->csp_cipher_alg) {
case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ case CRYPTO_CHACHA20_POLY1305:
panic("bad eta cipher algo");
}
switch (csp->csp_auth_alg) {
diff --git a/sys/opencrypto/xform_auth.h b/sys/opencrypto/xform_auth.h
--- a/sys/opencrypto/xform_auth.h
+++ b/sys/opencrypto/xform_auth.h
@@ -84,6 +84,7 @@
extern struct auth_hash auth_hash_ccm_cbc_mac_128;
extern struct auth_hash auth_hash_ccm_cbc_mac_192;
extern struct auth_hash auth_hash_ccm_cbc_mac_256;
+extern struct auth_hash auth_hash_chacha20_poly1305;
union authctx {
SHA1_CTX sha1ctx;
diff --git a/sys/opencrypto/xform_chacha20_poly1305.c b/sys/opencrypto/xform_chacha20_poly1305.c
--- a/sys/opencrypto/xform_chacha20_poly1305.c
+++ b/sys/opencrypto/xform_chacha20_poly1305.c
@@ -25,17 +25,139 @@
* SUCH DAMAGE.
*/
-#include <crypto/chacha20/chacha.h>
+#include <opencrypto/xform_auth.h>
#include <opencrypto/xform_enc.h>
+#include <sodium/crypto_onetimeauth_poly1305.h>
+#include <sodium/crypto_stream_chacha20.h>
+
+struct chacha20_poly1305_cipher_ctx {
+ const void *key;
+ uint32_t ic;
+ char nonce[CHACHA20_POLY1305_IV_LEN];
+};
+
+static int
+chacha20_poly1305_setkey(void *vctx, const uint8_t *key, int len)
+{
+ struct chacha20_poly1305_cipher_ctx *ctx = vctx;
+
+ if (len != CHACHA20_POLY1305_KEY)
+ return (EINVAL);
+
+ ctx->key = key;
+ return (0);
+}
+
+static void
+chacha20_poly1305_reinit(void *vctx, const uint8_t *iv)
+{
+ struct chacha20_poly1305_cipher_ctx *ctx = vctx;
+
+ /* Block 0 is used for the poly1305 key. */
+ memcpy(ctx->nonce, iv, sizeof(ctx->nonce));
+ ctx->ic = 1;
+}
+
+static void
+chacha20_poly1305_crypt(void *vctx, const uint8_t *in, uint8_t *out)
+{
+ struct chacha20_poly1305_cipher_ctx *ctx = vctx;
+ int error;
+
+ error = crypto_stream_chacha20_ietf_xor_ic(out, in,
+ CHACHA20_NATIVE_BLOCK_LEN, ctx->nonce, ctx->ic, ctx->key);
+ KASSERT(error == 0, ("%s failed: %d", __func__, error));
+ ctx->ic++;
+}
+
+static void
+chacha20_poly1305_crypt_last(void *vctx, const uint8_t *in, uint8_t *out,
+ size_t len)
+{
+ struct chacha20_poly1305_cipher_ctx *ctx = vctx;
+
+ int error;
+
+ error = crypto_stream_chacha20_ietf_xor_ic(out, in, len, ctx->nonce,
+ ctx->ic, ctx->key);
+ KASSERT(error == 0, ("%s failed: %d", __func__, error));
+}
+
struct enc_xform enc_xform_chacha20_poly1305 = {
.type = CRYPTO_CHACHA20_POLY1305,
.name = "ChaCha20-Poly1305",
- .ctxsize = sizeof(struct chacha_ctx),
+ .ctxsize = sizeof(struct chacha20_poly1305_cipher_ctx),
.blocksize = 1,
- .native_blocksize = CHACHA_BLOCKLEN,
+ .native_blocksize = CHACHA20_NATIVE_BLOCK_LEN,
.ivsize = CHACHA20_POLY1305_IV_LEN,
.minkey = CHACHA20_POLY1305_KEY,
.maxkey = CHACHA20_POLY1305_KEY,
+ .encrypt = chacha20_poly1305_crypt,
+ .decrypt = chacha20_poly1305_crypt,
+ .setkey = chacha20_poly1305_setkey,
+ .reinit = chacha20_poly1305_reinit,
+ .encrypt_last = chacha20_poly1305_crypt_last,
+ .decrypt_last = chacha20_poly1305_crypt_last,
};
+struct chacha20_poly1305_auth_ctx {
+ struct crypto_onetimeauth_poly1305_state state;
+ const void *key;
+};
+CTASSERT(sizeof(union authctx) >= sizeof(struct chacha20_poly1305_auth_ctx));
+
+static void
+chacha20_poly1305_Init(void *vctx)
+{
+}
+
+static void
+chacha20_poly1305_Setkey(void *vctx, const uint8_t *key, u_int klen)
+{
+ struct chacha20_poly1305_auth_ctx *ctx = vctx;
+
+ ctx->key = key;
+}
+
+static void
+chacha20_poly1305_Reinit(void *vctx, const uint8_t *nonce, u_int noncelen)
+{
+ struct chacha20_poly1305_auth_ctx *ctx = vctx;
+ char block[CHACHA20_NATIVE_BLOCK_LEN];
+
+ crypto_stream_chacha20_ietf(block, sizeof(block), nonce, ctx->key);
+ crypto_onetimeauth_poly1305_init(&ctx->state, block);
+ explicit_bzero(block, sizeof(block));
+}
+
+static int
+chacha20_poly1305_Update(void *vctx, const void *data, u_int len)
+{
+ struct chacha20_poly1305_auth_ctx *ctx = vctx;
+
+ crypto_onetimeauth_poly1305_update(&ctx->state, data, len);
+ return (0);
+}
+
+static void
+chacha20_poly1305_Final(uint8_t *digest, void *vctx)
+{
+ struct chacha20_poly1305_auth_ctx *ctx = vctx;
+
+ crypto_onetimeauth_poly1305_final(&ctx->state, digest);
+}
+
+struct auth_hash auth_hash_chacha20_poly1305 = {
+ .type = CRYPTO_POLY1305,
+ .name = "ChaCha20-Poly1305",
+ .keysize = POLY1305_KEY_LEN,
+ .hashsize = POLY1305_HASH_LEN,
+ .ctxsize = sizeof(struct chacha20_poly1305_auth_ctx),
+ .blocksize = crypto_onetimeauth_poly1305_BYTES,
+ .Init = chacha20_poly1305_Init,
+ .Setkey = chacha20_poly1305_Setkey,
+ .Reinit = chacha20_poly1305_Reinit,
+ .Update = chacha20_poly1305_Update,
+ .Final = chacha20_poly1305_Final,
+};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 2, 9:57 PM (15 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30737410
Default Alt Text
D27837.diff (13 KB)
Attached To
Mode
D27837: Add an implementation of CHACHA20_POLY1035 to cryptosoft.
Attached
Detach File
Event Timeline
Log In to Comment