From nobody Tue Jan 11 22:38:09 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 313E5194C051; Tue, 11 Jan 2022 22:38:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JYQZT5SBnz4m96; Tue, 11 Jan 2022 22:38:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7C90021C16; Tue, 11 Jan 2022 22:38:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 20BMc9fn075834; Tue, 11 Jan 2022 22:38:09 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 20BMc9Yu075833; Tue, 11 Jan 2022 22:38:09 GMT (envelope-from git) Date: Tue, 11 Jan 2022 22:38:09 GMT Message-Id: <202201112238.20BMc9Yu075833@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: d7f0b3ce6dbd - main - crypto: Re-add encrypt/decrypt_multi hooks to enc_xform. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d7f0b3ce6dbde5b6810cda2c14acbbce5172f53c Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1641940689; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=rfXox5POdEpvst7d7yFYIBP+w1JiwgcPqjnkUboaNHQ=; b=gH6mYBJ9YmoPiz2qQfDZhzNJQp+XR4K4KhQlktQxV7y32n2YC2RQzjHH+Bv+FdpfZ5o0WP YRfcSJwBOb5cMkL7Z+MAJMzfDESDTBTQojDGlRI3CPY0JgGk58Affpb40ZjsxlrGphyoRp 9sANEvZOgeHLsDT/5/OTEfWzt/kP1AtqOaNvJL4antInHYyz9MFL7iPhc6C75O1+kIrjl+ J5K0igpX/hvYuOwhifNQ+jGWQZ7+uLiN328HCwotsa+cKwSZT3UvT38HxU7S+Wh1tyDHCy BAExwvrs8pXJdbqGP+fbnZzMx4J+MlBBLDYFMSms2Oahw2YtR9r/Hoe0lVo8bA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1641940689; a=rsa-sha256; cv=none; b=aJnVudFfFoPcCOxO4Bpc8DNW2uiFKuq2I2z563e3m/wVIhUI8NePa1pdAMEj4Gj7yivzyx l1uRk6x6bFxi17In/7N8H9Lwi/2BAZgrpPFxowMKKEROoLuy8BaukF/oqCoP4ipU/bR8og RjQuy4Cys9HsIcA0hqBW5yMet9Q88gWIn9mfuSuj2KWvpg91ZUSJn/IMecye7zYSsQlMW0 jTpLtvmKfZfETA05QEJOGYop9IVJ25F1S7lqmOBtO5XKVlB3Aj/2fvmQhNF/JXbb4wB2Ck B/H6AaFePxXE2u4kXEOr38eaWxHz/EoPAin8rQa0L3VxcEbyO9DqFDEQ995dxg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=d7f0b3ce6dbde5b6810cda2c14acbbce5172f53c commit d7f0b3ce6dbde5b6810cda2c14acbbce5172f53c Author: John Baldwin AuthorDate: 2022-01-11 22:17:41 +0000 Commit: John Baldwin CommitDate: 2022-01-11 22:17:41 +0000 crypto: Re-add encrypt/decrypt_multi hooks to enc_xform. These callbacks allow multiple contiguous blocks to be manipulated in a single call. Note that any trailing partial block for a stream cipher must still be passed to encrypt/decrypt_last. While here, document the setkey and reinit hooks and reorder the hooks in 'struct enc_xform' to better reflect the life cycle. Reviewed by: markj Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D33529 --- sys/crypto/chacha20/chacha-sw.c | 14 ++++++- sys/opencrypto/xform_aes_cbc.c | 45 +++++++++++++++++++- sys/opencrypto/xform_aes_icm.c | 44 +++++++++++++++++--- sys/opencrypto/xform_aes_xts.c | 71 +++++++++++++++++++++----------- sys/opencrypto/xform_chacha20_poly1305.c | 30 ++++++++++++-- sys/opencrypto/xform_cml.c | 47 ++++++++++++++++++++- sys/opencrypto/xform_enc.h | 16 ++++++- sys/opencrypto/xform_null.c | 10 ++++- 8 files changed, 234 insertions(+), 43 deletions(-) diff --git a/sys/crypto/chacha20/chacha-sw.c b/sys/crypto/chacha20/chacha-sw.c index 8041a3fee8a5..773ea9425b0a 100644 --- a/sys/crypto/chacha20/chacha-sw.c +++ b/sys/crypto/chacha20/chacha-sw.c @@ -32,6 +32,14 @@ chacha20_xform_crypt(void *ctx, const uint8_t *in, uint8_t *out) chacha_encrypt_bytes(ctx, in, out, CHACHA_BLOCKLEN); } +static void +chacha20_xform_crypt_multi(void *ctx, const uint8_t *in, uint8_t *out, + size_t len) +{ + KASSERT(len % CHACHA_BLOCKLEN == 0, ("%s: invalid length", __func__)); + chacha_encrypt_bytes(ctx, in, out, len); +} + static void chacha20_xform_crypt_last(void *ctx, const uint8_t *in, uint8_t *out, size_t len) @@ -49,10 +57,12 @@ const struct enc_xform enc_xform_chacha20 = { .ivsize = CHACHA_NONCELEN + CHACHA_CTRLEN, .minkey = CHACHA_MINKEYLEN, .maxkey = 32, - .encrypt = chacha20_xform_crypt, - .decrypt = chacha20_xform_crypt, .setkey = chacha20_xform_setkey, .reinit = chacha20_xform_reinit, + .encrypt = chacha20_xform_crypt, + .decrypt = chacha20_xform_crypt, + .encrypt_multi = chacha20_xform_crypt_multi, + .decrypt_multi = chacha20_xform_crypt_multi, .encrypt_last = chacha20_xform_crypt_last, .decrypt_last = chacha20_xform_crypt_last, }; diff --git a/sys/opencrypto/xform_aes_cbc.c b/sys/opencrypto/xform_aes_cbc.c index b2a45e595fda..a1e6093cccf4 100644 --- a/sys/opencrypto/xform_aes_cbc.c +++ b/sys/opencrypto/xform_aes_cbc.c @@ -61,6 +61,8 @@ struct aes_cbc_ctx { static int aes_cbc_setkey(void *, const uint8_t *, int); static void aes_cbc_encrypt(void *, const uint8_t *, uint8_t *); static void aes_cbc_decrypt(void *, const uint8_t *, uint8_t *); +static void aes_cbc_encrypt_multi(void *, const uint8_t *, uint8_t *, size_t); +static void aes_cbc_decrypt_multi(void *, const uint8_t *, uint8_t *, size_t); static void aes_cbc_reinit(void *, const uint8_t *, size_t); /* Encryption instances */ @@ -72,10 +74,12 @@ const struct enc_xform enc_xform_aes_cbc = { .ivsize = AES_BLOCK_LEN, .minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY, - .encrypt = aes_cbc_encrypt, - .decrypt = aes_cbc_decrypt, .setkey = aes_cbc_setkey, .reinit = aes_cbc_reinit, + .encrypt = aes_cbc_encrypt, + .decrypt = aes_cbc_decrypt, + .encrypt_multi = aes_cbc_encrypt_multi, + .decrypt_multi = aes_cbc_decrypt_multi, }; /* @@ -106,6 +110,43 @@ aes_cbc_decrypt(void *vctx, const uint8_t *in, uint8_t *out) explicit_bzero(block, sizeof(block)); } +static void +aes_cbc_encrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + struct aes_cbc_ctx *ctx = vctx; + + KASSERT(len % AES_BLOCK_LEN == 0, ("%s: invalid length", __func__)); + while (len > 0) { + for (u_int i = 0; i < AES_BLOCK_LEN; i++) + out[i] = in[i] ^ ctx->iv[i]; + rijndael_encrypt(&ctx->key, out, out); + memcpy(ctx->iv, out, AES_BLOCK_LEN); + out += AES_BLOCK_LEN; + in += AES_BLOCK_LEN; + len -= AES_BLOCK_LEN; + } +} + +static void +aes_cbc_decrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + struct aes_cbc_ctx *ctx = vctx; + char block[AES_BLOCK_LEN]; + + KASSERT(len % AES_BLOCK_LEN == 0, ("%s: invalid length", __func__)); + while (len > 0) { + memcpy(block, in, AES_BLOCK_LEN); + rijndael_decrypt(&ctx->key, in, out); + for (u_int i = 0; i < AES_BLOCK_LEN; i++) + out[i] ^= ctx->iv[i]; + memcpy(ctx->iv, block, AES_BLOCK_LEN); + out += AES_BLOCK_LEN; + in += AES_BLOCK_LEN; + len -= AES_BLOCK_LEN; + } + explicit_bzero(block, sizeof(block)); +} + static int aes_cbc_setkey(void *vctx, const uint8_t *key, int len) { diff --git a/sys/opencrypto/xform_aes_icm.c b/sys/opencrypto/xform_aes_icm.c index c33839d8a931..d25e4545c3ab 100644 --- a/sys/opencrypto/xform_aes_icm.c +++ b/sys/opencrypto/xform_aes_icm.c @@ -66,6 +66,7 @@ struct aes_ccm_ctx { static int aes_icm_setkey(void *, const uint8_t *, int); static void aes_icm_crypt(void *, const uint8_t *, uint8_t *); +static void aes_icm_crypt_multi(void *, const uint8_t *, uint8_t *, size_t); static void aes_icm_crypt_last(void *, const uint8_t *, uint8_t *, size_t); static void aes_icm_reinit(void *, const uint8_t *, size_t); static int aes_gcm_setkey(void *, const uint8_t *, int); @@ -87,10 +88,12 @@ const struct enc_xform enc_xform_aes_icm = { .ivsize = AES_BLOCK_LEN, .minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY, - .encrypt = aes_icm_crypt, - .decrypt = aes_icm_crypt, .setkey = aes_icm_setkey, .reinit = aes_icm_reinit, + .encrypt = aes_icm_crypt, + .decrypt = aes_icm_crypt, + .encrypt_multi = aes_icm_crypt_multi, + .decrypt_multi = aes_icm_crypt_multi, .encrypt_last = aes_icm_crypt_last, .decrypt_last = aes_icm_crypt_last, }; @@ -105,10 +108,12 @@ const struct enc_xform enc_xform_aes_nist_gcm = { .minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY, .macsize = AES_GMAC_HASH_LEN, - .encrypt = aes_icm_crypt, - .decrypt = aes_icm_crypt, .setkey = aes_gcm_setkey, .reinit = aes_gcm_reinit, + .encrypt = aes_icm_crypt, + .decrypt = aes_icm_crypt, + .encrypt_multi = aes_icm_crypt_multi, + .decrypt_multi = aes_icm_crypt_multi, .encrypt_last = aes_icm_crypt_last, .decrypt_last = aes_icm_crypt_last, .update = aes_gcm_update, @@ -124,10 +129,12 @@ const struct enc_xform enc_xform_ccm = { .ivsize = AES_CCM_IV_LEN, .minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY, .macsize = AES_CBC_MAC_HASH_LEN, - .encrypt = aes_icm_crypt, - .decrypt = aes_icm_crypt, .setkey = aes_ccm_setkey, .reinit = aes_ccm_reinit, + .encrypt = aes_icm_crypt, + .decrypt = aes_icm_crypt, + .encrypt_multi = aes_icm_crypt_multi, + .decrypt_multi = aes_icm_crypt_multi, .encrypt_last = aes_icm_crypt_last, .decrypt_last = aes_icm_crypt_last, .update = aes_ccm_update, @@ -197,6 +204,31 @@ aes_icm_crypt(void *key, const uint8_t *in, uint8_t *out) break; } +static void +aes_icm_crypt_multi(void *key, const uint8_t *in, uint8_t *out, size_t len) +{ + struct aes_icm_ctx *ctx = key; + uint8_t keystream[AESICM_BLOCKSIZE]; + int i; + + KASSERT(len % AESICM_BLOCKSIZE == 0, ("%s: invalid length", __func__)); + while (len > 0) { + rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream); + for (i = 0; i < AESICM_BLOCKSIZE; i++) + out[i] = in[i] ^ keystream[i]; + + /* increment counter */ + for (i = AESICM_BLOCKSIZE - 1; i >= 0; i--) + if (++ctx->ac_block[i]) /* continue on overflow */ + break; + + out += AESICM_BLOCKSIZE; + in += AESICM_BLOCKSIZE; + len -= AESICM_BLOCKSIZE; + } + explicit_bzero(keystream, sizeof(keystream)); +} + static void aes_icm_crypt_last(void *key, const uint8_t *in, uint8_t *out, size_t len) { diff --git a/sys/opencrypto/xform_aes_xts.c b/sys/opencrypto/xform_aes_xts.c index 9894158c0b79..cc3f1127d1b8 100644 --- a/sys/opencrypto/xform_aes_xts.c +++ b/sys/opencrypto/xform_aes_xts.c @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); static int aes_xts_setkey(void *, const uint8_t *, int); static void aes_xts_encrypt(void *, const uint8_t *, uint8_t *); static void aes_xts_decrypt(void *, const uint8_t *, uint8_t *); +static void aes_xts_encrypt_multi(void *, const uint8_t *, uint8_t *, size_t); +static void aes_xts_decrypt_multi(void *, const uint8_t *, uint8_t *, size_t); static void aes_xts_reinit(void *, const uint8_t *, size_t); /* Encryption instances */ @@ -67,10 +69,12 @@ const struct enc_xform enc_xform_aes_xts = { .ivsize = AES_XTS_IV_LEN, .minkey = AES_XTS_MIN_KEY, .maxkey = AES_XTS_MAX_KEY, + .setkey = aes_xts_setkey, + .reinit = aes_xts_reinit, .encrypt = aes_xts_encrypt, .decrypt = aes_xts_decrypt, - .setkey = aes_xts_setkey, - .reinit = aes_xts_reinit + .encrypt_multi = aes_xts_encrypt_multi, + .decrypt_multi = aes_xts_decrypt_multi, }; /* @@ -105,44 +109,63 @@ aes_xts_reinit(void *key, const uint8_t *iv, size_t ivlen) static void aes_xts_crypt(struct aes_xts_ctx *ctx, const uint8_t *in, uint8_t *out, - u_int do_encrypt) + size_t len, bool do_encrypt) { uint8_t block[AES_XTS_BLOCKSIZE]; u_int i, carry_in, carry_out; - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) - block[i] = in[i] ^ ctx->tweak[i]; - - if (do_encrypt) - rijndael_encrypt(&ctx->key1, block, out); - else - rijndael_decrypt(&ctx->key1, block, out); - - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) - out[i] ^= ctx->tweak[i]; - - /* Exponentiate tweak */ - carry_in = 0; - for (i = 0; i < AES_XTS_BLOCKSIZE; i++) { - carry_out = ctx->tweak[i] & 0x80; - ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); - carry_in = carry_out; + KASSERT(len % AES_XTS_BLOCKSIZE == 0, ("%s: invalid length", __func__)); + while (len > 0) { + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + block[i] = in[i] ^ ctx->tweak[i]; + + if (do_encrypt) + rijndael_encrypt(&ctx->key1, block, out); + else + rijndael_decrypt(&ctx->key1, block, out); + + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) + out[i] ^= ctx->tweak[i]; + + /* Exponentiate tweak */ + carry_in = 0; + for (i = 0; i < AES_XTS_BLOCKSIZE; i++) { + carry_out = ctx->tweak[i] & 0x80; + ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); + carry_in = carry_out; + } + if (carry_in) + ctx->tweak[0] ^= AES_XTS_ALPHA; + + in += AES_XTS_BLOCKSIZE; + out += AES_XTS_BLOCKSIZE; + len -= AES_XTS_BLOCKSIZE; } - if (carry_in) - ctx->tweak[0] ^= AES_XTS_ALPHA; explicit_bzero(block, sizeof(block)); } static void aes_xts_encrypt(void *key, const uint8_t *in, uint8_t *out) { - aes_xts_crypt(key, in, out, 1); + aes_xts_crypt(key, in, out, AES_XTS_BLOCKSIZE, true); } static void aes_xts_decrypt(void *key, const uint8_t *in, uint8_t *out) { - aes_xts_crypt(key, in, out, 0); + aes_xts_crypt(key, in, out, AES_XTS_BLOCKSIZE, false); +} + +static void +aes_xts_encrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + aes_xts_crypt(vctx, in, out, len, true); +} + +static void +aes_xts_decrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + aes_xts_crypt(vctx, in, out, len, false); } static int diff --git a/sys/opencrypto/xform_chacha20_poly1305.c b/sys/opencrypto/xform_chacha20_poly1305.c index eec82681bd2c..9fadc28252c6 100644 --- a/sys/opencrypto/xform_chacha20_poly1305.c +++ b/sys/opencrypto/xform_chacha20_poly1305.c @@ -98,6 +98,24 @@ chacha20_poly1305_crypt(void *vctx, const uint8_t *in, uint8_t *out) ctx->ic++; } +static void +chacha20_poly1305_crypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + struct chacha20_poly1305_ctx *ctx = vctx; + int error __diagused; + + KASSERT(len % CHACHA20_NATIVE_BLOCK_LEN == 0, ("%s: invalid length", + __func__)); + if (ctx->ietf) + error = crypto_stream_chacha20_ietf_xor_ic(out, in, len, + ctx->nonce, ctx->ic, ctx->key); + else + error = crypto_stream_chacha20_xor_ic(out, in, len, ctx->nonce, + ctx->ic, ctx->key); + KASSERT(error == 0, ("%s failed: %d", __func__, error)); + ctx->ic += len / CHACHA20_NATIVE_BLOCK_LEN; +} + static void chacha20_poly1305_crypt_last(void *vctx, const uint8_t *in, uint8_t *out, size_t len) @@ -142,10 +160,12 @@ const struct enc_xform enc_xform_chacha20_poly1305 = { .minkey = CHACHA20_POLY1305_KEY, .maxkey = CHACHA20_POLY1305_KEY, .macsize = POLY1305_HASH_LEN, - .encrypt = chacha20_poly1305_crypt, - .decrypt = chacha20_poly1305_crypt, .setkey = chacha20_poly1305_setkey, .reinit = chacha20_poly1305_reinit, + .encrypt = chacha20_poly1305_crypt, + .decrypt = chacha20_poly1305_crypt, + .encrypt_multi = chacha20_poly1305_crypt_multi, + .decrypt_multi = chacha20_poly1305_crypt_multi, .encrypt_last = chacha20_poly1305_crypt_last, .decrypt_last = chacha20_poly1305_crypt_last, .update = chacha20_poly1305_update, @@ -197,10 +217,12 @@ const struct enc_xform enc_xform_xchacha20_poly1305 = { .minkey = XCHACHA20_POLY1305_KEY, .maxkey = XCHACHA20_POLY1305_KEY, .macsize = POLY1305_HASH_LEN, - .encrypt = chacha20_poly1305_crypt, - .decrypt = chacha20_poly1305_crypt, .setkey = xchacha20_poly1305_setkey, .reinit = xchacha20_poly1305_reinit, + .encrypt = chacha20_poly1305_crypt, + .decrypt = chacha20_poly1305_crypt, + .encrypt_multi = chacha20_poly1305_crypt_multi, + .decrypt_multi = chacha20_poly1305_crypt_multi, .encrypt_last = chacha20_poly1305_crypt_last, .decrypt_last = chacha20_poly1305_crypt_last, .update = chacha20_poly1305_update, diff --git a/sys/opencrypto/xform_cml.c b/sys/opencrypto/xform_cml.c index af8ad22f9b18..5afca93b796b 100644 --- a/sys/opencrypto/xform_cml.c +++ b/sys/opencrypto/xform_cml.c @@ -61,6 +61,8 @@ struct camellia_cbc_ctx { static int cml_setkey(void *, const uint8_t *, int); static void cml_encrypt(void *, const uint8_t *, uint8_t *); static void cml_decrypt(void *, const uint8_t *, uint8_t *); +static void cml_encrypt_multi(void *, const uint8_t *, uint8_t *, size_t); +static void cml_decrypt_multi(void *, const uint8_t *, uint8_t *, size_t); static void cml_reinit(void *, const uint8_t *, size_t); /* Encryption instances */ @@ -72,10 +74,12 @@ const struct enc_xform enc_xform_camellia = { .ivsize = CAMELLIA_BLOCK_LEN, .minkey = CAMELLIA_MIN_KEY, .maxkey = CAMELLIA_MAX_KEY, - .encrypt = cml_encrypt, - .decrypt = cml_decrypt, .setkey = cml_setkey, .reinit = cml_reinit, + .encrypt = cml_encrypt, + .decrypt = cml_decrypt, + .encrypt_multi = cml_encrypt_multi, + .decrypt_multi = cml_decrypt_multi, }; /* @@ -106,6 +110,45 @@ cml_decrypt(void *vctx, const uint8_t *in, uint8_t *out) explicit_bzero(block, sizeof(block)); } +static void +cml_encrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + struct camellia_cbc_ctx *ctx = vctx; + + KASSERT(len % CAMELLIA_BLOCK_LEN == 0, ("%s: invalid length", + __func__)); + while (len > 0) { + for (u_int i = 0; i < CAMELLIA_BLOCK_LEN; i++) + out[i] = in[i] ^ ctx->iv[i]; + camellia_encrypt(&ctx->state, out, out); + memcpy(ctx->iv, out, CAMELLIA_BLOCK_LEN); + out += CAMELLIA_BLOCK_LEN; + in += CAMELLIA_BLOCK_LEN; + len -= CAMELLIA_BLOCK_LEN; + } +} + +static void +cml_decrypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len) +{ + struct camellia_cbc_ctx *ctx = vctx; + char block[CAMELLIA_BLOCK_LEN]; + + KASSERT(len % CAMELLIA_BLOCK_LEN == 0, ("%s: invalid length", + __func__)); + while (len > 0) { + memcpy(block, in, CAMELLIA_BLOCK_LEN); + camellia_decrypt(&ctx->state, in, out); + for (u_int i = 0; i < CAMELLIA_BLOCK_LEN; i++) + out[i] ^= ctx->iv[i]; + memcpy(ctx->iv, block, CAMELLIA_BLOCK_LEN); + out += CAMELLIA_BLOCK_LEN; + in += CAMELLIA_BLOCK_LEN; + len -= CAMELLIA_BLOCK_LEN; + } + explicit_bzero(block, sizeof(block)); +} + static int cml_setkey(void *vctx, const uint8_t *key, int len) { diff --git a/sys/opencrypto/xform_enc.h b/sys/opencrypto/xform_enc.h index 9364ff36431c..5bcd144c410d 100644 --- a/sys/opencrypto/xform_enc.h +++ b/sys/opencrypto/xform_enc.h @@ -56,14 +56,26 @@ struct enc_xform { uint16_t minkey, maxkey; uint16_t macsize; /* For AEAD ciphers. */ + /* Initialize context and set key. */ + int (*setkey) (void *, const uint8_t *, int len); + + /* Supply context with nonce/IV. */ + void (*reinit) (void *, const uint8_t *, size_t); + /* * Encrypt/decrypt a single block. For stream ciphers this * encrypts/decrypts a single "native" block. */ void (*encrypt) (void *, const uint8_t *, uint8_t *); void (*decrypt) (void *, const uint8_t *, uint8_t *); - int (*setkey) (void *, const uint8_t *, int len); - void (*reinit) (void *, const uint8_t *, size_t); + + /* + * Encrypt/decrypt multiple blocks. For stream ciphers this + * encrypts/decrypts multiple "native" blocks. The fourth + * argument is a count of bytes. + */ + void (*encrypt_multi) (void *, const uint8_t *, uint8_t *, size_t); + void (*decrypt_multi) (void *, const uint8_t *, uint8_t *, size_t); /* * For stream ciphers, encrypt/decrypt the final partial block diff --git a/sys/opencrypto/xform_null.c b/sys/opencrypto/xform_null.c index 6cd49baab0ac..e070a4a97142 100644 --- a/sys/opencrypto/xform_null.c +++ b/sys/opencrypto/xform_null.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); static int null_setkey(void *, const uint8_t *, int); static void null_crypt(void *, const uint8_t *, uint8_t *); +static void null_crypt_multi(void *, const uint8_t *, uint8_t *, size_t); static void null_init(void *); static void null_reinit(void *ctx, const uint8_t *buf, u_int len); @@ -70,9 +71,11 @@ const struct enc_xform enc_xform_null = { .ivsize = 0, .minkey = NULL_MIN_KEY, .maxkey = NULL_MAX_KEY, + .setkey = null_setkey, .encrypt = null_crypt, .decrypt = null_crypt, - .setkey = null_setkey, + .encrypt_multi = null_crypt_multi, + .decrypt_multi = null_crypt_multi, }; /* Authentication instances */ @@ -98,6 +101,11 @@ null_crypt(void *key, const uint8_t *in, uint8_t *out) { } +static void +null_crypt_multi(void *key, const uint8_t *in, uint8_t *out, size_t len) +{ +} + static int null_setkey(void *sched, const uint8_t *key, int len) {