Page MenuHomeFreeBSD

D24906.diff
No OneTemporary

D24906.diff

Index: head/share/man/man7/crypto.7
===================================================================
--- head/share/man/man7/crypto.7
+++ head/share/man/man7/crypto.7
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 3, 2020
+.Dd May 22, 2020
.Dt CRYPTO 7
.Os
.Sh NAME
@@ -82,7 +82,7 @@
.It IV size :
16
.It Block size :
-1 (aesni), 16 (software)
+1
.It Key size :
16, 24 or 32
.El
Index: head/sys/crypto/chacha20/chacha-sw.c
===================================================================
--- head/sys/crypto/chacha20/chacha-sw.c
+++ head/sys/crypto/chacha20/chacha-sw.c
@@ -28,11 +28,11 @@
chacha20_xform_crypt(void *ctx, const uint8_t *in, uint8_t *out)
{
- chacha_encrypt_bytes(ctx, in, out, 1);
+ chacha_encrypt_bytes(ctx, in, out, CHACHA_BLOCKLEN);
}
static void
-chacha20_xform_crypt_multi(void *ctx, const uint8_t *in, uint8_t *out,
+chacha20_xform_crypt_last(void *ctx, const uint8_t *in, uint8_t *out,
size_t len)
{
@@ -44,6 +44,7 @@
.name = "chacha20",
.ctxsize = sizeof(struct chacha_ctx),
.blocksize = 1,
+ .native_blocksize = CHACHA_BLOCKLEN,
.ivsize = CHACHA_NONCELEN + CHACHA_CTRLEN,
.minkey = CHACHA_MINKEYLEN,
.maxkey = 32,
@@ -51,6 +52,6 @@
.decrypt = chacha20_xform_crypt,
.setkey = chacha20_xform_setkey,
.reinit = chacha20_xform_reinit,
- .encrypt_multi = chacha20_xform_crypt_multi,
- .decrypt_multi = chacha20_xform_crypt_multi,
+ .encrypt_last = chacha20_xform_crypt_last,
+ .decrypt_last = chacha20_xform_crypt_last,
};
Index: head/sys/opencrypto/cryptosoft.c
===================================================================
--- head/sys/opencrypto/cryptosoft.c
+++ head/sys/opencrypto/cryptosoft.c
@@ -117,13 +117,17 @@
sw = &ses->swcr_encdec;
exf = sw->sw_exf;
- blks = exf->blocksize;
ivlen = exf->ivsize;
- /* Check for non-padded data */
- if ((crp->crp_payload_length % blks) != 0)
- return EINVAL;
+ if (exf->native_blocksize == 0) {
+ /* Check for non-padded data */
+ if ((crp->crp_payload_length % exf->blocksize) != 0)
+ return (EINVAL);
+ blks = exf->blocksize;
+ } else
+ blks = exf->native_blocksize;
+
if (exf == &enc_xform_aes_icm &&
(crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
return (EINVAL);
@@ -182,7 +186,7 @@
i = crp->crp_payload_length;
encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
- while (i > 0) {
+ while (i >= blks) {
/*
* If there's insufficient data at the end of
* an iovec, we have to do some copying.
@@ -249,31 +253,18 @@
break;
}
- while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) {
+ while (uio->uio_iov[ind].iov_len >= k + blks && i >= blks) {
uint8_t *idat;
- size_t nb, rem;
- nb = blks;
- rem = MIN((size_t)i,
- uio->uio_iov[ind].iov_len - (size_t)k);
idat = (uint8_t *)uio->uio_iov[ind].iov_base + k;
if (exf->reinit) {
- if (encrypting && exf->encrypt_multi == NULL)
+ if (encrypting)
exf->encrypt(sw->sw_kschedule,
idat, idat);
- else if (encrypting) {
- nb = rounddown(rem, blks);
- exf->encrypt_multi(sw->sw_kschedule,
- idat, idat, nb);
- } else if (exf->decrypt_multi == NULL)
+ else
exf->decrypt(sw->sw_kschedule,
idat, idat);
- else {
- nb = rounddown(rem, blks);
- exf->decrypt_multi(sw->sw_kschedule,
- idat, idat, nb);
- }
} else if (encrypting) {
/* XOR with previous block/IV */
for (j = 0; j < blks; j++)
@@ -298,9 +289,9 @@
ivp = nivp;
}
- count += nb;
- k += nb;
- i -= nb;
+ count += blks;
+ k += blks;
+ i -= blks;
}
/*
@@ -319,6 +310,25 @@
}
}
+ /* Handle trailing partial block for stream ciphers. */
+ if (i > 0) {
+ KASSERT(exf->native_blocksize != 0,
+ ("%s: partial block of %d bytes for cipher %s",
+ __func__, i, exf->name));
+ KASSERT(exf->reinit != NULL,
+ ("%s: partial block cipher %s without reinit hook",
+ __func__, exf->name));
+ KASSERT(i < blks, ("%s: partial block too big", __func__));
+
+ cuio_copydata(uio, count, i, blk);
+ if (encrypting) {
+ exf->encrypt_last(sw->sw_kschedule, blk, blk, i);
+ } else {
+ exf->decrypt_last(sw->sw_kschedule, blk, blk, i);
+ }
+ cuio_copyback(uio, count, i, blk);
+ }
+
out:
if (iovalloc)
free(iov, M_CRYPTO_DATA);
@@ -512,6 +522,8 @@
swe = &ses->swcr_encdec;
exf = swe->sw_exf;
+ KASSERT(axf->blocksize == exf->native_blocksize,
+ ("%s: blocksize mismatch", __func__));
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
return (EINVAL);
@@ -665,6 +677,8 @@
swe = &ses->swcr_encdec;
exf = swe->sw_exf;
+ KASSERT(axf->blocksize == exf->native_blocksize,
+ ("%s: blocksize mismatch", __func__));
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
return (EINVAL);
Index: head/sys/opencrypto/xform_aes_icm.c
===================================================================
--- head/sys/opencrypto/xform_aes_icm.c
+++ head/sys/opencrypto/xform_aes_icm.c
@@ -54,6 +54,7 @@
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_last(void *, const uint8_t *, uint8_t *, size_t);
static void aes_icm_reinit(void *, const uint8_t *);
static void aes_gcm_reinit(void *, const uint8_t *);
static void aes_ccm_reinit(void *, const uint8_t *);
@@ -63,7 +64,8 @@
.type = CRYPTO_AES_ICM,
.name = "AES-ICM",
.ctxsize = sizeof(struct aes_icm_ctx),
- .blocksize = AES_BLOCK_LEN,
+ .blocksize = 1,
+ .native_blocksize = AES_BLOCK_LEN,
.ivsize = AES_BLOCK_LEN,
.minkey = AES_MIN_KEY,
.maxkey = AES_MAX_KEY,
@@ -71,13 +73,16 @@
.decrypt = aes_icm_crypt,
.setkey = aes_icm_setkey,
.reinit = aes_icm_reinit,
+ .encrypt_last = aes_icm_crypt_last,
+ .decrypt_last = aes_icm_crypt_last,
};
struct enc_xform enc_xform_aes_nist_gcm = {
.type = CRYPTO_AES_NIST_GCM_16,
.name = "AES-GCM",
.ctxsize = sizeof(struct aes_icm_ctx),
- .blocksize = AES_ICM_BLOCK_LEN,
+ .blocksize = 1,
+ .native_blocksize = AES_BLOCK_LEN,
.ivsize = AES_GCM_IV_LEN,
.minkey = AES_MIN_KEY,
.maxkey = AES_MAX_KEY,
@@ -85,18 +90,24 @@
.decrypt = aes_icm_crypt,
.setkey = aes_icm_setkey,
.reinit = aes_gcm_reinit,
+ .encrypt_last = aes_icm_crypt_last,
+ .decrypt_last = aes_icm_crypt_last,
};
struct enc_xform enc_xform_ccm = {
.type = CRYPTO_AES_CCM_16,
.name = "AES-CCM",
.ctxsize = sizeof(struct aes_icm_ctx),
- .blocksize = AES_ICM_BLOCK_LEN, .ivsize = AES_CCM_IV_LEN,
+ .blocksize = 1,
+ .native_blocksize = AES_BLOCK_LEN,
+ .ivsize = AES_CCM_IV_LEN,
.minkey = AES_MIN_KEY, .maxkey = AES_MAX_KEY,
.encrypt = aes_icm_crypt,
.decrypt = aes_icm_crypt,
.setkey = aes_icm_setkey,
.reinit = aes_ccm_reinit,
+ .encrypt_last = aes_icm_crypt_last,
+ .decrypt_last = aes_icm_crypt_last,
};
/*
@@ -143,20 +154,30 @@
aes_icm_crypt(void *key, const uint8_t *in, uint8_t *out)
{
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 < AESICM_BLOCKSIZE; i++)
- out[i] = in[i] ^ keystream[i];
- explicit_bzero(keystream, sizeof(keystream));
+ 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_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
Index: head/sys/opencrypto/xform_enc.h
===================================================================
--- head/sys/opencrypto/xform_enc.h
+++ head/sys/opencrypto/xform_enc.h
@@ -51,20 +51,25 @@
char *name;
size_t ctxsize;
u_int16_t blocksize; /* Required input block size -- 1 for stream ciphers. */
+ uint16_t native_blocksize; /* Used for stream ciphers. */
u_int16_t ivsize;
u_int16_t minkey, maxkey;
+
+ /*
+ * 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 u_int8_t *);
+
/*
- * Encrypt/decrypt 1+ blocks of input -- total size is 'len' bytes.
- * Len is guaranteed to be a multiple of the defined 'blocksize'.
- * Optional interface -- most useful for stream ciphers with a small
- * blocksize (1).
+ * For stream ciphers, encrypt/decrypt the final partial block
+ * of 'len' bytes.
*/
- void (*encrypt_multi) (void *, const uint8_t *, uint8_t *, size_t len);
- void (*decrypt_multi) (void *, const uint8_t *, uint8_t *, size_t len);
+ void (*encrypt_last) (void *, const uint8_t *, uint8_t *, size_t len);
+ void (*decrypt_last) (void *, const uint8_t *, uint8_t *, size_t len);
};

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 28, 4:00 AM (15 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17824291
Default Alt Text
D24906.diff (8 KB)

Event Timeline