From 5b750b9a6889dda96c02517133fd2237311ecbb4 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 23 Jun 2020 00:02:28 +0000 Subject: [PATCH] Store the AAD in a separate buffer for KTLS. For TLS 1.2 this permits reusing one of the existing iovecs without always having to duplicate both. While here, only duplicate the output iovec for TLS 1.3 if it will be used. Reviewed by: gallatin Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D25291 --- sys/opencrypto/ktls_ocf.c | 113 +++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 63 deletions(-) diff --git a/sys/opencrypto/ktls_ocf.c b/sys/opencrypto/ktls_ocf.c index b6981cca58a..a07d6c4dbfb 100644 --- a/sys/opencrypto/ktls_ocf.c +++ b/sys/opencrypto/ktls_ocf.c @@ -112,25 +112,24 @@ ktls_ocf_tls12_gcm_encrypt(struct ktls_session *tls, struct cryptop *crp; struct ocf_session *os; struct ocf_operation *oo; - struct iovec *iov, *out_iov; int i, error; uint16_t tls_comp_len; bool inplace; os = tls->cipher; - oo = malloc(sizeof(*oo) + (iovcnt + 2) * sizeof(*iov) * 2, M_KTLS_OCF, - M_WAITOK | M_ZERO); + oo = malloc(sizeof(*oo) + (iovcnt + 1) * sizeof(struct iovec), + M_KTLS_OCF, M_WAITOK | M_ZERO); oo->os = os; - iov = oo->iov; - out_iov = iov + iovcnt + 2; - uio.uio_iov = iov; + uio.uio_iov = iniov; + uio.uio_iovcnt = iovcnt; uio.uio_offset = 0; uio.uio_segflg = UIO_SYSSPACE; uio.uio_td = curthread; - out_uio.uio_iov = out_iov; + out_uio.uio_iov = outiov; + out_uio.uio_iovcnt = iovcnt; out_uio.uio_offset = 0; out_uio.uio_segflg = UIO_SYSSPACE; out_uio.uio_td = curthread; @@ -149,26 +148,18 @@ ktls_ocf_tls12_gcm_encrypt(struct ktls_session *tls, ad.tls_vmajor = hdr->tls_vmajor; ad.tls_vminor = hdr->tls_vminor; ad.tls_length = htons(tls_comp_len); - iov[0].iov_base = &ad; - iov[0].iov_len = sizeof(ad); - crp->crp_aad_start = 0; + crp->crp_aad = &ad; crp->crp_aad_length = sizeof(ad); - /* Copy iov's. */ - memcpy(iov + 1, iniov, iovcnt * sizeof(*iov)); - uio.uio_iovcnt = iovcnt + 1; - memcpy(out_iov, outiov, iovcnt * sizeof(*out_iov)); - out_uio.uio_iovcnt = iovcnt; - /* Compute payload length and determine if encryption is in place. */ inplace = true; - crp->crp_payload_start = sizeof(ad); + crp->crp_payload_start = 0; for (i = 0; i < iovcnt; i++) { if (iniov[i].iov_base != outiov[i].iov_base) inplace = false; crp->crp_payload_length += iniov[i].iov_len; } - uio.uio_resid = sizeof(ad) + crp->crp_payload_length; + uio.uio_resid = crp->crp_payload_length; out_uio.uio_resid = crp->crp_payload_length; if (inplace) @@ -176,8 +167,11 @@ ktls_ocf_tls12_gcm_encrypt(struct ktls_session *tls, else tag_uio = &out_uio; - tag_uio->uio_iov[tag_uio->uio_iovcnt].iov_base = trailer; - tag_uio->uio_iov[tag_uio->uio_iovcnt].iov_len = AES_GMAC_HASH_LEN; + /* Duplicate iovec and append vector for tag. */ + memcpy(oo->iov, tag_uio->uio_iov, iovcnt * sizeof(struct iovec)); + tag_uio->uio_iov = oo->iov; + tag_uio->uio_iov[iovcnt].iov_base = trailer; + tag_uio->uio_iov[iovcnt].iov_len = AES_GMAC_HASH_LEN; tag_uio->uio_iovcnt++; crp->crp_digest_start = tag_uio->uio_resid; tag_uio->uio_resid += AES_GMAC_HASH_LEN; @@ -238,23 +232,12 @@ ktls_ocf_tls13_gcm_encrypt(struct ktls_session *tls, os = tls->cipher; - oo = malloc(sizeof(*oo) + (iovcnt + 2) * sizeof(*iov) * 2, M_KTLS_OCF, + oo = malloc(sizeof(*oo) + (iovcnt + 1) * sizeof(*iov) * 2, M_KTLS_OCF, M_WAITOK | M_ZERO); oo->os = os; iov = oo->iov; - out_iov = iov + iovcnt + 2; - uio.uio_iov = iov; - uio.uio_offset = 0; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_td = curthread; - - out_uio.uio_iov = out_iov; - out_uio.uio_offset = 0; - out_uio.uio_segflg = UIO_SYSSPACE; - out_uio.uio_td = curthread; - crp = crypto_getreq(os->sid, M_WAITOK); /* Setup the nonce. */ @@ -266,52 +249,56 @@ ktls_ocf_tls13_gcm_encrypt(struct ktls_session *tls, ad.tls_vmajor = hdr->tls_vmajor; ad.tls_vminor = hdr->tls_vminor; ad.tls_length = hdr->tls_length; - iov[0].iov_base = &ad; - iov[0].iov_len = sizeof(ad); - crp->crp_aad_start = 0; + crp->crp_aad = &ad; crp->crp_aad_length = sizeof(ad); - /* Copy iov's. */ - memcpy(iov + 1, iniov, iovcnt * sizeof(*iov)); - uio.uio_iovcnt = iovcnt + 1; - memcpy(out_iov, outiov, iovcnt * sizeof(*out_iov)); - out_uio.uio_iovcnt = iovcnt; - /* Compute payload length and determine if encryption is in place. */ inplace = true; - crp->crp_payload_start = sizeof(ad); + crp->crp_payload_start = 0; for (i = 0; i < iovcnt; i++) { if (iniov[i].iov_base != outiov[i].iov_base) inplace = false; crp->crp_payload_length += iniov[i].iov_len; } - uio.uio_resid = sizeof(ad) + crp->crp_payload_length; - out_uio.uio_resid = crp->crp_payload_length; - /* - * Always include the full trailer as input to get the - * record_type even if only the first byte is used. - */ + /* Store the record type as the first byte of the trailer. */ trailer[0] = record_type; crp->crp_payload_length++; - iov[iovcnt + 1].iov_base = trailer; - iov[iovcnt + 1].iov_len = AES_GMAC_HASH_LEN + 1; - uio.uio_iovcnt++; - uio.uio_resid += AES_GMAC_HASH_LEN + 1; - if (inplace) { - crp->crp_digest_start = uio.uio_resid - AES_GMAC_HASH_LEN; - } else { - out_iov[iovcnt] = iov[iovcnt + 1]; - out_uio.uio_iovcnt++; - out_uio.uio_resid += AES_GMAC_HASH_LEN + 1; - crp->crp_digest_start = out_uio.uio_resid - AES_GMAC_HASH_LEN; + crp->crp_digest_start = crp->crp_payload_length; + + /* + * Duplicate the input iov to append the trailer. Always + * include the full trailer as input to get the record_type + * even if only the first byte is used. + */ + memcpy(iov, iniov, iovcnt * sizeof(*iov)); + iov[iovcnt].iov_base = trailer; + iov[iovcnt].iov_len = AES_GMAC_HASH_LEN + 1; + uio.uio_iov = iov; + uio.uio_iovcnt = iovcnt + 1; + uio.uio_offset = 0; + uio.uio_resid = crp->crp_payload_length + AES_GMAC_HASH_LEN; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_td = curthread; + crypto_use_uio(crp, &uio); + + if (!inplace) { + /* Duplicate the output iov to append the trailer. */ + memcpy(out_iov, outiov, iovcnt * sizeof(*out_iov)); + out_iov[iovcnt] = iov[iovcnt]; + + out_uio.uio_iov = out_iov; + out_uio.uio_iovcnt = iovcnt + 1; + out_uio.uio_offset = 0; + out_uio.uio_resid = crp->crp_payload_length + + AES_GMAC_HASH_LEN; + out_uio.uio_segflg = UIO_SYSSPACE; + out_uio.uio_td = curthread; + crypto_use_output_uio(crp, &out_uio); } crp->crp_op = CRYPTO_OP_ENCRYPT | CRYPTO_OP_COMPUTE_DIGEST; crp->crp_flags = CRYPTO_F_CBIMM | CRYPTO_F_IV_SEPARATE; - crypto_use_uio(crp, &uio); - if (!inplace) - crypto_use_output_uio(crp, &out_uio); crp->crp_opaque = oo; crp->crp_callback = ktls_ocf_callback; @@ -368,7 +355,7 @@ ktls_ocf_try(struct socket *so, struct ktls_session *tls) int error; memset(&csp, 0, sizeof(csp)); - csp.csp_flags |= CSP_F_SEPARATE_OUTPUT; + csp.csp_flags |= CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD; switch (tls->params.cipher_algorithm) { case CRYPTO_AES_NIST_GCM_16: -- 2.45.0