svn commit: r319721 - head/sys/dev/cxgbe/crypto
John Baldwin
jhb at FreeBSD.org
Thu Jun 8 21:06:20 UTC 2017
Author: jhb
Date: Thu Jun 8 21:06:18 2017
New Revision: 319721
URL: https://svnweb.freebsd.org/changeset/base/319721
Log:
Add explicit handling for requests with an empty payload.
- For HMAC requests, construct a special input buffer to request an empty
hash result.
- For plain cipher requests and requests that chain an AES cipher with an
HMAC, fail with EINVAL if there is no cipher payload. If needed in
the future, chained requests that only contain AAD could be serviced as
HMAC-only requests.
- For GCM requests, the hardware does not support generating the tag for
an AAD-only request. Instead, complete these requests synchronously
in software on the assumption that such requests are rare.
Sponsored by: Chelsio Communications
Modified:
head/sys/dev/cxgbe/crypto/t4_crypto.c
Modified: head/sys/dev/cxgbe/crypto/t4_crypto.c
==============================================================================
--- head/sys/dev/cxgbe/crypto/t4_crypto.c Thu Jun 8 20:47:18 2017 (r319720)
+++ head/sys/dev/cxgbe/crypto/t4_crypto.c Thu Jun 8 21:06:18 2017 (r319721)
@@ -438,7 +438,11 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct cc
hash_size_in_response = axf->hashsize;
transhdr_len = HASH_TRANSHDR_SIZE(kctx_len);
- if (ccr_use_imm_data(transhdr_len, crd->crd_len)) {
+ if (crd->crd_len == 0) {
+ imm_len = axf->blocksize;
+ sgl_nsegs = 0;
+ sgl_len = 0;
+ } else if (ccr_use_imm_data(transhdr_len, crd->crd_len)) {
imm_len = crd->crd_len;
sgl_nsegs = 0;
sgl_len = 0;
@@ -473,7 +477,8 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct cc
V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
V_CPL_TX_SEC_PDU_IVINSRTOFST(0));
- crwr->sec_cpl.pldlen = htobe32(crd->crd_len);
+ crwr->sec_cpl.pldlen = htobe32(crd->crd_len == 0 ? axf->blocksize :
+ crd->crd_len);
crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
V_CPL_TX_SEC_PDU_AUTHSTART(1) | V_CPL_TX_SEC_PDU_AUTHSTOP(0));
@@ -486,7 +491,8 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct cc
V_SCMD_AUTH_MODE(s->hmac.auth_mode) |
V_SCMD_HMAC_CTRL(CHCR_SCMD_HMAC_CTRL_NO_TRUNC));
crwr->sec_cpl.ivgen_hdrlen = htobe32(
- V_SCMD_LAST_FRAG(0) | V_SCMD_MORE_FRAGS(0) | V_SCMD_MAC_ONLY(1));
+ V_SCMD_LAST_FRAG(0) |
+ V_SCMD_MORE_FRAGS(crd->crd_len == 0 ? 1 : 0) | V_SCMD_MAC_ONLY(1));
memcpy(crwr->key_ctx.key, s->hmac.ipad, s->hmac.partial_digest_len);
memcpy(crwr->key_ctx.key + iopad_size, s->hmac.opad,
@@ -500,7 +506,11 @@ ccr_hmac(struct ccr_softc *sc, uint32_t sid, struct cc
V_KEY_CONTEXT_MK_SIZE(s->hmac.mk_size) | V_KEY_CONTEXT_VALID(1));
dst = (char *)(crwr + 1) + kctx_len + DUMMY_BYTES;
- if (imm_len != 0)
+ if (crd->crd_len == 0) {
+ dst[0] = 0x80;
+ *(uint64_t *)(dst + axf->blocksize - sizeof(uint64_t)) =
+ htobe64(axf->blocksize << 3);
+ } else if (imm_len != 0)
crypto_copydata(crp->crp_flags, crp->crp_buf, crd->crd_skip,
crd->crd_len, dst);
else
@@ -544,7 +554,7 @@ ccr_blkcipher(struct ccr_softc *sc, uint32_t sid, stru
crd = crp->crp_desc;
- if (s->blkcipher.key_len == 0)
+ if (s->blkcipher.key_len == 0 || crd->crd_len == 0)
return (EINVAL);
if (crd->crd_alg == CRYPTO_AES_CBC &&
(crd->crd_len % AES_BLOCK_LEN) != 0)
@@ -755,7 +765,11 @@ ccr_authenc(struct ccr_softc *sc, uint32_t sid, struct
int sgl_nsegs, sgl_len;
int error;
- if (s->blkcipher.key_len == 0)
+ /*
+ * If there is a need in the future, requests with an empty
+ * payload could be supported as HMAC-only requests.
+ */
+ if (s->blkcipher.key_len == 0 || crde->crd_len == 0)
return (EINVAL);
if (crde->crd_alg == CRYPTO_AES_CBC &&
(crde->crd_len % AES_BLOCK_LEN) != 0)
@@ -1332,7 +1346,65 @@ ccr_gcm_done(struct ccr_softc *sc, struct ccr_session
return (error);
}
+/*
+ * Handle a GCM request with an empty payload by performing the
+ * operation in software. Derived from swcr_authenc().
+ */
static void
+ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp,
+ struct cryptodesc *crda, struct cryptodesc *crde)
+{
+ struct aes_gmac_ctx gmac_ctx;
+ char block[GMAC_BLOCK_LEN];
+ char digest[GMAC_DIGEST_LEN];
+ char iv[AES_BLOCK_LEN];
+ int i, len;
+
+ /*
+ * This assumes a 12-byte IV from the crp. See longer comment
+ * above in ccr_gcm() for more details.
+ */
+ if (crde->crd_flags & CRD_F_ENCRYPT) {
+ if (crde->crd_flags & CRD_F_IV_EXPLICIT)
+ memcpy(iv, crde->crd_iv, 12);
+ else
+ arc4rand(iv, 12, 0);
+ } else {
+ if (crde->crd_flags & CRD_F_IV_EXPLICIT)
+ memcpy(iv, crde->crd_iv, 12);
+ else
+ crypto_copydata(crp->crp_flags, crp->crp_buf,
+ crde->crd_inject, 12, iv);
+ }
+ *(uint32_t *)&iv[12] = htobe32(1);
+
+ /* Initialize the MAC. */
+ AES_GMAC_Init(&gmac_ctx);
+ AES_GMAC_Setkey(&gmac_ctx, s->blkcipher.enckey, s->blkcipher.key_len);
+ AES_GMAC_Reinit(&gmac_ctx, iv, sizeof(iv));
+
+ /* MAC the AAD. */
+ for (i = 0; i < crda->crd_len; i += sizeof(block)) {
+ len = imin(crda->crd_len - i, sizeof(block));
+ crypto_copydata(crp->crp_flags, crp->crp_buf, crda->crd_skip +
+ i, len, block);
+ bzero(block + len, sizeof(block) - len);
+ AES_GMAC_Update(&gmac_ctx, block, sizeof(block));
+ }
+
+ /* Length block. */
+ bzero(block, sizeof(block));
+ ((uint32_t *)block)[1] = htobe32(crda->crd_len * 8);
+ AES_GMAC_Update(&gmac_ctx, block, sizeof(block));
+ AES_GMAC_Final(digest, &gmac_ctx);
+
+ crypto_copyback(crp->crp_flags, crp->crp_buf, crda->crd_inject,
+ sizeof(digest), digest);
+ crp->crp_etype = 0;
+ crypto_done(crp);
+}
+
+static void
ccr_identify(driver_t *driver, device_t parent)
{
struct adapter *sc;
@@ -2016,6 +2088,11 @@ ccr_process(device_t dev, struct cryptop *crp, int hin
break;
ccr_aes_setkey(s, crde->crd_alg, crde->crd_key,
crde->crd_klen);
+ }
+ if (crde->crd_len == 0) {
+ mtx_unlock(&sc->lock);
+ ccr_gcm_soft(s, crp, crda, crde);
+ return (0);
}
error = ccr_gcm(sc, sid, s, crp, crda, crde);
if (error == 0) {
More information about the svn-src-head
mailing list