Page MenuHomeFreeBSD

D32111.diff
No OneTemporary

D32111.diff

diff --git a/share/man/man7/crypto.7 b/share/man/man7/crypto.7
--- a/share/man/man7/crypto.7
+++ b/share/man/man7/crypto.7
@@ -1,9 +1,13 @@
-.\" Copyright (c) 2014 The FreeBSD Foundation
+.\" Copyright (c) 2014-2021 The FreeBSD Foundation
.\" All rights reserved.
.\"
-.\" This documentation was written by John-Mark Gurney under
-.\" the sponsorship of the FreeBSD Foundation and
+.\" Portions of this documentation were written by John-Mark Gurney
+.\" under the sponsorship of the FreeBSD Foundation and
.\" Rubicon Communications, LLC (Netgate).
+.\"
+.\" Portions of this documentation were written by Ararat River
+.\" Consulting, LLC under sponsorship of the FreeBSD Foundation.
+.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -27,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 3, 2021
+.Dd October 6, 2021
.Dt CRYPTO 7
.Os
.Sh NAME
@@ -153,13 +157,15 @@
via the
.Dv CRYPTO_F_IV_SEPARATE
flag.
+Some AEAD algorithms support multiple nonce sizes.
+The first size listed is the default nonce size.
.Pp
The following AEAD algorithms are supported:
-.Bl -column "CRYPTO_AES_NIST_GCM_16" "Nonce" "16, 24, 32" "Tag"
+.Bl -column "CRYPTO_AES_NIST_GCM_16" "12, 7-13" "16, 24, 32" "Tag"
.It Sy Name Ta Sy Nonce Ta Sy Key Sizes Ta Sy Tag Ta Sy Description
.It Dv CRYPTO_AES_NIST_GCM_16 Ta 12 Ta 16, 24, 32 Ta 16 Ta
AES Galois/Counter Mode
-.It Dv CRYPTO_AES_CCM_16 Ta 12 Ta 16, 24, 32 Ta 16 Ta
+.It Dv CRYPTO_AES_CCM_16 Ta 12, 7-13 Ta 16, 24, 32 Ta 16 Ta
AES Counter with CBC-MAC
.It Dv CRYPTO_CHACHA20_POLY1305 Ta 12 Ta 32 Ta 16 Ta
ChaCha20-Poly1305
diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c
--- a/sys/opencrypto/crypto.c
+++ b/sys/opencrypto/crypto.c
@@ -1,5 +1,9 @@
/*-
* Copyright (c) 2002-2006 Sam Leffler. All rights reserved.
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Ararat River
+ * Consulting, LLC under sponsorship of the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -713,6 +717,24 @@
return (alg_type(alg) == ALG_AEAD);
}
+static bool
+ccm_tag_length_valid(int len)
+{
+ /* RFC 3610 */
+ switch (len) {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ return (true);
+ default:
+ return (false);
+ }
+}
+
#define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
/* Various sanity checks on crypto session parameters. */
@@ -770,8 +792,21 @@
return (false);
/* IV is optional for digests (e.g. GMAC). */
- if (csp->csp_ivlen >= EALG_MAX_BLOCK_LEN)
- return (false);
+ switch (csp->csp_auth_alg) {
+ case CRYPTO_AES_CCM_CBC_MAC:
+ if (csp->csp_ivlen < 7 || csp->csp_ivlen > 13)
+ return (false);
+ break;
+ case CRYPTO_AES_NIST_GMAC:
+ if (csp->csp_ivlen != AES_GCM_IV_LEN)
+ return (false);
+ break;
+ default:
+ if (csp->csp_ivlen != 0)
+ return (false);
+ break;
+ }
+
if (!alg_is_digest(csp->csp_auth_alg))
return (false);
@@ -790,6 +825,10 @@
axf = crypto_auth_hash(csp);
if (axf == NULL || csp->csp_auth_mlen > axf->hashsize)
return (false);
+
+ if (csp->csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC &&
+ !ccm_tag_length_valid(csp->csp_auth_mlen))
+ return (false);
}
break;
case CSP_MODE_AEAD:
@@ -803,13 +842,16 @@
if (csp->csp_auth_alg != 0 || csp->csp_auth_klen != 0)
return (false);
- /*
- * XXX: Would be nice to have a better way to get this
- * value.
- */
switch (csp->csp_cipher_alg) {
- case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_AES_CCM_16:
+ if (csp->csp_auth_mlen != 0 &&
+ !ccm_tag_length_valid(csp->csp_auth_mlen))
+ return (false);
+
+ if (csp->csp_ivlen < 7 || csp->csp_ivlen > 13)
+ return (false);
+ break;
+ case CRYPTO_AES_NIST_GCM_16:
case CRYPTO_CHACHA20_POLY1305:
if (csp->csp_auth_mlen > 16)
return (false);
diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
--- a/sys/opencrypto/cryptodev.h
+++ b/sys/opencrypto/cryptodev.h
@@ -686,5 +686,34 @@
crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, iv);
}
+static __inline size_t
+ccm_max_payload_length(const struct crypto_session_params *csp)
+{
+ /* RFC 3160 */
+ const u_int L = 15 - csp->csp_ivlen;
+
+ switch (L) {
+ case 2:
+ return (0xffff);
+ case 3:
+ return (0xffffff);
+#ifdef __LP64__
+ case 4:
+ return (0xffffffff);
+ case 5:
+ return (0xffffffffff);
+ case 6:
+ return (0xffffffffffff);
+ case 7:
+ return (0xffffffffffffff);
+ default:
+ return (0xffffffffffffffff);
+#else
+ default:
+ return (0xffffffff);
+#endif
+ }
+}
+
#endif /* _KERNEL */
#endif /* _CRYPTO_CRYPTO_H_ */
diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
--- a/sys/opencrypto/cryptosoft.c
+++ b/sys/opencrypto/cryptosoft.c
@@ -642,17 +642,19 @@
u_char tag[AES_CBC_MAC_HASH_LEN];
u_char iv[AES_BLOCK_LEN];
union authctx ctx;
+ const struct crypto_session_params *csp;
struct swcr_auth *swa;
const struct auth_hash *axf;
int error, ivlen;
+ csp = crypto_get_params(crp->crp_session);
swa = &ses->swcr_auth;
axf = swa->sw_axf;
bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
/* Initialize the IV */
- ivlen = AES_CCM_IV_LEN;
+ ivlen = csp->csp_ivlen;
crypto_read_iv(crp, iv);
/*
@@ -694,6 +696,7 @@
static int
swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
{
+ const struct crypto_session_params *csp;
uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
u_char *blk = (u_char *)blkbuf;
u_char tag[AES_CBC_MAC_HASH_LEN];
@@ -708,6 +711,7 @@
size_t len;
int blksz, error, ivlen, r, resid;
+ csp = crypto_get_params(crp->crp_session);
swa = &ses->swcr_auth;
axf = swa->sw_axf;
@@ -721,10 +725,13 @@
KASSERT(axf->blocksize == exf->native_blocksize,
("%s: blocksize mismatch", __func__));
+ if (crp->crp_payload_length > ccm_max_payload_length(csp))
+ return (EMSGSIZE);
+
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
return (EINVAL);
- ivlen = AES_CCM_IV_LEN;
+ ivlen = csp->csp_ivlen;
/*
* AES CCM-CBC-MAC needs to know the length of both the auth
@@ -1130,7 +1137,6 @@
swe = &ses->swcr_encdec;
txf = crypto_cipher(csp);
- MPASS(txf->ivsize == csp->csp_ivlen);
if (txf->ctxsize != 0) {
swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
@@ -1282,9 +1288,6 @@
struct swcr_auth *swa;
const struct auth_hash *axf;
- if (csp->csp_ivlen != AES_CCM_IV_LEN)
- return (EINVAL);
-
/* First, setup the auth side. */
swa = &ses->swcr_auth;
switch (csp->csp_cipher_klen * 8) {
@@ -1392,8 +1395,6 @@
}
if (csp->csp_auth_key == NULL)
return (false);
- if (csp->csp_ivlen != AES_CCM_IV_LEN)
- return (false);
break;
}
return (true);
diff --git a/sys/opencrypto/xform_aes_icm.c b/sys/opencrypto/xform_aes_icm.c
--- a/sys/opencrypto/xform_aes_icm.c
+++ b/sys/opencrypto/xform_aes_icm.c
@@ -144,15 +144,14 @@
{
struct aes_icm_ctx *ctx;
- KASSERT(ivlen == AES_CCM_IV_LEN,
+ KASSERT(ivlen >= 7 && ivlen <= 13,
("%s: invalid IV length", __func__));
ctx = key;
/* CCM has flags, then the IV, then the counter, which starts at 1 */
bzero(ctx->ac_block, sizeof(ctx->ac_block));
- /* 3 bytes for length field; this gives a nonce of 12 bytes */
- ctx->ac_block[0] = (15 - AES_CCM_IV_LEN) - 1;
- bcopy(iv, ctx->ac_block+1, AES_CCM_IV_LEN);
+ ctx->ac_block[0] = (15 - ivlen) - 1;
+ bcopy(iv, ctx->ac_block + 1, ivlen);
ctx->ac_block[AESICM_BLOCKSIZE - 1] = 1;
}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 7, 2:06 AM (17 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17023417
Default Alt Text
D32111.diff (7 KB)

Event Timeline