From owner-svn-src-head@freebsd.org Mon Jun 22 23:20:45 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 70C2333F2F6; Mon, 22 Jun 2020 23:20:45 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49rQPn2cvWz4YQj; Mon, 22 Jun 2020 23:20:45 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5541C15D4D; Mon, 22 Jun 2020 23:20:45 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05MNKjDn015981; Mon, 22 Jun 2020 23:20:45 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05MNKivu015975; Mon, 22 Jun 2020 23:20:44 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <202006222320.05MNKivu015975@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Mon, 22 Jun 2020 23:20:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362517 - in head: share/man/man9 sys/opencrypto X-SVN-Group: head X-SVN-Commit-Author: jhb X-SVN-Commit-Paths: in head: share/man/man9 sys/opencrypto X-SVN-Commit-Revision: 362517 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Jun 2020 23:20:45 -0000 Author: jhb Date: Mon Jun 22 23:20:43 2020 New Revision: 362517 URL: https://svnweb.freebsd.org/changeset/base/362517 Log: Add support to the crypto framework for separate AAD buffers. This permits requests to provide the AAD in a separate side buffer instead of as a region in the crypto request input buffer. This is useful when the main data buffer might not contain the full AAD (e.g. for TLS or IPsec with ESN). Unlike separate IVs which are constrained in size and stored in an array in struct cryptop, separate AAD is provided by the caller setting a new crp_aad pointer to the buffer. The caller must ensure the pointer remains valid and the buffer contents static until the request is completed (e.g. when the callback routine is invoked). As with separate output buffers, not all drivers support this feature. Consumers must request use of this feature via a new session flag. To aid in driver testing, kern.crypto.cryptodev_separate_aad can be set to force /dev/crypto requests to use a separate AAD buffer. Discussed with: cem Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D25288 Modified: head/share/man/man9/crypto_request.9 head/share/man/man9/crypto_session.9 head/sys/opencrypto/crypto.c head/sys/opencrypto/cryptodev.c head/sys/opencrypto/cryptodev.h head/sys/opencrypto/cryptosoft.c Modified: head/share/man/man9/crypto_request.9 ============================================================================== --- head/share/man/man9/crypto_request.9 Mon Jun 22 23:13:14 2020 (r362516) +++ head/share/man/man9/crypto_request.9 Mon Jun 22 23:20:43 2020 (r362517) @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 25, 2020 +.Dd June 22, 2020 .Dt CRYPTO_REQUEST 9 .Os .Sh NAME @@ -181,7 +181,7 @@ The following regions are defined: .Bl -column "Payload Output" "Input/Output" .It Sy Region Ta Sy Buffer Ta Sy Description .It AAD Ta Input Ta -Additional Authenticated Data +Embedded Additional Authenticated Data .It IV Ta Input Ta Embedded IV or nonce .It Payload Ta Input Ta @@ -256,6 +256,15 @@ If the digests do not match, fail the request with .Er EBADMSG . .El +.Ss Request AAD +AEAD and Encrypt-then-Authenticate requests may optionally include +Additional Authenticated Data. +AAD may either be supplied in the AAD region of the input buffer or +as a single buffer pointed to by +.Fa crp_aad . +In either case, +.Fa crp_aad_length +always indicates the amount of AAD in bytes. .Ss Request IV and/or Nonce Some cryptographic operations require an IV or nonce as an input. An IV may be stored either in the IV region of the data buffer or in Modified: head/share/man/man9/crypto_session.9 ============================================================================== --- head/share/man/man9/crypto_session.9 Mon Jun 22 23:13:14 2020 (r362516) +++ head/share/man/man9/crypto_session.9 Mon Jun 22 23:20:43 2020 (r362517) @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 25, 2020 +.Dd June 22, 2020 .Dt CRYPTO_SESSION 9 .Os .Sh NAME @@ -194,6 +194,13 @@ that is modified in-place, or requests with separate i buffers. Sessions without this flag only permit requests with a single buffer that is modified in-place. +.It Dv CSP_F_SEPARATE_AAD +Support requests that use a separate buffer for AAD rather than providing +AAD as a region in the input buffer. +Sessions with this flag set permit requests with AAD passed in either in +a region of the input buffer or in a single, virtually-contiguous buffer. +Sessions without this flag only permit requests with AAD passed in as +a region in the input buffer. .El .It Fa csp_ivlen If either the cipher or authentication algorithms require an explicit Modified: head/sys/opencrypto/crypto.c ============================================================================== --- head/sys/opencrypto/crypto.c Mon Jun 22 23:13:14 2020 (r362516) +++ head/sys/opencrypto/crypto.c Mon Jun 22 23:20:43 2020 (r362517) @@ -755,7 +755,8 @@ check_csp(const struct crypto_session_params *csp) struct auth_hash *axf; /* Mode-independent checks. */ - if ((csp->csp_flags & ~CSP_F_SEPARATE_OUTPUT) != 0) + if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != + 0) return (false); if (csp->csp_ivlen < 0 || csp->csp_cipher_klen < 0 || csp->csp_auth_klen < 0 || csp->csp_auth_mlen < 0) @@ -771,6 +772,8 @@ check_csp(const struct crypto_session_params *csp) return (false); if (csp->csp_flags & CSP_F_SEPARATE_OUTPUT) return (false); + if (csp->csp_flags & CSP_F_SEPARATE_AAD) + return (false); if (csp->csp_cipher_klen != 0 || csp->csp_ivlen != 0 || csp->csp_auth_alg != 0 || csp->csp_auth_klen != 0 || csp->csp_auth_mlen != 0) @@ -779,6 +782,8 @@ check_csp(const struct crypto_session_params *csp) case CSP_MODE_CIPHER: if (!alg_is_cipher(csp->csp_cipher_alg)) return (false); + if (csp->csp_flags & CSP_F_SEPARATE_AAD) + return (false); if (csp->csp_cipher_alg != CRYPTO_NULL_CBC) { if (csp->csp_cipher_klen == 0) return (false); @@ -795,6 +800,9 @@ check_csp(const struct crypto_session_params *csp) if (csp->csp_cipher_alg != 0 || csp->csp_cipher_klen != 0) return (false); + if (csp->csp_flags & CSP_F_SEPARATE_AAD) + return (false); + /* IV is optional for digests (e.g. GMAC). */ if (csp->csp_ivlen >= EALG_MAX_BLOCK_LEN) return (false); @@ -1306,16 +1314,27 @@ crp_sanity(struct cryptop *crp) break; } if (csp->csp_mode == CSP_MODE_AEAD || csp->csp_mode == CSP_MODE_ETA) { - KASSERT(crp->crp_aad_start == 0 || - crp->crp_aad_start < ilen, - ("invalid AAD start")); - KASSERT(crp->crp_aad_length != 0 || crp->crp_aad_start == 0, - ("AAD with zero length and non-zero start")); - KASSERT(crp->crp_aad_length == 0 || - crp->crp_aad_start + crp->crp_aad_length <= ilen, - ("AAD outside input length")); + if (crp->crp_aad == NULL) { + KASSERT(crp->crp_aad_start == 0 || + crp->crp_aad_start < ilen, + ("invalid AAD start")); + KASSERT(crp->crp_aad_length != 0 || + crp->crp_aad_start == 0, + ("AAD with zero length and non-zero start")); + KASSERT(crp->crp_aad_length == 0 || + crp->crp_aad_start + crp->crp_aad_length <= ilen, + ("AAD outside input length")); + } else { + KASSERT(csp->csp_flags & CSP_F_SEPARATE_AAD, + ("session doesn't support separate AAD buffer")); + KASSERT(crp->crp_aad_start == 0, + ("separate AAD buffer with non-zero AAD start")); + KASSERT(crp->crp_aad_length != 0, + ("separate AAD buffer with zero length")); + } } else { - KASSERT(crp->crp_aad_start == 0 && crp->crp_aad_length == 0, + KASSERT(crp->crp_aad == NULL && crp->crp_aad_start == 0 && + crp->crp_aad_length == 0, ("AAD region in request not supporting AAD")); } if (csp->csp_ivlen == 0) { Modified: head/sys/opencrypto/cryptodev.c ============================================================================== --- head/sys/opencrypto/cryptodev.c Mon Jun 22 23:13:14 2020 (r362516) +++ head/sys/opencrypto/cryptodev.c Mon Jun 22 23:20:43 2020 (r362517) @@ -283,6 +283,7 @@ struct cryptop_data { char *buf; char *obuf; + char *aad; bool done; }; @@ -297,6 +298,11 @@ SYSCTL_BOOL(_kern_crypto, OID_AUTO, cryptodev_use_outp &use_outputbuffers, 0, "Use separate output buffers for /dev/crypto requests."); +static bool use_separate_aad; +SYSCTL_BOOL(_kern_crypto, OID_AUTO, cryptodev_separate_aad, CTLFLAG_RW, + &use_separate_aad, 0, + "Use separate AAD buffer for /dev/crypto requests."); + static int cryptof_ioctl(struct file *, u_long, void *, struct ucred *, struct thread *); static int cryptof_stat(struct file *, struct stat *, @@ -604,6 +610,14 @@ cryptof_ioctl( else csp.csp_mode = CSP_MODE_DIGEST; + switch (csp.csp_mode) { + case CSP_MODE_AEAD: + case CSP_MODE_ETA: + if (use_separate_aad) + csp.csp_flags |= CSP_F_SEPARATE_AAD; + break; + } + if (txform) { csp.csp_cipher_alg = txform->type; csp.csp_cipher_klen = sop->keylen; @@ -819,14 +833,19 @@ bail: static int cryptodev_cb(struct cryptop *); static struct cryptop_data * -cod_alloc(struct csession *cse, size_t len, struct thread *td) +cod_alloc(struct csession *cse, size_t aad_len, size_t len, struct thread *td) { struct cryptop_data *cod; cod = malloc(sizeof(struct cryptop_data), M_XDATA, M_WAITOK | M_ZERO); cod->cse = cse; - cod->buf = malloc(len, M_XDATA, M_WAITOK); + if (crypto_get_params(cse->cses)->csp_flags & CSP_F_SEPARATE_AAD) { + if (aad_len != 0) + cod->aad = malloc(aad_len, M_XDATA, M_WAITOK); + cod->buf = malloc(len, M_XDATA, M_WAITOK); + } else + cod->buf = malloc(aad_len + len, M_XDATA, M_WAITOK); if (crypto_get_params(cse->cses)->csp_flags & CSP_F_SEPARATE_OUTPUT) cod->obuf = malloc(len, M_XDATA, M_WAITOK); return (cod); @@ -836,6 +855,7 @@ static void cod_free(struct cryptop_data *cod) { + free(cod->aad, M_XDATA); free(cod->obuf, M_XDATA); free(cod->buf, M_XDATA); free(cod, M_XDATA); @@ -881,7 +901,7 @@ cryptodev_op( } } - cod = cod_alloc(cse, cop->len + cse->hashsize, td); + cod = cod_alloc(cse, 0, cop->len + cse->hashsize, td); crp = crypto_getreq(cse->cses, M_WAITOK); @@ -1087,29 +1107,38 @@ cryptodev_aead( } } - cod = cod_alloc(cse, caead->aadlen + caead->len + cse->hashsize, td); + cod = cod_alloc(cse, caead->aadlen, caead->len + cse->hashsize, td); crp = crypto_getreq(cse->cses, M_WAITOK); - error = copyin(caead->aad, cod->buf, caead->aadlen); + if (cod->aad != NULL) + error = copyin(caead->aad, cod->aad, caead->aadlen); + else + error = copyin(caead->aad, cod->buf, caead->aadlen); if (error) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } + crp->crp_aad = cod->aad; crp->crp_aad_start = 0; crp->crp_aad_length = caead->aadlen; - error = copyin(caead->src, cod->buf + caead->aadlen, caead->len); + if (cod->aad != NULL) + crp->crp_payload_start = 0; + else + crp->crp_payload_start = caead->aadlen; + error = copyin(caead->src, cod->buf + crp->crp_payload_start, + caead->len); if (error) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - crp->crp_payload_start = caead->aadlen; crp->crp_payload_length = caead->len; if (caead->op == COP_ENCRYPT && cod->obuf != NULL) - crp->crp_digest_start = caead->len; + crp->crp_digest_start = crp->crp_payload_output_start + + caead->len; else - crp->crp_digest_start = caead->aadlen + caead->len; + crp->crp_digest_start = crp->crp_payload_start + caead->len; switch (cse->mode) { case CSP_MODE_AEAD: @@ -1136,7 +1165,7 @@ cryptodev_aead( } crp->crp_flags = CRYPTO_F_CBIMM | (caead->flags & COP_F_BATCH); - crypto_use_buf(crp, cod->buf, caead->aadlen + caead->len + + crypto_use_buf(crp, cod->buf, crp->crp_payload_start + caead->len + cse->hashsize); if (cod->obuf != NULL) crypto_use_output_buf(crp, cod->obuf, caead->len + Modified: head/sys/opencrypto/cryptodev.h ============================================================================== --- head/sys/opencrypto/cryptodev.h Mon Jun 22 23:13:14 2020 (r362516) +++ head/sys/opencrypto/cryptodev.h Mon Jun 22 23:20:43 2020 (r362517) @@ -384,6 +384,7 @@ struct crypto_session_params { int csp_flags; #define CSP_F_SEPARATE_OUTPUT 0x0001 /* Requests can use separate output */ +#define CSP_F_SEPARATE_AAD 0x0002 /* Requests can use separate AAD */ int csp_ivlen; /* IV length in bytes. */ @@ -479,6 +480,7 @@ struct cryptop { struct crypto_buffer crp_buf; struct crypto_buffer crp_obuf; + void *crp_aad; /* AAD buffer. */ int crp_aad_start; /* Location of AAD. */ int crp_aad_length; /* 0 => no AAD. */ int crp_iv_start; /* Location of IV. IV length is from Modified: head/sys/opencrypto/cryptosoft.c ============================================================================== --- head/sys/opencrypto/cryptosoft.c Mon Jun 22 23:13:14 2020 (r362516) +++ head/sys/opencrypto/cryptosoft.c Mon Jun 22 23:20:43 2020 (r362517) @@ -335,8 +335,11 @@ swcr_authcompute(struct swcr_session *ses, struct cryp bcopy(sw->sw_ictx, &ctx, axf->ctxsize); - err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, - axf->Update, &ctx); + if (crp->crp_aad != NULL) + err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); + else + err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, + axf->Update, &ctx); if (err) return err; @@ -503,7 +506,7 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp blksz = GMAC_BLOCK_LEN; KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", __func__)); - + swe = &ses->swcr_encdec; exf = swe->sw_exf; KASSERT(axf->blocksize == exf->native_blocksize, @@ -520,26 +523,39 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp axf->Reinit(&ctx, iv, ivlen); /* Supply MAC with AAD */ - crypto_cursor_init(&cc_in, &crp->crp_buf); - crypto_cursor_advance(&cc_in, crp->crp_aad_start); - for (resid = crp->crp_aad_length; resid >= blksz; resid -= len) { - len = crypto_cursor_seglen(&cc_in); - if (len >= blksz) { - inblk = crypto_cursor_segbase(&cc_in); - len = rounddown(MIN(len, resid), blksz); - crypto_cursor_advance(&cc_in, len); - } else { - len = blksz; - crypto_cursor_copydata(&cc_in, len, blk); - inblk = blk; + if (crp->crp_aad != NULL) { + len = rounddown(crp->crp_aad_length, blksz); + if (len != 0) + axf->Update(&ctx, crp->crp_aad, len); + if (crp->crp_aad_length != len) { + memset(blk, 0, blksz); + memcpy(blk, (char *)crp->crp_aad + len, + crp->crp_aad_length - len); + axf->Update(&ctx, blk, blksz); } - axf->Update(&ctx, inblk, len); + } else { + crypto_cursor_init(&cc_in, &crp->crp_buf); + crypto_cursor_advance(&cc_in, crp->crp_aad_start); + for (resid = crp->crp_aad_length; resid >= blksz; + resid -= len) { + len = crypto_cursor_seglen(&cc_in); + if (len >= blksz) { + inblk = crypto_cursor_segbase(&cc_in); + len = rounddown(MIN(len, resid), blksz); + crypto_cursor_advance(&cc_in, len); + } else { + len = blksz; + crypto_cursor_copydata(&cc_in, len, blk); + inblk = blk; + } + axf->Update(&ctx, inblk, len); + } + if (resid > 0) { + memset(blk, 0, blksz); + crypto_cursor_copydata(&cc_in, resid, blk); + axf->Update(&ctx, blk, blksz); + } } - if (resid > 0) { - memset(blk, 0, blksz); - crypto_cursor_copydata(&cc_in, resid, blk); - axf->Update(&ctx, blk, blksz); - } exf->reinit(swe->sw_kschedule, iv); @@ -607,7 +623,7 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp error = EBADMSG; goto out; } - + /* tag matches, decrypt data */ crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_advance(&cc_in, crp->crp_payload_start); @@ -675,8 +691,11 @@ swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryp ctx.aes_cbc_mac_ctx.cryptDataLength = 0; axf->Reinit(&ctx, iv, ivlen); - error = crypto_apply(crp, crp->crp_payload_start, - crp->crp_payload_length, axf->Update, &ctx); + if (crp->crp_aad != NULL) + error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); + else + error = crypto_apply(crp, crp->crp_payload_start, + crp->crp_payload_length, axf->Update, &ctx); if (error) return (error); @@ -724,7 +743,7 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp blksz = AES_BLOCK_LEN; KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", __func__)); - + swe = &ses->swcr_encdec; exf = swe->sw_exf; KASSERT(axf->blocksize == exf->native_blocksize, @@ -748,8 +767,11 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp axf->Reinit(&ctx, iv, ivlen); /* Supply MAC with AAD */ - error = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, - axf->Update, &ctx); + if (crp->crp_aad != NULL) + error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); + else + error = crypto_apply(crp, crp->crp_aad_start, + crp->crp_aad_length, axf->Update, &ctx); if (error) return (error); @@ -1013,7 +1035,7 @@ swcr_setup_auth(struct swcr_session *ses, swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); if (swa->sw_ictx == NULL) return (ENOBUFS); - + switch (csp->csp_auth_alg) { case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_224_HMAC: @@ -1236,7 +1258,8 @@ static int swcr_probesession(device_t dev, const struct crypto_session_params *csp) { - if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT)) != 0) + if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != + 0) return (EINVAL); switch (csp->csp_mode) { case CSP_MODE_COMPRESS: