aboutsummaryrefslogtreecommitdiff
path: root/sys/opencrypto/xform_chacha20_poly1305.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/opencrypto/xform_chacha20_poly1305.c')
-rw-r--r--sys/opencrypto/xform_chacha20_poly1305.c128
1 files changed, 125 insertions, 3 deletions
diff --git a/sys/opencrypto/xform_chacha20_poly1305.c b/sys/opencrypto/xform_chacha20_poly1305.c
index e568e76cad51..3a72c06f931b 100644
--- 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,
+};