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 @@ -1,58 +1,68 @@ /* This file is in the public domain. */ #include __FBSDID("$FreeBSD$"); #include #include static int chacha20_xform_setkey(void *ctx, const uint8_t *key, int len) { if (len != CHACHA_MINKEYLEN && len != 32) return (EINVAL); chacha_keysetup(ctx, key, len * 8); return (0); } static void chacha20_xform_reinit(void *ctx, const uint8_t *iv, size_t ivlen) { KASSERT(ivlen == CHACHA_NONCELEN + CHACHA_CTRLEN, ("%s: invalid IV length", __func__)); chacha_ivsetup(ctx, iv + 8, iv); } static void 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) { chacha_encrypt_bytes(ctx, in, out, len); } const struct enc_xform enc_xform_chacha20 = { .type = CRYPTO_CHACHA20, .name = "chacha20", .ctxsize = sizeof(struct chacha_ctx), .blocksize = 1, .native_blocksize = CHACHA_BLOCKLEN, .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 @@ -1,128 +1,169 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include struct aes_cbc_ctx { rijndael_ctx key; char iv[AES_BLOCK_LEN]; }; 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 */ const struct enc_xform enc_xform_aes_cbc = { .type = CRYPTO_AES_CBC, .name = "AES-CBC", .ctxsize = sizeof(struct aes_cbc_ctx), .blocksize = AES_BLOCK_LEN, .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, }; /* * Encryption wrapper routines. */ static void aes_cbc_encrypt(void *vctx, const uint8_t *in, uint8_t *out) { struct aes_cbc_ctx *ctx = vctx; 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); } static void aes_cbc_decrypt(void *vctx, const uint8_t *in, uint8_t *out) { struct aes_cbc_ctx *ctx = vctx; char block[AES_BLOCK_LEN]; 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); 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) { struct aes_cbc_ctx *ctx = vctx; if (len != 16 && len != 24 && len != 32) return (EINVAL); rijndael_set_key(&ctx->key, key, len * 8); return (0); } static void aes_cbc_reinit(void *vctx, const uint8_t *iv, size_t iv_len) { struct aes_cbc_ctx *ctx = vctx; KASSERT(iv_len == sizeof(ctx->iv), ("%s: bad IV length", __func__)); memcpy(ctx->iv, iv, sizeof(ctx->iv)); } 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 @@ -1,285 +1,317 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include #include struct aes_gcm_ctx { struct aes_icm_ctx cipher; struct aes_gmac_ctx gmac; }; struct aes_ccm_ctx { struct aes_icm_ctx cipher; struct aes_cbc_mac_ctx cbc_mac; }; 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); static void aes_gcm_reinit(void *, const uint8_t *, size_t); static int aes_gcm_update(void *, const void *, u_int); static void aes_gcm_final(uint8_t *, void *); static int aes_ccm_setkey(void *, const uint8_t *, int); static void aes_ccm_reinit(void *, const uint8_t *, size_t); static int aes_ccm_update(void *, const void *, u_int); static void aes_ccm_final(uint8_t *, void *); /* Encryption instances */ const struct enc_xform enc_xform_aes_icm = { .type = CRYPTO_AES_ICM, .name = "AES-ICM", .ctxsize = sizeof(struct aes_icm_ctx), .blocksize = 1, .native_blocksize = AES_BLOCK_LEN, .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, }; const struct enc_xform enc_xform_aes_nist_gcm = { .type = CRYPTO_AES_NIST_GCM_16, .name = "AES-GCM", .ctxsize = sizeof(struct aes_gcm_ctx), .blocksize = 1, .native_blocksize = AES_BLOCK_LEN, .ivsize = AES_GCM_IV_LEN, .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, .final = aes_gcm_final, }; const struct enc_xform enc_xform_ccm = { .type = CRYPTO_AES_CCM_16, .name = "AES-CCM", .ctxsize = sizeof(struct aes_ccm_ctx), .blocksize = 1, .native_blocksize = AES_BLOCK_LEN, .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, .final = aes_ccm_final, }; /* * Encryption wrapper routines. */ static void aes_icm_reinit(void *key, const uint8_t *iv, size_t ivlen) { struct aes_icm_ctx *ctx; ctx = key; KASSERT(ivlen <= sizeof(ctx->ac_block), ("%s: ivlen too large", __func__)); bcopy(iv, ctx->ac_block, ivlen); } static void aes_gcm_reinit(void *vctx, const uint8_t *iv, size_t ivlen) { struct aes_gcm_ctx *ctx = vctx; KASSERT(ivlen == AES_GCM_IV_LEN, ("%s: invalid IV length", __func__)); aes_icm_reinit(&ctx->cipher, iv, ivlen); /* GCM starts with 2 as counter 1 is used for final xor of tag. */ bzero(&ctx->cipher.ac_block[AESICM_BLOCKSIZE - 4], 4); ctx->cipher.ac_block[AESICM_BLOCKSIZE - 1] = 2; AES_GMAC_Reinit(&ctx->gmac, iv, ivlen); } static void aes_ccm_reinit(void *vctx, const uint8_t *iv, size_t ivlen) { struct aes_ccm_ctx *ctx = vctx; KASSERT(ivlen >= 7 && ivlen <= 13, ("%s: invalid IV length", __func__)); /* CCM has flags, then the IV, then the counter, which starts at 1 */ bzero(ctx->cipher.ac_block, sizeof(ctx->cipher.ac_block)); ctx->cipher.ac_block[0] = (15 - ivlen) - 1; bcopy(iv, ctx->cipher.ac_block + 1, ivlen); ctx->cipher.ac_block[AESICM_BLOCKSIZE - 1] = 1; AES_CBC_MAC_Reinit(&ctx->cbc_mac, iv, ivlen); } static void aes_icm_crypt(void *key, const uint8_t *in, uint8_t *out) { struct aes_icm_ctx *ctx; int i; ctx = key; aes_icm_crypt_last(key, in, out, AESICM_BLOCKSIZE); /* increment counter */ for (i = AESICM_BLOCKSIZE - 1; i >= 0; i--) if (++ctx->ac_block[i]) /* continue on overflow */ 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) { struct aes_icm_ctx *ctx; uint8_t keystream[AESICM_BLOCKSIZE]; int i; ctx = key; rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream); for (i = 0; i < len; i++) out[i] = in[i] ^ keystream[i]; explicit_bzero(keystream, sizeof(keystream)); } static int aes_icm_setkey(void *sched, const uint8_t *key, int len) { struct aes_icm_ctx *ctx; if (len != 16 && len != 24 && len != 32) return (EINVAL); ctx = sched; ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, key, len * 8); return (0); } static int aes_gcm_setkey(void *vctx, const uint8_t *key, int len) { struct aes_gcm_ctx *ctx = vctx; int error; error = aes_icm_setkey(&ctx->cipher, key, len); if (error != 0) return (error); AES_GMAC_Setkey(&ctx->gmac, key, len); return (0); } static int aes_ccm_setkey(void *vctx, const uint8_t *key, int len) { struct aes_ccm_ctx *ctx = vctx; int error; error = aes_icm_setkey(&ctx->cipher, key, len); if (error != 0) return (error); AES_CBC_MAC_Setkey(&ctx->cbc_mac, key, len); return (0); } static int aes_gcm_update(void *vctx, const void *buf, u_int len) { struct aes_gcm_ctx *ctx = vctx; return (AES_GMAC_Update(&ctx->gmac, buf, len)); } static int aes_ccm_update(void *vctx, const void *buf, u_int len) { struct aes_ccm_ctx *ctx = vctx; return (AES_CBC_MAC_Update(&ctx->cbc_mac, buf, len)); } static void aes_gcm_final(uint8_t *tag, void *vctx) { struct aes_gcm_ctx *ctx = vctx; AES_GMAC_Final(tag, &ctx->gmac); } static void aes_ccm_final(uint8_t *tag, void *vctx) { struct aes_ccm_ctx *ctx = vctx; AES_CBC_MAC_Final(tag, &ctx->cbc_mac); } 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 @@ -1,162 +1,185 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include 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 */ const struct enc_xform enc_xform_aes_xts = { .type = CRYPTO_AES_XTS, .name = "AES-XTS", .ctxsize = sizeof(struct aes_xts_ctx), .blocksize = AES_BLOCK_LEN, .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, }; /* * Encryption wrapper routines. */ static void aes_xts_reinit(void *key, const uint8_t *iv, size_t ivlen) { struct aes_xts_ctx *ctx = key; uint64_t blocknum; u_int i; #ifndef _STANDALONE KASSERT(ivlen == sizeof(blocknum), ("%s: invalid IV length", __func__)); #endif /* * Prepare tweak as E_k2(IV). IV is specified as LE representation * of a 64-bit block number which we allow to be passed in directly. */ bcopy(iv, &blocknum, AES_XTS_IVSIZE); for (i = 0; i < AES_XTS_IVSIZE; i++) { ctx->tweak[i] = blocknum & 0xff; blocknum >>= 8; } /* Last 64 bits of IV are always zero */ bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE); rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak); } 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 aes_xts_setkey(void *sched, const uint8_t *key, int len) { struct aes_xts_ctx *ctx; if (len != 32 && len != 64) return (EINVAL); ctx = sched; rijndael_set_key(&ctx->key1, key, len * 4); rijndael_set_key(&ctx->key2, key + (len / 2), len * 4); return (0); } 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 @@ -1,208 +1,230 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2020 Netflix Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include struct chacha20_poly1305_ctx { struct crypto_onetimeauth_poly1305_state auth; const void *key; uint32_t ic; bool ietf; char nonce[CHACHA20_POLY1305_IV_LEN]; }; struct xchacha20_poly1305_ctx { struct chacha20_poly1305_ctx base_ctx; /* must be first */ const void *key; char derived_key[CHACHA20_POLY1305_KEY]; }; static int chacha20_poly1305_setkey(void *vctx, const uint8_t *key, int len) { struct chacha20_poly1305_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, size_t ivlen) { struct chacha20_poly1305_ctx *ctx = vctx; char block[CHACHA20_NATIVE_BLOCK_LEN]; KASSERT(ivlen == 8 || ivlen == sizeof(ctx->nonce), ("%s: invalid nonce length", __func__)); memcpy(ctx->nonce, iv, ivlen); ctx->ietf = (ivlen == CHACHA20_POLY1305_IV_LEN); /* Block 0 is used for the poly1305 key. */ if (ctx->ietf) crypto_stream_chacha20_ietf(block, sizeof(block), iv, ctx->key); else crypto_stream_chacha20(block, sizeof(block), iv, ctx->key); crypto_onetimeauth_poly1305_init(&ctx->auth, block); explicit_bzero(block, sizeof(block)); /* Start with block 1 for ciphertext. */ ctx->ic = 1; } static void chacha20_poly1305_crypt(void *vctx, const uint8_t *in, uint8_t *out) { struct chacha20_poly1305_ctx *ctx = vctx; int error __diagused; if (ctx->ietf) error = crypto_stream_chacha20_ietf_xor_ic(out, in, CHACHA20_NATIVE_BLOCK_LEN, ctx->nonce, ctx->ic, ctx->key); else error = crypto_stream_chacha20_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_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) { struct chacha20_poly1305_ctx *ctx = vctx; int error __diagused; 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)); } static int chacha20_poly1305_update(void *vctx, const void *data, u_int len) { struct chacha20_poly1305_ctx *ctx = vctx; crypto_onetimeauth_poly1305_update(&ctx->auth, data, len); return (0); } static void chacha20_poly1305_final(uint8_t *digest, void *vctx) { struct chacha20_poly1305_ctx *ctx = vctx; crypto_onetimeauth_poly1305_final(&ctx->auth, digest); } const struct enc_xform enc_xform_chacha20_poly1305 = { .type = CRYPTO_CHACHA20_POLY1305, .name = "ChaCha20-Poly1305", .ctxsize = sizeof(struct chacha20_poly1305_ctx), .blocksize = 1, .native_blocksize = CHACHA20_NATIVE_BLOCK_LEN, .ivsize = CHACHA20_POLY1305_IV_LEN, .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, .final = chacha20_poly1305_final, }; static int xchacha20_poly1305_setkey(void *vctx, const uint8_t *key, int len) { struct xchacha20_poly1305_ctx *ctx = vctx; if (len != XCHACHA20_POLY1305_KEY) return (EINVAL); ctx->key = key; ctx->base_ctx.key = ctx->derived_key; return (0); } static void xchacha20_poly1305_reinit(void *vctx, const uint8_t *iv, size_t ivlen) { struct xchacha20_poly1305_ctx *ctx = vctx; char nonce[CHACHA20_POLY1305_IV_LEN]; KASSERT(ivlen == XCHACHA20_POLY1305_IV_LEN, ("%s: invalid nonce length", __func__)); /* * Use HChaCha20 to derive the internal key used for * ChaCha20-Poly1305. */ crypto_core_hchacha20(ctx->derived_key, iv, ctx->key, NULL); memset(nonce, 0, 4); memcpy(nonce + 4, iv + crypto_core_hchacha20_INPUTBYTES, sizeof(nonce) - 4); chacha20_poly1305_reinit(&ctx->base_ctx, nonce, sizeof(nonce)); explicit_bzero(nonce, sizeof(nonce)); } const struct enc_xform enc_xform_xchacha20_poly1305 = { .type = CRYPTO_XCHACHA20_POLY1305, .name = "XChaCha20-Poly1305", .ctxsize = sizeof(struct xchacha20_poly1305_ctx), .blocksize = 1, .native_blocksize = CHACHA20_NATIVE_BLOCK_LEN, .ivsize = XCHACHA20_POLY1305_IV_LEN, .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, .final = chacha20_poly1305_final, }; 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 @@ -1,128 +1,171 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include struct camellia_cbc_ctx { camellia_ctx state; char iv[CAMELLIA_BLOCK_LEN]; }; 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 */ const struct enc_xform enc_xform_camellia = { .type = CRYPTO_CAMELLIA_CBC, .name = "Camellia-CBC", .ctxsize = sizeof(struct camellia_cbc_ctx), .blocksize = CAMELLIA_BLOCK_LEN, .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, }; /* * Encryption wrapper routines. */ static void cml_encrypt(void *vctx, const uint8_t *in, uint8_t *out) { struct camellia_cbc_ctx *ctx = vctx; 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); } static void cml_decrypt(void *vctx, const uint8_t *in, uint8_t *out) { struct camellia_cbc_ctx *ctx = vctx; char block[CAMELLIA_BLOCK_LEN]; 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); 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) { struct camellia_cbc_ctx *ctx = vctx; if (len != 16 && len != 24 && len != 32) return (EINVAL); camellia_set_key(&ctx->state, key, len * 8); return (0); } static void cml_reinit(void *vctx, const uint8_t *iv, size_t iv_len) { struct camellia_cbc_ctx *ctx = vctx; KASSERT(iv_len == sizeof(ctx->iv), ("%s: bad IV length", __func__)); memcpy(ctx->iv, iv, sizeof(ctx->iv)); } 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 @@ -1,108 +1,120 @@ /* $FreeBSD$ */ /* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */ /*- * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * * This code was written by Angelos D. Keromytis in Athens, Greece, in * February 2000. Network Security Technologies Inc. (NSTI) kindly * supported the development of this code. * * Copyright (c) 2000 Angelos D. Keromytis * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software without fee * is hereby granted, provided that this entire notice is included in * all source code copies of any software which is or includes a copy or * modification of this software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #ifndef _CRYPTO_XFORM_ENC_H_ #define _CRYPTO_XFORM_ENC_H_ #include #include #include #include #include #ifdef _STANDALONE #include #endif #define AESICM_BLOCKSIZE AES_BLOCK_LEN #define AES_XTS_BLOCKSIZE 16 #define AES_XTS_IVSIZE 8 #define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */ /* Declarations */ struct enc_xform { int type; const char *name; size_t ctxsize; uint16_t blocksize; /* Required input block size -- 1 for stream ciphers. */ uint16_t native_blocksize; /* Used for stream ciphers. */ uint16_t ivsize; 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 * of 'len' bytes. */ void (*encrypt_last) (void *, const uint8_t *, uint8_t *, size_t len); void (*decrypt_last) (void *, const uint8_t *, uint8_t *, size_t len); /* * For AEAD ciphers, update and generate MAC/tag. */ int (*update) (void *, const void *, u_int); void (*final) (uint8_t *, void *); }; extern const struct enc_xform enc_xform_null; extern const struct enc_xform enc_xform_aes_cbc; extern const struct enc_xform enc_xform_aes_icm; extern const struct enc_xform enc_xform_aes_nist_gcm; extern const struct enc_xform enc_xform_aes_nist_gmac; extern const struct enc_xform enc_xform_aes_xts; extern const struct enc_xform enc_xform_camellia; extern const struct enc_xform enc_xform_chacha20; extern const struct enc_xform enc_xform_chacha20_poly1305; extern const struct enc_xform enc_xform_xchacha20_poly1305; extern const struct enc_xform enc_xform_ccm; struct aes_icm_ctx { uint32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)]; /* ac_block is initialized to IV */ uint8_t ac_block[AESICM_BLOCKSIZE]; int ac_nr; }; struct aes_xts_ctx { rijndael_ctx key1; rijndael_ctx key2; uint8_t tweak[AES_XTS_BLOCKSIZE]; }; #endif /* _CRYPTO_XFORM_ENC_H_ */ 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 @@ -1,132 +1,140 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * AES XTS implementation in 2008 by Damien Miller * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * * Copyright (C) 2008, Damien Miller * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by John-Mark Gurney * under sponsorship of the FreeBSD Foundation and * Rubicon Communications, LLC (Netgate). * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include __FBSDID("$FreeBSD$"); #include #include 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); static int null_update(void *, const void *, u_int); static void null_final(uint8_t *, void *); /* Encryption instances */ const struct enc_xform enc_xform_null = { .type = CRYPTO_NULL_CBC, .name = "NULL", /* NB: blocksize of 4 is to generate a properly aligned ESP header */ .blocksize = NULL_BLOCK_LEN, .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 */ const struct auth_hash auth_hash_null = { .type = CRYPTO_NULL_HMAC, .name = "NULL-HMAC", .keysize = 0, .hashsize = NULL_HASH_LEN, .ctxsize = sizeof(int), /* NB: context isn't used */ .blocksize = NULL_HMAC_BLOCK_LEN, .Init = null_init, .Setkey = null_reinit, .Reinit = null_reinit, .Update = null_update, .Final = null_final, }; /* * Encryption wrapper routines. */ static void 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) { return (0); } /* * And now for auth. */ static void null_init(void *ctx) { } static void null_reinit(void *ctx, const uint8_t *buf, u_int len) { } static int null_update(void *ctx, const void *buf, u_int len) { return 0; } static void null_final(uint8_t *buf, void *ctx) { if (buf != (uint8_t *) 0) bzero(buf, 12); }