diff options
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/cesa/cesa.c | 599 | ||||
| -rw-r--r-- | sys/dev/cesa/cesa.h | 5 | ||||
| -rw-r--r-- | sys/dev/cxgbe/adapter.h | 2 | ||||
| -rw-r--r-- | sys/dev/cxgbe/crypto/t4_crypto.c | 1299 | ||||
| -rw-r--r-- | sys/dev/cxgbe/crypto/t4_keyctx.c | 40 | ||||
| -rw-r--r-- | sys/dev/cxgbe/tom/t4_tls.c | 4 | ||||
| -rw-r--r-- | sys/dev/glxsb/glxsb.c | 268 | ||||
| -rw-r--r-- | sys/dev/glxsb/glxsb.h | 6 | ||||
| -rw-r--r-- | sys/dev/glxsb/glxsb_hash.c | 100 | ||||
| -rw-r--r-- | sys/dev/hifn/hifn7751.c | 622 | ||||
| -rw-r--r-- | sys/dev/hifn/hifn7751var.h | 15 | ||||
| -rw-r--r-- | sys/dev/safe/safe.c | 915 | ||||
| -rw-r--r-- | sys/dev/safe/safevar.h | 12 | ||||
| -rw-r--r-- | sys/dev/sec/sec.c | 540 | ||||
| -rw-r--r-- | sys/dev/sec/sec.h | 18 | ||||
| -rw-r--r-- | sys/dev/ubsec/ubsec.c | 585 | ||||
| -rw-r--r-- | sys/dev/ubsec/ubsecvar.h | 10 |
17 files changed, 2191 insertions, 2849 deletions
diff --git a/sys/dev/cesa/cesa.c b/sys/dev/cesa/cesa.c index 6cbac049bb42..d4e056d2a09b 100644 --- a/sys/dev/cesa/cesa.c +++ b/sys/dev/cesa/cesa.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include <crypto/sha2/sha256.h> #include <crypto/rijndael/rijndael.h> #include <opencrypto/cryptodev.h> +#include <opencrypto/xform.h> #include "cryptodev_if.h" #include <arm/mv/mvreg.h> @@ -80,7 +81,10 @@ static int cesa_attach(device_t); static int cesa_attach_late(device_t); static int cesa_detach(device_t); static void cesa_intr(void *); -static int cesa_newsession(device_t, crypto_session_t, struct cryptoini *); +static int cesa_probesession(device_t, + const struct crypto_session_params *); +static int cesa_newsession(device_t, crypto_session_t, + const struct crypto_session_params *); static int cesa_process(device_t, struct cryptop *, int); static struct resource_spec cesa_res_spec[] = { @@ -97,6 +101,7 @@ static device_method_t cesa_methods[] = { DEVMETHOD(device_detach, cesa_detach), /* Crypto device methods */ + DEVMETHOD(cryptodev_probesession, cesa_probesession), DEVMETHOD(cryptodev_newsession, cesa_newsession), DEVMETHOD(cryptodev_process, cesa_process), @@ -417,78 +422,68 @@ cesa_append_packet(struct cesa_softc *sc, struct cesa_request *cr, return (0); } -static int +static void cesa_set_mkey(struct cesa_session *cs, int alg, const uint8_t *mkey, int mklen) { - uint8_t ipad[CESA_MAX_HMAC_BLOCK_LEN]; - uint8_t opad[CESA_MAX_HMAC_BLOCK_LEN]; - SHA1_CTX sha1ctx; - SHA256_CTX sha256ctx; - MD5_CTX md5ctx; + union authctx auth_ctx; uint32_t *hout; uint32_t *hin; int i; - memset(ipad, HMAC_IPAD_VAL, CESA_MAX_HMAC_BLOCK_LEN); - memset(opad, HMAC_OPAD_VAL, CESA_MAX_HMAC_BLOCK_LEN); - for (i = 0; i < mklen; i++) { - ipad[i] ^= mkey[i]; - opad[i] ^= mkey[i]; - } - hin = (uint32_t *)cs->cs_hiv_in; hout = (uint32_t *)cs->cs_hiv_out; switch (alg) { case CRYPTO_MD5_HMAC: - MD5Init(&md5ctx); - MD5Update(&md5ctx, ipad, MD5_BLOCK_LEN); - memcpy(hin, md5ctx.state, sizeof(md5ctx.state)); - MD5Init(&md5ctx); - MD5Update(&md5ctx, opad, MD5_BLOCK_LEN); - memcpy(hout, md5ctx.state, sizeof(md5ctx.state)); + hmac_init_ipad(&auth_hash_hmac_md5, mkey, mklen, &auth_ctx); + memcpy(hin, auth_ctx.md5ctx.state, + sizeof(auth_ctx.md5ctx.state)); + hmac_init_opad(&auth_hash_hmac_md5, mkey, mklen, &auth_ctx); + memcpy(hout, auth_ctx.md5ctx.state, + sizeof(auth_ctx.md5ctx.state)); break; case CRYPTO_SHA1_HMAC: - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, ipad, SHA1_BLOCK_LEN); - memcpy(hin, sha1ctx.h.b32, sizeof(sha1ctx.h.b32)); - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, opad, SHA1_BLOCK_LEN); - memcpy(hout, sha1ctx.h.b32, sizeof(sha1ctx.h.b32)); + hmac_init_ipad(&auth_hash_hmac_sha1, mkey, mklen, &auth_ctx); + memcpy(hin, auth_ctx.sha1ctx.h.b32, + sizeof(auth_ctx.sha1ctx.h.b32)); + hmac_init_opad(&auth_hash_hmac_sha1, mkey, mklen, &auth_ctx); + memcpy(hout, auth_ctx.sha1ctx.h.b32, + sizeof(auth_ctx.sha1ctx.h.b32)); break; case CRYPTO_SHA2_256_HMAC: - SHA256_Init(&sha256ctx); - SHA256_Update(&sha256ctx, ipad, SHA2_256_BLOCK_LEN); - memcpy(hin, sha256ctx.state, sizeof(sha256ctx.state)); - SHA256_Init(&sha256ctx); - SHA256_Update(&sha256ctx, opad, SHA2_256_BLOCK_LEN); - memcpy(hout, sha256ctx.state, sizeof(sha256ctx.state)); + hmac_init_ipad(&auth_hash_hmac_sha2_256, mkey, mklen, + &auth_ctx); + memcpy(hin, auth_ctx.sha256ctx.state, + sizeof(auth_ctx.sha256ctx.state)); + hmac_init_opad(&auth_hash_hmac_sha2_256, mkey, mklen, + &auth_ctx); + memcpy(hout, auth_ctx.sha256ctx.state, + sizeof(auth_ctx.sha256ctx.state)); break; default: - return (EINVAL); + panic("shouldn't get here"); } for (i = 0; i < CESA_MAX_HASH_LEN / sizeof(uint32_t); i++) { hin[i] = htobe32(hin[i]); hout[i] = htobe32(hout[i]); } - - return (0); } static int -cesa_prep_aes_key(struct cesa_session *cs) +cesa_prep_aes_key(struct cesa_session *cs, + const struct crypto_session_params *csp) { uint32_t ek[4 * (RIJNDAEL_MAXNR + 1)]; uint32_t *dkey; int i; - rijndaelKeySetupEnc(ek, cs->cs_key, cs->cs_klen * 8); + rijndaelKeySetupEnc(ek, cs->cs_key, csp->csp_cipher_klen * 8); cs->cs_config &= ~CESA_CSH_AES_KLEN_MASK; dkey = (uint32_t *)cs->cs_aes_dkey; - switch (cs->cs_klen) { + switch (csp->csp_cipher_klen) { case 16: cs->cs_config |= CESA_CSH_AES_KLEN_128; for (i = 0; i < 4; i++) @@ -515,22 +510,6 @@ cesa_prep_aes_key(struct cesa_session *cs) return (0); } -static int -cesa_is_hash(int alg) -{ - - switch (alg) { - case CRYPTO_MD5: - case CRYPTO_MD5_HMAC: - case CRYPTO_SHA1: - case CRYPTO_SHA1_HMAC: - case CRYPTO_SHA2_256_HMAC: - return (1); - default: - return (0); - } -} - static void cesa_start_packet(struct cesa_packet *cp, unsigned int size) { @@ -584,6 +563,7 @@ cesa_create_chain_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) unsigned int skip, len; struct cesa_sa_desc *csd; struct cesa_request *cr; + struct cryptop *crp; struct cesa_softc *sc; struct cesa_packet cp; bus_dma_segment_t seg; @@ -593,73 +573,107 @@ cesa_create_chain_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) cci = arg; sc = cci->cci_sc; cr = cci->cci_cr; + crp = cr->cr_crp; if (error) { cci->cci_error = error; return; } - elen = cci->cci_enc ? cci->cci_enc->crd_len : 0; - eskip = cci->cci_enc ? cci->cci_enc->crd_skip : 0; - mlen = cci->cci_mac ? cci->cci_mac->crd_len : 0; - mskip = cci->cci_mac ? cci->cci_mac->crd_skip : 0; - - if (elen && mlen && - ((eskip > mskip && ((eskip - mskip) & (cr->cr_cs->cs_ivlen - 1))) || - (mskip > eskip && ((mskip - eskip) & (cr->cr_cs->cs_mblen - 1))) || - (eskip > (mskip + mlen)) || (mskip > (eskip + elen)))) { + /* + * Only do a combined op if the AAD is adjacent to the payload + * and the AAD length is a multiple of the IV length. The + * checks against 'config' are to avoid recursing when the + * logic below invokes separate operations. + */ + config = cci->cci_config; + if (((config & CESA_CSHD_OP_MASK) == CESA_CSHD_MAC_AND_ENC || + (config & CESA_CSHD_OP_MASK) == CESA_CSHD_ENC_AND_MAC) && + crp->crp_aad_length != 0 && + (crp->crp_aad_length & (cr->cr_cs->cs_ivlen - 1)) != 0) { /* * Data alignment in the request does not meet CESA requiremnts * for combined encryption/decryption and hashing. We have to * split the request to separate operations and process them * one by one. */ - config = cci->cci_config; if ((config & CESA_CSHD_OP_MASK) == CESA_CSHD_MAC_AND_ENC) { config &= ~CESA_CSHD_OP_MASK; cci->cci_config = config | CESA_CSHD_MAC; - cci->cci_enc = NULL; - cci->cci_mac = cr->cr_mac; - cesa_create_chain_cb(cci, segs, nseg, cci->cci_error); + cesa_create_chain_cb(cci, segs, nseg, 0); cci->cci_config = config | CESA_CSHD_ENC; - cci->cci_enc = cr->cr_enc; - cci->cci_mac = NULL; - cesa_create_chain_cb(cci, segs, nseg, cci->cci_error); + cesa_create_chain_cb(cci, segs, nseg, 0); } else { config &= ~CESA_CSHD_OP_MASK; cci->cci_config = config | CESA_CSHD_ENC; - cci->cci_enc = cr->cr_enc; - cci->cci_mac = NULL; - cesa_create_chain_cb(cci, segs, nseg, cci->cci_error); + cesa_create_chain_cb(cci, segs, nseg, 0); cci->cci_config = config | CESA_CSHD_MAC; - cci->cci_enc = NULL; - cci->cci_mac = cr->cr_mac; - cesa_create_chain_cb(cci, segs, nseg, cci->cci_error); + cesa_create_chain_cb(cci, segs, nseg, 0); } return; } + mskip = mlen = eskip = elen = 0; + + if (crp->crp_aad_length == 0) { + skip = crp->crp_payload_start; + len = crp->crp_payload_length; + switch (config & CESA_CSHD_OP_MASK) { + case CESA_CSHD_ENC: + eskip = skip; + elen = len; + break; + case CESA_CSHD_MAC: + mskip = skip; + mlen = len; + break; + default: + eskip = skip; + elen = len; + mskip = skip; + mlen = len; + break; + } + } else { + /* + * For an encryption-only separate request, only + * process the payload. For combined requests and + * hash-only requests, process the entire region. + */ + switch (config & CESA_CSHD_OP_MASK) { + case CESA_CSHD_ENC: + skip = crp->crp_payload_start; + len = crp->crp_payload_length; + eskip = skip; + elen = len; + break; + case CESA_CSHD_MAC: + skip = crp->crp_aad_start; + len = crp->crp_aad_length + crp->crp_payload_length; + mskip = skip; + mlen = len; + break; + default: + skip = crp->crp_aad_start; + len = crp->crp_aad_length + crp->crp_payload_length; + mskip = skip; + mlen = len; + eskip = crp->crp_payload_start; + elen = crp->crp_payload_length; + break; + } + } + tmlen = mlen; fragmented = 0; mpsize = CESA_MAX_PACKET_SIZE; mpsize &= ~((cr->cr_cs->cs_ivlen - 1) | (cr->cr_cs->cs_mblen - 1)); - if (elen && mlen) { - skip = MIN(eskip, mskip); - len = MAX(elen + eskip, mlen + mskip) - skip; - } else if (elen) { - skip = eskip; - len = elen; - } else { - skip = mskip; - len = mlen; - } - /* Start first packet in chain */ cesa_start_packet(&cp, MIN(mpsize, len)); @@ -777,16 +791,9 @@ cesa_create_chain_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) } } -static void -cesa_create_chain_cb2(void *arg, bus_dma_segment_t *segs, int nseg, - bus_size_t size, int error) -{ - - cesa_create_chain_cb(arg, segs, nseg, error); -} - static int -cesa_create_chain(struct cesa_softc *sc, struct cesa_request *cr) +cesa_create_chain(struct cesa_softc *sc, + const struct crypto_session_params *csp, struct cesa_request *cr) { struct cesa_chain_info cci; struct cesa_tdma_desc *ctd; @@ -797,17 +804,17 @@ cesa_create_chain(struct cesa_softc *sc, struct cesa_request *cr) CESA_LOCK_ASSERT(sc, sessions); /* Create request metadata */ - if (cr->cr_enc) { - if (cr->cr_enc->crd_alg == CRYPTO_AES_CBC && - (cr->cr_enc->crd_flags & CRD_F_ENCRYPT) == 0) + if (csp->csp_cipher_klen != 0) { + if (csp->csp_cipher_alg == CRYPTO_AES_CBC && + !CRYPTO_OP_IS_ENCRYPT(cr->cr_crp->crp_op)) memcpy(cr->cr_csd->csd_key, cr->cr_cs->cs_aes_dkey, - cr->cr_cs->cs_klen); + csp->csp_cipher_klen); else memcpy(cr->cr_csd->csd_key, cr->cr_cs->cs_key, - cr->cr_cs->cs_klen); + csp->csp_cipher_klen); } - if (cr->cr_mac) { + if (csp->csp_auth_klen != 0) { memcpy(cr->cr_csd->csd_hiv_in, cr->cr_cs->cs_hiv_in, CESA_MAX_HASH_LEN); memcpy(cr->cr_csd->csd_hiv_out, cr->cr_cs->cs_hiv_out, @@ -823,37 +830,30 @@ cesa_create_chain(struct cesa_softc *sc, struct cesa_request *cr) /* Prepare SA configuration */ config = cr->cr_cs->cs_config; - if (cr->cr_enc && (cr->cr_enc->crd_flags & CRD_F_ENCRYPT) == 0) + if (csp->csp_cipher_alg != 0 && + !CRYPTO_OP_IS_ENCRYPT(cr->cr_crp->crp_op)) config |= CESA_CSHD_DECRYPT; - if (cr->cr_enc && !cr->cr_mac) + switch (csp->csp_mode) { + case CSP_MODE_CIPHER: config |= CESA_CSHD_ENC; - if (!cr->cr_enc && cr->cr_mac) + break; + case CSP_MODE_DIGEST: config |= CESA_CSHD_MAC; - if (cr->cr_enc && cr->cr_mac) + break; + case CSP_MODE_ETA: config |= (config & CESA_CSHD_DECRYPT) ? CESA_CSHD_MAC_AND_ENC : CESA_CSHD_ENC_AND_MAC; + break; + } /* Create data packets */ cci.cci_sc = sc; cci.cci_cr = cr; - cci.cci_enc = cr->cr_enc; - cci.cci_mac = cr->cr_mac; cci.cci_config = config; cci.cci_error = 0; - if (cr->cr_crp->crp_flags & CRYPTO_F_IOV) - error = bus_dmamap_load_uio(sc->sc_data_dtag, - cr->cr_dmap, (struct uio *)cr->cr_crp->crp_buf, - cesa_create_chain_cb2, &cci, BUS_DMA_NOWAIT); - else if (cr->cr_crp->crp_flags & CRYPTO_F_IMBUF) - error = bus_dmamap_load_mbuf(sc->sc_data_dtag, - cr->cr_dmap, (struct mbuf *)cr->cr_crp->crp_buf, - cesa_create_chain_cb2, &cci, BUS_DMA_NOWAIT); - else - error = bus_dmamap_load(sc->sc_data_dtag, - cr->cr_dmap, cr->cr_crp->crp_buf, - cr->cr_crp->crp_ilen, cesa_create_chain_cb, &cci, - BUS_DMA_NOWAIT); + error = bus_dmamap_load_crp(sc->sc_data_dtag, cr->cr_dmap, cr->cr_crp, + cesa_create_chain_cb, &cci, BUS_DMA_NOWAIT); if (!error) cr->cr_dmap_loaded = 1; @@ -1385,18 +1385,6 @@ cesa_attach_late(device_t dev) goto err8; } - crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); - if (sc->sc_soc_id == MV_DEV_88F6828 || - sc->sc_soc_id == MV_DEV_88F6820 || - sc->sc_soc_id == MV_DEV_88F6810) - crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0); - return (0); err8: for (i = 0; i < CESA_REQUESTS; i++) @@ -1487,6 +1475,7 @@ cesa_intr(void *arg) struct cesa_request *cr, *tmp; struct cesa_softc *sc; uint32_t ecr, icr; + uint8_t hash[HASH_MAX_LEN]; int blocked; sc = arg; @@ -1547,11 +1536,19 @@ cesa_intr(void *arg) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); cr->cr_crp->crp_etype = sc->sc_error; - if (cr->cr_mac) - crypto_copyback(cr->cr_crp->crp_flags, - cr->cr_crp->crp_buf, cr->cr_mac->crd_inject, - cr->cr_cs->cs_hlen, cr->cr_csd->csd_hash); - + if (cr->cr_cs->cs_hlen != 0 && cr->cr_crp->crp_etype == 0) { + if (cr->cr_crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(cr->cr_crp, + cr->cr_crp->crp_digest_start, + cr->cr_cs->cs_hlen, hash); + if (timingsafe_bcmp(hash, cr->cr_csd->csd_hash, + cr->cr_cs->cs_hlen) != 0) + cr->cr_crp->crp_etype = EBADMSG; + } else + crypto_copyback(cr->cr_crp, + cr->cr_crp->crp_digest_start, + cr->cr_cs->cs_hlen, cr->cr_csd->csd_hash); + } crypto_done(cr->cr_crp); cesa_free_request(sc, cr); } @@ -1571,42 +1568,98 @@ cesa_intr(void *arg) crypto_unblock(sc->sc_cid, blocked); } -static int -cesa_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +static bool +cesa_cipher_supported(const struct crypto_session_params *csp) { - struct cesa_session *cs; - struct cesa_softc *sc; - struct cryptoini *enc; - struct cryptoini *mac; - int error; - - sc = device_get_softc(dev); - enc = NULL; - mac = NULL; - error = 0; - /* Check and parse input */ - if (cesa_is_hash(cri->cri_alg)) - mac = cri; - else - enc = cri; + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + if (csp->csp_ivlen != AES_BLOCK_LEN) + return (false); + break; + case CRYPTO_DES_CBC: + if (csp->csp_ivlen != DES_BLOCK_LEN) + return (false); + break; + case CRYPTO_3DES_CBC: + if (csp->csp_ivlen != DES3_BLOCK_LEN) + return (false); + break; + default: + return (false); + } - cri = cri->cri_next; + if (csp->csp_cipher_klen > CESA_MAX_KEY_LEN) + return (false); - if (cri) { - if (!enc && !cesa_is_hash(cri->cri_alg)) - enc = cri; + return (true); +} - if (!mac && cesa_is_hash(cri->cri_alg)) - mac = cri; +static bool +cesa_auth_supported(struct cesa_softc *sc, + const struct crypto_session_params *csp) +{ - if (cri->cri_next || !(enc && mac)) + switch (csp->csp_auth_alg) { + case CRYPTO_SHA2_256_HMAC: + if (!(sc->sc_soc_id == MV_DEV_88F6828 || + sc->sc_soc_id == MV_DEV_88F6820 || + sc->sc_soc_id == MV_DEV_88F6810)) + return (false); + /* FALLTHROUGH */ + case CRYPTO_MD5: + case CRYPTO_MD5_HMAC: + case CRYPTO_SHA1: + case CRYPTO_SHA1_HMAC: + break; + default: + return (false); + } + + if (csp->csp_auth_klen > CESA_MAX_MKEY_LEN) + return (false); + + return (true); +} + +static int +cesa_probesession(device_t dev, const struct crypto_session_params *csp) +{ + struct cesa_softc *sc; + + sc = device_get_softc(dev); + if (csp->csp_flags != 0) + return (EINVAL); + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!cesa_auth_supported(sc, csp)) return (EINVAL); + break; + case CSP_MODE_CIPHER: + if (!cesa_cipher_supported(csp)) + return (EINVAL); + break; + case CSP_MODE_ETA: + if (!cesa_auth_supported(sc, csp) || + !cesa_cipher_supported(csp)) + return (EINVAL); + break; + default: + return (EINVAL); } + return (CRYPTODEV_PROBE_HARDWARE); +} - if ((enc && (enc->cri_klen / 8) > CESA_MAX_KEY_LEN) || - (mac && (mac->cri_klen / 8) > CESA_MAX_MKEY_LEN)) - return (E2BIG); +static int +cesa_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct cesa_session *cs; + struct cesa_softc *sc; + int error; + + sc = device_get_softc(dev); + error = 0; /* Allocate session */ cs = crypto_get_driver_session(cses); @@ -1616,106 +1669,89 @@ cesa_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) cs->cs_ivlen = 1; cs->cs_mblen = 1; - if (enc) { - switch (enc->cri_alg) { - case CRYPTO_AES_CBC: - cs->cs_config |= CESA_CSHD_AES | CESA_CSHD_CBC; - cs->cs_ivlen = AES_BLOCK_LEN; - break; - case CRYPTO_DES_CBC: - cs->cs_config |= CESA_CSHD_DES | CESA_CSHD_CBC; - cs->cs_ivlen = DES_BLOCK_LEN; - break; - case CRYPTO_3DES_CBC: - cs->cs_config |= CESA_CSHD_3DES | CESA_CSHD_3DES_EDE | - CESA_CSHD_CBC; - cs->cs_ivlen = DES3_BLOCK_LEN; - break; - default: - error = EINVAL; - break; - } + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + cs->cs_config |= CESA_CSHD_AES | CESA_CSHD_CBC; + cs->cs_ivlen = AES_BLOCK_LEN; + break; + case CRYPTO_DES_CBC: + cs->cs_config |= CESA_CSHD_DES | CESA_CSHD_CBC; + cs->cs_ivlen = DES_BLOCK_LEN; + break; + case CRYPTO_3DES_CBC: + cs->cs_config |= CESA_CSHD_3DES | CESA_CSHD_3DES_EDE | + CESA_CSHD_CBC; + cs->cs_ivlen = DES3_BLOCK_LEN; + break; } - if (!error && mac) { - switch (mac->cri_alg) { - case CRYPTO_MD5: - cs->cs_mblen = 1; - cs->cs_hlen = (mac->cri_mlen == 0) ? MD5_HASH_LEN : - mac->cri_mlen; - cs->cs_config |= CESA_CSHD_MD5; - break; - case CRYPTO_MD5_HMAC: - cs->cs_mblen = MD5_BLOCK_LEN; - cs->cs_hlen = (mac->cri_mlen == 0) ? MD5_HASH_LEN : - mac->cri_mlen; - cs->cs_config |= CESA_CSHD_MD5_HMAC; - if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN) - cs->cs_config |= CESA_CSHD_96_BIT_HMAC; - break; - case CRYPTO_SHA1: - cs->cs_mblen = 1; - cs->cs_hlen = (mac->cri_mlen == 0) ? SHA1_HASH_LEN : - mac->cri_mlen; - cs->cs_config |= CESA_CSHD_SHA1; - break; - case CRYPTO_SHA1_HMAC: - cs->cs_mblen = SHA1_BLOCK_LEN; - cs->cs_hlen = (mac->cri_mlen == 0) ? SHA1_HASH_LEN : - mac->cri_mlen; - cs->cs_config |= CESA_CSHD_SHA1_HMAC; - if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN) - cs->cs_config |= CESA_CSHD_96_BIT_HMAC; - break; - case CRYPTO_SHA2_256_HMAC: - cs->cs_mblen = SHA2_256_BLOCK_LEN; - cs->cs_hlen = (mac->cri_mlen == 0) ? SHA2_256_HASH_LEN : - mac->cri_mlen; - cs->cs_config |= CESA_CSHD_SHA2_256_HMAC; - break; - default: - error = EINVAL; - break; - } + switch (csp->csp_auth_alg) { + case CRYPTO_MD5: + cs->cs_mblen = 1; + cs->cs_hlen = (csp->csp_auth_mlen == 0) ? MD5_HASH_LEN : + csp->csp_auth_mlen; + cs->cs_config |= CESA_CSHD_MD5; + break; + case CRYPTO_MD5_HMAC: + cs->cs_mblen = MD5_BLOCK_LEN; + cs->cs_hlen = (csp->csp_auth_mlen == 0) ? MD5_HASH_LEN : + csp->csp_auth_mlen; + cs->cs_config |= CESA_CSHD_MD5_HMAC; + if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN) + cs->cs_config |= CESA_CSHD_96_BIT_HMAC; + break; + case CRYPTO_SHA1: + cs->cs_mblen = 1; + cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA1_HASH_LEN : + csp->csp_auth_mlen; + cs->cs_config |= CESA_CSHD_SHA1; + break; + case CRYPTO_SHA1_HMAC: + cs->cs_mblen = SHA1_BLOCK_LEN; + cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA1_HASH_LEN : + csp->csp_auth_mlen; + cs->cs_config |= CESA_CSHD_SHA1_HMAC; + if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN) + cs->cs_config |= CESA_CSHD_96_BIT_HMAC; + break; + case CRYPTO_SHA2_256_HMAC: + cs->cs_mblen = SHA2_256_BLOCK_LEN; + cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA2_256_HASH_LEN : + csp->csp_auth_mlen; + cs->cs_config |= CESA_CSHD_SHA2_256_HMAC; + break; } /* Save cipher key */ - if (!error && enc && enc->cri_key) { - cs->cs_klen = enc->cri_klen / 8; - memcpy(cs->cs_key, enc->cri_key, cs->cs_klen); - if (enc->cri_alg == CRYPTO_AES_CBC) - error = cesa_prep_aes_key(cs); + if (csp->csp_cipher_key != NULL) { + memcpy(cs->cs_key, csp->csp_cipher_key, + csp->csp_cipher_klen); + if (csp->csp_cipher_alg == CRYPTO_AES_CBC) + error = cesa_prep_aes_key(cs, csp); } /* Save digest key */ - if (!error && mac && mac->cri_key) - error = cesa_set_mkey(cs, mac->cri_alg, mac->cri_key, - mac->cri_klen / 8); + if (csp->csp_auth_key != NULL) + cesa_set_mkey(cs, csp->csp_auth_alg, csp->csp_auth_key, + csp->csp_auth_klen); - if (error) - return (error); - - return (0); + return (error); } static int cesa_process(device_t dev, struct cryptop *crp, int hint) { + const struct crypto_session_params *csp; struct cesa_request *cr; struct cesa_session *cs; - struct cryptodesc *crd; - struct cryptodesc *enc; - struct cryptodesc *mac; struct cesa_softc *sc; int error; sc = device_get_softc(dev); - crd = crp->crp_desc; - enc = NULL; - mac = NULL; error = 0; cs = crypto_get_driver_session(crp->crp_session); + csp = crypto_get_params(crp->crp_session); /* Check and parse input */ if (crp->crp_ilen > CESA_MAX_REQUEST_SIZE) { @@ -1724,25 +1760,16 @@ cesa_process(device_t dev, struct cryptop *crp, int hint) return (0); } - if (cesa_is_hash(crd->crd_alg)) - mac = crd; - else - enc = crd; - - crd = crd->crd_next; - - if (crd) { - if (!enc && !cesa_is_hash(crd->crd_alg)) - enc = crd; - - if (!mac && cesa_is_hash(crd->crd_alg)) - mac = crd; - - if (crd->crd_next || !(enc && mac)) { - crp->crp_etype = EINVAL; - crypto_done(crp); - return (0); - } + /* + * For requests with AAD, only requests where the AAD is + * immediately adjacent to the payload are supported. + */ + if (crp->crp_aad_length != 0 && + (crp->crp_aad_start + crp->crp_aad_length) != + crp->crp_payload_start) { + crp->crp_etype = EINVAL; + crypto_done(crp); + return (0); } /* @@ -1759,51 +1786,37 @@ cesa_process(device_t dev, struct cryptop *crp, int hint) /* Prepare request */ cr->cr_crp = crp; - cr->cr_enc = enc; - cr->cr_mac = mac; cr->cr_cs = cs; CESA_LOCK(sc, sessions); cesa_sync_desc(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - if (enc && enc->crd_flags & CRD_F_ENCRYPT) { - if (enc->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(cr->cr_csd->csd_iv, enc->crd_iv, cs->cs_ivlen); + if (csp->csp_cipher_alg != 0) { + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(cr->cr_csd->csd_iv, csp->csp_ivlen, 0); + crypto_copyback(crp, crp->crp_iv_start, csp->csp_ivlen, + cr->cr_csd->csd_iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(cr->cr_csd->csd_iv, crp->crp_iv, csp->csp_ivlen); else - arc4rand(cr->cr_csd->csd_iv, cs->cs_ivlen, 0); - - if ((enc->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - enc->crd_inject, cs->cs_ivlen, cr->cr_csd->csd_iv); - } else if (enc) { - if (enc->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(cr->cr_csd->csd_iv, enc->crd_iv, cs->cs_ivlen); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - enc->crd_inject, cs->cs_ivlen, cr->cr_csd->csd_iv); + crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, + cr->cr_csd->csd_iv); } - if (enc && enc->crd_flags & CRD_F_KEY_EXPLICIT) { - if ((enc->crd_klen / 8) <= CESA_MAX_KEY_LEN) { - cs->cs_klen = enc->crd_klen / 8; - memcpy(cs->cs_key, enc->crd_key, cs->cs_klen); - if (enc->crd_alg == CRYPTO_AES_CBC) - error = cesa_prep_aes_key(cs); - } else - error = E2BIG; + if (crp->crp_cipher_key != NULL) { + memcpy(cs->cs_key, crp->crp_cipher_key, + csp->csp_cipher_klen); + if (csp->csp_cipher_alg == CRYPTO_AES_CBC) + error = cesa_prep_aes_key(cs, csp); } - if (!error && mac && mac->crd_flags & CRD_F_KEY_EXPLICIT) { - if ((mac->crd_klen / 8) <= CESA_MAX_MKEY_LEN) - error = cesa_set_mkey(cs, mac->crd_alg, mac->crd_key, - mac->crd_klen / 8); - else - error = E2BIG; - } + if (!error && crp->crp_auth_key != NULL) + cesa_set_mkey(cs, csp->csp_auth_alg, crp->crp_auth_key, + csp->csp_auth_klen); /* Convert request to chain of TDMA and SA descriptors */ if (!error) - error = cesa_create_chain(sc, cr); + error = cesa_create_chain(sc, csp, cr); cesa_sync_desc(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); CESA_UNLOCK(sc, sessions); diff --git a/sys/dev/cesa/cesa.h b/sys/dev/cesa/cesa.h index 9fa35b89b18f..449f4ecce5b2 100644 --- a/sys/dev/cesa/cesa.h +++ b/sys/dev/cesa/cesa.h @@ -194,7 +194,6 @@ struct cesa_sa_desc { struct cesa_session { uint32_t cs_config; - unsigned int cs_klen; unsigned int cs_ivlen; unsigned int cs_hlen; unsigned int cs_mblen; @@ -208,8 +207,6 @@ struct cesa_request { struct cesa_sa_data *cr_csd; bus_addr_t cr_csd_paddr; struct cryptop *cr_crp; - struct cryptodesc *cr_enc; - struct cryptodesc *cr_mac; struct cesa_session *cr_cs; bus_dmamap_t cr_dmap; int cr_dmap_loaded; @@ -272,8 +269,6 @@ struct cesa_softc { struct cesa_chain_info { struct cesa_softc *cci_sc; struct cesa_request *cci_cr; - struct cryptodesc *cci_enc; - struct cryptodesc *cci_mac; uint32_t cci_config; int cci_error; }; diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index fd5487b01179..1f3ccedca9b3 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -1204,7 +1204,7 @@ union authctx; void t4_aes_getdeckey(void *, const void *, unsigned int); void t4_copy_partial_hash(int, union authctx *, void *); void t4_init_gmac_hash(const char *, int, char *); -void t4_init_hmac_digest(struct auth_hash *, u_int, char *, int, char *); +void t4_init_hmac_digest(struct auth_hash *, u_int, const char *, int, char *); #ifdef DEV_NETMAP /* t4_netmap.c */ diff --git a/sys/dev/cxgbe/crypto/t4_crypto.c b/sys/dev/cxgbe/crypto/t4_crypto.c index 5b924125b6e4..5ab8048ece4d 100644 --- a/sys/dev/cxgbe/crypto/t4_crypto.c +++ b/sys/dev/cxgbe/crypto/t4_crypto.c @@ -165,7 +165,7 @@ struct ccr_session_blkcipher { struct ccr_session { bool active; int pending; - enum { HASH, HMAC, BLKCIPHER, AUTHENC, GCM, CCM } mode; + enum { HASH, HMAC, BLKCIPHER, ETA, GCM, CCM } mode; union { struct ccr_session_hmac hmac; struct ccr_session_gmac gmac; @@ -208,8 +208,8 @@ struct ccr_softc { uint64_t stats_blkcipher_decrypt; uint64_t stats_hash; uint64_t stats_hmac; - uint64_t stats_authenc_encrypt; - uint64_t stats_authenc_decrypt; + uint64_t stats_eta_encrypt; + uint64_t stats_eta_decrypt; uint64_t stats_gcm_encrypt; uint64_t stats_gcm_decrypt; uint64_t stats_ccm_encrypt; @@ -230,9 +230,9 @@ struct ccr_softc { * Non-hash-only requests require a PHYS_DSGL that describes the * location to store the results of the encryption or decryption * operation. This SGL uses a different format (PHYS_DSGL) and should - * exclude the crd_skip bytes at the start of the data as well as - * any AAD or IV. For authenticated encryption requests it should - * cover include the destination of the hash or tag. + * exclude the skip bytes at the start of the data as well as any AAD + * or IV. For authenticated encryption requests it should include the + * destination of the hash or tag. * * The input payload may either be supplied inline as immediate data, * or via a standard ULP_TX SGL. This SGL should include AAD, @@ -251,12 +251,19 @@ ccr_populate_sglist(struct sglist *sg, struct cryptop *crp) int error; sglist_reset(sg); - if (crp->crp_flags & CRYPTO_F_IMBUF) - error = sglist_append_mbuf(sg, (struct mbuf *)crp->crp_buf); - else if (crp->crp_flags & CRYPTO_F_IOV) - error = sglist_append_uio(sg, (struct uio *)crp->crp_buf); - else + switch (crp->crp_buf_type) { + case CRYPTO_BUF_MBUF: + error = sglist_append_mbuf(sg, crp->crp_mbuf); + break; + case CRYPTO_BUF_UIO: + error = sglist_append_uio(sg, crp->crp_uio); + break; + case CRYPTO_BUF_CONTIG: error = sglist_append(sg, crp->crp_buf, crp->crp_ilen); + break; + default: + error = EINVAL; + } return (error); } @@ -436,16 +443,13 @@ ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) struct chcr_wr *crwr; struct wrqe *wr; struct auth_hash *axf; - struct cryptodesc *crd; char *dst; u_int hash_size_in_response, kctx_flits, kctx_len, transhdr_len, wr_len; u_int hmac_ctrl, imm_len, iopad_size; int error, sgl_nsegs, sgl_len, use_opad; - crd = crp->crp_desc; - /* Reject requests with too large of an input buffer. */ - if (crd->crd_len > MAX_REQUEST_SIZE) + if (crp->crp_payload_length > MAX_REQUEST_SIZE) return (EFBIG); axf = s->hmac.auth_hash; @@ -471,19 +475,19 @@ ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) hash_size_in_response = axf->hashsize; transhdr_len = HASH_TRANSHDR_SIZE(kctx_len); - if (crd->crd_len == 0) { + if (crp->crp_payload_length == 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; + } else if (ccr_use_imm_data(transhdr_len, crp->crp_payload_length)) { + imm_len = crp->crp_payload_length; sgl_nsegs = 0; sgl_len = 0; } else { imm_len = 0; sglist_reset(sc->sg_ulptx); error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crd->crd_skip, crd->crd_len); + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); sgl_nsegs = sc->sg_ulptx->sg_nseg; @@ -512,8 +516,8 @@ ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) 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 == 0 ? axf->blocksize : - crd->crd_len); + crwr->sec_cpl.pldlen = htobe32(crp->crp_payload_length == 0 ? + axf->blocksize : crp->crp_payload_length); crwr->sec_cpl.cipherstop_lo_authinsert = htobe32( V_CPL_TX_SEC_PDU_AUTHSTART(1) | V_CPL_TX_SEC_PDU_AUTHSTOP(0)); @@ -527,7 +531,8 @@ ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) V_SCMD_HMAC_CTRL(hmac_ctrl)); crwr->sec_cpl.ivgen_hdrlen = htobe32( V_SCMD_LAST_FRAG(0) | - V_SCMD_MORE_FRAGS(crd->crd_len == 0 ? 1 : 0) | V_SCMD_MAC_ONLY(1)); + V_SCMD_MORE_FRAGS(crp->crp_payload_length == 0 ? 1 : 0) | + V_SCMD_MAC_ONLY(1)); memcpy(crwr->key_ctx.key, s->hmac.pads, kctx_len); @@ -540,14 +545,14 @@ ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) V_KEY_CONTEXT_MK_SIZE(s->hmac.mk_size) | V_KEY_CONTEXT_VALID(1)); dst = (char *)(crwr + 1) + kctx_len + DUMMY_BYTES; - if (crd->crd_len == 0) { + if (crp->crp_payload_length == 0) { dst[0] = 0x80; if (s->mode == HMAC) *(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); + crypto_copydata(crp, crp->crp_payload_start, + crp->crp_payload_length, dst); else ccr_write_ulptx_sgl(sc, dst, sgl_nsegs); @@ -561,15 +566,20 @@ static int ccr_hash_done(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error) { - struct cryptodesc *crd; + uint8_t hash[HASH_MAX_LEN]; - crd = crp->crp_desc; - if (error == 0) { - crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, - s->hmac.hash_len, (c_caddr_t)(cpl + 1)); - } + if (error) + return (error); - return (error); + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, crp->crp_digest_start, s->hmac.hash_len, + hash); + if (timingsafe_bcmp((cpl + 1), hash, s->hmac.hash_len) != 0) + return (EBADMSG); + } else + crypto_copyback(crp, crp->crp_digest_start, s->hmac.hash_len, + (cpl + 1)); + return (0); } static int @@ -578,34 +588,31 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) char iv[CHCR_MAX_CRYPTO_IV_LEN]; struct chcr_wr *crwr; struct wrqe *wr; - struct cryptodesc *crd; char *dst; u_int kctx_len, key_half, op_type, transhdr_len, wr_len; - u_int imm_len; + u_int imm_len, iv_len; int dsgl_nsegs, dsgl_len; int sgl_nsegs, sgl_len; int error; - crd = crp->crp_desc; - - if (s->blkcipher.key_len == 0 || crd->crd_len == 0) + if (s->blkcipher.key_len == 0 || crp->crp_payload_length == 0) return (EINVAL); - if (crd->crd_alg == CRYPTO_AES_CBC && - (crd->crd_len % AES_BLOCK_LEN) != 0) + if (s->blkcipher.cipher_mode == SCMD_CIPH_MODE_AES_CBC && + (crp->crp_payload_length % AES_BLOCK_LEN) != 0) return (EINVAL); /* Reject requests with too large of an input buffer. */ - if (crd->crd_len > MAX_REQUEST_SIZE) + if (crp->crp_payload_length > MAX_REQUEST_SIZE) return (EFBIG); - if (crd->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) op_type = CHCR_ENCRYPT_OP; else op_type = CHCR_DECRYPT_OP; sglist_reset(sc->sg_dsgl); - error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crd->crd_skip, - crd->crd_len); + error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); dsgl_nsegs = ccr_count_sgl(sc->sg_dsgl, DSGL_SGE_MAXLEN); @@ -617,23 +624,28 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) kctx_len = roundup2(s->blkcipher.key_len, 16); transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dsgl_len); - if (ccr_use_imm_data(transhdr_len, crd->crd_len + - s->blkcipher.iv_len)) { - imm_len = crd->crd_len; + /* For AES-XTS we send a 16-byte IV in the work request. */ + if (s->blkcipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS) + iv_len = AES_BLOCK_LEN; + else + iv_len = s->blkcipher.iv_len; + + if (ccr_use_imm_data(transhdr_len, crp->crp_payload_length + iv_len)) { + imm_len = crp->crp_payload_length; sgl_nsegs = 0; sgl_len = 0; } else { imm_len = 0; sglist_reset(sc->sg_ulptx); error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crd->crd_skip, crd->crd_len); + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); sgl_nsegs = sc->sg_ulptx->sg_nseg; sgl_len = ccr_ulptx_sgl_len(sgl_nsegs); } - wr_len = roundup2(transhdr_len, 16) + s->blkcipher.iv_len + + wr_len = roundup2(transhdr_len, 16) + iv_len + roundup2(imm_len, 16) + sgl_len; if (wr_len > SGE_MAX_WR_LEN) return (EFBIG); @@ -647,24 +659,20 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) /* * Read the existing IV from the request or generate a random - * one if none is provided. Optionally copy the generated IV - * into the output buffer if requested. + * one if none is provided. */ - if (op_type == CHCR_ENCRYPT_OP) { - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crd->crd_iv, s->blkcipher.iv_len); - else - arc4rand(iv, s->blkcipher.iv_len, 0); - if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crd->crd_inject, s->blkcipher.iv_len, iv); - } else { - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crd->crd_iv, s->blkcipher.iv_len); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_inject, s->blkcipher.iv_len, iv); - } + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(iv, s->blkcipher.iv_len, 0); + crypto_copyback(crp, crp->crp_iv_start, s->blkcipher.iv_len, + iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(iv, crp->crp_iv, s->blkcipher.iv_len); + else + crypto_copydata(crp, crp->crp_iv_start, s->blkcipher.iv_len, + iv); + + /* Zero the remainder of the IV for AES-XTS. */ + memset(iv + s->blkcipher.iv_len, 0, iv_len - s->blkcipher.iv_len); ccr_populate_wreq(sc, crwr, kctx_len, wr_len, imm_len, sgl_len, 0, crp); @@ -677,10 +685,10 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) | V_CPL_TX_SEC_PDU_IVINSRTOFST(1)); - crwr->sec_cpl.pldlen = htobe32(s->blkcipher.iv_len + crd->crd_len); + crwr->sec_cpl.pldlen = htobe32(iv_len + crp->crp_payload_length); crwr->sec_cpl.aadstart_cipherstop_hi = htobe32( - V_CPL_TX_SEC_PDU_CIPHERSTART(s->blkcipher.iv_len + 1) | + V_CPL_TX_SEC_PDU_CIPHERSTART(iv_len + 1) | V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(0)); crwr->sec_cpl.cipherstop_lo_authinsert = htobe32( V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(0)); @@ -693,7 +701,7 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) V_SCMD_CIPH_MODE(s->blkcipher.cipher_mode) | V_SCMD_AUTH_MODE(SCMD_AUTH_MODE_NOP) | V_SCMD_HMAC_CTRL(SCMD_HMAC_CTRL_NOP) | - V_SCMD_IV_SIZE(s->blkcipher.iv_len / 2) | + V_SCMD_IV_SIZE(iv_len / 2) | V_SCMD_NUM_IVS(0)); crwr->sec_cpl.ivgen_hdrlen = htobe32( V_SCMD_IV_GEN_CTRL(0) | @@ -701,24 +709,24 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) V_SCMD_AADIVDROP(1) | V_SCMD_HDR_LEN(dsgl_len)); crwr->key_ctx.ctx_hdr = s->blkcipher.key_ctx_hdr; - switch (crd->crd_alg) { - case CRYPTO_AES_CBC: - if (crd->crd_flags & CRD_F_ENCRYPT) + switch (s->blkcipher.cipher_mode) { + case SCMD_CIPH_MODE_AES_CBC: + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) memcpy(crwr->key_ctx.key, s->blkcipher.enckey, s->blkcipher.key_len); else memcpy(crwr->key_ctx.key, s->blkcipher.deckey, s->blkcipher.key_len); break; - case CRYPTO_AES_ICM: + case SCMD_CIPH_MODE_AES_CTR: memcpy(crwr->key_ctx.key, s->blkcipher.enckey, s->blkcipher.key_len); break; - case CRYPTO_AES_XTS: + case SCMD_CIPH_MODE_AES_XTS: key_half = s->blkcipher.key_len / 2; memcpy(crwr->key_ctx.key, s->blkcipher.enckey + key_half, key_half); - if (crd->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) memcpy(crwr->key_ctx.key + key_half, s->blkcipher.enckey, key_half); else @@ -730,11 +738,11 @@ ccr_blkcipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) dst = (char *)(crwr + 1) + kctx_len; ccr_write_phys_dsgl(sc, dst, dsgl_nsegs); dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len; - memcpy(dst, iv, s->blkcipher.iv_len); - dst += s->blkcipher.iv_len; + memcpy(dst, iv, iv_len); + dst += iv_len; if (imm_len != 0) - crypto_copydata(crp->crp_flags, crp->crp_buf, crd->crd_skip, - crd->crd_len, dst); + crypto_copydata(crp, crp->crp_payload_start, + crp->crp_payload_length, dst); else ccr_write_ulptx_sgl(sc, dst, sgl_nsegs); @@ -775,8 +783,7 @@ ccr_hmac_ctrl(unsigned int hashsize, unsigned int authsize) } static int -ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, - struct cryptodesc *crda, struct cryptodesc *crde) +ccr_eta(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) { char iv[CHCR_MAX_CRYPTO_IV_LEN]; struct chcr_wr *crwr; @@ -784,9 +791,9 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, struct auth_hash *axf; char *dst; u_int kctx_len, key_half, op_type, transhdr_len, wr_len; - u_int hash_size_in_response, imm_len, iopad_size; - u_int aad_start, aad_len, aad_stop; - u_int auth_start, auth_stop, auth_insert; + u_int hash_size_in_response, imm_len, iopad_size, iv_len; + u_int aad_start, aad_stop; + u_int auth_insert; u_int cipher_start, cipher_stop; u_int hmac_ctrl, input_len; int dsgl_nsegs, dsgl_len; @@ -797,34 +804,24 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * 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) + if (s->blkcipher.key_len == 0 || crp->crp_payload_length == 0) return (EINVAL); - if (crde->crd_alg == CRYPTO_AES_CBC && - (crde->crd_len % AES_BLOCK_LEN) != 0) + if (s->blkcipher.cipher_mode == SCMD_CIPH_MODE_AES_CBC && + (crp->crp_payload_length % AES_BLOCK_LEN) != 0) return (EINVAL); - /* - * Compute the length of the AAD (data covered by the - * authentication descriptor but not the encryption - * descriptor). To simplify the logic, AAD is only permitted - * before the cipher/plain text, not after. This is true of - * all currently-generated requests. - */ - if (crda->crd_len + crda->crd_skip > crde->crd_len + crde->crd_skip) - return (EINVAL); - if (crda->crd_skip < crde->crd_skip) { - if (crda->crd_skip + crda->crd_len > crde->crd_skip) - aad_len = (crde->crd_skip - crda->crd_skip); - else - aad_len = crda->crd_len; - } else - aad_len = 0; - if (aad_len + s->blkcipher.iv_len > MAX_AAD_LEN) + /* For AES-XTS we send a 16-byte IV in the work request. */ + if (s->blkcipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS) + iv_len = AES_BLOCK_LEN; + else + iv_len = s->blkcipher.iv_len; + + if (crp->crp_aad_length + iv_len > MAX_AAD_LEN) return (EINVAL); axf = s->hmac.auth_hash; hash_size_in_response = s->hmac.hash_len; - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) op_type = CHCR_ENCRYPT_OP; else op_type = CHCR_DECRYPT_OP; @@ -839,26 +836,26 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * output buffer. */ if (op_type == CHCR_ENCRYPT_OP) { - if (s->blkcipher.iv_len + aad_len + crde->crd_len + + if (iv_len + crp->crp_aad_length + crp->crp_payload_length + hash_size_in_response > MAX_REQUEST_SIZE) return (EFBIG); } else { - if (s->blkcipher.iv_len + aad_len + crde->crd_len > + if (iv_len + crp->crp_aad_length + crp->crp_payload_length > MAX_REQUEST_SIZE) return (EFBIG); } sglist_reset(sc->sg_dsgl); error = sglist_append_sglist(sc->sg_dsgl, sc->sg_iv_aad, 0, - s->blkcipher.iv_len + aad_len); + iv_len + crp->crp_aad_length); if (error) return (error); - error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip, - crde->crd_len); + error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_ENCRYPT_OP) { error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -888,7 +885,7 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * inside of the AAD region, so a second copy is always * required. */ - input_len = aad_len + crde->crd_len; + input_len = crp->crp_aad_length + crp->crp_payload_length; /* * The firmware hangs if sent a request which is a @@ -902,26 +899,27 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, return (EFBIG); if (op_type == CHCR_DECRYPT_OP) input_len += hash_size_in_response; - if (ccr_use_imm_data(transhdr_len, s->blkcipher.iv_len + input_len)) { + + if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) { imm_len = input_len; sgl_nsegs = 0; sgl_len = 0; } else { imm_len = 0; sglist_reset(sc->sg_ulptx); - if (aad_len != 0) { + if (crp->crp_aad_length != 0) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_skip, aad_len); + crp->crp_aad_start, crp->crp_aad_length); if (error) return (error); } error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crde->crd_skip, crde->crd_len); + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_DECRYPT_OP) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -934,37 +932,25 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * Auth-data that overlaps with the cipher region is placed in * the auth section. */ - if (aad_len != 0) { - aad_start = s->blkcipher.iv_len + 1; - aad_stop = aad_start + aad_len - 1; + if (crp->crp_aad_length != 0) { + aad_start = iv_len + 1; + aad_stop = aad_start + crp->crp_aad_length - 1; } else { aad_start = 0; aad_stop = 0; } - cipher_start = s->blkcipher.iv_len + aad_len + 1; + cipher_start = iv_len + crp->crp_aad_length + 1; if (op_type == CHCR_DECRYPT_OP) cipher_stop = hash_size_in_response; else cipher_stop = 0; - if (aad_len == crda->crd_len) { - auth_start = 0; - auth_stop = 0; - } else { - if (aad_len != 0) - auth_start = cipher_start; - else - auth_start = s->blkcipher.iv_len + crda->crd_skip - - crde->crd_skip + 1; - auth_stop = (crde->crd_skip + crde->crd_len) - - (crda->crd_skip + crda->crd_len) + cipher_stop; - } if (op_type == CHCR_DECRYPT_OP) auth_insert = hash_size_in_response; else auth_insert = 0; - wr_len = roundup2(transhdr_len, 16) + s->blkcipher.iv_len + - roundup2(imm_len, 16) + sgl_len; + wr_len = roundup2(transhdr_len, 16) + iv_len + roundup2(imm_len, 16) + + sgl_len; if (wr_len > SGE_MAX_WR_LEN) return (EFBIG); wr = alloc_wrqe(wr_len, sc->txq); @@ -977,24 +963,20 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, /* * Read the existing IV from the request or generate a random - * one if none is provided. Optionally copy the generated IV - * into the output buffer if requested. + * one if none is provided. */ - if (op_type == CHCR_ENCRYPT_OP) { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, s->blkcipher.iv_len); - else - arc4rand(iv, s->blkcipher.iv_len, 0); - if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_inject, s->blkcipher.iv_len, iv); - } else { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, s->blkcipher.iv_len); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_inject, s->blkcipher.iv_len, iv); - } + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(iv, s->blkcipher.iv_len, 0); + crypto_copyback(crp, crp->crp_iv_start, s->blkcipher.iv_len, + iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(iv, crp->crp_iv, s->blkcipher.iv_len); + else + crypto_copydata(crp, crp->crp_iv_start, s->blkcipher.iv_len, + iv); + + /* Zero the remainder of the IV for AES-XTS. */ + memset(iv + s->blkcipher.iv_len, 0, iv_len - s->blkcipher.iv_len); ccr_populate_wreq(sc, crwr, kctx_len, wr_len, imm_len, sgl_len, op_type == CHCR_DECRYPT_OP ? hash_size_in_response : 0, crp); @@ -1007,7 +989,7 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) | V_CPL_TX_SEC_PDU_IVINSRTOFST(1)); - crwr->sec_cpl.pldlen = htobe32(s->blkcipher.iv_len + input_len); + crwr->sec_cpl.pldlen = htobe32(iv_len + input_len); crwr->sec_cpl.aadstart_cipherstop_hi = htobe32( V_CPL_TX_SEC_PDU_AADSTART(aad_start) | @@ -1016,8 +998,8 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(cipher_stop >> 4)); crwr->sec_cpl.cipherstop_lo_authinsert = htobe32( V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(cipher_stop & 0xf) | - V_CPL_TX_SEC_PDU_AUTHSTART(auth_start) | - V_CPL_TX_SEC_PDU_AUTHSTOP(auth_stop) | + V_CPL_TX_SEC_PDU_AUTHSTART(cipher_start) | + V_CPL_TX_SEC_PDU_AUTHSTOP(cipher_stop) | V_CPL_TX_SEC_PDU_AUTHINSERT(auth_insert)); /* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */ @@ -1030,7 +1012,7 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, V_SCMD_CIPH_MODE(s->blkcipher.cipher_mode) | V_SCMD_AUTH_MODE(s->hmac.auth_mode) | V_SCMD_HMAC_CTRL(hmac_ctrl) | - V_SCMD_IV_SIZE(s->blkcipher.iv_len / 2) | + V_SCMD_IV_SIZE(iv_len / 2) | V_SCMD_NUM_IVS(0)); crwr->sec_cpl.ivgen_hdrlen = htobe32( V_SCMD_IV_GEN_CTRL(0) | @@ -1038,24 +1020,24 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, V_SCMD_AADIVDROP(0) | V_SCMD_HDR_LEN(dsgl_len)); crwr->key_ctx.ctx_hdr = s->blkcipher.key_ctx_hdr; - switch (crde->crd_alg) { - case CRYPTO_AES_CBC: - if (crde->crd_flags & CRD_F_ENCRYPT) + switch (s->blkcipher.cipher_mode) { + case SCMD_CIPH_MODE_AES_CBC: + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) memcpy(crwr->key_ctx.key, s->blkcipher.enckey, s->blkcipher.key_len); else memcpy(crwr->key_ctx.key, s->blkcipher.deckey, s->blkcipher.key_len); break; - case CRYPTO_AES_ICM: + case SCMD_CIPH_MODE_AES_CTR: memcpy(crwr->key_ctx.key, s->blkcipher.enckey, s->blkcipher.key_len); break; - case CRYPTO_AES_XTS: + case SCMD_CIPH_MODE_AES_XTS: key_half = s->blkcipher.key_len / 2; memcpy(crwr->key_ctx.key, s->blkcipher.enckey + key_half, key_half); - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) memcpy(crwr->key_ctx.key + key_half, s->blkcipher.enckey, key_half); else @@ -1070,20 +1052,20 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, dst = (char *)(crwr + 1) + kctx_len; ccr_write_phys_dsgl(sc, dst, dsgl_nsegs); dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len; - memcpy(dst, iv, s->blkcipher.iv_len); - dst += s->blkcipher.iv_len; + memcpy(dst, iv, iv_len); + dst += iv_len; if (imm_len != 0) { - if (aad_len != 0) { - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_skip, aad_len, dst); - dst += aad_len; + if (crp->crp_aad_length != 0) { + crypto_copydata(crp, crp->crp_aad_start, + crp->crp_aad_length, dst); + dst += crp->crp_aad_length; } - crypto_copydata(crp->crp_flags, crp->crp_buf, crde->crd_skip, - crde->crd_len, dst); - dst += crde->crd_len; + crypto_copydata(crp, crp->crp_payload_start, + crp->crp_payload_length, dst); + dst += crp->crp_payload_length; if (op_type == CHCR_DECRYPT_OP) - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_inject, hash_size_in_response, dst); + crypto_copydata(crp, crp->crp_digest_start, + hash_size_in_response, dst); } else ccr_write_ulptx_sgl(sc, dst, sgl_nsegs); @@ -1094,38 +1076,19 @@ ccr_authenc(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, } static int -ccr_authenc_done(struct ccr_softc *sc, struct ccr_session *s, +ccr_eta_done(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error) { - struct cryptodesc *crd; /* * The updated IV to permit chained requests is at * cpl->data[2], but OCF doesn't permit chained requests. - * - * For a decryption request, the hardware may do a verification - * of the HMAC which will fail if the existing HMAC isn't in the - * buffer. If that happens, clear the error and copy the HMAC - * from the CPL reply into the buffer. - * - * For encryption requests, crd should be the cipher request - * which will have CRD_F_ENCRYPT set. For decryption - * requests, crp_desc will be the HMAC request which should - * not have this flag set. */ - crd = crp->crp_desc; - if (error == EBADMSG && !CHK_PAD_ERR_BIT(be64toh(cpl->data[0])) && - !(crd->crd_flags & CRD_F_ENCRYPT)) { - crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, - s->hmac.hash_len, (c_caddr_t)(cpl + 1)); - error = 0; - } return (error); } static int -ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, - struct cryptodesc *crda, struct cryptodesc *crde) +ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) { char iv[CHCR_MAX_CRYPTO_IV_LEN]; struct chcr_wr *crwr; @@ -1146,21 +1109,14 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * The crypto engine doesn't handle GCM requests with an empty * payload, so handle those in software instead. */ - if (crde->crd_len == 0) + if (crp->crp_payload_length == 0) return (EMSGSIZE); - /* - * AAD is only permitted before the cipher/plain text, not - * after. - */ - if (crda->crd_len + crda->crd_skip > crde->crd_len + crde->crd_skip) - return (EMSGSIZE); - - if (crda->crd_len + AES_BLOCK_LEN > MAX_AAD_LEN) + if (crp->crp_aad_length + AES_BLOCK_LEN > MAX_AAD_LEN) return (EMSGSIZE); hash_size_in_response = s->gmac.hash_len; - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) op_type = CHCR_ENCRYPT_OP; else op_type = CHCR_DECRYPT_OP; @@ -1187,6 +1143,12 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, iv_len = s->blkcipher.iv_len; /* + * GCM requests should always provide an explicit IV. + */ + if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) + return (EINVAL); + + /* * The output buffer consists of the cipher text followed by * the tag when encrypting. For decryption it only contains * the plain text. @@ -1196,25 +1158,26 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * output buffer. */ if (op_type == CHCR_ENCRYPT_OP) { - if (iv_len + crda->crd_len + crde->crd_len + + if (iv_len + crp->crp_aad_length + crp->crp_payload_length + hash_size_in_response > MAX_REQUEST_SIZE) return (EFBIG); } else { - if (iv_len + crda->crd_len + crde->crd_len > MAX_REQUEST_SIZE) + if (iv_len + crp->crp_aad_length + crp->crp_payload_length > + MAX_REQUEST_SIZE) return (EFBIG); } sglist_reset(sc->sg_dsgl); error = sglist_append_sglist(sc->sg_dsgl, sc->sg_iv_aad, 0, iv_len + - crda->crd_len); + crp->crp_aad_length); if (error) return (error); - error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip, - crde->crd_len); + error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_ENCRYPT_OP) { error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -1241,7 +1204,7 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * inside of the AAD region, so a second copy is always * required. */ - input_len = crda->crd_len + crde->crd_len; + input_len = crp->crp_aad_length + crp->crp_payload_length; if (op_type == CHCR_DECRYPT_OP) input_len += hash_size_in_response; if (input_len > MAX_REQUEST_SIZE) @@ -1253,19 +1216,19 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, } else { imm_len = 0; sglist_reset(sc->sg_ulptx); - if (crda->crd_len != 0) { + if (crp->crp_aad_length != 0) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_skip, crda->crd_len); + crp->crp_aad_start, crp->crp_aad_length); if (error) return (error); } error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crde->crd_skip, crde->crd_len); + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_DECRYPT_OP) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -1273,14 +1236,14 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, sgl_len = ccr_ulptx_sgl_len(sgl_nsegs); } - if (crda->crd_len != 0) { + if (crp->crp_aad_length != 0) { aad_start = iv_len + 1; - aad_stop = aad_start + crda->crd_len - 1; + aad_stop = aad_start + crp->crp_aad_length - 1; } else { aad_start = 0; aad_stop = 0; } - cipher_start = iv_len + crda->crd_len + 1; + cipher_start = iv_len + crp->crp_aad_length + 1; if (op_type == CHCR_DECRYPT_OP) cipher_stop = hash_size_in_response; else @@ -1302,29 +1265,7 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, crwr = wrtod(wr); memset(crwr, 0, wr_len); - /* - * Read the existing IV from the request or generate a random - * one if none is provided. Optionally copy the generated IV - * into the output buffer if requested. - * - * If the input IV is 12 bytes, append an explicit 4-byte - * counter of 1. - */ - if (op_type == CHCR_ENCRYPT_OP) { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, s->blkcipher.iv_len); - else - arc4rand(iv, s->blkcipher.iv_len, 0); - if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_inject, s->blkcipher.iv_len, iv); - } else { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, s->blkcipher.iv_len); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_inject, s->blkcipher.iv_len, iv); - } + memcpy(iv, crp->crp_iv, s->blkcipher.iv_len); if (s->blkcipher.iv_len == 12) *(uint32_t *)&iv[12] = htobe32(1); @@ -1343,13 +1284,12 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, /* * NB: cipherstop is explicitly set to 0. On encrypt it - * should normally be set to 0 anyway (as the encrypt crd ends - * at the end of the input). However, for decrypt the cipher - * ends before the tag in the AUTHENC case (and authstop is - * set to stop before the tag), but for GCM the cipher still - * runs to the end of the buffer. Not sure if this is - * intentional or a firmware quirk, but it is required for - * working tag validation with GCM decryption. + * should normally be set to 0 anyway. However, for decrypt + * the cipher ends before the tag in the ETA case (and + * authstop is set to stop before the tag), but for GCM the + * cipher still runs to the end of the buffer. Not sure if + * this is intentional or a firmware quirk, but it is required + * for working tag validation with GCM decryption. */ crwr->sec_cpl.aadstart_cipherstop_hi = htobe32( V_CPL_TX_SEC_PDU_AADSTART(aad_start) | @@ -1390,17 +1330,17 @@ ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, memcpy(dst, iv, iv_len); dst += iv_len; if (imm_len != 0) { - if (crda->crd_len != 0) { - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_skip, crda->crd_len, dst); - dst += crda->crd_len; + if (crp->crp_aad_length != 0) { + crypto_copydata(crp, crp->crp_aad_start, + crp->crp_aad_length, dst); + dst += crp->crp_aad_length; } - crypto_copydata(crp->crp_flags, crp->crp_buf, crde->crd_skip, - crde->crd_len, dst); - dst += crde->crd_len; + crypto_copydata(crp, crp->crp_payload_start, + crp->crp_payload_length, dst); + dst += crp->crp_payload_length; if (op_type == CHCR_DECRYPT_OP) - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_inject, hash_size_in_response, dst); + crypto_copydata(crp, crp->crp_digest_start, + hash_size_in_response, dst); } else ccr_write_ulptx_sgl(sc, dst, sgl_nsegs); @@ -1429,8 +1369,7 @@ ccr_gcm_done(struct ccr_softc *sc, struct ccr_session *s, * 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) +ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp) { struct auth_hash *axf; struct enc_xform *exf; @@ -1478,30 +1417,19 @@ ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp, * 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); - if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_inject, 12, iv); - } 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); + if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) { + error = EINVAL; + goto out; } + memcpy(iv, crp->crp_iv, 12); *(uint32_t *)&iv[12] = htobe32(1); axf->Reinit(auth_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); + for (i = 0; i < crp->crp_aad_length; i += sizeof(block)) { + len = imin(crp->crp_aad_length - i, sizeof(block)); + crypto_copydata(crp, crp->crp_aad_start + i, len, block); bzero(block + len, sizeof(block) - len); axf->Update(auth_ctx, block, sizeof(block)); } @@ -1509,16 +1437,15 @@ ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp, exf->reinit(kschedule, iv); /* Do encryption with MAC */ - for (i = 0; i < crde->crd_len; i += sizeof(block)) { - len = imin(crde->crd_len - i, sizeof(block)); - crypto_copydata(crp->crp_flags, crp->crp_buf, crde->crd_skip + - i, len, block); + for (i = 0; i < crp->crp_payload_length; i += sizeof(block)) { + len = imin(crp->crp_payload_length - i, sizeof(block)); + crypto_copydata(crp, crp->crp_payload_start + i, len, block); bzero(block + len, sizeof(block) - len); - if (crde->crd_flags & CRD_F_ENCRYPT) { + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { exf->encrypt(kschedule, block); axf->Update(auth_ctx, block, len); - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + crypto_copyback(crp, crp->crp_payload_start + i, len, + block); } else { axf->Update(auth_ctx, block, len); } @@ -1526,35 +1453,37 @@ ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp, /* Length block. */ bzero(block, sizeof(block)); - ((uint32_t *)block)[1] = htobe32(crda->crd_len * 8); - ((uint32_t *)block)[3] = htobe32(crde->crd_len * 8); + ((uint32_t *)block)[1] = htobe32(crp->crp_aad_length * 8); + ((uint32_t *)block)[3] = htobe32(crp->crp_payload_length * 8); axf->Update(auth_ctx, block, sizeof(block)); /* Finalize MAC. */ axf->Final(digest, auth_ctx); /* Inject or validate tag. */ - if (crde->crd_flags & CRD_F_ENCRYPT) { - crypto_copyback(crp->crp_flags, crp->crp_buf, crda->crd_inject, - sizeof(digest), digest); + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + crypto_copyback(crp, crp->crp_digest_start, sizeof(digest), + digest); error = 0; } else { char digest2[GMAC_DIGEST_LEN]; - crypto_copydata(crp->crp_flags, crp->crp_buf, crda->crd_inject, - sizeof(digest2), digest2); + crypto_copydata(crp, crp->crp_digest_start, sizeof(digest2), + digest2); if (timingsafe_bcmp(digest, digest2, sizeof(digest)) == 0) { error = 0; /* Tag matches, decrypt data. */ - for (i = 0; i < crde->crd_len; i += sizeof(block)) { - len = imin(crde->crd_len - i, sizeof(block)); - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + for (i = 0; i < crp->crp_payload_length; + i += sizeof(block)) { + len = imin(crp->crp_payload_length - i, + sizeof(block)); + crypto_copydata(crp, crp->crp_payload_start + i, + len, block); bzero(block + len, sizeof(block) - len); exf->decrypt(kschedule, block); - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + crypto_copyback(crp, crp->crp_payload_start + i, + len, block); } } else error = EBADMSG; @@ -1571,8 +1500,8 @@ out: } static void -generate_ccm_b0(struct cryptodesc *crda, struct cryptodesc *crde, - u_int hash_size_in_response, const char *iv, char *b0) +generate_ccm_b0(struct cryptop *crp, u_int hash_size_in_response, + const char *iv, char *b0) { u_int i, payload_len; @@ -1583,7 +1512,7 @@ generate_ccm_b0(struct cryptodesc *crda, struct cryptodesc *crde, b0[0] |= (((hash_size_in_response - 2) / 2) << 3); /* Store the payload length as a big-endian value. */ - payload_len = crde->crd_len; + payload_len = crp->crp_payload_length; for (i = 0; i < iv[0]; i++) { b0[CCM_CBC_BLOCK_LEN - 1 - i] = payload_len; payload_len >>= 8; @@ -1595,15 +1524,14 @@ generate_ccm_b0(struct cryptodesc *crda, struct cryptodesc *crde, * start of block 1. This only assumes a 16-bit AAD length * since T6 doesn't support large AAD sizes. */ - if (crda->crd_len != 0) { + if (crp->crp_aad_length != 0) { b0[0] |= (1 << 6); - *(uint16_t *)(b0 + CCM_B0_SIZE) = htobe16(crda->crd_len); + *(uint16_t *)(b0 + CCM_B0_SIZE) = htobe16(crp->crp_aad_length); } } static int -ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, - struct cryptodesc *crda, struct cryptodesc *crde) +ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp) { char iv[CHCR_MAX_CRYPTO_IV_LEN]; struct ulptx_idata *idata; @@ -1625,14 +1553,7 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * The crypto engine doesn't handle CCM requests with an empty * payload, so handle those in software instead. */ - if (crde->crd_len == 0) - return (EMSGSIZE); - - /* - * AAD is only permitted before the cipher/plain text, not - * after. - */ - if (crda->crd_len + crda->crd_skip > crde->crd_len + crde->crd_skip) + if (crp->crp_payload_length == 0) return (EMSGSIZE); /* @@ -1640,14 +1561,21 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * request. */ b0_len = CCM_B0_SIZE; - if (crda->crd_len != 0) + if (crp->crp_aad_length != 0) b0_len += CCM_AAD_FIELD_SIZE; - aad_len = b0_len + crda->crd_len; + aad_len = b0_len + crp->crp_aad_length; + + /* + * CCM requests should always provide an explicit IV (really + * the nonce). + */ + if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) + return (EINVAL); /* - * Always assume a 12 byte input IV for now since that is what - * OCF always generates. The full IV in the work request is - * 16 bytes. + * Always assume a 12 byte input nonce for now since that is + * what OCF always generates. The full IV in the work request + * is 16 bytes. */ iv_len = AES_BLOCK_LEN; @@ -1655,7 +1583,7 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, return (EMSGSIZE); hash_size_in_response = s->ccm_mac.hash_len; - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) op_type = CHCR_ENCRYPT_OP; else op_type = CHCR_DECRYPT_OP; @@ -1670,11 +1598,12 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * output buffer. */ if (op_type == CHCR_ENCRYPT_OP) { - if (iv_len + aad_len + crde->crd_len + hash_size_in_response > - MAX_REQUEST_SIZE) + if (iv_len + aad_len + crp->crp_payload_length + + hash_size_in_response > MAX_REQUEST_SIZE) return (EFBIG); } else { - if (iv_len + aad_len + crde->crd_len > MAX_REQUEST_SIZE) + if (iv_len + aad_len + crp->crp_payload_length > + MAX_REQUEST_SIZE) return (EFBIG); } sglist_reset(sc->sg_dsgl); @@ -1682,13 +1611,13 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, aad_len); if (error) return (error); - error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip, - crde->crd_len); + error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_ENCRYPT_OP) { error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -1715,7 +1644,7 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, * inside of the AAD region, so a second copy is always * required. */ - input_len = aad_len + crde->crd_len; + input_len = aad_len + crp->crp_payload_length; if (op_type == CHCR_DECRYPT_OP) input_len += hash_size_in_response; if (input_len > MAX_REQUEST_SIZE) @@ -1729,19 +1658,19 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, imm_len = b0_len; sglist_reset(sc->sg_ulptx); - if (crda->crd_len != 0) { + if (crp->crp_aad_length != 0) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_skip, crda->crd_len); + crp->crp_aad_start, crp->crp_aad_length); if (error) return (error); } error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crde->crd_skip, crde->crd_len); + crp->crp_payload_start, crp->crp_payload_length); if (error) return (error); if (op_type == CHCR_DECRYPT_OP) { error = sglist_append_sglist(sc->sg_ulptx, sc->sg_crp, - crda->crd_inject, hash_size_in_response); + crp->crp_digest_start, hash_size_in_response); if (error) return (error); } @@ -1774,27 +1703,12 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, memset(crwr, 0, wr_len); /* - * Read the nonce from the request or generate a random one if - * none is provided. Use the nonce to generate the full IV - * with the counter set to 0. + * Read the nonce from the request. Use the nonce to generate + * the full IV with the counter set to 0. */ memset(iv, 0, iv_len); iv[0] = (15 - AES_CCM_IV_LEN) - 1; - if (op_type == CHCR_ENCRYPT_OP) { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv + 1, crde->crd_iv, AES_CCM_IV_LEN); - else - arc4rand(iv + 1, AES_CCM_IV_LEN, 0); - if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_inject, AES_CCM_IV_LEN, iv + 1); - } else { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv + 1, crde->crd_iv, AES_CCM_IV_LEN); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_inject, AES_CCM_IV_LEN, iv + 1); - } + memcpy(iv + 1, crp->crp_iv, AES_CCM_IV_LEN); ccr_populate_wreq(sc, crwr, kctx_len, wr_len, imm_len, sgl_len, 0, crp); @@ -1851,20 +1765,20 @@ ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp, dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len; memcpy(dst, iv, iv_len); dst += iv_len; - generate_ccm_b0(crda, crde, hash_size_in_response, iv, dst); + generate_ccm_b0(crp, hash_size_in_response, iv, dst); if (sgl_nsegs == 0) { dst += b0_len; - if (crda->crd_len != 0) { - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_skip, crda->crd_len, dst); - dst += crda->crd_len; + if (crp->crp_aad_length != 0) { + crypto_copydata(crp, crp->crp_aad_start, + crp->crp_aad_length, dst); + dst += crp->crp_aad_length; } - crypto_copydata(crp->crp_flags, crp->crp_buf, crde->crd_skip, - crde->crd_len, dst); - dst += crde->crd_len; + crypto_copydata(crp, crp->crp_payload_start, + crp->crp_payload_length, dst); + dst += crp->crp_payload_length; if (op_type == CHCR_DECRYPT_OP) - crypto_copydata(crp->crp_flags, crp->crp_buf, - crda->crd_inject, hash_size_in_response, dst); + crypto_copydata(crp, crp->crp_digest_start, + hash_size_in_response, dst); } else { dst += CCM_B0_SIZE; if (b0_len > CCM_B0_SIZE) { @@ -1911,8 +1825,7 @@ ccr_ccm_done(struct ccr_softc *sc, struct ccr_session *s, * performing the operation in software. Derived from swcr_authenc(). */ static void -ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp, - struct cryptodesc *crda, struct cryptodesc *crde) +ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp) { struct auth_hash *axf; struct enc_xform *exf; @@ -1956,31 +1869,20 @@ ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp, if (error) goto out; - if (crde->crd_flags & CRD_F_ENCRYPT) { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, AES_CCM_IV_LEN); - else - arc4rand(iv, AES_CCM_IV_LEN, 0); - if ((crde->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_inject, AES_CCM_IV_LEN, iv); - } else { - if (crde->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(iv, crde->crd_iv, AES_CCM_IV_LEN); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_inject, AES_CCM_IV_LEN, iv); + if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) { + error = EINVAL; + goto out; } + memcpy(iv, crp->crp_iv, AES_CCM_IV_LEN); - auth_ctx->aes_cbc_mac_ctx.authDataLength = crda->crd_len; - auth_ctx->aes_cbc_mac_ctx.cryptDataLength = crde->crd_len; + auth_ctx->aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length; + auth_ctx->aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length; axf->Reinit(auth_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); + for (i = 0; i < crp->crp_aad_length; i += sizeof(block)) { + len = imin(crp->crp_aad_length - i, sizeof(block)); + crypto_copydata(crp, crp->crp_aad_start + i, len, block); bzero(block + len, sizeof(block) - len); axf->Update(auth_ctx, block, sizeof(block)); } @@ -1988,16 +1890,15 @@ ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp, exf->reinit(kschedule, iv); /* Do encryption/decryption with MAC */ - for (i = 0; i < crde->crd_len; i += sizeof(block)) { - len = imin(crde->crd_len - i, sizeof(block)); - crypto_copydata(crp->crp_flags, crp->crp_buf, crde->crd_skip + - i, len, block); + for (i = 0; i < crp->crp_payload_length; i += sizeof(block)) { + len = imin(crp->crp_payload_length - i, sizeof(block)); + crypto_copydata(crp, crp->crp_payload_start + i, len, block); bzero(block + len, sizeof(block) - len); - if (crde->crd_flags & CRD_F_ENCRYPT) { + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { axf->Update(auth_ctx, block, len); exf->encrypt(kschedule, block); - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + crypto_copyback(crp, crp->crp_payload_start + i, len, + block); } else { exf->decrypt(kschedule, block); axf->Update(auth_ctx, block, len); @@ -2008,28 +1909,30 @@ ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp, axf->Final(digest, auth_ctx); /* Inject or validate tag. */ - if (crde->crd_flags & CRD_F_ENCRYPT) { - crypto_copyback(crp->crp_flags, crp->crp_buf, crda->crd_inject, - sizeof(digest), digest); + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + crypto_copyback(crp, crp->crp_digest_start, sizeof(digest), + digest); error = 0; } else { - char digest2[GMAC_DIGEST_LEN]; + char digest2[AES_CBC_MAC_HASH_LEN]; - crypto_copydata(crp->crp_flags, crp->crp_buf, crda->crd_inject, - sizeof(digest2), digest2); + crypto_copydata(crp, crp->crp_digest_start, sizeof(digest2), + digest2); if (timingsafe_bcmp(digest, digest2, sizeof(digest)) == 0) { error = 0; /* Tag matches, decrypt data. */ exf->reinit(kschedule, iv); - for (i = 0; i < crde->crd_len; i += sizeof(block)) { - len = imin(crde->crd_len - i, sizeof(block)); - crypto_copydata(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + for (i = 0; i < crp->crp_payload_length; + i += sizeof(block)) { + len = imin(crp->crp_payload_length - i, + sizeof(block)); + crypto_copydata(crp, crp->crp_payload_start + i, + len, block); bzero(block + len, sizeof(block) - len); exf->decrypt(kschedule, block); - crypto_copyback(crp->crp_flags, crp->crp_buf, - crde->crd_skip + i, len, block); + crypto_copyback(crp, crp->crp_payload_start + i, + len, block); } } else error = EBADMSG; @@ -2096,11 +1999,11 @@ ccr_sysctls(struct ccr_softc *sc) SYSCTL_ADD_U64(ctx, children, OID_AUTO, "cipher_decrypt", CTLFLAG_RD, &sc->stats_blkcipher_decrypt, 0, "Cipher decryption requests submitted"); - SYSCTL_ADD_U64(ctx, children, OID_AUTO, "authenc_encrypt", CTLFLAG_RD, - &sc->stats_authenc_encrypt, 0, + SYSCTL_ADD_U64(ctx, children, OID_AUTO, "eta_encrypt", CTLFLAG_RD, + &sc->stats_eta_encrypt, 0, "Combined AES+HMAC encryption requests submitted"); - SYSCTL_ADD_U64(ctx, children, OID_AUTO, "authenc_decrypt", CTLFLAG_RD, - &sc->stats_authenc_decrypt, 0, + SYSCTL_ADD_U64(ctx, children, OID_AUTO, "eta_decrypt", CTLFLAG_RD, + &sc->stats_eta_decrypt, 0, "Combined AES+HMAC decryption requests submitted"); SYSCTL_ADD_U64(ctx, children, OID_AUTO, "gcm_encrypt", CTLFLAG_RD, &sc->stats_gcm_encrypt, 0, "AES-GCM encryption requests submitted"); @@ -2161,25 +2064,6 @@ ccr_attach(device_t dev) sc->sg_iv_aad = sglist_build(sc->iv_aad_buf, MAX_AAD_LEN, M_WAITOK); ccr_sysctls(sc); - crypto_register(cid, CRYPTO_SHA1, 0, 0); - crypto_register(cid, CRYPTO_SHA2_224, 0, 0); - crypto_register(cid, CRYPTO_SHA2_256, 0, 0); - crypto_register(cid, CRYPTO_SHA2_384, 0, 0); - crypto_register(cid, CRYPTO_SHA2_512, 0, 0); - crypto_register(cid, CRYPTO_SHA1_HMAC, 0, 0); - crypto_register(cid, CRYPTO_SHA2_224_HMAC, 0, 0); - crypto_register(cid, CRYPTO_SHA2_256_HMAC, 0, 0); - crypto_register(cid, CRYPTO_SHA2_384_HMAC, 0, 0); - crypto_register(cid, CRYPTO_SHA2_512_HMAC, 0, 0); - crypto_register(cid, CRYPTO_AES_CBC, 0, 0); - crypto_register(cid, CRYPTO_AES_ICM, 0, 0); - crypto_register(cid, CRYPTO_AES_NIST_GCM_16, 0, 0); - crypto_register(cid, CRYPTO_AES_128_NIST_GMAC, 0, 0); - crypto_register(cid, CRYPTO_AES_192_NIST_GMAC, 0, 0); - crypto_register(cid, CRYPTO_AES_256_NIST_GMAC, 0, 0); - crypto_register(cid, CRYPTO_AES_XTS, 0, 0); - crypto_register(cid, CRYPTO_AES_CCM_16, 0, 0); - crypto_register(cid, CRYPTO_AES_CCM_CBC_MAC, 0, 0); return (0); } @@ -2207,48 +2091,48 @@ ccr_detach(device_t dev) } static void -ccr_init_hash_digest(struct ccr_session *s, int cri_alg) +ccr_init_hash_digest(struct ccr_session *s) { union authctx auth_ctx; struct auth_hash *axf; axf = s->hmac.auth_hash; axf->Init(&auth_ctx); - t4_copy_partial_hash(cri_alg, &auth_ctx, s->hmac.pads); + t4_copy_partial_hash(axf->type, &auth_ctx, s->hmac.pads); } -static int +static bool ccr_aes_check_keylen(int alg, int klen) { - switch (klen) { + switch (klen * 8) { case 128: case 192: if (alg == CRYPTO_AES_XTS) - return (EINVAL); + return (false); break; case 256: break; case 512: if (alg != CRYPTO_AES_XTS) - return (EINVAL); + return (false); break; default: - return (EINVAL); + return (false); } - return (0); + return (true); } static void -ccr_aes_setkey(struct ccr_session *s, int alg, const void *key, int klen) +ccr_aes_setkey(struct ccr_session *s, const void *key, int klen) { unsigned int ck_size, iopad_size, kctx_flits, kctx_len, kbits, mk_size; unsigned int opad_present; - if (alg == CRYPTO_AES_XTS) - kbits = klen / 2; + if (s->blkcipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS) + kbits = (klen / 2) * 8; else - kbits = klen; + kbits = klen * 8; switch (kbits) { case 128: ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; @@ -2263,18 +2147,18 @@ ccr_aes_setkey(struct ccr_session *s, int alg, const void *key, int klen) panic("should not get here"); } - s->blkcipher.key_len = klen / 8; + s->blkcipher.key_len = klen; memcpy(s->blkcipher.enckey, key, s->blkcipher.key_len); - switch (alg) { - case CRYPTO_AES_CBC: - case CRYPTO_AES_XTS: + switch (s->blkcipher.cipher_mode) { + case SCMD_CIPH_MODE_AES_CBC: + case SCMD_CIPH_MODE_AES_XTS: t4_aes_getdeckey(s->blkcipher.deckey, key, kbits); break; } kctx_len = roundup2(s->blkcipher.key_len, 16); switch (s->mode) { - case AUTHENC: + case ETA: mk_size = s->hmac.mk_size; opad_present = 1; iopad_size = roundup2(s->hmac.partial_digest_len, 16); @@ -2309,171 +2193,220 @@ ccr_aes_setkey(struct ccr_session *s, int alg, const void *key, int klen) } kctx_flits = (sizeof(struct _key_ctx) + kctx_len) / 16; s->blkcipher.key_ctx_hdr = htobe32(V_KEY_CONTEXT_CTX_LEN(kctx_flits) | - V_KEY_CONTEXT_DUAL_CK(alg == CRYPTO_AES_XTS) | + V_KEY_CONTEXT_DUAL_CK(s->blkcipher.cipher_mode == + SCMD_CIPH_MODE_AES_XTS) | V_KEY_CONTEXT_OPAD_PRESENT(opad_present) | V_KEY_CONTEXT_SALT_PRESENT(1) | V_KEY_CONTEXT_CK_SIZE(ck_size) | V_KEY_CONTEXT_MK_SIZE(mk_size) | V_KEY_CONTEXT_VALID(1)); } +static bool +ccr_auth_supported(const struct crypto_session_params *csp) +{ + + switch (csp->csp_auth_alg) { + case CRYPTO_SHA1: + case CRYPTO_SHA2_224: + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_512: + case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_224_HMAC: + case CRYPTO_SHA2_256_HMAC: + case CRYPTO_SHA2_384_HMAC: + case CRYPTO_SHA2_512_HMAC: + break; + default: + return (false); + } + return (true); +} + +static bool +ccr_cipher_supported(const struct crypto_session_params *csp) +{ + + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + if (csp->csp_ivlen != AES_BLOCK_LEN) + return (false); + break; + case CRYPTO_AES_ICM: + if (csp->csp_ivlen != AES_BLOCK_LEN) + return (false); + break; + case CRYPTO_AES_XTS: + if (csp->csp_ivlen != AES_XTS_IV_LEN) + return (false); + break; + default: + return (false); + } + return (ccr_aes_check_keylen(csp->csp_cipher_alg, + csp->csp_cipher_klen)); +} + static int -ccr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +ccr_cipher_mode(const struct crypto_session_params *csp) { - struct ccr_softc *sc; - struct ccr_session *s; - struct auth_hash *auth_hash; - struct cryptoini *c, *hash, *cipher; - unsigned int auth_mode, cipher_mode, iv_len, mk_size; - unsigned int partial_digest_len; - int error; - bool gcm_hash, hmac; - if (cri == NULL) - return (EINVAL); + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + return (SCMD_CIPH_MODE_AES_CBC); + case CRYPTO_AES_ICM: + return (SCMD_CIPH_MODE_AES_CTR); + case CRYPTO_AES_NIST_GCM_16: + return (SCMD_CIPH_MODE_AES_GCM); + case CRYPTO_AES_XTS: + return (SCMD_CIPH_MODE_AES_XTS); + case CRYPTO_AES_CCM_16: + return (SCMD_CIPH_MODE_AES_CCM); + default: + return (SCMD_CIPH_MODE_NOP); + } +} + +static int +ccr_probesession(device_t dev, const struct crypto_session_params *csp) +{ + unsigned int cipher_mode; - gcm_hash = false; - hmac = false; - cipher = NULL; - hash = NULL; - auth_hash = NULL; - auth_mode = SCMD_AUTH_MODE_NOP; - cipher_mode = SCMD_CIPH_MODE_NOP; - iv_len = 0; - mk_size = 0; - partial_digest_len = 0; - for (c = cri; c != NULL; c = c->cri_next) { - switch (c->cri_alg) { - case CRYPTO_SHA1: - case CRYPTO_SHA2_224: - case CRYPTO_SHA2_256: - case CRYPTO_SHA2_384: - case CRYPTO_SHA2_512: - case CRYPTO_SHA1_HMAC: - case CRYPTO_SHA2_224_HMAC: - case CRYPTO_SHA2_256_HMAC: - case CRYPTO_SHA2_384_HMAC: - case CRYPTO_SHA2_512_HMAC: - case CRYPTO_AES_128_NIST_GMAC: - case CRYPTO_AES_192_NIST_GMAC: - case CRYPTO_AES_256_NIST_GMAC: - case CRYPTO_AES_CCM_CBC_MAC: - if (hash) + if (csp->csp_flags != 0) + return (EINVAL); + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!ccr_auth_supported(csp)) + return (EINVAL); + break; + case CSP_MODE_CIPHER: + if (!ccr_cipher_supported(csp)) + return (EINVAL); + break; + case CSP_MODE_AEAD: + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_NIST_GCM_16: + if (csp->csp_ivlen != AES_GCM_IV_LEN) + return (EINVAL); + if (csp->csp_auth_mlen < 0 || + csp->csp_auth_mlen > AES_GMAC_HASH_LEN) return (EINVAL); - hash = c; - switch (c->cri_alg) { - case CRYPTO_SHA1: - case CRYPTO_SHA1_HMAC: - auth_hash = &auth_hash_hmac_sha1; - auth_mode = SCMD_AUTH_MODE_SHA1; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160; - partial_digest_len = SHA1_HASH_LEN; - break; - case CRYPTO_SHA2_224: - case CRYPTO_SHA2_224_HMAC: - auth_hash = &auth_hash_hmac_sha2_224; - auth_mode = SCMD_AUTH_MODE_SHA224; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; - partial_digest_len = SHA2_256_HASH_LEN; - break; - case CRYPTO_SHA2_256: - case CRYPTO_SHA2_256_HMAC: - auth_hash = &auth_hash_hmac_sha2_256; - auth_mode = SCMD_AUTH_MODE_SHA256; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; - partial_digest_len = SHA2_256_HASH_LEN; - break; - case CRYPTO_SHA2_384: - case CRYPTO_SHA2_384_HMAC: - auth_hash = &auth_hash_hmac_sha2_384; - auth_mode = SCMD_AUTH_MODE_SHA512_384; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; - partial_digest_len = SHA2_512_HASH_LEN; - break; - case CRYPTO_SHA2_512: - case CRYPTO_SHA2_512_HMAC: - auth_hash = &auth_hash_hmac_sha2_512; - auth_mode = SCMD_AUTH_MODE_SHA512_512; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; - partial_digest_len = SHA2_512_HASH_LEN; - break; - case CRYPTO_AES_128_NIST_GMAC: - case CRYPTO_AES_192_NIST_GMAC: - case CRYPTO_AES_256_NIST_GMAC: - gcm_hash = true; - auth_mode = SCMD_AUTH_MODE_GHASH; - mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128; - break; - case CRYPTO_AES_CCM_CBC_MAC: - auth_mode = SCMD_AUTH_MODE_CBCMAC; - break; - } - switch (c->cri_alg) { - case CRYPTO_SHA1_HMAC: - case CRYPTO_SHA2_224_HMAC: - case CRYPTO_SHA2_256_HMAC: - case CRYPTO_SHA2_384_HMAC: - case CRYPTO_SHA2_512_HMAC: - hmac = true; - break; - } break; - case CRYPTO_AES_CBC: - case CRYPTO_AES_ICM: - case CRYPTO_AES_NIST_GCM_16: - case CRYPTO_AES_XTS: case CRYPTO_AES_CCM_16: - if (cipher) + if (csp->csp_ivlen != AES_CCM_IV_LEN) + return (EINVAL); + if (csp->csp_auth_mlen < 0 || + csp->csp_auth_mlen > AES_CBC_MAC_HASH_LEN) return (EINVAL); - cipher = c; - switch (c->cri_alg) { - case CRYPTO_AES_CBC: - cipher_mode = SCMD_CIPH_MODE_AES_CBC; - iv_len = AES_BLOCK_LEN; - break; - case CRYPTO_AES_ICM: - cipher_mode = SCMD_CIPH_MODE_AES_CTR; - iv_len = AES_BLOCK_LEN; - break; - case CRYPTO_AES_NIST_GCM_16: - cipher_mode = SCMD_CIPH_MODE_AES_GCM; - iv_len = AES_GCM_IV_LEN; - break; - case CRYPTO_AES_XTS: - cipher_mode = SCMD_CIPH_MODE_AES_XTS; - iv_len = AES_BLOCK_LEN; - break; - case CRYPTO_AES_CCM_16: - cipher_mode = SCMD_CIPH_MODE_AES_CCM; - iv_len = AES_CCM_IV_LEN; - break; - } - if (c->cri_key != NULL) { - error = ccr_aes_check_keylen(c->cri_alg, - c->cri_klen); - if (error) - return (error); - } break; default: return (EINVAL); } - } - if (gcm_hash != (cipher_mode == SCMD_CIPH_MODE_AES_GCM)) - return (EINVAL); - if ((auth_mode == SCMD_AUTH_MODE_CBCMAC) != - (cipher_mode == SCMD_CIPH_MODE_AES_CCM)) - return (EINVAL); - if (hash == NULL && cipher == NULL) + break; + case CSP_MODE_ETA: + if (!ccr_auth_supported(csp) || !ccr_cipher_supported(csp)) + return (EINVAL); + break; + default: return (EINVAL); - if (hash != NULL) { - if (hmac || gcm_hash || auth_mode == SCMD_AUTH_MODE_CBCMAC) { - if (hash->cri_key == NULL) - return (EINVAL); - } else { - if (hash->cri_key != NULL) - return (EINVAL); - } } + if (csp->csp_cipher_klen != 0) { + cipher_mode = ccr_cipher_mode(csp); + if (cipher_mode == SCMD_CIPH_MODE_NOP) + return (EINVAL); + } + + return (CRYPTODEV_PROBE_HARDWARE); +} + +static int +ccr_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct ccr_softc *sc; + struct ccr_session *s; + struct auth_hash *auth_hash; + unsigned int auth_mode, cipher_mode, mk_size; + unsigned int partial_digest_len; + + switch (csp->csp_auth_alg) { + case CRYPTO_SHA1: + case CRYPTO_SHA1_HMAC: + auth_hash = &auth_hash_hmac_sha1; + auth_mode = SCMD_AUTH_MODE_SHA1; + mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160; + partial_digest_len = SHA1_HASH_LEN; + break; + case CRYPTO_SHA2_224: + case CRYPTO_SHA2_224_HMAC: + auth_hash = &auth_hash_hmac_sha2_224; + auth_mode = SCMD_AUTH_MODE_SHA224; + mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; + partial_digest_len = SHA2_256_HASH_LEN; + break; + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_256_HMAC: + auth_hash = &auth_hash_hmac_sha2_256; + auth_mode = SCMD_AUTH_MODE_SHA256; + mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; + partial_digest_len = SHA2_256_HASH_LEN; + break; + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_384_HMAC: + auth_hash = &auth_hash_hmac_sha2_384; + auth_mode = SCMD_AUTH_MODE_SHA512_384; + mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; + partial_digest_len = SHA2_512_HASH_LEN; + break; + case CRYPTO_SHA2_512: + case CRYPTO_SHA2_512_HMAC: + auth_hash = &auth_hash_hmac_sha2_512; + auth_mode = SCMD_AUTH_MODE_SHA512_512; + mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; + partial_digest_len = SHA2_512_HASH_LEN; + break; + default: + auth_hash = NULL; + auth_mode = SCMD_AUTH_MODE_NOP; + mk_size = 0; + partial_digest_len = 0; + break; + } + + cipher_mode = ccr_cipher_mode(csp); + +#ifdef INVARIANTS + switch (csp->csp_mode) { + case CSP_MODE_CIPHER: + if (cipher_mode == SCMD_CIPH_MODE_NOP || + cipher_mode == SCMD_CIPH_MODE_AES_GCM || + cipher_mode == SCMD_CIPH_MODE_AES_CCM) + panic("invalid cipher algo"); + break; + case CSP_MODE_DIGEST: + if (auth_mode == SCMD_AUTH_MODE_NOP) + panic("invalid auth algo"); + break; + case CSP_MODE_AEAD: + if (cipher_mode != SCMD_CIPH_MODE_AES_GCM && + cipher_mode != SCMD_CIPH_MODE_AES_CCM) + panic("invalid aead cipher algo"); + if (auth_mode != SCMD_AUTH_MODE_NOP) + panic("invalid aead auth aglo"); + break; + case CSP_MODE_ETA: + if (cipher_mode == SCMD_CIPH_MODE_NOP || + cipher_mode == SCMD_CIPH_MODE_AES_GCM || + cipher_mode == SCMD_CIPH_MODE_AES_CCM) + panic("invalid cipher algo"); + if (auth_mode == SCMD_AUTH_MODE_NOP) + panic("invalid auth algo"); + break; + default: + panic("invalid csp mode"); + } +#endif + sc = device_get_softc(dev); /* @@ -2493,54 +2426,61 @@ ccr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) s = crypto_get_driver_session(cses); - if (gcm_hash) - s->mode = GCM; - else if (cipher_mode == SCMD_CIPH_MODE_AES_CCM) - s->mode = CCM; - else if (hash != NULL && cipher != NULL) - s->mode = AUTHENC; - else if (hash != NULL) { - if (hmac) + switch (csp->csp_mode) { + case CSP_MODE_AEAD: + if (cipher_mode == SCMD_CIPH_MODE_AES_CCM) + s->mode = CCM; + else + s->mode = GCM; + break; + case CSP_MODE_ETA: + s->mode = ETA; + break; + case CSP_MODE_DIGEST: + if (csp->csp_auth_klen != 0) s->mode = HMAC; else s->mode = HASH; - } else { - MPASS(cipher != NULL); + break; + case CSP_MODE_CIPHER: s->mode = BLKCIPHER; + break; } - if (gcm_hash) { - if (hash->cri_mlen == 0) + + if (s->mode == GCM) { + if (csp->csp_auth_mlen == 0) s->gmac.hash_len = AES_GMAC_HASH_LEN; else - s->gmac.hash_len = hash->cri_mlen; - t4_init_gmac_hash(hash->cri_key, hash->cri_klen, + s->gmac.hash_len = csp->csp_auth_mlen; + t4_init_gmac_hash(csp->csp_cipher_key, csp->csp_cipher_klen, s->gmac.ghash_h); - } else if (auth_mode == SCMD_AUTH_MODE_CBCMAC) { - if (hash->cri_mlen == 0) + } else if (s->mode == CCM) { + if (csp->csp_auth_mlen == 0) s->ccm_mac.hash_len = AES_CBC_MAC_HASH_LEN; else - s->ccm_mac.hash_len = hash->cri_mlen; - } else if (hash != NULL) { + s->ccm_mac.hash_len = csp->csp_auth_mlen; + } else if (auth_mode != SCMD_AUTH_MODE_NOP) { s->hmac.auth_hash = auth_hash; s->hmac.auth_mode = auth_mode; s->hmac.mk_size = mk_size; s->hmac.partial_digest_len = partial_digest_len; - if (hash->cri_mlen == 0) + if (csp->csp_auth_mlen == 0) s->hmac.hash_len = auth_hash->hashsize; else - s->hmac.hash_len = hash->cri_mlen; - if (hmac) + s->hmac.hash_len = csp->csp_auth_mlen; + if (csp->csp_auth_key != NULL) t4_init_hmac_digest(auth_hash, partial_digest_len, - hash->cri_key, hash->cri_klen, s->hmac.pads); + csp->csp_auth_key, csp->csp_auth_klen, + s->hmac.pads); else - ccr_init_hash_digest(s, hash->cri_alg); + ccr_init_hash_digest(s); } - if (cipher != NULL) { + if (cipher_mode != SCMD_CIPH_MODE_NOP) { s->blkcipher.cipher_mode = cipher_mode; - s->blkcipher.iv_len = iv_len; - if (cipher->cri_key != NULL) - ccr_aes_setkey(s, cipher->cri_alg, cipher->cri_key, - cipher->cri_klen); + s->blkcipher.iv_len = csp->csp_ivlen; + if (csp->csp_cipher_key != NULL) + ccr_aes_setkey(s, csp->csp_cipher_key, + csp->csp_cipher_klen); } s->active = true; @@ -2568,15 +2508,12 @@ ccr_freesession(device_t dev, crypto_session_t cses) static int ccr_process(device_t dev, struct cryptop *crp, int hint) { + const struct crypto_session_params *csp; struct ccr_softc *sc; struct ccr_session *s; - struct cryptodesc *crd, *crda, *crde; int error; - if (crp == NULL) - return (EINVAL); - - crd = crp->crp_desc; + csp = crypto_get_params(crp->crp_session); s = crypto_get_driver_session(crp->crp_session); sc = device_get_softc(dev); @@ -2594,141 +2531,82 @@ ccr_process(device_t dev, struct cryptop *crp, int hint) sc->stats_hash++; break; case HMAC: - if (crd->crd_flags & CRD_F_KEY_EXPLICIT) + if (crp->crp_auth_key != NULL) t4_init_hmac_digest(s->hmac.auth_hash, - s->hmac.partial_digest_len, crd->crd_key, - crd->crd_klen, s->hmac.pads); + s->hmac.partial_digest_len, crp->crp_auth_key, + csp->csp_auth_klen, s->hmac.pads); error = ccr_hash(sc, s, crp); if (error == 0) sc->stats_hmac++; break; case BLKCIPHER: - if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { - error = ccr_aes_check_keylen(crd->crd_alg, - crd->crd_klen); - if (error) - break; - ccr_aes_setkey(s, crd->crd_alg, crd->crd_key, - crd->crd_klen); - } + if (crp->crp_cipher_key != NULL) + ccr_aes_setkey(s, crp->crp_cipher_key, + csp->csp_cipher_klen); error = ccr_blkcipher(sc, s, crp); if (error == 0) { - if (crd->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) sc->stats_blkcipher_encrypt++; else sc->stats_blkcipher_decrypt++; } break; - case AUTHENC: - error = 0; - switch (crd->crd_alg) { - case CRYPTO_AES_CBC: - case CRYPTO_AES_ICM: - case CRYPTO_AES_XTS: - /* Only encrypt-then-authenticate supported. */ - crde = crd; - crda = crd->crd_next; - if (!(crde->crd_flags & CRD_F_ENCRYPT)) { - error = EINVAL; - break; - } - break; - default: - crda = crd; - crde = crd->crd_next; - if (crde->crd_flags & CRD_F_ENCRYPT) { - error = EINVAL; - break; - } - break; - } - if (error) - break; - if (crda->crd_flags & CRD_F_KEY_EXPLICIT) + case ETA: + if (crp->crp_auth_key != NULL) t4_init_hmac_digest(s->hmac.auth_hash, - s->hmac.partial_digest_len, crda->crd_key, - crda->crd_klen, s->hmac.pads); - if (crde->crd_flags & CRD_F_KEY_EXPLICIT) { - error = ccr_aes_check_keylen(crde->crd_alg, - crde->crd_klen); - if (error) - break; - ccr_aes_setkey(s, crde->crd_alg, crde->crd_key, - crde->crd_klen); - } - error = ccr_authenc(sc, s, crp, crda, crde); + s->hmac.partial_digest_len, crp->crp_auth_key, + csp->csp_auth_klen, s->hmac.pads); + if (crp->crp_cipher_key != NULL) + ccr_aes_setkey(s, crp->crp_cipher_key, + csp->csp_cipher_klen); + error = ccr_eta(sc, s, crp); if (error == 0) { - if (crde->crd_flags & CRD_F_ENCRYPT) - sc->stats_authenc_encrypt++; + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) + sc->stats_eta_encrypt++; else - sc->stats_authenc_decrypt++; + sc->stats_eta_decrypt++; } break; case GCM: - error = 0; - if (crd->crd_alg == CRYPTO_AES_NIST_GCM_16) { - crde = crd; - crda = crd->crd_next; - } else { - crda = crd; - crde = crd->crd_next; - } - if (crda->crd_flags & CRD_F_KEY_EXPLICIT) - t4_init_gmac_hash(crda->crd_key, crda->crd_klen, - s->gmac.ghash_h); - if (crde->crd_flags & CRD_F_KEY_EXPLICIT) { - error = ccr_aes_check_keylen(crde->crd_alg, - crde->crd_klen); - if (error) - break; - ccr_aes_setkey(s, crde->crd_alg, crde->crd_key, - crde->crd_klen); + if (crp->crp_cipher_key != NULL) { + t4_init_gmac_hash(crp->crp_cipher_key, + csp->csp_cipher_klen, s->gmac.ghash_h); + ccr_aes_setkey(s, crp->crp_cipher_key, + csp->csp_cipher_klen); } - if (crde->crd_len == 0) { + if (crp->crp_payload_length == 0) { mtx_unlock(&sc->lock); - ccr_gcm_soft(s, crp, crda, crde); + ccr_gcm_soft(s, crp); return (0); } - error = ccr_gcm(sc, s, crp, crda, crde); + error = ccr_gcm(sc, s, crp); if (error == EMSGSIZE) { sc->stats_sw_fallback++; mtx_unlock(&sc->lock); - ccr_gcm_soft(s, crp, crda, crde); + ccr_gcm_soft(s, crp); return (0); } if (error == 0) { - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) sc->stats_gcm_encrypt++; else sc->stats_gcm_decrypt++; } break; case CCM: - error = 0; - if (crd->crd_alg == CRYPTO_AES_CCM_16) { - crde = crd; - crda = crd->crd_next; - } else { - crda = crd; - crde = crd->crd_next; - } - if (crde->crd_flags & CRD_F_KEY_EXPLICIT) { - error = ccr_aes_check_keylen(crde->crd_alg, - crde->crd_klen); - if (error) - break; - ccr_aes_setkey(s, crde->crd_alg, crde->crd_key, - crde->crd_klen); + if (crp->crp_cipher_key != NULL) { + ccr_aes_setkey(s, crp->crp_cipher_key, + csp->csp_cipher_klen); } - error = ccr_ccm(sc, s, crp, crda, crde); + error = ccr_ccm(sc, s, crp); if (error == EMSGSIZE) { sc->stats_sw_fallback++; mtx_unlock(&sc->lock); - ccr_ccm_soft(s, crp, crda, crde); + ccr_ccm_soft(s, crp); return (0); } if (error == 0) { - if (crde->crd_flags & CRD_F_ENCRYPT) + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) sc->stats_ccm_encrypt++; else sc->stats_ccm_decrypt++; @@ -2789,8 +2667,8 @@ do_cpl6_fw_pld(struct sge_iq *iq, const struct rss_header *rss, case BLKCIPHER: error = ccr_blkcipher_done(sc, s, crp, cpl, error); break; - case AUTHENC: - error = ccr_authenc_done(sc, s, crp, cpl, error); + case ETA: + error = ccr_eta_done(sc, s, crp, cpl, error); break; case GCM: error = ccr_gcm_done(sc, s, crp, cpl, error); @@ -2835,6 +2713,7 @@ static device_method_t ccr_methods[] = { DEVMETHOD(device_attach, ccr_attach), DEVMETHOD(device_detach, ccr_detach), + DEVMETHOD(cryptodev_probesession, ccr_probesession), DEVMETHOD(cryptodev_newsession, ccr_newsession), DEVMETHOD(cryptodev_freesession, ccr_freesession), DEVMETHOD(cryptodev_process, ccr_process), diff --git a/sys/dev/cxgbe/crypto/t4_keyctx.c b/sys/dev/cxgbe/crypto/t4_keyctx.c index bceade0ec810..0f034f1be334 100644 --- a/sys/dev/cxgbe/crypto/t4_keyctx.c +++ b/sys/dev/cxgbe/crypto/t4_keyctx.c @@ -73,7 +73,7 @@ t4_init_gmac_hash(const char *key, int klen, char *ghash) uint32_t keysched[4 * (RIJNDAEL_MAXNR + 1)]; int rounds; - rounds = rijndaelKeySetupEnc(keysched, key, klen); + rounds = rijndaelKeySetupEnc(keysched, key, klen * 8); rijndaelEncrypt(keysched, rounds, zeroes, ghash); } @@ -118,45 +118,19 @@ t4_copy_partial_hash(int alg, union authctx *auth_ctx, void *dst) void t4_init_hmac_digest(struct auth_hash *axf, u_int partial_digest_len, - char *key, int klen, char *dst) + const char *key, int klen, char *dst) { union authctx auth_ctx; - char ipad[SHA2_512_BLOCK_LEN], opad[SHA2_512_BLOCK_LEN]; - u_int i; - - /* - * If the key is larger than the block size, use the digest of - * the key as the key instead. - */ - klen /= 8; - if (klen > axf->blocksize) { - axf->Init(&auth_ctx); - axf->Update(&auth_ctx, key, klen); - axf->Final(ipad, &auth_ctx); - klen = axf->hashsize; - } else - memcpy(ipad, key, klen); - memset(ipad + klen, 0, axf->blocksize - klen); - memcpy(opad, ipad, axf->blocksize); - - for (i = 0; i < axf->blocksize; i++) { - ipad[i] ^= HMAC_IPAD_VAL; - opad[i] ^= HMAC_OPAD_VAL; - } - - /* - * Hash the raw ipad and opad and store the partial results in - * the key context. - */ - axf->Init(&auth_ctx); - axf->Update(&auth_ctx, ipad, axf->blocksize); + hmac_init_ipad(axf, key, klen, &auth_ctx); t4_copy_partial_hash(axf->type, &auth_ctx, dst); dst += roundup2(partial_digest_len, 16); - axf->Init(&auth_ctx); - axf->Update(&auth_ctx, opad, axf->blocksize); + + hmac_init_opad(axf, key, klen, &auth_ctx); t4_copy_partial_hash(axf->type, &auth_ctx, dst); + + explicit_bzero(&auth_ctx, sizeof(auth_ctx)); } /* diff --git a/sys/dev/cxgbe/tom/t4_tls.c b/sys/dev/cxgbe/tom/t4_tls.c index 57bae811f0f6..a82edd29bc3f 100644 --- a/sys/dev/cxgbe/tom/t4_tls.c +++ b/sys/dev/cxgbe/tom/t4_tls.c @@ -892,7 +892,7 @@ init_ktls_key_context(struct ktls_session *tls, struct tls_key_context *k_ctx) k_ctx->tx_key_info_size += GMAC_BLOCK_LEN; memcpy(k_ctx->tx.salt, tls->params.iv, SALT_SIZE); t4_init_gmac_hash(tls->params.cipher_key, - tls->params.cipher_key_len * 8, hash); + tls->params.cipher_key_len, hash); } else { switch (tls->params.auth_algorithm) { case CRYPTO_SHA1_HMAC: @@ -920,7 +920,7 @@ init_ktls_key_context(struct ktls_session *tls, struct tls_key_context *k_ctx) k_ctx->tx_key_info_size += roundup2(mac_key_size, 16) * 2; k_ctx->mac_secret_size = mac_key_size; t4_init_hmac_digest(axf, mac_key_size, tls->params.auth_key, - tls->params.auth_key_len * 8, hash); + tls->params.auth_key_len, hash); } k_ctx->frag_size = tls->params.max_frame_len; diff --git a/sys/dev/glxsb/glxsb.c b/sys/dev/glxsb/glxsb.c index 4d89e7d6756a..0e80b1dba2aa 100644 --- a/sys/dev/glxsb/glxsb.c +++ b/sys/dev/glxsb/glxsb.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcireg.h> #include <opencrypto/cryptodev.h> -#include <opencrypto/cryptosoft.h> #include <opencrypto/xform.h> #include "cryptodev_if.h" @@ -172,8 +171,6 @@ struct glxsb_dma_map { struct glxsb_taskop { struct glxsb_session *to_ses; /* crypto session */ struct cryptop *to_crp; /* cryptop to perfom */ - struct cryptodesc *to_enccrd; /* enccrd to perform */ - struct cryptodesc *to_maccrd; /* maccrd to perform */ }; struct glxsb_softc { @@ -204,13 +201,16 @@ static void glxsb_dma_free(struct glxsb_softc *, struct glxsb_dma_map *); static void glxsb_rnd(void *); static int glxsb_crypto_setup(struct glxsb_softc *); -static int glxsb_crypto_newsession(device_t, crypto_session_t, struct cryptoini *); +static int glxsb_crypto_probesession(device_t, + const struct crypto_session_params *); +static int glxsb_crypto_newsession(device_t, crypto_session_t, + const struct crypto_session_params *); static void glxsb_crypto_freesession(device_t, crypto_session_t); static int glxsb_aes(struct glxsb_softc *, uint32_t, uint32_t, - uint32_t, void *, int, void *); + uint32_t, const void *, int, const void *); -static int glxsb_crypto_encdec(struct cryptop *, struct cryptodesc *, - struct glxsb_session *, struct glxsb_softc *); +static int glxsb_crypto_encdec(struct cryptop *, struct glxsb_session *, + struct glxsb_softc *); static void glxsb_crypto_task(void *, int); static int glxsb_crypto_process(device_t, struct cryptop *, int); @@ -222,6 +222,7 @@ static device_method_t glxsb_methods[] = { DEVMETHOD(device_detach, glxsb_detach), /* crypto device methods */ + DEVMETHOD(cryptodev_probesession, glxsb_crypto_probesession), DEVMETHOD(cryptodev_newsession, glxsb_crypto_newsession), DEVMETHOD(cryptodev_freesession, glxsb_crypto_freesession), DEVMETHOD(cryptodev_process, glxsb_crypto_process), @@ -477,47 +478,24 @@ glxsb_crypto_setup(struct glxsb_softc *sc) mtx_init(&sc->sc_task_mtx, "glxsb_crypto_mtx", NULL, MTX_DEF); - if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0) != 0) - goto crypto_fail; - if (crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0) != 0) - goto crypto_fail; - return (0); - -crypto_fail: - device_printf(sc->sc_dev, "cannot register crypto\n"); - crypto_unregister_all(sc->sc_cid); - mtx_destroy(&sc->sc_task_mtx); - return (ENOMEM); } static int -glxsb_crypto_newsession(device_t dev, crypto_session_t cses, - struct cryptoini *cri) +glxsb_crypto_probesession(device_t dev, const struct crypto_session_params *csp) { - struct glxsb_softc *sc = device_get_softc(dev); - struct glxsb_session *ses; - struct cryptoini *encini, *macini; - int error; - if (sc == NULL || cri == NULL) + if (csp->csp_flags != 0) return (EINVAL); - encini = macini = NULL; - for (; cri != NULL; cri = cri->cri_next) { - switch(cri->cri_alg) { + /* + * We only support HMAC algorithms to be able to work with + * ipsec(4), so if we are asked only for authentication without + * encryption, don't pretend we can accelerate it. + */ + switch (csp->csp_mode) { + case CSP_MODE_ETA: + switch (csp->csp_auth_alg) { case CRYPTO_NULL_HMAC: case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: @@ -525,43 +503,42 @@ glxsb_crypto_newsession(device_t dev, crypto_session_t cses, case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: - if (macini != NULL) - return (EINVAL); - macini = cri; break; + default: + return (EINVAL); + } + /* FALLTHROUGH */ + case CSP_MODE_CIPHER: + switch (csp->csp_cipher_alg) { case CRYPTO_AES_CBC: - if (encini != NULL) + if (csp->csp_cipher_klen * 8 != 128) return (EINVAL); - encini = cri; break; default: return (EINVAL); } + default: + return (EINVAL); } + return (CRYPTODEV_PROBE_HARDWARE); +} - /* - * We only support HMAC algorithms to be able to work with - * ipsec(4), so if we are asked only for authentication without - * encryption, don't pretend we can accellerate it. - */ - if (encini == NULL) - return (EINVAL); +static int +glxsb_crypto_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct glxsb_softc *sc = device_get_softc(dev); + struct glxsb_session *ses; + int error; ses = crypto_get_driver_session(cses); - if (encini->cri_alg == CRYPTO_AES_CBC) { - if (encini->cri_klen != 128) { - glxsb_crypto_freesession(sc->sc_dev, cses); - return (EINVAL); - } - arc4rand(ses->ses_iv, sizeof(ses->ses_iv), 0); - ses->ses_klen = encini->cri_klen; - /* Copy the key (Geode LX wants the primary key only) */ - bcopy(encini->cri_key, ses->ses_key, sizeof(ses->ses_key)); - } + /* Copy the key (Geode LX wants the primary key only) */ + if (csp->csp_cipher_key != NULL) + bcopy(csp->csp_cipher_key, ses->ses_key, sizeof(ses->ses_key)); - if (macini != NULL) { - error = glxsb_hash_setup(ses, macini); + if (csp->csp_auth_alg != 0) { + error = glxsb_hash_setup(ses, csp); if (error != 0) { glxsb_crypto_freesession(sc->sc_dev, cses); return (error); @@ -574,19 +551,15 @@ glxsb_crypto_newsession(device_t dev, crypto_session_t cses, static void glxsb_crypto_freesession(device_t dev, crypto_session_t cses) { - struct glxsb_softc *sc = device_get_softc(dev); struct glxsb_session *ses; - if (sc == NULL) - return; - ses = crypto_get_driver_session(cses); glxsb_hash_free(ses); } static int glxsb_aes(struct glxsb_softc *sc, uint32_t control, uint32_t psrc, - uint32_t pdst, void *key, int len, void *iv) + uint32_t pdst, const void *key, int len, const void *iv) { uint32_t status; int i; @@ -652,23 +625,24 @@ glxsb_aes(struct glxsb_softc *sc, uint32_t control, uint32_t psrc, } static int -glxsb_crypto_encdec(struct cryptop *crp, struct cryptodesc *crd, - struct glxsb_session *ses, struct glxsb_softc *sc) +glxsb_crypto_encdec(struct cryptop *crp, struct glxsb_session *ses, + struct glxsb_softc *sc) { char *op_src, *op_dst; + const void *key; uint32_t op_psrc, op_pdst; - uint8_t op_iv[SB_AES_BLOCK_SIZE], *piv; + uint8_t op_iv[SB_AES_BLOCK_SIZE]; int error; int len, tlen, xlen; int offset; uint32_t control; - if (crd == NULL || (crd->crd_len % SB_AES_BLOCK_SIZE) != 0) + if ((crp->crp_payload_length % SB_AES_BLOCK_SIZE) != 0) return (EINVAL); /* How much of our buffer will we need to use? */ - xlen = crd->crd_len > GLXSB_MAX_AES_LEN ? - GLXSB_MAX_AES_LEN : crd->crd_len; + xlen = crp->crp_payload_length > GLXSB_MAX_AES_LEN ? + GLXSB_MAX_AES_LEN : crp->crp_payload_length; /* * XXX Check if we can have input == output on Geode LX. @@ -680,73 +654,57 @@ glxsb_crypto_encdec(struct cryptop *crp, struct cryptodesc *crd, op_psrc = sc->sc_dma.dma_paddr; op_pdst = sc->sc_dma.dma_paddr + xlen; - if (crd->crd_flags & CRD_F_ENCRYPT) { + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) control = SB_CTL_ENC; - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(crd->crd_iv, op_iv, sizeof(op_iv)); - else - bcopy(ses->ses_iv, op_iv, sizeof(op_iv)); - - if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) { - crypto_copyback(crp->crp_flags, crp->crp_buf, - crd->crd_inject, sizeof(op_iv), op_iv); - } - } else { + else control = SB_CTL_DEC; - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(crd->crd_iv, op_iv, sizeof(op_iv)); - else { - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_inject, sizeof(op_iv), op_iv); - } - } + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(op_iv, sizeof(op_iv), 0); + crypto_copyback(crp, crp->crp_iv_start, sizeof(op_iv), op_iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(op_iv, crp->crp_iv, sizeof(op_iv)); + else + crypto_copydata(crp, crp->crp_iv_start, sizeof(op_iv), op_iv); + offset = 0; - tlen = crd->crd_len; - piv = op_iv; + tlen = crp->crp_payload_length; + + if (crp->crp_cipher_key != NULL) + key = crp->crp_cipher_key; + else + key = ses->ses_key; /* Process the data in GLXSB_MAX_AES_LEN chunks */ while (tlen > 0) { len = (tlen > GLXSB_MAX_AES_LEN) ? GLXSB_MAX_AES_LEN : tlen; - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_skip + offset, len, op_src); + crypto_copydata(crp, crp->crp_payload_start + offset, len, + op_src); glxsb_dma_pre_op(sc, &sc->sc_dma); - error = glxsb_aes(sc, control, op_psrc, op_pdst, ses->ses_key, - len, op_iv); + error = glxsb_aes(sc, control, op_psrc, op_pdst, key, len, + op_iv); glxsb_dma_post_op(sc, &sc->sc_dma); if (error != 0) return (error); - crypto_copyback(crp->crp_flags, crp->crp_buf, - crd->crd_skip + offset, len, op_dst); + crypto_copyback(crp, crp->crp_payload_start + offset, len, + op_dst); offset += len; tlen -= len; - if (tlen <= 0) { /* Ideally, just == 0 */ - /* Finished - put the IV in session IV */ - piv = ses->ses_iv; - } - /* - * Copy out last block for use as next iteration/session IV. - * - * piv is set to op_iv[] before the loop starts, but is - * set to ses->ses_iv if we're going to exit the loop this - * time. + * Copy out last block for use as next iteration IV. */ - if (crd->crd_flags & CRD_F_ENCRYPT) - bcopy(op_dst + len - sizeof(op_iv), piv, sizeof(op_iv)); - else { - /* Decryption, only need this if another iteration */ - if (tlen > 0) { - bcopy(op_src + len - sizeof(op_iv), piv, - sizeof(op_iv)); - } - } + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) + bcopy(op_dst + len - sizeof(op_iv), op_iv, + sizeof(op_iv)); + else + bcopy(op_src + len - sizeof(op_iv), op_iv, + sizeof(op_iv)); } /* while */ /* All AES processing has now been done. */ @@ -759,30 +717,31 @@ static void glxsb_crypto_task(void *arg, int pending) { struct glxsb_softc *sc = arg; + const struct crypto_session_params *csp; struct glxsb_session *ses; struct cryptop *crp; - struct cryptodesc *enccrd, *maccrd; int error; - maccrd = sc->sc_to.to_maccrd; - enccrd = sc->sc_to.to_enccrd; crp = sc->sc_to.to_crp; ses = sc->sc_to.to_ses; + csp = crypto_get_params(crp->crp_session); /* Perform data authentication if requested before encryption */ - if (maccrd != NULL && maccrd->crd_next == enccrd) { - error = glxsb_hash_process(ses, maccrd, crp); + if (csp->csp_mode == CSP_MODE_ETA && + !CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + error = glxsb_hash_process(ses, csp, crp); if (error != 0) goto out; } - error = glxsb_crypto_encdec(crp, enccrd, ses, sc); + error = glxsb_crypto_encdec(crp, ses, sc); if (error != 0) goto out; /* Perform data authentication if requested after encryption */ - if (maccrd != NULL && enccrd->crd_next == maccrd) { - error = glxsb_hash_process(ses, maccrd, crp); + if (csp->csp_mode == CSP_MODE_ETA && + CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + error = glxsb_hash_process(ses, csp, crp); if (error != 0) goto out; } @@ -801,52 +760,6 @@ glxsb_crypto_process(device_t dev, struct cryptop *crp, int hint) { struct glxsb_softc *sc = device_get_softc(dev); struct glxsb_session *ses; - struct cryptodesc *crd, *enccrd, *maccrd; - int error = 0; - - enccrd = maccrd = NULL; - - /* Sanity check. */ - if (crp == NULL) - return (EINVAL); - - if (crp->crp_callback == NULL || crp->crp_desc == NULL) { - error = EINVAL; - goto fail; - } - - for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) { - switch (crd->crd_alg) { - case CRYPTO_NULL_HMAC: - case CRYPTO_MD5_HMAC: - case CRYPTO_SHA1_HMAC: - case CRYPTO_RIPEMD160_HMAC: - case CRYPTO_SHA2_256_HMAC: - case CRYPTO_SHA2_384_HMAC: - case CRYPTO_SHA2_512_HMAC: - if (maccrd != NULL) { - error = EINVAL; - goto fail; - } - maccrd = crd; - break; - case CRYPTO_AES_CBC: - if (enccrd != NULL) { - error = EINVAL; - goto fail; - } - enccrd = crd; - break; - default: - error = EINVAL; - goto fail; - } - } - - if (enccrd == NULL || enccrd->crd_len % AES_BLOCK_LEN != 0) { - error = EINVAL; - goto fail; - } ses = crypto_get_driver_session(crp->crp_session); @@ -857,17 +770,10 @@ glxsb_crypto_process(device_t dev, struct cryptop *crp, int hint) } sc->sc_task_count++; - sc->sc_to.to_maccrd = maccrd; - sc->sc_to.to_enccrd = enccrd; sc->sc_to.to_crp = crp; sc->sc_to.to_ses = ses; mtx_unlock(&sc->sc_task_mtx); taskqueue_enqueue(sc->sc_tq, &sc->sc_cryptotask); return(0); - -fail: - crp->crp_etype = error; - crypto_done(crp); - return (error); } diff --git a/sys/dev/glxsb/glxsb.h b/sys/dev/glxsb/glxsb.h index fe5128a744c6..27e5bb44709c 100644 --- a/sys/dev/glxsb/glxsb.h +++ b/sys/dev/glxsb/glxsb.h @@ -37,8 +37,6 @@ struct glxsb_session { uint32_t ses_key[4]; /* key */ - uint8_t ses_iv[SB_AES_BLOCK_SIZE]; /* initialization vector */ - int ses_klen; /* key len */ struct auth_hash *ses_axf; uint8_t *ses_ictx; uint8_t *ses_octx; @@ -46,10 +44,10 @@ struct glxsb_session { }; int glxsb_hash_setup(struct glxsb_session *ses, - struct cryptoini *macini); + const struct crypto_session_params *csp); int glxsb_hash_process(struct glxsb_session *ses, - struct cryptodesc *maccrd, struct cryptop *crp); + const struct crypto_session_params *csp, struct cryptop *crp); void glxsb_hash_free(struct glxsb_session *ses); diff --git a/sys/dev/glxsb/glxsb_hash.c b/sys/dev/glxsb/glxsb_hash.c index c5c2028103f2..73d9896ffc01 100644 --- a/sys/dev/glxsb/glxsb_hash.c +++ b/sys/dev/glxsb/glxsb_hash.c @@ -33,7 +33,6 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/malloc.h> -#include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */ #include <opencrypto/xform.h> #include "glxsb.h" @@ -51,92 +50,66 @@ __FBSDID("$FreeBSD$"); MALLOC_DECLARE(M_GLXSB); static void -glxsb_hash_key_setup(struct glxsb_session *ses, caddr_t key, int klen) +glxsb_hash_key_setup(struct glxsb_session *ses, const char *key, int klen) { struct auth_hash *axf; - int i; - klen /= 8; axf = ses->ses_axf; - - for (i = 0; i < klen; i++) - key[i] ^= HMAC_IPAD_VAL; - - axf->Init(ses->ses_ictx); - axf->Update(ses->ses_ictx, key, klen); - axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen); - - for (i = 0; i < klen; i++) - key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - - axf->Init(ses->ses_octx); - axf->Update(ses->ses_octx, key, klen); - axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen); - - for (i = 0; i < klen; i++) - key[i] ^= HMAC_OPAD_VAL; + hmac_init_ipad(axf, key, klen, ses->ses_ictx); + hmac_init_opad(axf, key, klen, ses->ses_octx); } /* * Compute keyed-hash authenticator. */ static int -glxsb_authcompute(struct glxsb_session *ses, struct cryptodesc *crd, - caddr_t buf, int flags) +glxsb_authcompute(struct glxsb_session *ses, struct cryptop *crp) { - u_char hash[HASH_MAX_LEN]; + u_char hash[HASH_MAX_LEN], hash2[HASH_MAX_LEN]; struct auth_hash *axf; union authctx ctx; int error; axf = ses->ses_axf; bcopy(ses->ses_ictx, &ctx, axf->ctxsize); - error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, + error = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); if (error != 0) return (error); + error = crypto_apply(crp, crp->crp_payload_start, + crp->crp_payload_length, + (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); + if (error != 0) + return (error); + axf->Final(hash, &ctx); bcopy(ses->ses_octx, &ctx, axf->ctxsize); axf->Update(&ctx, hash, axf->hashsize); axf->Final(hash, &ctx); - /* Inject the authentication data */ - crypto_copyback(flags, buf, crd->crd_inject, - ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash); + /* Verify or inject the authentication data */ + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, crp->crp_digest_start, ses->ses_mlen, + hash2); + if (timingsafe_bcmp(hash, hash2, ses->ses_mlen) != 0) + return (EBADMSG); + } else + crypto_copyback(crp, crp->crp_digest_start, ses->ses_mlen, + hash); return (0); } int -glxsb_hash_setup(struct glxsb_session *ses, struct cryptoini *macini) +glxsb_hash_setup(struct glxsb_session *ses, + const struct crypto_session_params *csp) { - ses->ses_mlen = macini->cri_mlen; - - /* Find software structure which describes HMAC algorithm. */ - switch (macini->cri_alg) { - case CRYPTO_NULL_HMAC: - ses->ses_axf = &auth_hash_null; - break; - case CRYPTO_MD5_HMAC: - ses->ses_axf = &auth_hash_hmac_md5; - break; - case CRYPTO_SHA1_HMAC: - ses->ses_axf = &auth_hash_hmac_sha1; - break; - case CRYPTO_RIPEMD160_HMAC: - ses->ses_axf = &auth_hash_hmac_ripemd_160; - break; - case CRYPTO_SHA2_256_HMAC: - ses->ses_axf = &auth_hash_hmac_sha2_256; - break; - case CRYPTO_SHA2_384_HMAC: - ses->ses_axf = &auth_hash_hmac_sha2_384; - break; - case CRYPTO_SHA2_512_HMAC: - ses->ses_axf = &auth_hash_hmac_sha2_512; - break; - } + ses->ses_axf = crypto_auth_hash(csp); + if (csp->csp_auth_mlen == 0) + ses->ses_mlen = ses->ses_axf->hashsize; + else + ses->ses_mlen = csp->csp_auth_mlen; /* Allocate memory for HMAC inner and outer contexts. */ ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_GLXSB, @@ -147,23 +120,24 @@ glxsb_hash_setup(struct glxsb_session *ses, struct cryptoini *macini) return (ENOMEM); /* Setup key if given. */ - if (macini->cri_key != NULL) { - glxsb_hash_key_setup(ses, macini->cri_key, - macini->cri_klen); + if (csp->csp_auth_key != NULL) { + glxsb_hash_key_setup(ses, csp->csp_auth_key, + csp->csp_auth_klen); } return (0); } int -glxsb_hash_process(struct glxsb_session *ses, struct cryptodesc *maccrd, - struct cryptop *crp) +glxsb_hash_process(struct glxsb_session *ses, + const struct crypto_session_params *csp, struct cryptop *crp) { int error; - if ((maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) - glxsb_hash_key_setup(ses, maccrd->crd_key, maccrd->crd_klen); + if (crp->crp_auth_key != NULL) + glxsb_hash_key_setup(ses, crp->crp_auth_key, + csp->csp_auth_klen); - error = glxsb_authcompute(ses, maccrd, crp->crp_buf, crp->crp_flags); + error = glxsb_authcompute(ses, crp); return (error); } diff --git a/sys/dev/hifn/hifn7751.c b/sys/dev/hifn/hifn7751.c index ce0f060aa7d2..7f1889767090 100644 --- a/sys/dev/hifn/hifn7751.c +++ b/sys/dev/hifn/hifn7751.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/sysctl.h> +#include <sys/uio.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -71,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <opencrypto/cryptodev.h> +#include <opencrypto/xform_auth.h> #include <sys/random.h> #include <sys/kobj.h> @@ -102,7 +104,9 @@ static int hifn_suspend(device_t); static int hifn_resume(device_t); static int hifn_shutdown(device_t); -static int hifn_newsession(device_t, crypto_session_t, struct cryptoini *); +static int hifn_probesession(device_t, const struct crypto_session_params *); +static int hifn_newsession(device_t, crypto_session_t, + const struct crypto_session_params *); static int hifn_process(device_t, struct cryptop *, int); static device_method_t hifn_methods[] = { @@ -115,6 +119,7 @@ static device_method_t hifn_methods[] = { DEVMETHOD(device_shutdown, hifn_shutdown), /* crypto device methods */ + DEVMETHOD(cryptodev_probesession, hifn_probesession), DEVMETHOD(cryptodev_newsession, hifn_newsession), DEVMETHOD(cryptodev_process, hifn_process), @@ -356,7 +361,7 @@ hifn_attach(device_t dev) caddr_t kva; int rseg, rid; char rbase; - u_int16_t ena, rev; + uint16_t rev; sc->sc_dev = dev; @@ -558,33 +563,22 @@ hifn_attach(device_t dev) 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11)); printf("\n"); - sc->sc_cid = crypto_get_driverid(dev, sizeof(struct hifn_session), - CRYPTOCAP_F_HARDWARE); - if (sc->sc_cid < 0) { - device_printf(dev, "could not get crypto driver id\n"); - goto fail_intr; - } - WRITE_REG_0(sc, HIFN_0_PUCNFG, READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID); - ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA; + sc->sc_ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA; - switch (ena) { + switch (sc->sc_ena) { case HIFN_PUSTAT_ENA_2: - crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0); - if (sc->sc_flags & HIFN_HAS_AES) - crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); - /*FALLTHROUGH*/ case HIFN_PUSTAT_ENA_1: - crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); + sc->sc_cid = crypto_get_driverid(dev, + sizeof(struct hifn_session), CRYPTOCAP_F_HARDWARE); + if (sc->sc_cid < 0) { + device_printf(dev, "could not get crypto driver id\n"); + goto fail_intr; + } break; } - + bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -1547,6 +1541,7 @@ hifn_init_dma(struct hifn_softc *sc) static u_int hifn_write_command(struct hifn_command *cmd, u_int8_t *buf) { + struct cryptop *crp; u_int8_t *buf_pos; hifn_base_command_t *base_cmd; hifn_mac_command_t *mac_cmd; @@ -1554,6 +1549,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf) int using_mac, using_crypt, len, ivlen; u_int32_t dlen, slen; + crp = cmd->crp; buf_pos = buf; using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC; using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT; @@ -1576,24 +1572,27 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf) if (using_mac) { mac_cmd = (hifn_mac_command_t *)buf_pos; - dlen = cmd->maccrd->crd_len; + dlen = crp->crp_aad_length + crp->crp_payload_length; mac_cmd->source_count = htole16(dlen & 0xffff); dlen >>= 16; mac_cmd->masks = htole16(cmd->mac_masks | ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M)); - mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip); + if (crp->crp_aad_length != 0) + mac_cmd->header_skip = htole16(crp->crp_aad_start); + else + mac_cmd->header_skip = htole16(crp->crp_payload_start); mac_cmd->reserved = 0; buf_pos += sizeof(hifn_mac_command_t); } if (using_crypt) { cry_cmd = (hifn_crypt_command_t *)buf_pos; - dlen = cmd->enccrd->crd_len; + dlen = crp->crp_payload_length; cry_cmd->source_count = htole16(dlen & 0xffff); dlen >>= 16; cry_cmd->masks = htole16(cmd->cry_masks | ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M)); - cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip); + cry_cmd->header_skip = htole16(crp->crp_payload_length); cry_cmd->reserved = 0; buf_pos += sizeof(hifn_crypt_command_t); } @@ -1782,15 +1781,30 @@ hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd) return (idx); } +static bus_size_t +hifn_crp_length(struct cryptop *crp) +{ + + switch (crp->crp_buf_type) { + case CRYPTO_BUF_MBUF: + return (crp->crp_mbuf->m_pkthdr.len); + case CRYPTO_BUF_UIO: + return (crp->crp_uio->uio_resid); + case CRYPTO_BUF_CONTIG: + return (crp->crp_ilen); + default: + panic("bad crp buffer type"); + } +} + static void -hifn_op_cb(void* arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int error) +hifn_op_cb(void* arg, bus_dma_segment_t *seg, int nsegs, int error) { struct hifn_operand *op = arg; KASSERT(nsegs <= MAX_SCATTER, ("hifn_op_cb: too many DMA segments (%u > %u) " "returned when mapping operand", nsegs, MAX_SCATTER)); - op->mapsize = mapsize; op->nsegs = nsegs; bcopy(seg, op->segs, nsegs * sizeof (seg[0])); } @@ -1832,130 +1846,110 @@ hifn_crypto( return (ENOMEM); } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map, - cmd->src_m, hifn_op_cb, &cmd->src, BUS_DMA_NOWAIT)) { - hifnstats.hst_nomem_load++; - err = ENOMEM; - goto err_srcmap1; - } - } else if (crp->crp_flags & CRYPTO_F_IOV) { - if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map, - cmd->src_io, hifn_op_cb, &cmd->src, BUS_DMA_NOWAIT)) { - hifnstats.hst_nomem_load++; - err = ENOMEM; - goto err_srcmap1; - } - } else { - err = EINVAL; + if (bus_dmamap_load_crp(sc->sc_dmat, cmd->src_map, crp, hifn_op_cb, + &cmd->src, BUS_DMA_NOWAIT)) { + hifnstats.hst_nomem_load++; + err = ENOMEM; goto err_srcmap1; } + cmd->src_mapsize = hifn_crp_length(crp); if (hifn_dmamap_aligned(&cmd->src)) { cmd->sloplen = cmd->src_mapsize & 3; cmd->dst = cmd->src; - } else { - if (crp->crp_flags & CRYPTO_F_IOV) { - err = EINVAL; - goto err_srcmap; - } else if (crp->crp_flags & CRYPTO_F_IMBUF) { - int totlen, len; - struct mbuf *m, *m0, *mlast; + } else if (crp->crp_buf_type == CRYPTO_BUF_MBUF) { + int totlen, len; + struct mbuf *m, *m0, *mlast; - KASSERT(cmd->dst_m == cmd->src_m, - ("hifn_crypto: dst_m initialized improperly")); - hifnstats.hst_unaligned++; - /* - * Source is not aligned on a longword boundary. - * Copy the data to insure alignment. If we fail - * to allocate mbufs or clusters while doing this - * we return ERESTART so the operation is requeued - * at the crypto later, but only if there are - * ops already posted to the hardware; otherwise we - * have no guarantee that we'll be re-entered. - */ - totlen = cmd->src_mapsize; - if (cmd->src_m->m_flags & M_PKTHDR) { - len = MHLEN; - MGETHDR(m0, M_NOWAIT, MT_DATA); - if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_NOWAIT)) { - m_free(m0); - m0 = NULL; - } - } else { - len = MLEN; - MGET(m0, M_NOWAIT, MT_DATA); + KASSERT(cmd->dst_m == NULL, + ("hifn_crypto: dst_m initialized improperly")); + hifnstats.hst_unaligned++; + + /* + * Source is not aligned on a longword boundary. + * Copy the data to insure alignment. If we fail + * to allocate mbufs or clusters while doing this + * we return ERESTART so the operation is requeued + * at the crypto later, but only if there are + * ops already posted to the hardware; otherwise we + * have no guarantee that we'll be re-entered. + */ + totlen = cmd->src_mapsize; + if (crp->crp_mbuf->m_flags & M_PKTHDR) { + len = MHLEN; + MGETHDR(m0, M_NOWAIT, MT_DATA); + if (m0 && !m_dup_pkthdr(m0, crp->crp_mbuf, M_NOWAIT)) { + m_free(m0); + m0 = NULL; } - if (m0 == NULL) { + } else { + len = MLEN; + MGET(m0, M_NOWAIT, MT_DATA); + } + if (m0 == NULL) { + hifnstats.hst_nomem_mbuf++; + err = sc->sc_cmdu ? ERESTART : ENOMEM; + goto err_srcmap; + } + if (totlen >= MINCLSIZE) { + if (!(MCLGET(m0, M_NOWAIT))) { + hifnstats.hst_nomem_mcl++; + err = sc->sc_cmdu ? ERESTART : ENOMEM; + m_freem(m0); + goto err_srcmap; + } + len = MCLBYTES; + } + totlen -= len; + m0->m_pkthdr.len = m0->m_len = len; + mlast = m0; + + while (totlen > 0) { + MGET(m, M_NOWAIT, MT_DATA); + if (m == NULL) { hifnstats.hst_nomem_mbuf++; err = sc->sc_cmdu ? ERESTART : ENOMEM; + m_freem(m0); goto err_srcmap; } + len = MLEN; if (totlen >= MINCLSIZE) { - if (!(MCLGET(m0, M_NOWAIT))) { + if (!(MCLGET(m, M_NOWAIT))) { hifnstats.hst_nomem_mcl++; err = sc->sc_cmdu ? ERESTART : ENOMEM; + mlast->m_next = m; m_freem(m0); goto err_srcmap; } len = MCLBYTES; } - totlen -= len; - m0->m_pkthdr.len = m0->m_len = len; - mlast = m0; - while (totlen > 0) { - MGET(m, M_NOWAIT, MT_DATA); - if (m == NULL) { - hifnstats.hst_nomem_mbuf++; - err = sc->sc_cmdu ? ERESTART : ENOMEM; - m_freem(m0); - goto err_srcmap; - } - len = MLEN; - if (totlen >= MINCLSIZE) { - if (!(MCLGET(m, M_NOWAIT))) { - hifnstats.hst_nomem_mcl++; - err = sc->sc_cmdu ? ERESTART : ENOMEM; - mlast->m_next = m; - m_freem(m0); - goto err_srcmap; - } - len = MCLBYTES; - } - - m->m_len = len; - m0->m_pkthdr.len += len; - totlen -= len; + m->m_len = len; + m0->m_pkthdr.len += len; + totlen -= len; - mlast->m_next = m; - mlast = m; - } - cmd->dst_m = m0; + mlast->m_next = m; + mlast = m; } - } + cmd->dst_m = m0; - if (cmd->dst_map == NULL) { - if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &cmd->dst_map)) { + if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, + &cmd->dst_map)) { hifnstats.hst_nomem_map++; err = ENOMEM; goto err_srcmap; } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, - cmd->dst_m, hifn_op_cb, &cmd->dst, BUS_DMA_NOWAIT)) { - hifnstats.hst_nomem_map++; - err = ENOMEM; - goto err_dstmap1; - } - } else if (crp->crp_flags & CRYPTO_F_IOV) { - if (bus_dmamap_load_uio(sc->sc_dmat, cmd->dst_map, - cmd->dst_io, hifn_op_cb, &cmd->dst, BUS_DMA_NOWAIT)) { - hifnstats.hst_nomem_load++; - err = ENOMEM; - goto err_dstmap1; - } + + if (bus_dmamap_load_mbuf_sg(sc->sc_dmat, cmd->dst_map, m0, + cmd->dst_segs, &cmd->dst_nsegs, 0)) { + hifnstats.hst_nomem_map++; + err = ENOMEM; + goto err_dstmap1; } + cmd->dst_mapsize = m0->m_pkthdr.len; + } else { + err = EINVAL; + goto err_srcmap; } #ifdef HIFN_DEBUG @@ -2111,8 +2105,8 @@ err_dstmap1: if (cmd->src_map != cmd->dst_map) bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); err_srcmap: - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (cmd->src_m != cmd->dst_m) + if (crp->crp_buf_type == CRYPTO_BUF_MBUF) { + if (cmd->dst_m != NULL) m_freem(cmd->dst_m); } bus_dmamap_unload(sc->sc_dmat, cmd->src_map); @@ -2307,67 +2301,121 @@ hifn_intr(void *arg) } } -/* - * Allocate a new 'session' and return an encoded session id. 'sidp' - * contains our registration id, and should contain an encoded session - * id on successful allocation. - */ -static int -hifn_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +static bool +hifn_auth_supported(struct hifn_softc *sc, + const struct crypto_session_params *csp) { - struct hifn_softc *sc = device_get_softc(dev); - struct cryptoini *c; - int mac = 0, cry = 0; - struct hifn_session *ses; - KASSERT(sc != NULL, ("hifn_newsession: null softc")); - if (cri == NULL || sc == NULL) - return (EINVAL); + switch (sc->sc_ena) { + case HIFN_PUSTAT_ENA_2: + case HIFN_PUSTAT_ENA_1: + break; + default: + return (false); + } + + switch (csp->csp_auth_alg) { + case CRYPTO_MD5: + case CRYPTO_SHA1: + break; + case CRYPTO_MD5_HMAC: + case CRYPTO_SHA1_HMAC: + if (csp->csp_auth_klen > HIFN_MAC_KEY_LENGTH) + return (false); + break; + default: + return (false); + } - ses = crypto_get_driver_session(cses); + return (true); +} - for (c = cri; c != NULL; c = c->cri_next) { - switch (c->cri_alg) { - case CRYPTO_MD5: - case CRYPTO_SHA1: - case CRYPTO_MD5_HMAC: - case CRYPTO_SHA1_HMAC: - if (mac) - return (EINVAL); - mac = 1; - ses->hs_mlen = c->cri_mlen; - if (ses->hs_mlen == 0) { - switch (c->cri_alg) { - case CRYPTO_MD5: - case CRYPTO_MD5_HMAC: - ses->hs_mlen = 16; - break; - case CRYPTO_SHA1: - case CRYPTO_SHA1_HMAC: - ses->hs_mlen = 20; - break; - } - } - break; - case CRYPTO_DES_CBC: +static bool +hifn_cipher_supported(struct hifn_softc *sc, + const struct crypto_session_params *csp) +{ + + if (csp->csp_cipher_klen == 0) + return (false); + if (csp->csp_ivlen > HIFN_MAX_IV_LENGTH) + return (false); + switch (sc->sc_ena) { + case HIFN_PUSTAT_ENA_2: + switch (csp->csp_cipher_alg) { case CRYPTO_3DES_CBC: - case CRYPTO_AES_CBC: - /* XXX this may read fewer, does it matter? */ - read_random(ses->hs_iv, - c->cri_alg == CRYPTO_AES_CBC ? - HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); - /*FALLTHROUGH*/ case CRYPTO_ARC4: - if (cry) - return (EINVAL); - cry = 1; break; - default: - return (EINVAL); + case CRYPTO_AES_CBC: + if ((sc->sc_flags & HIFN_HAS_AES) == 0) + return (false); + switch (csp->csp_cipher_klen) { + case 128: + case 192: + case 256: + break; + default: + return (false); + } + return (true); } + /*FALLTHROUGH*/ + case HIFN_PUSTAT_ENA_1: + switch (csp->csp_cipher_alg) { + case CRYPTO_DES_CBC: + return (true); + } + break; } - if (mac == 0 && cry == 0) + return (false); +} + +static int +hifn_probesession(device_t dev, const struct crypto_session_params *csp) +{ + struct hifn_softc *sc; + + sc = device_get_softc(dev); + if (csp->csp_flags != 0) + return (EINVAL); + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!hifn_auth_supported(sc, csp)) + return (EINVAL); + break; + case CSP_MODE_CIPHER: + if (!hifn_cipher_supported(sc, csp)) + return (EINVAL); + break; + case CSP_MODE_ETA: + if (!hifn_auth_supported(sc, csp) || + !hifn_cipher_supported(sc, csp)) + return (EINVAL); + break; + default: return (EINVAL); + } + + return (CRYPTODEV_PROBE_HARDWARE); +} + +/* + * Allocate a new 'session'. + */ +static int +hifn_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct hifn_session *ses; + + ses = crypto_get_driver_session(cses); + + if (csp->csp_auth_alg != 0) { + if (csp->csp_auth_mlen == 0) + ses->hs_mlen = crypto_auth_hash(csp)->hashsize; + else + ses->hs_mlen = csp->csp_auth_mlen; + } + return (0); } @@ -2379,18 +2427,15 @@ hifn_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) static int hifn_process(device_t dev, struct cryptop *crp, int hint) { + const struct crypto_session_params *csp; struct hifn_softc *sc = device_get_softc(dev); struct hifn_command *cmd = NULL; - int err, ivlen; - struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; + const void *mackey; + int err, ivlen, keylen; struct hifn_session *ses; - if (crp == NULL || crp->crp_callback == NULL) { - hifnstats.hst_invalid++; - return (EINVAL); - } - ses = crypto_get_driver_session(crp->crp_session); + cmd = malloc(sizeof(struct hifn_command), M_DEVBUF, M_NOWAIT | M_ZERO); if (cmd == NULL) { hifnstats.hst_nomem++; @@ -2398,80 +2443,26 @@ hifn_process(device_t dev, struct cryptop *crp, int hint) goto errout; } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - cmd->src_m = (struct mbuf *)crp->crp_buf; - cmd->dst_m = (struct mbuf *)crp->crp_buf; - } else if (crp->crp_flags & CRYPTO_F_IOV) { - cmd->src_io = (struct uio *)crp->crp_buf; - cmd->dst_io = (struct uio *)crp->crp_buf; - } else { - err = EINVAL; - goto errout; /* XXX we don't handle contiguous buffers! */ - } + csp = crypto_get_params(crp->crp_session); - crd1 = crp->crp_desc; - if (crd1 == NULL) { + /* + * The driver only supports ETA requests where there is no + * gap between the AAD and payload. + */ + if (csp->csp_mode == CSP_MODE_ETA && crp->crp_aad_length != 0 && + crp->crp_aad_start + crp->crp_aad_length != + crp->crp_payload_start) { err = EINVAL; goto errout; } - crd2 = crd1->crd_next; - - if (crd2 == NULL) { - if (crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC || - crd1->crd_alg == CRYPTO_SHA1 || - crd1->crd_alg == CRYPTO_MD5) { - maccrd = crd1; - enccrd = NULL; - } else if (crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_3DES_CBC || - crd1->crd_alg == CRYPTO_AES_CBC || - crd1->crd_alg == CRYPTO_ARC4) { - if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0) - cmd->base_masks |= HIFN_BASE_CMD_DECODE; - maccrd = NULL; - enccrd = crd1; - } else { - err = EINVAL; - goto errout; - } - } else { - if ((crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC || - crd1->crd_alg == CRYPTO_MD5 || - crd1->crd_alg == CRYPTO_SHA1) && - (crd2->crd_alg == CRYPTO_DES_CBC || - crd2->crd_alg == CRYPTO_3DES_CBC || - crd2->crd_alg == CRYPTO_AES_CBC || - crd2->crd_alg == CRYPTO_ARC4) && - ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) { - cmd->base_masks = HIFN_BASE_CMD_DECODE; - maccrd = crd1; - enccrd = crd2; - } else if ((crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_ARC4 || - crd1->crd_alg == CRYPTO_3DES_CBC || - crd1->crd_alg == CRYPTO_AES_CBC) && - (crd2->crd_alg == CRYPTO_MD5_HMAC || - crd2->crd_alg == CRYPTO_SHA1_HMAC || - crd2->crd_alg == CRYPTO_MD5 || - crd2->crd_alg == CRYPTO_SHA1) && - (crd1->crd_flags & CRD_F_ENCRYPT)) { - enccrd = crd1; - maccrd = crd2; - } else { - /* - * We cannot order the 7751 as requested - */ - err = EINVAL; - goto errout; - } - } - if (enccrd) { - cmd->enccrd = enccrd; + switch (csp->csp_mode) { + case CSP_MODE_CIPHER: + case CSP_MODE_ETA: + if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) + cmd->base_masks |= HIFN_BASE_CMD_DECODE; cmd->base_masks |= HIFN_BASE_CMD_CRYPT; - switch (enccrd->crd_alg) { + switch (csp->csp_cipher_alg) { case CRYPTO_ARC4: cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4; break; @@ -2494,36 +2485,24 @@ hifn_process(device_t dev, struct cryptop *crp, int hint) err = EINVAL; goto errout; } - if (enccrd->crd_alg != CRYPTO_ARC4) { - ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ? - HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); - if (enccrd->crd_flags & CRD_F_ENCRYPT) { - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(enccrd->crd_iv, cmd->iv, ivlen); - else - bcopy(ses->hs_iv, cmd->iv, ivlen); - - if ((enccrd->crd_flags & CRD_F_IV_PRESENT) - == 0) { - crypto_copyback(crp->crp_flags, - crp->crp_buf, enccrd->crd_inject, - ivlen, cmd->iv); - } - } else { - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(enccrd->crd_iv, cmd->iv, ivlen); - else { - crypto_copydata(crp->crp_flags, - crp->crp_buf, enccrd->crd_inject, - ivlen, cmd->iv); - } - } + if (csp->csp_cipher_alg != CRYPTO_ARC4) { + ivlen = csp->csp_ivlen; + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(cmd->iv, ivlen, 0); + crypto_copyback(crp, crp->crp_iv_start, ivlen, + cmd->iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(cmd->iv, crp->crp_iv, ivlen); + else + crypto_copydata(crp, crp->crp_iv_start, ivlen, + cmd->iv); } - if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) - cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY; - cmd->ck = enccrd->crd_key; - cmd->cklen = enccrd->crd_klen >> 3; + if (crp->crp_cipher_key != NULL) + cmd->ck = crp->crp_cipher_key; + else + cmd->ck = csp->csp_cipher_key; + cmd->cklen = csp->csp_cipher_klen; cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY; /* @@ -2546,13 +2525,15 @@ hifn_process(device_t dev, struct cryptop *crp, int hint) goto errout; } } + break; } - if (maccrd) { - cmd->maccrd = maccrd; + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + case CSP_MODE_ETA: cmd->base_masks |= HIFN_BASE_CMD_MAC; - switch (maccrd->crd_alg) { + switch (csp->csp_auth_alg) { case CRYPTO_MD5: cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 | HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH | @@ -2575,12 +2556,16 @@ hifn_process(device_t dev, struct cryptop *crp, int hint) break; } - if (maccrd->crd_alg == CRYPTO_SHA1_HMAC || - maccrd->crd_alg == CRYPTO_MD5_HMAC) { + if (csp->csp_auth_alg == CRYPTO_SHA1_HMAC || + csp->csp_auth_alg == CRYPTO_MD5_HMAC) { cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY; - bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3); - bzero(cmd->mac + (maccrd->crd_klen >> 3), - HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3)); + if (crp->crp_auth_key != NULL) + mackey = crp->crp_auth_key; + else + mackey = csp->csp_auth_key; + keylen = csp->csp_auth_klen; + bcopy(mackey, cmd->mac, keylen); + bzero(cmd->mac + keylen, HIFN_MAC_KEY_LENGTH - keylen); } } @@ -2655,9 +2640,8 @@ hifn_abort(struct hifn_softc *sc) BUS_DMASYNC_POSTREAD); } - if (cmd->src_m != cmd->dst_m) { - m_freem(cmd->src_m); - crp->crp_buf = (caddr_t)cmd->dst_m; + if (cmd->dst_m != NULL) { + m_freem(cmd->dst_m); } /* non-shared buffers cannot be restarted */ @@ -2696,9 +2680,9 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf) { struct hifn_dma *dma = sc->sc_dma; struct cryptop *crp = cmd->crp; - struct cryptodesc *crd; + uint8_t macbuf2[SHA1_HASH_LEN]; struct mbuf *m; - int totlen, i, u, ivlen; + int totlen, i, u; if (cmd->src_map == cmd->dst_map) { bus_dmamap_sync(sc->sc_dmat, cmd->src_map, @@ -2710,9 +2694,8 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf) BUS_DMASYNC_POSTREAD); } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (cmd->src_m != cmd->dst_m) { - crp->crp_buf = (caddr_t)cmd->dst_m; + if (crp->crp_buf_type == CRYPTO_BUF_MBUF) { + if (cmd->dst_m != NULL) { totlen = cmd->src_mapsize; for (m = cmd->dst_m; m != NULL; m = m->m_next) { if (totlen < m->m_len) { @@ -2721,15 +2704,15 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf) } else totlen -= m->m_len; } - cmd->dst_m->m_pkthdr.len = cmd->src_m->m_pkthdr.len; - m_freem(cmd->src_m); + cmd->dst_m->m_pkthdr.len = crp->crp_mbuf->m_pkthdr.len; + m_freem(crp->crp_mbuf); + crp->crp_mbuf = cmd->dst_m; } } if (cmd->sloplen != 0) { - crypto_copyback(crp->crp_flags, crp->crp_buf, - cmd->src_mapsize - cmd->sloplen, cmd->sloplen, - (caddr_t)&dma->slop[cmd->slopidx]); + crypto_copyback(crp, cmd->src_mapsize - cmd->sloplen, + cmd->sloplen, &dma->slop[cmd->slopidx]); } i = sc->sc_dstk; u = sc->sc_dstu; @@ -2749,37 +2732,16 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf) hifnstats.hst_obytes += cmd->dst_mapsize; - if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) == - HIFN_BASE_CMD_CRYPT) { - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - if (crd->crd_alg != CRYPTO_DES_CBC && - crd->crd_alg != CRYPTO_3DES_CBC && - crd->crd_alg != CRYPTO_AES_CBC) - continue; - ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ? - HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_skip + crd->crd_len - ivlen, ivlen, - cmd->session->hs_iv); - break; - } - } - if (macbuf != NULL) { - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - int len; - - if (crd->crd_alg != CRYPTO_MD5 && - crd->crd_alg != CRYPTO_SHA1 && - crd->crd_alg != CRYPTO_MD5_HMAC && - crd->crd_alg != CRYPTO_SHA1_HMAC) { - continue; - } - len = cmd->session->hs_mlen; - crypto_copyback(crp->crp_flags, crp->crp_buf, - crd->crd_inject, len, macbuf); - break; - } + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, crp->crp_digest_start, + cmd->session->hs_mlen, macbuf2); + if (timingsafe_bcmp(macbuf, macbuf2, + cmd->session->hs_mlen) != 0) + crp->crp_etype = EBADMSG; + } else + crypto_copyback(crp, crp->crp_digest_start, + cmd->session->hs_mlen, macbuf); } if (cmd->src_map != cmd->dst_map) { diff --git a/sys/dev/hifn/hifn7751var.h b/sys/dev/hifn/hifn7751var.h index e7ace8bcc977..ec0d96ec20a4 100644 --- a/sys/dev/hifn/hifn7751var.h +++ b/sys/dev/hifn/hifn7751var.h @@ -105,7 +105,6 @@ struct hifn_dma { struct hifn_session { - u_int8_t hs_iv[HIFN_MAX_IV_LENGTH]; int hs_mlen; }; @@ -160,6 +159,7 @@ struct hifn_softc { int sc_cmdk, sc_srck, sc_dstk, sc_resk; int32_t sc_cid; + uint16_t sc_ena; int sc_maxses; int sc_ramsize; int sc_flags; @@ -257,10 +257,6 @@ struct hifn_softc { * */ struct hifn_operand { - union { - struct mbuf *m; - struct uio *io; - } u; bus_dmamap_t map; bus_size_t mapsize; int nsegs; @@ -269,27 +265,24 @@ struct hifn_operand { struct hifn_command { struct hifn_session *session; u_int16_t base_masks, cry_masks, mac_masks; - u_int8_t iv[HIFN_MAX_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH]; + u_int8_t iv[HIFN_MAX_IV_LENGTH], mac[HIFN_MAC_KEY_LENGTH]; + const uint8_t *ck; int cklen; int sloplen, slopidx; struct hifn_operand src; struct hifn_operand dst; + struct mbuf *dst_m; struct hifn_softc *softc; struct cryptop *crp; - struct cryptodesc *enccrd, *maccrd; }; -#define src_m src.u.m -#define src_io src.u.io #define src_map src.map #define src_mapsize src.mapsize #define src_segs src.segs #define src_nsegs src.nsegs -#define dst_m dst.u.m -#define dst_io dst.u.io #define dst_map dst.map #define dst_mapsize dst.mapsize #define dst_segs dst.segs diff --git a/sys/dev/safe/safe.c b/sys/dev/safe/safe.c index 7a577dfd0a8c..99f16de56c50 100644 --- a/sys/dev/safe/safe.c +++ b/sys/dev/safe/safe.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/sysctl.h> #include <sys/endian.h> +#include <sys/uio.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -56,10 +57,8 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/rman.h> -#include <crypto/sha1.h> #include <opencrypto/cryptodev.h> -#include <opencrypto/cryptosoft.h> -#include <sys/md5.h> +#include <opencrypto/xform_auth.h> #include <sys/random.h> #include <sys/kobj.h> @@ -88,7 +87,9 @@ static int safe_suspend(device_t); static int safe_resume(device_t); static int safe_shutdown(device_t); -static int safe_newsession(device_t, crypto_session_t, struct cryptoini *); +static int safe_probesession(device_t, const struct crypto_session_params *); +static int safe_newsession(device_t, crypto_session_t, + const struct crypto_session_params *); static int safe_process(device_t, struct cryptop *, int); static device_method_t safe_methods[] = { @@ -101,6 +102,7 @@ static device_method_t safe_methods[] = { DEVMETHOD(device_shutdown, safe_shutdown), /* crypto device methods */ + DEVMETHOD(cryptodev_probesession, safe_probesession), DEVMETHOD(cryptodev_newsession, safe_newsession), DEVMETHOD(cryptodev_process, safe_process), @@ -221,7 +223,7 @@ safe_attach(device_t dev) { struct safe_softc *sc = device_get_softc(dev); u_int32_t raddr; - u_int32_t i, devinfo; + u_int32_t i; int rid; bzero(sc, sizeof (*sc)); @@ -374,12 +376,12 @@ safe_attach(device_t dev) device_printf(sc->sc_dev, "%s", safe_partname(sc)); - devinfo = READ_REG(sc, SAFE_DEVINFO); - if (devinfo & SAFE_DEVINFO_RNG) { + sc->sc_devinfo = READ_REG(sc, SAFE_DEVINFO); + if (sc->sc_devinfo & SAFE_DEVINFO_RNG) { sc->sc_flags |= SAFE_FLAGS_RNG; printf(" rng"); } - if (devinfo & SAFE_DEVINFO_PKEY) { + if (sc->sc_devinfo & SAFE_DEVINFO_PKEY) { #if 0 printf(" key"); sc->sc_flags |= SAFE_FLAGS_KEY; @@ -387,26 +389,18 @@ safe_attach(device_t dev) crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0); #endif } - if (devinfo & SAFE_DEVINFO_DES) { + if (sc->sc_devinfo & SAFE_DEVINFO_DES) { printf(" des/3des"); - crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); } - if (devinfo & SAFE_DEVINFO_AES) { + if (sc->sc_devinfo & SAFE_DEVINFO_AES) { printf(" aes"); - crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); } - if (devinfo & SAFE_DEVINFO_MD5) { + if (sc->sc_devinfo & SAFE_DEVINFO_MD5) { printf(" md5"); - crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); } - if (devinfo & SAFE_DEVINFO_SHA1) { + if (sc->sc_devinfo & SAFE_DEVINFO_SHA1) { printf(" sha1"); - crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); } - printf(" null"); - crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0); /* XXX other supported algorithms */ printf("\n"); @@ -629,11 +623,11 @@ safe_feed(struct safe_softc *sc, struct safe_ringentry *re) #define N(a) (sizeof(a) / sizeof (a[0])) static void -safe_setup_enckey(struct safe_session *ses, caddr_t key) +safe_setup_enckey(struct safe_session *ses, const void *key) { int i; - bcopy(key, ses->ses_key, ses->ses_klen / 8); + bcopy(key, ses->ses_key, ses->ses_klen); /* PE is little-endian, insure proper byte order */ for (i = 0; i < N(ses->ses_key); i++) @@ -641,47 +635,30 @@ safe_setup_enckey(struct safe_session *ses, caddr_t key) } static void -safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen) +safe_setup_mackey(struct safe_session *ses, int algo, const uint8_t *key, + int klen) { MD5_CTX md5ctx; SHA1_CTX sha1ctx; int i; - - for (i = 0; i < klen; i++) - key[i] ^= HMAC_IPAD_VAL; - if (algo == CRYPTO_MD5_HMAC) { - MD5Init(&md5ctx); - MD5Update(&md5ctx, key, klen); - MD5Update(&md5ctx, hmac_ipad_buffer, MD5_BLOCK_LEN - klen); + hmac_init_ipad(&auth_hash_hmac_md5, key, klen, &md5ctx); bcopy(md5ctx.state, ses->ses_hminner, sizeof(md5ctx.state)); - } else { - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, key, klen); - SHA1Update(&sha1ctx, hmac_ipad_buffer, - SHA1_BLOCK_LEN - klen); - bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32)); - } - - for (i = 0; i < klen; i++) - key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - if (algo == CRYPTO_MD5_HMAC) { - MD5Init(&md5ctx); - MD5Update(&md5ctx, key, klen); - MD5Update(&md5ctx, hmac_opad_buffer, MD5_BLOCK_LEN - klen); + hmac_init_opad(&auth_hash_hmac_md5, key, klen, &md5ctx); bcopy(md5ctx.state, ses->ses_hmouter, sizeof(md5ctx.state)); + + explicit_bzero(&md5ctx, sizeof(md5ctx)); } else { - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, key, klen); - SHA1Update(&sha1ctx, hmac_opad_buffer, - SHA1_BLOCK_LEN - klen); + hmac_init_ipad(&auth_hash_hmac_sha1, key, klen, &sha1ctx); + bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32)); + + hmac_init_opad(&auth_hash_hmac_sha1, key, klen, &sha1ctx); bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32)); - } - for (i = 0; i < klen; i++) - key[i] ^= HMAC_OPAD_VAL; + explicit_bzero(&sha1ctx, sizeof(sha1ctx)); + } /* PE is little-endian, insure proper byte order */ for (i = 0; i < N(ses->ses_hminner); i++) { @@ -691,98 +668,147 @@ safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen) } #undef N -/* - * Allocate a new 'session' and return an encoded session id. 'sidp' - * contains our registration id, and should contain an encoded session - * id on successful allocation. - */ +static bool +safe_auth_supported(struct safe_softc *sc, + const struct crypto_session_params *csp) +{ + + switch (csp->csp_auth_alg) { + case CRYPTO_MD5_HMAC: + if ((sc->sc_devinfo & SAFE_DEVINFO_MD5) == 0) + return (false); + break; + case CRYPTO_SHA1_HMAC: + if ((sc->sc_devinfo & SAFE_DEVINFO_SHA1) == 0) + return (false); + break; + default: + return (false); + } + return (true); +} + +static bool +safe_cipher_supported(struct safe_softc *sc, + const struct crypto_session_params *csp) +{ + + switch (csp->csp_cipher_alg) { + case CRYPTO_DES_CBC: + case CRYPTO_3DES_CBC: + if ((sc->sc_devinfo & SAFE_DEVINFO_DES) == 0) + return (false); + if (csp->csp_ivlen != 8) + return (false); + if (csp->csp_cipher_alg == CRYPTO_DES_CBC) { + if (csp->csp_cipher_klen != 8) + return (false); + } else { + if (csp->csp_cipher_klen != 24) + return (false); + } + break; + case CRYPTO_AES_CBC: + if ((sc->sc_devinfo & SAFE_DEVINFO_AES) == 0) + return (false); + if (csp->csp_ivlen != 16) + return (false); + if (csp->csp_cipher_klen != 16 && + csp->csp_cipher_klen != 24 && + csp->csp_cipher_klen != 32) + return (false); + break; + } + return (true); +} + static int -safe_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +safe_probesession(device_t dev, const struct crypto_session_params *csp) { struct safe_softc *sc = device_get_softc(dev); - struct cryptoini *c, *encini = NULL, *macini = NULL; - struct safe_session *ses = NULL; - if (cri == NULL || sc == NULL) + if (csp->csp_flags != 0) return (EINVAL); - - for (c = cri; c != NULL; c = c->cri_next) { - if (c->cri_alg == CRYPTO_MD5_HMAC || - c->cri_alg == CRYPTO_SHA1_HMAC || - c->cri_alg == CRYPTO_NULL_HMAC) { - if (macini) - return (EINVAL); - macini = c; - } else if (c->cri_alg == CRYPTO_DES_CBC || - c->cri_alg == CRYPTO_3DES_CBC || - c->cri_alg == CRYPTO_AES_CBC || - c->cri_alg == CRYPTO_NULL_CBC) { - if (encini) - return (EINVAL); - encini = c; - } else + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!safe_auth_supported(sc, csp)) return (EINVAL); - } - if (encini == NULL && macini == NULL) + break; + case CSP_MODE_CIPHER: + if (!safe_cipher_supported(sc, csp)) + return (EINVAL); + break; + case CSP_MODE_ETA: + if (!safe_auth_supported(sc, csp) || + !safe_cipher_supported(sc, csp)) + return (EINVAL); + break; + default: return (EINVAL); - if (encini) { /* validate key length */ - switch (encini->cri_alg) { - case CRYPTO_DES_CBC: - if (encini->cri_klen != 64) - return (EINVAL); - break; - case CRYPTO_3DES_CBC: - if (encini->cri_klen != 192) - return (EINVAL); - break; - case CRYPTO_AES_CBC: - if (encini->cri_klen != 128 && - encini->cri_klen != 192 && - encini->cri_klen != 256) - return (EINVAL); - break; - } } - ses = crypto_get_driver_session(cses); - if (encini) { - /* get an IV */ - /* XXX may read fewer than requested */ - read_random(ses->ses_iv, sizeof(ses->ses_iv)); + return (CRYPTODEV_PROBE_HARDWARE); +} + +/* + * Allocate a new 'session'. + */ +static int +safe_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct safe_session *ses; - ses->ses_klen = encini->cri_klen; - if (encini->cri_key != NULL) - safe_setup_enckey(ses, encini->cri_key); + ses = crypto_get_driver_session(cses); + if (csp->csp_cipher_alg != 0) { + ses->ses_klen = csp->csp_cipher_klen; + if (csp->csp_cipher_key != NULL) + safe_setup_enckey(ses, csp->csp_cipher_key); } - if (macini) { - ses->ses_mlen = macini->cri_mlen; + if (csp->csp_auth_alg != 0) { + ses->ses_mlen = csp->csp_auth_mlen; if (ses->ses_mlen == 0) { - if (macini->cri_alg == CRYPTO_MD5_HMAC) + if (csp->csp_auth_alg == CRYPTO_MD5_HMAC) ses->ses_mlen = MD5_HASH_LEN; else ses->ses_mlen = SHA1_HASH_LEN; } - if (macini->cri_key != NULL) { - safe_setup_mackey(ses, macini->cri_alg, macini->cri_key, - macini->cri_klen / 8); + if (csp->csp_auth_key != NULL) { + safe_setup_mackey(ses, csp->csp_auth_alg, + csp->csp_auth_key, csp->csp_auth_klen); } } return (0); } +static bus_size_t +safe_crp_length(struct cryptop *crp) +{ + + switch (crp->crp_buf_type) { + case CRYPTO_BUF_MBUF: + return (crp->crp_mbuf->m_pkthdr.len); + case CRYPTO_BUF_UIO: + return (crp->crp_uio->uio_resid); + case CRYPTO_BUF_CONTIG: + return (crp->crp_ilen); + default: + panic("bad crp buffer type"); + } +} + static void -safe_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int error) +safe_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, int error) { struct safe_operand *op = arg; - DPRINTF(("%s: mapsize %u nsegs %d error %d\n", __func__, - (u_int) mapsize, nsegs, error)); + DPRINTF(("%s: nsegs %d error %d\n", __func__, + nsegs, error)); if (error != 0) return; - op->mapsize = mapsize; op->nsegs = nsegs; bcopy(seg, op->segs, nsegs * sizeof (seg[0])); } @@ -790,11 +816,10 @@ safe_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int static int safe_process(device_t dev, struct cryptop *crp, int hint) { - struct safe_softc *sc = device_get_softc(dev); + struct safe_softc *sc = device_get_softc(dev); + const struct crypto_session_params *csp; int err = 0, i, nicealign, uniform; - struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; - int bypass, oplen, ivsize; - caddr_t iv; + int bypass, oplen; int16_t coffset; struct safe_session *ses; struct safe_ringentry *re; @@ -802,11 +827,6 @@ safe_process(device_t dev, struct cryptop *crp, int hint) struct safe_pdesc *pd; u_int32_t cmd0, cmd1, staterec; - if (crp == NULL || crp->crp_callback == NULL || sc == NULL) { - safestats.st_invalid++; - return (EINVAL); - } - mtx_lock(&sc->sc_ringmtx); if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) { safestats.st_ringfull++; @@ -823,104 +843,46 @@ safe_process(device_t dev, struct cryptop *crp, int hint) re->re_crp = crp; - if (crp->crp_flags & CRYPTO_F_IMBUF) { - re->re_src_m = (struct mbuf *)crp->crp_buf; - re->re_dst_m = (struct mbuf *)crp->crp_buf; - } else if (crp->crp_flags & CRYPTO_F_IOV) { - re->re_src_io = (struct uio *)crp->crp_buf; - re->re_dst_io = (struct uio *)crp->crp_buf; - } else { - safestats.st_badflags++; - err = EINVAL; - goto errout; /* XXX we don't handle contiguous blocks! */ - } - sa = &re->re_sa; ses = crypto_get_driver_session(crp->crp_session); - - crd1 = crp->crp_desc; - if (crd1 == NULL) { - safestats.st_nodesc++; - err = EINVAL; - goto errout; - } - crd2 = crd1->crd_next; + csp = crypto_get_params(crp->crp_session); cmd0 = SAFE_SA_CMD0_BASIC; /* basic group operation */ cmd1 = 0; - if (crd2 == NULL) { - if (crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC || - crd1->crd_alg == CRYPTO_NULL_HMAC) { - maccrd = crd1; - enccrd = NULL; - cmd0 |= SAFE_SA_CMD0_OP_HASH; - } else if (crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_3DES_CBC || - crd1->crd_alg == CRYPTO_AES_CBC || - crd1->crd_alg == CRYPTO_NULL_CBC) { - maccrd = NULL; - enccrd = crd1; - cmd0 |= SAFE_SA_CMD0_OP_CRYPT; - } else { - safestats.st_badalg++; - err = EINVAL; - goto errout; - } - } else { - if ((crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC || - crd1->crd_alg == CRYPTO_NULL_HMAC) && - (crd2->crd_alg == CRYPTO_DES_CBC || - crd2->crd_alg == CRYPTO_3DES_CBC || - crd2->crd_alg == CRYPTO_AES_CBC || - crd2->crd_alg == CRYPTO_NULL_CBC) && - ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) { - maccrd = crd1; - enccrd = crd2; - } else if ((crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_3DES_CBC || - crd1->crd_alg == CRYPTO_AES_CBC || - crd1->crd_alg == CRYPTO_NULL_CBC) && - (crd2->crd_alg == CRYPTO_MD5_HMAC || - crd2->crd_alg == CRYPTO_SHA1_HMAC || - crd2->crd_alg == CRYPTO_NULL_HMAC) && - (crd1->crd_flags & CRD_F_ENCRYPT)) { - enccrd = crd1; - maccrd = crd2; - } else { - safestats.st_badalg++; - err = EINVAL; - goto errout; - } + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + cmd0 |= SAFE_SA_CMD0_OP_HASH; + break; + case CSP_MODE_CIPHER: + cmd0 |= SAFE_SA_CMD0_OP_CRYPT; + break; + case CSP_MODE_ETA: cmd0 |= SAFE_SA_CMD0_OP_BOTH; + break; } - if (enccrd) { - if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) - safe_setup_enckey(ses, enccrd->crd_key); + if (csp->csp_cipher_alg != 0) { + if (crp->crp_cipher_key != NULL) + safe_setup_enckey(ses, crp->crp_cipher_key); - if (enccrd->crd_alg == CRYPTO_DES_CBC) { + switch (csp->csp_cipher_alg) { + case CRYPTO_DES_CBC: cmd0 |= SAFE_SA_CMD0_DES; cmd1 |= SAFE_SA_CMD1_CBC; - ivsize = 2*sizeof(u_int32_t); - } else if (enccrd->crd_alg == CRYPTO_3DES_CBC) { + break; + case CRYPTO_3DES_CBC: cmd0 |= SAFE_SA_CMD0_3DES; cmd1 |= SAFE_SA_CMD1_CBC; - ivsize = 2*sizeof(u_int32_t); - } else if (enccrd->crd_alg == CRYPTO_AES_CBC) { + break; + case CRYPTO_AES_CBC: cmd0 |= SAFE_SA_CMD0_AES; cmd1 |= SAFE_SA_CMD1_CBC; - if (ses->ses_klen == 128) + if (ses->ses_klen * 8 == 128) cmd1 |= SAFE_SA_CMD1_AES128; - else if (ses->ses_klen == 192) + else if (ses->ses_klen * 8 == 192) cmd1 |= SAFE_SA_CMD1_AES192; else cmd1 |= SAFE_SA_CMD1_AES256; - ivsize = 4*sizeof(u_int32_t); - } else { - cmd0 |= SAFE_SA_CMD0_CRYPT_NULL; - ivsize = 0; } /* @@ -932,32 +894,28 @@ safe_process(device_t dev, struct cryptop *crp, int hint) * in the state record and set the hash/crypt offset to * copy both the header+IV. */ - if (enccrd->crd_flags & CRD_F_ENCRYPT) { + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(re->re_sastate.sa_saved_iv, csp->csp_ivlen, 0); + crypto_copyback(crp, crp->crp_iv_start, csp->csp_ivlen, + re->re_sastate.sa_saved_iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(re->re_sastate.sa_saved_iv, crp->crp_iv, + csp->csp_ivlen); + else + crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, + re->re_sastate.sa_saved_iv); + cmd0 |= SAFE_SA_CMD0_IVLD_STATE; + + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { cmd0 |= SAFE_SA_CMD0_OUTBOUND; - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) - iv = enccrd->crd_iv; - else - iv = (caddr_t) ses->ses_iv; - if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) { - crypto_copyback(crp->crp_flags, crp->crp_buf, - enccrd->crd_inject, ivsize, iv); - } - bcopy(iv, re->re_sastate.sa_saved_iv, ivsize); - cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV; - re->re_flags |= SAFE_QFLAGS_COPYOUTIV; + /* + * XXX: I suspect we don't need this since we + * don't save the returned IV. + */ + cmd0 |= SAFE_SA_CMD0_SAVEIV; } else { cmd0 |= SAFE_SA_CMD0_INBOUND; - - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) { - bcopy(enccrd->crd_iv, - re->re_sastate.sa_saved_iv, ivsize); - } else { - crypto_copydata(crp->crp_flags, crp->crp_buf, - enccrd->crd_inject, ivsize, - (caddr_t)re->re_sastate.sa_saved_iv); - } - cmd0 |= SAFE_SA_CMD0_IVLD_STATE; } /* * For basic encryption use the zero pad algorithm. @@ -973,21 +931,23 @@ safe_process(device_t dev, struct cryptop *crp, int hint) bcopy(ses->ses_key, sa->sa_key, sizeof(sa->sa_key)); } - if (maccrd) { - if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) { - safe_setup_mackey(ses, maccrd->crd_alg, - maccrd->crd_key, maccrd->crd_klen / 8); + if (csp->csp_auth_alg != 0) { + if (crp->crp_auth_key != NULL) { + safe_setup_mackey(ses, csp->csp_auth_alg, + crp->crp_auth_key, csp->csp_auth_klen); } - if (maccrd->crd_alg == CRYPTO_MD5_HMAC) { + switch (csp->csp_auth_alg) { + case CRYPTO_MD5_HMAC: cmd0 |= SAFE_SA_CMD0_MD5; cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */ - } else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) { + break; + case CRYPTO_SHA1_HMAC: cmd0 |= SAFE_SA_CMD0_SHA1; cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */ - } else { - cmd0 |= SAFE_SA_CMD0_HASH_NULL; + break; } + /* * Digest data is loaded from the SA and the hash * result is saved to the state block where we @@ -1003,38 +963,32 @@ safe_process(device_t dev, struct cryptop *crp, int hint) re->re_flags |= SAFE_QFLAGS_COPYOUTICV; } - if (enccrd && maccrd) { + if (csp->csp_mode == CSP_MODE_ETA) { /* - * The offset from hash data to the start of - * crypt data is the difference in the skips. + * The driver only supports ETA requests where there + * is no gap between the AAD and payload. */ - bypass = maccrd->crd_skip; - coffset = enccrd->crd_skip - maccrd->crd_skip; - if (coffset < 0) { - DPRINTF(("%s: hash does not precede crypt; " - "mac skip %u enc skip %u\n", - __func__, maccrd->crd_skip, enccrd->crd_skip)); - safestats.st_skipmismatch++; - err = EINVAL; - goto errout; - } - oplen = enccrd->crd_skip + enccrd->crd_len; - if (maccrd->crd_skip + maccrd->crd_len != oplen) { - DPRINTF(("%s: hash amount %u != crypt amount %u\n", - __func__, maccrd->crd_skip + maccrd->crd_len, - oplen)); + if (crp->crp_aad_length != 0 && + crp->crp_aad_start + crp->crp_aad_length != + crp->crp_payload_start) { safestats.st_lenmismatch++; err = EINVAL; goto errout; } + if (crp->crp_aad_length != 0) + bypass = crp->crp_aad_start; + else + bypass = crp->crp_payload_start; + coffset = crp->crp_aad_length; + oplen = crp->crp_payload_start + crp->crp_payload_length; #ifdef SAFE_DEBUG if (safe_debug) { - printf("mac: skip %d, len %d, inject %d\n", - maccrd->crd_skip, maccrd->crd_len, - maccrd->crd_inject); - printf("enc: skip %d, len %d, inject %d\n", - enccrd->crd_skip, enccrd->crd_len, - enccrd->crd_inject); + printf("AAD: skip %d, len %d, digest %d\n", + crp->crp_aad_start, crp->crp_aad_length, + crp->crp_digest_start); + printf("payload: skip %d, len %d, IV %d\n", + crp->crp_payload_start, crp->crp_payload_length, + crp->crp_iv_start); printf("bypass %d coffset %d oplen %d\n", bypass, coffset, oplen); } @@ -1070,13 +1024,8 @@ safe_process(device_t dev, struct cryptop *crp, int hint) */ cmd1 |= SAFE_SA_CMD1_MUTABLE; } else { - if (enccrd) { - bypass = enccrd->crd_skip; - oplen = bypass + enccrd->crd_len; - } else { - bypass = maccrd->crd_skip; - oplen = bypass + maccrd->crd_len; - } + bypass = crp->crp_payload_start; + oplen = bypass + crp->crp_payload_length; coffset = 0; } /* XXX verify multiple of 4 when using s/g */ @@ -1092,27 +1041,15 @@ safe_process(device_t dev, struct cryptop *crp, int hint) err = ENOMEM; goto errout; } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (bus_dmamap_load_mbuf(sc->sc_srcdmat, re->re_src_map, - re->re_src_m, safe_op_cb, - &re->re_src, BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_srcdmat, re->re_src_map); - re->re_src_map = NULL; - safestats.st_noload++; - err = ENOMEM; - goto errout; - } - } else if (crp->crp_flags & CRYPTO_F_IOV) { - if (bus_dmamap_load_uio(sc->sc_srcdmat, re->re_src_map, - re->re_src_io, safe_op_cb, - &re->re_src, BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_srcdmat, re->re_src_map); - re->re_src_map = NULL; - safestats.st_noload++; - err = ENOMEM; - goto errout; - } + if (bus_dmamap_load_crp(sc->sc_srcdmat, re->re_src_map, crp, safe_op_cb, + &re->re_src, BUS_DMA_NOWAIT) != 0) { + bus_dmamap_destroy(sc->sc_srcdmat, re->re_src_map); + re->re_src_map = NULL; + safestats.st_noload++; + err = ENOMEM; + goto errout; } + re->re_src_mapsize = safe_crp_length(crp); nicealign = safe_dmamap_aligned(&re->re_src); uniform = safe_dmamap_uniform(&re->re_src); @@ -1143,211 +1080,175 @@ safe_process(device_t dev, struct cryptop *crp, int hint) re->re_desc.d_src = re->re_src_segs[0].ds_addr; } - if (enccrd == NULL && maccrd != NULL) { + if (csp->csp_mode == CSP_MODE_DIGEST) { /* * Hash op; no destination needed. */ } else { - if (crp->crp_flags & CRYPTO_F_IOV) { - if (!nicealign) { - safestats.st_iovmisaligned++; - err = EINVAL; + if (nicealign && uniform == 1) { + /* + * Source layout is suitable for direct + * sharing of the DMA map and segment list. + */ + re->re_dst = re->re_src; + } else if (nicealign && uniform == 2) { + /* + * The source is properly aligned but requires a + * different particle list to handle DMA of the + * result. Create a new map and do the load to + * create the segment list. The particle + * descriptor setup code below will handle the + * rest. + */ + if (bus_dmamap_create(sc->sc_dstdmat, BUS_DMA_NOWAIT, + &re->re_dst_map)) { + safestats.st_nomap++; + err = ENOMEM; goto errout; } - if (uniform != 1) { - /* - * Source is not suitable for direct use as - * the destination. Create a new scatter/gather - * list based on the destination requirements - * and check if that's ok. - */ - if (bus_dmamap_create(sc->sc_dstdmat, - BUS_DMA_NOWAIT, &re->re_dst_map)) { - safestats.st_nomap++; - err = ENOMEM; - goto errout; - } - if (bus_dmamap_load_uio(sc->sc_dstdmat, - re->re_dst_map, re->re_dst_io, - safe_op_cb, &re->re_dst, - BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dstdmat, - re->re_dst_map); - re->re_dst_map = NULL; - safestats.st_noload++; - err = ENOMEM; - goto errout; - } - uniform = safe_dmamap_uniform(&re->re_dst); - if (!uniform) { - /* - * There's no way to handle the DMA - * requirements with this uio. We - * could create a separate DMA area for - * the result and then copy it back, - * but for now we just bail and return - * an error. Note that uio requests - * > SAFE_MAX_DSIZE are handled because - * the DMA map and segment list for the - * destination wil result in a - * destination particle list that does - * the necessary scatter DMA. - */ - safestats.st_iovnotuniform++; - err = EINVAL; - goto errout; - } - } else - re->re_dst = re->re_src; - } else if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (nicealign && uniform == 1) { - /* - * Source layout is suitable for direct - * sharing of the DMA map and segment list. - */ - re->re_dst = re->re_src; - } else if (nicealign && uniform == 2) { - /* - * The source is properly aligned but requires a - * different particle list to handle DMA of the - * result. Create a new map and do the load to - * create the segment list. The particle - * descriptor setup code below will handle the - * rest. - */ - if (bus_dmamap_create(sc->sc_dstdmat, - BUS_DMA_NOWAIT, &re->re_dst_map)) { - safestats.st_nomap++; - err = ENOMEM; - goto errout; + if (bus_dmamap_load_crp(sc->sc_dstdmat, re->re_dst_map, + crp, safe_op_cb, &re->re_dst, BUS_DMA_NOWAIT) != + 0) { + bus_dmamap_destroy(sc->sc_dstdmat, + re->re_dst_map); + re->re_dst_map = NULL; + safestats.st_noload++; + err = ENOMEM; + goto errout; + } + } else if (crp->crp_buf_type == CRYPTO_BUF_MBUF) { + int totlen, len; + struct mbuf *m, *top, **mp; + + /* + * DMA constraints require that we allocate a + * new mbuf chain for the destination. We + * allocate an entire new set of mbufs of + * optimal/required size and then tell the + * hardware to copy any bits that are not + * created as a byproduct of the operation. + */ + if (!nicealign) + safestats.st_unaligned++; + if (!uniform) + safestats.st_notuniform++; + totlen = re->re_src_mapsize; + if (crp->crp_mbuf->m_flags & M_PKTHDR) { + len = MHLEN; + MGETHDR(m, M_NOWAIT, MT_DATA); + if (m && !m_dup_pkthdr(m, crp->crp_mbuf, + M_NOWAIT)) { + m_free(m); + m = NULL; } - if (bus_dmamap_load_mbuf(sc->sc_dstdmat, - re->re_dst_map, re->re_dst_m, - safe_op_cb, &re->re_dst, - BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dstdmat, - re->re_dst_map); - re->re_dst_map = NULL; - safestats.st_noload++; - err = ENOMEM; + } else { + len = MLEN; + MGET(m, M_NOWAIT, MT_DATA); + } + if (m == NULL) { + safestats.st_nombuf++; + err = sc->sc_nqchip ? ERESTART : ENOMEM; + goto errout; + } + if (totlen >= MINCLSIZE) { + if (!(MCLGET(m, M_NOWAIT))) { + m_free(m); + safestats.st_nomcl++; + err = sc->sc_nqchip ? + ERESTART : ENOMEM; goto errout; } - } else { /* !(aligned and/or uniform) */ - int totlen, len; - struct mbuf *m, *top, **mp; + len = MCLBYTES; + } + m->m_len = len; + top = NULL; + mp = ⊤ - /* - * DMA constraints require that we allocate a - * new mbuf chain for the destination. We - * allocate an entire new set of mbufs of - * optimal/required size and then tell the - * hardware to copy any bits that are not - * created as a byproduct of the operation. - */ - if (!nicealign) - safestats.st_unaligned++; - if (!uniform) - safestats.st_notuniform++; - totlen = re->re_src_mapsize; - if (re->re_src_m->m_flags & M_PKTHDR) { - len = MHLEN; - MGETHDR(m, M_NOWAIT, MT_DATA); - if (m && !m_dup_pkthdr(m, re->re_src_m, - M_NOWAIT)) { - m_free(m); - m = NULL; + while (totlen > 0) { + if (top) { + MGET(m, M_NOWAIT, MT_DATA); + if (m == NULL) { + m_freem(top); + safestats.st_nombuf++; + err = sc->sc_nqchip ? + ERESTART : ENOMEM; + goto errout; } - } else { len = MLEN; - MGET(m, M_NOWAIT, MT_DATA); - } - if (m == NULL) { - safestats.st_nombuf++; - err = sc->sc_nqchip ? ERESTART : ENOMEM; - goto errout; } - if (totlen >= MINCLSIZE) { + if (top && totlen >= MINCLSIZE) { if (!(MCLGET(m, M_NOWAIT))) { - m_free(m); + *mp = m; + m_freem(top); safestats.st_nomcl++; err = sc->sc_nqchip ? - ERESTART : ENOMEM; + ERESTART : ENOMEM; goto errout; } len = MCLBYTES; } - m->m_len = len; - top = NULL; - mp = ⊤ - - while (totlen > 0) { - if (top) { - MGET(m, M_NOWAIT, MT_DATA); - if (m == NULL) { - m_freem(top); - safestats.st_nombuf++; - err = sc->sc_nqchip ? - ERESTART : ENOMEM; - goto errout; - } - len = MLEN; - } - if (top && totlen >= MINCLSIZE) { - if (!(MCLGET(m, M_NOWAIT))) { - *mp = m; - m_freem(top); - safestats.st_nomcl++; - err = sc->sc_nqchip ? - ERESTART : ENOMEM; - goto errout; - } - len = MCLBYTES; - } - m->m_len = len = min(totlen, len); - totlen -= len; - *mp = m; - mp = &m->m_next; - } - re->re_dst_m = top; - if (bus_dmamap_create(sc->sc_dstdmat, - BUS_DMA_NOWAIT, &re->re_dst_map) != 0) { - safestats.st_nomap++; - err = ENOMEM; - goto errout; - } - if (bus_dmamap_load_mbuf(sc->sc_dstdmat, - re->re_dst_map, re->re_dst_m, - safe_op_cb, &re->re_dst, - BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dstdmat, - re->re_dst_map); - re->re_dst_map = NULL; - safestats.st_noload++; - err = ENOMEM; - goto errout; - } - if (re->re_src.mapsize > oplen) { - /* - * There's data following what the - * hardware will copy for us. If this - * isn't just the ICV (that's going to - * be written on completion), copy it - * to the new mbufs - */ - if (!(maccrd && - (re->re_src.mapsize-oplen) == 12 && - maccrd->crd_inject == oplen)) - safe_mcopy(re->re_src_m, - re->re_dst_m, - oplen); - else - safestats.st_noicvcopy++; - } + m->m_len = len = min(totlen, len); + totlen -= len; + *mp = m; + mp = &m->m_next; + } + re->re_dst_m = top; + if (bus_dmamap_create(sc->sc_dstdmat, + BUS_DMA_NOWAIT, &re->re_dst_map) != 0) { + safestats.st_nomap++; + err = ENOMEM; + goto errout; + } + if (bus_dmamap_load_mbuf_sg(sc->sc_dstdmat, + re->re_dst_map, top, re->re_dst_segs, + &re->re_dst_nsegs, 0) != 0) { + bus_dmamap_destroy(sc->sc_dstdmat, + re->re_dst_map); + re->re_dst_map = NULL; + safestats.st_noload++; + err = ENOMEM; + goto errout; + } + re->re_dst_mapsize = re->re_src_mapsize; + if (re->re_src.mapsize > oplen) { + /* + * There's data following what the + * hardware will copy for us. If this + * isn't just the ICV (that's going to + * be written on completion), copy it + * to the new mbufs + */ + if (!(csp->csp_mode == CSP_MODE_ETA && + (re->re_src.mapsize-oplen) == ses->ses_mlen && + crp->crp_digest_start == oplen)) + safe_mcopy(crp->crp_mbuf, re->re_dst_m, + oplen); + else + safestats.st_noicvcopy++; } } else { - safestats.st_badflags++; - err = EINVAL; - goto errout; + if (!nicealign) { + safestats.st_iovmisaligned++; + err = EINVAL; + goto errout; + } else { + /* + * There's no way to handle the DMA + * requirements with this uio. We + * could create a separate DMA area for + * the result and then copy it back, + * but for now we just bail and return + * an error. Note that uio requests + * > SAFE_MAX_DSIZE are handled because + * the DMA map and segment list for the + * destination wil result in a + * destination particle list that does + * the necessary scatter DMA. + */ + safestats.st_iovnotuniform++; + err = EINVAL; + goto errout; + } } if (re->re_dst.nsegs > 1) { @@ -1393,7 +1294,7 @@ safe_process(device_t dev, struct cryptop *crp, int hint) * ready for processing. */ re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI; - if (maccrd) + if (csp->csp_auth_alg != 0) re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL; re->re_desc.d_len = oplen | SAFE_PE_LEN_READY @@ -1412,7 +1313,7 @@ safe_process(device_t dev, struct cryptop *crp, int hint) return (0); errout: - if ((re->re_dst_m != NULL) && (re->re_src_m != re->re_dst_m)) + if (re->re_dst_m != NULL) m_freem(re->re_dst_m); if (re->re_dst_map != NULL && re->re_dst_map != re->re_src_map) { @@ -1436,11 +1337,13 @@ errout: static void safe_callback(struct safe_softc *sc, struct safe_ringentry *re) { + const struct crypto_session_params *csp; struct cryptop *crp = (struct cryptop *)re->re_crp; struct safe_session *ses; - struct cryptodesc *crd; + uint8_t hash[HASH_MAX_LEN]; ses = crypto_get_driver_session(crp->crp_session); + csp = crypto_get_params(crp->crp_session); safestats.st_opackets++; safestats.st_obytes += re->re_dst.mapsize; @@ -1454,6 +1357,9 @@ safe_callback(struct safe_softc *sc, struct safe_ringentry *re) safestats.st_peoperr++; crp->crp_etype = EIO; /* something more meaningful? */ } + + /* XXX: Should crp_mbuf be updated to re->re_dst_m if it is non-NULL? */ + if (re->re_dst_map != NULL && re->re_dst_map != re->re_src_map) { bus_dmamap_sync(sc->sc_dstdmat, re->re_dst_map, BUS_DMASYNC_POSTREAD); @@ -1464,58 +1370,29 @@ safe_callback(struct safe_softc *sc, struct safe_ringentry *re) bus_dmamap_unload(sc->sc_srcdmat, re->re_src_map); bus_dmamap_destroy(sc->sc_srcdmat, re->re_src_map); - /* - * If result was written to a differet mbuf chain, swap - * it in as the return value and reclaim the original. - */ - if ((crp->crp_flags & CRYPTO_F_IMBUF) && re->re_src_m != re->re_dst_m) { - m_freem(re->re_src_m); - crp->crp_buf = (caddr_t)re->re_dst_m; - } - - if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) { - /* copy out IV for future use */ - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - int ivsize; - - if (crd->crd_alg == CRYPTO_DES_CBC || - crd->crd_alg == CRYPTO_3DES_CBC) { - ivsize = 2*sizeof(u_int32_t); - } else if (crd->crd_alg == CRYPTO_AES_CBC) { - ivsize = 4*sizeof(u_int32_t); - } else - continue; - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_skip + crd->crd_len - ivsize, ivsize, - (caddr_t)ses->ses_iv); - break; - } - } - if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) { - /* copy out ICV result */ - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - if (!(crd->crd_alg == CRYPTO_MD5_HMAC || - crd->crd_alg == CRYPTO_SHA1_HMAC || - crd->crd_alg == CRYPTO_NULL_HMAC)) - continue; - if (crd->crd_alg == CRYPTO_SHA1_HMAC) { - /* - * SHA-1 ICV's are byte-swapped; fix 'em up - * before copy them to their destination. - */ - re->re_sastate.sa_saved_indigest[0] = - bswap32(re->re_sastate.sa_saved_indigest[0]); - re->re_sastate.sa_saved_indigest[1] = - bswap32(re->re_sastate.sa_saved_indigest[1]); - re->re_sastate.sa_saved_indigest[2] = - bswap32(re->re_sastate.sa_saved_indigest[2]); - } - crypto_copyback(crp->crp_flags, crp->crp_buf, - crd->crd_inject, ses->ses_mlen, - (caddr_t)re->re_sastate.sa_saved_indigest); - break; + if (csp->csp_auth_alg == CRYPTO_SHA1_HMAC) { + /* + * SHA-1 ICV's are byte-swapped; fix 'em up + * before copying them to their destination. + */ + re->re_sastate.sa_saved_indigest[0] = + bswap32(re->re_sastate.sa_saved_indigest[0]); + re->re_sastate.sa_saved_indigest[1] = + bswap32(re->re_sastate.sa_saved_indigest[1]); + re->re_sastate.sa_saved_indigest[2] = + bswap32(re->re_sastate.sa_saved_indigest[2]); } + + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, crp->crp_digest_start, + ses->ses_mlen, hash); + if (timingsafe_bcmp(re->re_sastate.sa_saved_indigest, + hash, ses->ses_mlen) != 0) + crp->crp_etype = EBADMSG; + } else + crypto_copyback(crp, crp->crp_digest_start, + ses->ses_mlen, re->re_sastate.sa_saved_indigest); } crypto_done(crp); } @@ -1921,7 +1798,7 @@ safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re) /* * Free header MCR */ - if ((re->re_dst_m != NULL) && (re->re_src_m != re->re_dst_m)) + if (re->re_dst_m != NULL) m_freem(re->re_dst_m); crp = (struct cryptop *)re->re_crp; diff --git a/sys/dev/safe/safevar.h b/sys/dev/safe/safevar.h index 024d00564562..e7d238669ed6 100644 --- a/sys/dev/safe/safevar.h +++ b/sys/dev/safe/safevar.h @@ -75,10 +75,6 @@ struct safe_dma_alloc { * where each is mapped for DMA. */ struct safe_operand { - union { - struct mbuf *m; - struct uio *io; - } u; bus_dmamap_t map; bus_size_t mapsize; int nsegs; @@ -109,22 +105,18 @@ struct safe_ringentry { struct safe_operand re_src; /* source operand */ struct safe_operand re_dst; /* destination operand */ + struct mbuf *re_dst_m; int unused; int re_flags; -#define SAFE_QFLAGS_COPYOUTIV 0x1 /* copy back on completion */ #define SAFE_QFLAGS_COPYOUTICV 0x2 /* copy back on completion */ }; -#define re_src_m re_src.u.m -#define re_src_io re_src.u.io #define re_src_map re_src.map #define re_src_nsegs re_src.nsegs #define re_src_segs re_src.segs #define re_src_mapsize re_src.mapsize -#define re_dst_m re_dst.u.m -#define re_dst_io re_dst.u.io #define re_dst_map re_dst.map #define re_dst_nsegs re_dst.nsegs #define re_dst_segs re_dst.segs @@ -138,7 +130,6 @@ struct safe_session { u_int32_t ses_mlen; /* hmac length in bytes */ u_int32_t ses_hminner[5]; /* hmac inner state */ u_int32_t ses_hmouter[5]; /* hmac outer state */ - u_int32_t ses_iv[4]; /* DES/3DES/AES iv */ }; struct safe_softc { @@ -157,6 +148,7 @@ struct safe_softc { int sc_suspended; int sc_needwakeup; /* notify crypto layer */ int32_t sc_cid; /* crypto tag */ + uint32_t sc_devinfo; struct safe_dma_alloc sc_ringalloc; /* PE ring allocation state */ struct safe_ringentry *sc_ring; /* PE ring */ struct safe_ringentry *sc_ringtop; /* PE ring top */ diff --git a/sys/dev/sec/sec.c b/sys/dev/sec/sec.c index 76f808757845..3b3ea0018060 100644 --- a/sys/dev/sec/sec.c +++ b/sys/dev/sec/sec.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <opencrypto/cryptodev.h> +#include <opencrypto/xform_auth.h> #include "cryptodev_if.h" #include <dev/ofw/ofw_bus_subr.h> @@ -74,7 +75,7 @@ static int sec_init(struct sec_softc *sc); static int sec_alloc_dma_mem(struct sec_softc *sc, struct sec_dma_mem *dma_mem, bus_size_t size); static int sec_desc_map_dma(struct sec_softc *sc, - struct sec_dma_mem *dma_mem, void *mem, bus_size_t size, int type, + struct sec_dma_mem *dma_mem, struct cryptop *crp, bus_size_t size, struct sec_desc_map_info *sdmi); static void sec_free_dma_mem(struct sec_dma_mem *dma_mem); static void sec_enqueue(struct sec_softc *sc); @@ -82,48 +83,43 @@ static int sec_enqueue_desc(struct sec_softc *sc, struct sec_desc *desc, int channel); static int sec_eu_channel(struct sec_softc *sc, int eu); static int sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, - u_int n, void *data, bus_size_t doffset, bus_size_t dsize, int dtype); + u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize); static int sec_make_pointer_direct(struct sec_softc *sc, struct sec_desc *desc, u_int n, bus_addr_t data, bus_size_t dsize); +static int sec_probesession(device_t dev, + const struct crypto_session_params *csp); static int sec_newsession(device_t dev, crypto_session_t cses, - struct cryptoini *cri); + const struct crypto_session_params *csp); static int sec_process(device_t dev, struct cryptop *crp, int hint); -static int sec_split_cri(struct cryptoini *cri, struct cryptoini **enc, - struct cryptoini **mac); -static int sec_split_crp(struct cryptop *crp, struct cryptodesc **enc, - struct cryptodesc **mac); static int sec_build_common_ns_desc(struct sec_softc *sc, - struct sec_desc *desc, struct sec_session *ses, struct cryptop *crp, - struct cryptodesc *enc, int buftype); + struct sec_desc *desc, const struct crypto_session_params *csp, + struct cryptop *crp); static int sec_build_common_s_desc(struct sec_softc *sc, - struct sec_desc *desc, struct sec_session *ses, struct cryptop *crp, - struct cryptodesc *enc, struct cryptodesc *mac, int buftype); + struct sec_desc *desc, const struct crypto_session_params *csp, + struct cryptop *crp); static struct sec_desc *sec_find_desc(struct sec_softc *sc, bus_addr_t paddr); /* AESU */ -static int sec_aesu_newsession(struct sec_softc *sc, - struct sec_session *ses, struct cryptoini *enc, struct cryptoini *mac); +static bool sec_aesu_newsession(const struct crypto_session_params *csp); static int sec_aesu_make_desc(struct sec_softc *sc, - struct sec_session *ses, struct sec_desc *desc, struct cryptop *crp, - int buftype); + const struct crypto_session_params *csp, struct sec_desc *desc, + struct cryptop *crp); /* DEU */ -static int sec_deu_newsession(struct sec_softc *sc, - struct sec_session *ses, struct cryptoini *enc, struct cryptoini *mac); +static bool sec_deu_newsession(const struct crypto_session_params *csp); static int sec_deu_make_desc(struct sec_softc *sc, - struct sec_session *ses, struct sec_desc *desc, struct cryptop *crp, - int buftype); + const struct crypto_session_params *csp, struct sec_desc *desc, + struct cryptop *crp); /* MDEU */ -static int sec_mdeu_can_handle(u_int alg); -static int sec_mdeu_config(struct cryptodesc *crd, +static bool sec_mdeu_can_handle(u_int alg); +static int sec_mdeu_config(const struct crypto_session_params *csp, u_int *eu, u_int *mode, u_int *hashlen); -static int sec_mdeu_newsession(struct sec_softc *sc, - struct sec_session *ses, struct cryptoini *enc, struct cryptoini *mac); +static bool sec_mdeu_newsession(const struct crypto_session_params *csp); static int sec_mdeu_make_desc(struct sec_softc *sc, - struct sec_session *ses, struct sec_desc *desc, struct cryptop *crp, - int buftype); + const struct crypto_session_params *csp, struct sec_desc *desc, + struct cryptop *crp); static device_method_t sec_methods[] = { /* Device interface */ @@ -136,6 +132,7 @@ static device_method_t sec_methods[] = { DEVMETHOD(device_shutdown, sec_shutdown), /* Crypto methods */ + DEVMETHOD(cryptodev_probesession, sec_probesession), DEVMETHOD(cryptodev_newsession, sec_newsession), DEVMETHOD(cryptodev_process, sec_process), @@ -362,24 +359,6 @@ sec_attach(device_t dev) if (error) goto fail6; - /* Register in OCF (AESU) */ - crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); - - /* Register in OCF (DEU) */ - crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); - - /* Register in OCF (MDEU) */ - crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0); - if (sc->sc_version >= 3) { - crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0); - } - return (0); fail6: @@ -545,9 +524,12 @@ sec_release_intr(struct sec_softc *sc, struct resource *ires, void *ihand, static void sec_primary_intr(void *arg) { + struct sec_session *ses; struct sec_softc *sc = arg; struct sec_desc *desc; + struct cryptop *crp; uint64_t isr; + uint8_t hash[HASH_MAX_LEN]; int i, wakeup = 0; SEC_LOCK(sc, controller); @@ -595,7 +577,26 @@ sec_primary_intr(void *arg) SEC_DESC_SYNC_POINTERS(desc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - desc->sd_crp->crp_etype = desc->sd_error; + crp = desc->sd_crp; + crp->crp_etype = desc->sd_error; + if (crp->crp_etype == 0) { + ses = crypto_get_driver_session(crp->crp_session); + if (ses->ss_mlen != 0) { + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, + crp->crp_digest_start, + ses->ss_mlen, hash); + if (timingsafe_bcmp( + desc->sd_desc->shd_digest, + hash, ses->ss_mlen) != 0) + crp->crp_etype = EBADMSG; + } else + crypto_copyback(crp, + crp->crp_digest_start, + ses->ss_mlen, + desc->sd_desc->shd_digest); + } + } crypto_done(desc->sd_crp); SEC_DESC_FREE_POINTERS(desc); @@ -786,14 +787,6 @@ sec_dma_map_desc_cb(void *arg, bus_dma_segment_t *segs, int nseg, sdmi->sdmi_lt_last = lt; } -static void -sec_dma_map_desc_cb2(void *arg, bus_dma_segment_t *segs, int nseg, - bus_size_t size, int error) -{ - - sec_dma_map_desc_cb(arg, segs, nseg, error); -} - static int sec_alloc_dma_mem(struct sec_softc *sc, struct sec_dma_mem *dma_mem, bus_size_t size) @@ -851,22 +844,22 @@ err1: } static int -sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem, void *mem, - bus_size_t size, int type, struct sec_desc_map_info *sdmi) +sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem, + struct cryptop *crp, bus_size_t size, struct sec_desc_map_info *sdmi) { int error; if (dma_mem->dma_vaddr != NULL) return (EBUSY); - switch (type) { - case SEC_MEMORY: + switch (crp->crp_buf_type) { + case CRYPTO_BUF_CONTIG: break; - case SEC_UIO: + case CRYPTO_BUF_UIO: size = SEC_FREE_LT_CNT(sc) * SEC_MAX_DMA_BLOCK_SIZE; break; - case SEC_MBUF: - size = m_length((struct mbuf*)mem, NULL); + case CRYPTO_BUF_MBUF: + size = m_length(crp->crp_mbuf, NULL); break; default: return (EINVAL); @@ -899,20 +892,8 @@ sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem, void *mem, return (error); } - switch (type) { - case SEC_MEMORY: - error = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, - mem, size, sec_dma_map_desc_cb, sdmi, BUS_DMA_NOWAIT); - break; - case SEC_UIO: - error = bus_dmamap_load_uio(dma_mem->dma_tag, dma_mem->dma_map, - mem, sec_dma_map_desc_cb2, sdmi, BUS_DMA_NOWAIT); - break; - case SEC_MBUF: - error = bus_dmamap_load_mbuf(dma_mem->dma_tag, dma_mem->dma_map, - mem, sec_dma_map_desc_cb2, sdmi, BUS_DMA_NOWAIT); - break; - } + error = bus_dmamap_load_crp(dma_mem->dma_tag, dma_mem->dma_map, crp, + sec_dma_map_desc_cb, sdmi, BUS_DMA_NOWAIT); if (error) { device_printf(sc->sc_dev, "cannot get address of the DMA" @@ -923,7 +904,7 @@ sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem, void *mem, } dma_mem->dma_is_map = 1; - dma_mem->dma_vaddr = mem; + dma_mem->dma_vaddr = crp; return (0); } @@ -1130,7 +1111,7 @@ sec_make_pointer_direct(struct sec_softc *sc, struct sec_desc *desc, u_int n, static int sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, - u_int n, void *data, bus_size_t doffset, bus_size_t dsize, int dtype) + u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize) { struct sec_desc_map_info sdmi = { sc, dsize, doffset, NULL, NULL, 0 }; struct sec_hw_desc_ptr *ptr; @@ -1138,14 +1119,8 @@ sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, SEC_LOCK_ASSERT(sc, descriptors); - /* For flat memory map only requested region */ - if (dtype == SEC_MEMORY) { - data = (uint8_t*)(data) + doffset; - sdmi.sdmi_offset = 0; - } - - error = sec_desc_map_dma(sc, &(desc->sd_ptr_dmem[n]), data, dsize, - dtype, &sdmi); + error = sec_desc_map_dma(sc, &(desc->sd_ptr_dmem[n]), crp, dsize, + &sdmi); if (error) return (error); @@ -1162,115 +1137,116 @@ sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, return (0); } -static int -sec_split_cri(struct cryptoini *cri, struct cryptoini **enc, - struct cryptoini **mac) +static bool +sec_cipher_supported(const struct crypto_session_params *csp) { - struct cryptoini *e, *m; - - e = cri; - m = cri->cri_next; - /* We can haldle only two operations */ - if (m && m->cri_next) - return (EINVAL); - - if (sec_mdeu_can_handle(e->cri_alg)) { - cri = m; - m = e; - e = cri; + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + /* AESU */ + if (csp->csp_ivlen != AES_BLOCK_LEN) + return (false); + break; + case CRYPTO_DES_CBC: + case CRYPTO_3DES_CBC: + /* DEU */ + if (csp->csp_ivlen != DES_BLOCK_LEN) + return (false); + break; + default: + return (false); } - if (m && !sec_mdeu_can_handle(m->cri_alg)) - return (EINVAL); + if (csp->csp_cipher_klen == 0 || csp->csp_cipher_klen > SEC_MAX_KEY_LEN) + return (false); - *enc = e; - *mac = m; + return (true); +} - return (0); +static bool +sec_auth_supported(struct sec_softc *sc, + const struct crypto_session_params *csp) +{ + + switch (csp->csp_auth_alg) { + case CRYPTO_SHA2_384_HMAC: + case CRYPTO_SHA2_512_HMAC: + if (sc->sc_version < 3) + return (false); + /* FALLTHROUGH */ + case CRYPTO_MD5_HMAC: + case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_256_HMAC: + if (csp->csp_auth_klen > SEC_MAX_KEY_LEN) + return (false); + break; + case CRYPTO_MD5: + case CRYPTO_SHA1: + break; + default: + return (false); + } + return (true); } static int -sec_split_crp(struct cryptop *crp, struct cryptodesc **enc, - struct cryptodesc **mac) +sec_probesession(device_t dev, const struct crypto_session_params *csp) { - struct cryptodesc *e, *m, *t; - - e = crp->crp_desc; - m = e->crd_next; + struct sec_softc *sc = device_get_softc(dev); - /* We can haldle only two operations */ - if (m && m->crd_next) + if (csp->csp_flags != 0) return (EINVAL); - - if (sec_mdeu_can_handle(e->crd_alg)) { - t = m; - m = e; - e = t; - } - - if (m && !sec_mdeu_can_handle(m->crd_alg)) + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!sec_auth_supported(sc, csp)) + return (EINVAL); + break; + case CSP_MODE_CIPHER: + if (!sec_cipher_supported(csp)) + return (EINVAL); + break; + case CSP_MODE_ETA: + if (!sec_auth_supported(sc, csp) || !sec_cipher_supported(csp)) + return (EINVAL); + break; + default: return (EINVAL); - - *enc = e; - *mac = m; - - return (0); + } + return (CRYPTODEV_PROBE_HARDWARE); } static int -sec_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +sec_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) { - struct sec_softc *sc = device_get_softc(dev); struct sec_eu_methods *eu = sec_eus; - struct cryptoini *enc = NULL; - struct cryptoini *mac = NULL; struct sec_session *ses; - int error = -1; - - error = sec_split_cri(cri, &enc, &mac); - if (error) - return (error); - - /* Check key lengths */ - if (enc && enc->cri_key && (enc->cri_klen / 8) > SEC_MAX_KEY_LEN) - return (E2BIG); - - if (mac && mac->cri_key && (mac->cri_klen / 8) > SEC_MAX_KEY_LEN) - return (E2BIG); - - /* Only SEC 3.0 supports digests larger than 256 bits */ - if (sc->sc_version < 3 && mac && mac->cri_klen > 256) - return (E2BIG); ses = crypto_get_driver_session(cses); /* Find EU for this session */ while (eu->sem_make_desc != NULL) { - error = eu->sem_newsession(sc, ses, enc, mac); - if (error >= 0) + if (eu->sem_newsession(csp)) break; - eu++; } - - /* If not found, return EINVAL */ - if (error < 0) - return (EINVAL); + KASSERT(eu->sem_make_desc != NULL, ("failed to find eu for session")); /* Save cipher key */ - if (enc && enc->cri_key) { - ses->ss_klen = enc->cri_klen / 8; - memcpy(ses->ss_key, enc->cri_key, ses->ss_klen); - } + if (csp->csp_cipher_key != NULL) + memcpy(ses->ss_key, csp->csp_cipher_key, csp->csp_cipher_klen); /* Save digest key */ - if (mac && mac->cri_key) { - ses->ss_mklen = mac->cri_klen / 8; - memcpy(ses->ss_mkey, mac->cri_key, ses->ss_mklen); + if (csp->csp_auth_key != NULL) + memcpy(ses->ss_mkey, csp->csp_auth_key, csp->csp_auth_klen); + + if (csp->csp_auth_alg != 0) { + if (csp->csp_auth_mlen == 0) + ses->ss_mlen = crypto_auth_hash(csp)->hashsize; + else + ses->ss_mlen = csp->csp_auth_mlen; } - ses->ss_eu = eu; return (0); } @@ -1279,11 +1255,12 @@ sec_process(device_t dev, struct cryptop *crp, int hint) { struct sec_softc *sc = device_get_softc(dev); struct sec_desc *desc = NULL; - struct cryptodesc *mac, *enc; + const struct crypto_session_params *csp; struct sec_session *ses; - int buftype, error = 0; + int error = 0; ses = crypto_get_driver_session(crp->crp_session); + csp = crypto_get_params(crp->crp_session); /* Check for input length */ if (crp->crp_ilen > SEC_MAX_DMA_BLOCK_SIZE) { @@ -1292,13 +1269,6 @@ sec_process(device_t dev, struct cryptop *crp, int hint) return (0); } - /* Get descriptors */ - if (sec_split_crp(crp, &enc, &mac)) { - crp->crp_etype = EINVAL; - crypto_done(crp); - return (0); - } - SEC_LOCK(sc, descriptors); SEC_DESC_SYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -1315,56 +1285,29 @@ sec_process(device_t dev, struct cryptop *crp, int hint) desc->sd_error = 0; desc->sd_crp = crp; - if (crp->crp_flags & CRYPTO_F_IOV) - buftype = SEC_UIO; - else if (crp->crp_flags & CRYPTO_F_IMBUF) - buftype = SEC_MBUF; - else - buftype = SEC_MEMORY; - - if (enc && enc->crd_flags & CRD_F_ENCRYPT) { - if (enc->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(desc->sd_desc->shd_iv, enc->crd_iv, - ses->ss_ivlen); - else - arc4rand(desc->sd_desc->shd_iv, ses->ss_ivlen, 0); - - if ((enc->crd_flags & CRD_F_IV_PRESENT) == 0) - crypto_copyback(crp->crp_flags, crp->crp_buf, - enc->crd_inject, ses->ss_ivlen, + if (csp->csp_cipher_alg != 0) { + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(desc->sd_desc->shd_iv, csp->csp_ivlen, 0); + crypto_copyback(crp, crp->crp_iv_start, csp->csp_ivlen, desc->sd_desc->shd_iv); - } else if (enc) { - if (enc->crd_flags & CRD_F_IV_EXPLICIT) - memcpy(desc->sd_desc->shd_iv, enc->crd_iv, - ses->ss_ivlen); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(desc->sd_desc->shd_iv, crp->crp_iv, + csp->csp_ivlen); else - crypto_copydata(crp->crp_flags, crp->crp_buf, - enc->crd_inject, ses->ss_ivlen, + crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, desc->sd_desc->shd_iv); } - if (enc && enc->crd_flags & CRD_F_KEY_EXPLICIT) { - if ((enc->crd_klen / 8) <= SEC_MAX_KEY_LEN) { - ses->ss_klen = enc->crd_klen / 8; - memcpy(ses->ss_key, enc->crd_key, ses->ss_klen); - } else - error = E2BIG; - } + if (crp->crp_cipher_key != NULL) + memcpy(ses->ss_key, crp->crp_cipher_key, csp->csp_cipher_klen); - if (!error && mac && mac->crd_flags & CRD_F_KEY_EXPLICIT) { - if ((mac->crd_klen / 8) <= SEC_MAX_KEY_LEN) { - ses->ss_mklen = mac->crd_klen / 8; - memcpy(ses->ss_mkey, mac->crd_key, ses->ss_mklen); - } else - error = E2BIG; - } + if (crp->crp_auth_key != NULL) + memcpy(ses->ss_mkey, crp->crp_auth_key, csp->csp_auth_klen); - if (!error) { - memcpy(desc->sd_desc->shd_key, ses->ss_key, ses->ss_klen); - memcpy(desc->sd_desc->shd_mkey, ses->ss_mkey, ses->ss_mklen); + memcpy(desc->sd_desc->shd_key, ses->ss_key, csp->csp_cipher_klen); + memcpy(desc->sd_desc->shd_mkey, ses->ss_mkey, csp->csp_auth_klen); - error = ses->ss_eu->sem_make_desc(sc, ses, desc, crp, buftype); - } + error = ses->ss_eu->sem_make_desc(sc, csp, desc, crp); if (error) { SEC_DESC_FREE_POINTERS(desc); @@ -1400,8 +1343,7 @@ sec_process(device_t dev, struct cryptop *crp, int hint) static int sec_build_common_ns_desc(struct sec_softc *sc, struct sec_desc *desc, - struct sec_session *ses, struct cryptop *crp, struct cryptodesc *enc, - int buftype) + const struct crypto_session_params *csp, struct cryptop *crp) { struct sec_hw_desc *hd = desc->sd_desc; int error; @@ -1417,25 +1359,25 @@ sec_build_common_ns_desc(struct sec_softc *sc, struct sec_desc *desc, /* Pointer 1: IV IN */ error = sec_make_pointer_direct(sc, desc, 1, desc->sd_desc_paddr + - offsetof(struct sec_hw_desc, shd_iv), ses->ss_ivlen); + offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen); if (error) return (error); /* Pointer 2: Cipher Key */ error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr + - offsetof(struct sec_hw_desc, shd_key), ses->ss_klen); + offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen); if (error) return (error); /* Pointer 3: Data IN */ - error = sec_make_pointer(sc, desc, 3, crp->crp_buf, enc->crd_skip, - enc->crd_len, buftype); + error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start, + crp->crp_payload_length); if (error) return (error); /* Pointer 4: Data OUT */ - error = sec_make_pointer(sc, desc, 4, crp->crp_buf, enc->crd_skip, - enc->crd_len, buftype); + error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start, + crp->crp_payload_length); if (error) return (error); @@ -1452,20 +1394,13 @@ sec_build_common_ns_desc(struct sec_softc *sc, struct sec_desc *desc, static int sec_build_common_s_desc(struct sec_softc *sc, struct sec_desc *desc, - struct sec_session *ses, struct cryptop *crp, struct cryptodesc *enc, - struct cryptodesc *mac, int buftype) + const struct crypto_session_params *csp, struct cryptop *crp) { struct sec_hw_desc *hd = desc->sd_desc; u_int eu, mode, hashlen; int error; - if (mac->crd_len < enc->crd_len) - return (EINVAL); - - if (mac->crd_skip + mac->crd_len != enc->crd_skip + enc->crd_len) - return (EINVAL); - - error = sec_mdeu_config(mac, &eu, &mode, &hashlen); + error = sec_mdeu_config(csp, &eu, &mode, &hashlen); if (error) return (error); @@ -1475,144 +1410,107 @@ sec_build_common_s_desc(struct sec_softc *sc, struct sec_desc *desc, /* Pointer 0: HMAC Key */ error = sec_make_pointer_direct(sc, desc, 0, desc->sd_desc_paddr + - offsetof(struct sec_hw_desc, shd_mkey), ses->ss_mklen); + offsetof(struct sec_hw_desc, shd_mkey), csp->csp_auth_klen); if (error) return (error); /* Pointer 1: HMAC-Only Data IN */ - error = sec_make_pointer(sc, desc, 1, crp->crp_buf, mac->crd_skip, - mac->crd_len - enc->crd_len, buftype); + error = sec_make_pointer(sc, desc, 1, crp, crp->crp_aad_start, + crp->crp_aad_length); if (error) return (error); /* Pointer 2: Cipher Key */ error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr + - offsetof(struct sec_hw_desc, shd_key), ses->ss_klen); + offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen); if (error) return (error); /* Pointer 3: IV IN */ error = sec_make_pointer_direct(sc, desc, 3, desc->sd_desc_paddr + - offsetof(struct sec_hw_desc, shd_iv), ses->ss_ivlen); + offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen); if (error) return (error); /* Pointer 4: Data IN */ - error = sec_make_pointer(sc, desc, 4, crp->crp_buf, enc->crd_skip, - enc->crd_len, buftype); + error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start, + crp->crp_payload_length); if (error) return (error); /* Pointer 5: Data OUT */ - error = sec_make_pointer(sc, desc, 5, crp->crp_buf, enc->crd_skip, - enc->crd_len, buftype); + error = sec_make_pointer(sc, desc, 5, crp, crp->crp_payload_start, + crp->crp_payload_length); if (error) return (error); /* Pointer 6: HMAC OUT */ - error = sec_make_pointer(sc, desc, 6, crp->crp_buf, mac->crd_inject, - hashlen, buftype); + error = sec_make_pointer_direct(sc, desc, 6, desc->sd_desc_paddr + + offsetof(struct sec_hw_desc, shd_digest), hashlen); return (error); } /* AESU */ -static int -sec_aesu_newsession(struct sec_softc *sc, struct sec_session *ses, - struct cryptoini *enc, struct cryptoini *mac) +static bool +sec_aesu_newsession(const struct crypto_session_params *csp) { - if (enc == NULL) - return (-1); - - if (enc->cri_alg != CRYPTO_AES_CBC) - return (-1); - - ses->ss_ivlen = AES_BLOCK_LEN; - - return (0); + return (csp->csp_cipher_alg == CRYPTO_AES_CBC); } static int -sec_aesu_make_desc(struct sec_softc *sc, struct sec_session *ses, - struct sec_desc *desc, struct cryptop *crp, int buftype) +sec_aesu_make_desc(struct sec_softc *sc, + const struct crypto_session_params *csp, struct sec_desc *desc, + struct cryptop *crp) { struct sec_hw_desc *hd = desc->sd_desc; - struct cryptodesc *enc, *mac; int error; - error = sec_split_crp(crp, &enc, &mac); - if (error) - return (error); - - if (!enc) - return (EINVAL); - hd->shd_eu_sel0 = SEC_EU_AESU; hd->shd_mode0 = SEC_AESU_MODE_CBC; - if (enc->crd_alg != CRYPTO_AES_CBC) - return (EINVAL); - - if (enc->crd_flags & CRD_F_ENCRYPT) { + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { hd->shd_mode0 |= SEC_AESU_MODE_ED; hd->shd_dir = 0; } else hd->shd_dir = 1; - if (mac) - error = sec_build_common_s_desc(sc, desc, ses, crp, enc, mac, - buftype); + if (csp->csp_mode == CSP_MODE_ETA) + error = sec_build_common_s_desc(sc, desc, csp, crp); else - error = sec_build_common_ns_desc(sc, desc, ses, crp, enc, - buftype); + error = sec_build_common_ns_desc(sc, desc, csp, crp); return (error); } /* DEU */ -static int -sec_deu_newsession(struct sec_softc *sc, struct sec_session *ses, - struct cryptoini *enc, struct cryptoini *mac) +static bool +sec_deu_newsession(const struct crypto_session_params *csp) { - if (enc == NULL) - return (-1); - - switch (enc->cri_alg) { + switch (csp->csp_cipher_alg) { case CRYPTO_DES_CBC: case CRYPTO_3DES_CBC: - break; + return (true); default: - return (-1); + return (false); } - - ses->ss_ivlen = DES_BLOCK_LEN; - - return (0); } static int -sec_deu_make_desc(struct sec_softc *sc, struct sec_session *ses, - struct sec_desc *desc, struct cryptop *crp, int buftype) +sec_deu_make_desc(struct sec_softc *sc, const struct crypto_session_params *csp, + struct sec_desc *desc, struct cryptop *crp) { struct sec_hw_desc *hd = desc->sd_desc; - struct cryptodesc *enc, *mac; int error; - error = sec_split_crp(crp, &enc, &mac); - if (error) - return (error); - - if (!enc) - return (EINVAL); - hd->shd_eu_sel0 = SEC_EU_DEU; hd->shd_mode0 = SEC_DEU_MODE_CBC; - switch (enc->crd_alg) { + switch (csp->csp_cipher_alg) { case CRYPTO_3DES_CBC: hd->shd_mode0 |= SEC_DEU_MODE_TS; break; @@ -1622,25 +1520,23 @@ sec_deu_make_desc(struct sec_softc *sc, struct sec_session *ses, return (EINVAL); } - if (enc->crd_flags & CRD_F_ENCRYPT) { + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { hd->shd_mode0 |= SEC_DEU_MODE_ED; hd->shd_dir = 0; } else hd->shd_dir = 1; - if (mac) - error = sec_build_common_s_desc(sc, desc, ses, crp, enc, mac, - buftype); + if (csp->csp_mode == CSP_MODE_ETA) + error = sec_build_common_s_desc(sc, desc, csp, crp); else - error = sec_build_common_ns_desc(sc, desc, ses, crp, enc, - buftype); + error = sec_build_common_ns_desc(sc, desc, csp, crp); return (error); } /* MDEU */ -static int +static bool sec_mdeu_can_handle(u_int alg) { switch (alg) { @@ -1651,20 +1547,21 @@ sec_mdeu_can_handle(u_int alg) case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: - return (1); + return (true); default: - return (0); + return (false); } } static int -sec_mdeu_config(struct cryptodesc *crd, u_int *eu, u_int *mode, u_int *hashlen) +sec_mdeu_config(const struct crypto_session_params *csp, u_int *eu, u_int *mode, + u_int *hashlen) { *mode = SEC_MDEU_MODE_PD | SEC_MDEU_MODE_INIT; *eu = SEC_EU_NONE; - switch (crd->crd_alg) { + switch (csp->csp_auth_alg) { case CRYPTO_MD5_HMAC: *mode |= SEC_MDEU_MODE_HMAC; /* FALLTHROUGH */ @@ -1703,34 +1600,23 @@ sec_mdeu_config(struct cryptodesc *crd, u_int *eu, u_int *mode, u_int *hashlen) return (0); } -static int -sec_mdeu_newsession(struct sec_softc *sc, struct sec_session *ses, - struct cryptoini *enc, struct cryptoini *mac) +static bool +sec_mdeu_newsession(const struct crypto_session_params *csp) { - if (mac && sec_mdeu_can_handle(mac->cri_alg)) - return (0); - - return (-1); + return (sec_mdeu_can_handle(csp->csp_auth_alg)); } static int -sec_mdeu_make_desc(struct sec_softc *sc, struct sec_session *ses, - struct sec_desc *desc, struct cryptop *crp, int buftype) +sec_mdeu_make_desc(struct sec_softc *sc, + const struct crypto_session_params *csp, + struct sec_desc *desc, struct cryptop *crp) { - struct cryptodesc *enc, *mac; struct sec_hw_desc *hd = desc->sd_desc; u_int eu, mode, hashlen; int error; - error = sec_split_crp(crp, &enc, &mac); - if (error) - return (error); - - if (enc) - return (EINVAL); - - error = sec_mdeu_config(mac, &eu, &mode, &hashlen); + error = sec_mdeu_config(csp, &eu, &mode, &hashlen); if (error) return (error); @@ -1754,7 +1640,7 @@ sec_mdeu_make_desc(struct sec_softc *sc, struct sec_session *ses, if (hd->shd_mode0 & SEC_MDEU_MODE_HMAC) error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr + offsetof(struct sec_hw_desc, - shd_mkey), ses->ss_mklen); + shd_mkey), csp->csp_auth_klen); else error = sec_make_pointer_direct(sc, desc, 2, 0, 0); @@ -1762,8 +1648,8 @@ sec_mdeu_make_desc(struct sec_softc *sc, struct sec_session *ses, return (error); /* Pointer 3: Input Data */ - error = sec_make_pointer(sc, desc, 3, crp->crp_buf, mac->crd_skip, - mac->crd_len, buftype); + error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start, + crp->crp_payload_length); if (error) return (error); @@ -1773,8 +1659,8 @@ sec_mdeu_make_desc(struct sec_softc *sc, struct sec_session *ses, return (error); /* Pointer 5: Hash out */ - error = sec_make_pointer(sc, desc, 5, crp->crp_buf, - mac->crd_inject, hashlen, buftype); + error = sec_make_pointer_direct(sc, desc, 5, desc->sd_desc_paddr + + offsetof(struct sec_hw_desc, shd_digest), hashlen); if (error) return (error); diff --git a/sys/dev/sec/sec.h b/sys/dev/sec/sec.h index 05b15039ad64..6ad482316a54 100644 --- a/sys/dev/sec/sec.h +++ b/sys/dev/sec/sec.h @@ -98,6 +98,7 @@ struct sec_hw_desc { uint8_t shd_iv[SEC_MAX_IV_LEN]; uint8_t shd_key[SEC_MAX_KEY_LEN]; uint8_t shd_mkey[SEC_MAX_KEY_LEN]; + uint8_t shd_digest[HASH_MAX_LEN]; } __packed__; #define shd_eu_sel0 shd_control.request.eu_sel0 @@ -144,21 +145,17 @@ struct sec_lt { }; struct sec_eu_methods { - int (*sem_newsession)(struct sec_softc *sc, - struct sec_session *ses, struct cryptoini *enc, - struct cryptoini *mac); + bool (*sem_newsession)(const struct crypto_session_params *csp); int (*sem_make_desc)(struct sec_softc *sc, - struct sec_session *ses, struct sec_desc *desc, - struct cryptop *crp, int buftype); + const struct crypto_session_params *csp, struct sec_desc *desc, + struct cryptop *crp); }; struct sec_session { struct sec_eu_methods *ss_eu; uint8_t ss_key[SEC_MAX_KEY_LEN]; uint8_t ss_mkey[SEC_MAX_KEY_LEN]; - u_int ss_klen; - u_int ss_mklen; - u_int ss_ivlen; + int ss_mlen; }; struct sec_desc_map_info { @@ -319,11 +316,6 @@ struct sec_softc { (((sc)->sc_lt_free_cnt - (sc)->sc_lt_alloc_cnt - 1) \ & (SEC_LT_ENTRIES - 1)) -/* DMA Maping defines */ -#define SEC_MEMORY 0 -#define SEC_UIO 1 -#define SEC_MBUF 2 - /* Size of SEC registers area */ #define SEC_IO_SIZE 0x10000 diff --git a/sys/dev/ubsec/ubsec.c b/sys/dev/ubsec/ubsec.c index 19f46458ac3b..e4b324e05f86 100644 --- a/sys/dev/ubsec/ubsec.c +++ b/sys/dev/ubsec/ubsec.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/sysctl.h> #include <sys/endian.h> +#include <sys/uio.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -70,10 +71,8 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/rman.h> -#include <crypto/sha1.h> #include <opencrypto/cryptodev.h> -#include <opencrypto/cryptosoft.h> -#include <sys/md5.h> +#include <opencrypto/xform_auth.h> #include <sys/random.h> #include <sys/kobj.h> @@ -111,7 +110,9 @@ static int ubsec_suspend(device_t); static int ubsec_resume(device_t); static int ubsec_shutdown(device_t); -static int ubsec_newsession(device_t, crypto_session_t, struct cryptoini *); +static int ubsec_probesession(device_t, const struct crypto_session_params *); +static int ubsec_newsession(device_t, crypto_session_t, + const struct crypto_session_params *); static int ubsec_process(device_t, struct cryptop *, int); static int ubsec_kprocess(device_t, struct cryptkop *, int); @@ -125,6 +126,7 @@ static device_method_t ubsec_methods[] = { DEVMETHOD(device_shutdown, ubsec_shutdown), /* crypto device methods */ + DEVMETHOD(cryptodev_probesession, ubsec_probesession), DEVMETHOD(cryptodev_newsession, ubsec_newsession), DEVMETHOD(cryptodev_process, ubsec_process), DEVMETHOD(cryptodev_kprocess, ubsec_kprocess), @@ -348,13 +350,6 @@ ubsec_attach(device_t dev) goto bad2; } - sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ubsec_session), - CRYPTOCAP_F_HARDWARE); - if (sc->sc_cid < 0) { - device_printf(dev, "could not get crypto driver id\n"); - goto bad3; - } - /* * Setup DMA descriptor area. */ @@ -370,7 +365,7 @@ ubsec_attach(device_t dev) NULL, NULL, /* lockfunc, lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); - goto bad4; + goto bad3; } SIMPLEQ_INIT(&sc->sc_freequeue); dmap = sc->sc_dmaa; @@ -404,11 +399,6 @@ ubsec_attach(device_t dev) device_printf(sc->sc_dev, "%s\n", ubsec_partname(sc)); - crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); - crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); - /* * Reset Broadcom chip */ @@ -424,6 +414,13 @@ ubsec_attach(device_t dev) */ ubsec_init_board(sc); + sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ubsec_session), + CRYPTOCAP_F_HARDWARE); + if (sc->sc_cid < 0) { + device_printf(dev, "could not get crypto driver id\n"); + goto bad4; + } + #ifndef UBSEC_NO_RNG if (sc->sc_flags & UBS_FLAGS_RNG) { sc->sc_statmask |= BS_STAT_MCR2_DONE; @@ -477,7 +474,15 @@ skip_rng: } return (0); bad4: - crypto_unregister_all(sc->sc_cid); + while (!SIMPLEQ_EMPTY(&sc->sc_freequeue)) { + struct ubsec_q *q; + + q = SIMPLEQ_FIRST(&sc->sc_freequeue); + SIMPLEQ_REMOVE_HEAD(&sc->sc_freequeue, q_next); + ubsec_dma_free(sc, &q->q_dma->d_alloc); + free(q, M_DEVBUF); + } + bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); bad2: @@ -498,13 +503,14 @@ ubsec_detach(device_t dev) /* XXX wait/abort active ops */ + crypto_unregister_all(sc->sc_cid); + /* disable interrupts */ WRITE_REG(sc, BS_CTRL, READ_REG(sc, BS_CTRL) &~ (BS_CTRL_MCR2INT | BS_CTRL_MCR1INT | BS_CTRL_DMAERR)); callout_stop(&sc->sc_rngto); - - crypto_unregister_all(sc->sc_cid); + bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); #ifdef UBSEC_RNDTEST if (sc->sc_rndtest) @@ -531,7 +537,6 @@ ubsec_detach(device_t dev) mtx_destroy(&sc->sc_mcr2lock); bus_generic_detach(dev); - bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); bus_dma_tag_destroy(sc->sc_dmat); @@ -826,7 +831,7 @@ feed1: } static void -ubsec_setup_enckey(struct ubsec_session *ses, int algo, caddr_t key) +ubsec_setup_enckey(struct ubsec_session *ses, int algo, const void *key) { /* Go ahead and compute key in ubsec's byte order */ @@ -846,112 +851,134 @@ ubsec_setup_enckey(struct ubsec_session *ses, int algo, caddr_t key) } static void -ubsec_setup_mackey(struct ubsec_session *ses, int algo, caddr_t key, int klen) +ubsec_setup_mackey(struct ubsec_session *ses, int algo, const char *key, + int klen) { MD5_CTX md5ctx; SHA1_CTX sha1ctx; - int i; - - for (i = 0; i < klen; i++) - key[i] ^= HMAC_IPAD_VAL; if (algo == CRYPTO_MD5_HMAC) { - MD5Init(&md5ctx); - MD5Update(&md5ctx, key, klen); - MD5Update(&md5ctx, hmac_ipad_buffer, MD5_BLOCK_LEN - klen); + hmac_init_ipad(&auth_hash_hmac_md5, key, klen, &md5ctx); bcopy(md5ctx.state, ses->ses_hminner, sizeof(md5ctx.state)); + + hmac_init_opad(&auth_hash_hmac_md5, key, klen, &md5ctx); + bcopy(md5ctx.state, ses->ses_hmouter, sizeof(md5ctx.state)); + + explicit_bzero(&md5ctx, sizeof(md5ctx)); } else { - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, key, klen); - SHA1Update(&sha1ctx, hmac_ipad_buffer, - SHA1_BLOCK_LEN - klen); + hmac_init_ipad(&auth_hash_hmac_sha1, key, klen, &sha1ctx); bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32)); + + hmac_init_opad(&auth_hash_hmac_sha1, key, klen, &sha1ctx); + bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32)); + + explicit_bzero(&sha1ctx, sizeof(sha1ctx)); } +} - for (i = 0; i < klen; i++) - key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); +static bool +ubsec_auth_supported(const struct crypto_session_params *csp) +{ - if (algo == CRYPTO_MD5_HMAC) { - MD5Init(&md5ctx); - MD5Update(&md5ctx, key, klen); - MD5Update(&md5ctx, hmac_opad_buffer, MD5_BLOCK_LEN - klen); - bcopy(md5ctx.state, ses->ses_hmouter, sizeof(md5ctx.state)); - } else { - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, key, klen); - SHA1Update(&sha1ctx, hmac_opad_buffer, - SHA1_BLOCK_LEN - klen); - bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32)); + switch (csp->csp_auth_alg) { + case CRYPTO_MD5_HMAC: + case CRYPTO_SHA1_HMAC: + return (true); + default: + return (false); } +} + +static bool +ubsec_cipher_supported(const struct crypto_session_params *csp) +{ - for (i = 0; i < klen; i++) - key[i] ^= HMAC_OPAD_VAL; + switch (csp->csp_cipher_alg) { + case CRYPTO_DES_CBC: + case CRYPTO_3DES_CBC: + return (csp->csp_ivlen == 8); + default: + return (false); + } } -/* - * Allocate a new 'session' and return an encoded session id. 'sidp' - * contains our registration id, and should contain an encoded session - * id on successful allocation. - */ static int -ubsec_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) +ubsec_probesession(device_t dev, const struct crypto_session_params *csp) { - struct ubsec_softc *sc = device_get_softc(dev); - struct cryptoini *c, *encini = NULL, *macini = NULL; - struct ubsec_session *ses = NULL; - if (cri == NULL || sc == NULL) + if (csp->csp_flags != 0) return (EINVAL); - - for (c = cri; c != NULL; c = c->cri_next) { - if (c->cri_alg == CRYPTO_MD5_HMAC || - c->cri_alg == CRYPTO_SHA1_HMAC) { - if (macini) - return (EINVAL); - macini = c; - } else if (c->cri_alg == CRYPTO_DES_CBC || - c->cri_alg == CRYPTO_3DES_CBC) { - if (encini) - return (EINVAL); - encini = c; - } else + switch (csp->csp_mode) { + case CSP_MODE_DIGEST: + if (!ubsec_auth_supported(csp)) return (EINVAL); - } - if (encini == NULL && macini == NULL) + break; + case CSP_MODE_CIPHER: + if (!ubsec_cipher_supported(csp)) + return (EINVAL); + break; + case CSP_MODE_ETA: + if (!ubsec_auth_supported(csp) || + !ubsec_cipher_supported(csp)) + return (EINVAL); + break; + default: return (EINVAL); + } - ses = crypto_get_driver_session(cses); - if (encini) { - /* get an IV, network byte order */ - /* XXX may read fewer than requested */ - read_random(ses->ses_iv, sizeof(ses->ses_iv)); + return (CRYPTODEV_PROBE_HARDWARE); +} - if (encini->cri_key != NULL) { - ubsec_setup_enckey(ses, encini->cri_alg, - encini->cri_key); - } - } +/* + * Allocate a new 'session'. + */ +static int +ubsec_newsession(device_t dev, crypto_session_t cses, + const struct crypto_session_params *csp) +{ + struct ubsec_session *ses; + + ses = crypto_get_driver_session(cses); + if (csp->csp_cipher_alg != 0 && csp->csp_cipher_key != NULL) + ubsec_setup_enckey(ses, csp->csp_cipher_alg, + csp->csp_cipher_key); - if (macini) { - ses->ses_mlen = macini->cri_mlen; + if (csp->csp_auth_alg != 0) { + ses->ses_mlen = csp->csp_auth_mlen; if (ses->ses_mlen == 0) { - if (macini->cri_alg == CRYPTO_MD5_HMAC) + if (csp->csp_auth_alg == CRYPTO_MD5_HMAC) ses->ses_mlen = MD5_HASH_LEN; else ses->ses_mlen = SHA1_HASH_LEN; } - if (macini->cri_key != NULL) { - ubsec_setup_mackey(ses, macini->cri_alg, - macini->cri_key, macini->cri_klen / 8); + if (csp->csp_auth_key != NULL) { + ubsec_setup_mackey(ses, csp->csp_auth_alg, + csp->csp_auth_key, csp->csp_auth_klen); } } return (0); } +static bus_size_t +ubsec_crp_length(struct cryptop *crp) +{ + + switch (crp->crp_buf_type) { + case CRYPTO_BUF_MBUF: + return (crp->crp_mbuf->m_pkthdr.len); + case CRYPTO_BUF_UIO: + return (crp->crp_uio->uio_resid); + case CRYPTO_BUF_CONTIG: + return (crp->crp_ilen); + default: + panic("bad crp buffer type"); + } +} + static void -ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int error) +ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, int error) { struct ubsec_operand *op = arg; @@ -959,12 +986,11 @@ ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, in ("Too many DMA segments returned when mapping operand")); #ifdef UBSEC_DEBUG if (ubsec_debug) - printf("ubsec_op_cb: mapsize %u nsegs %d error %d\n", - (u_int) mapsize, nsegs, error); + printf("ubsec_op_cb: nsegs %d error %d\n", + nsegs, error); #endif if (error != 0) return; - op->mapsize = mapsize; op->nsegs = nsegs; bcopy(seg, op->segs, nsegs * sizeof (seg[0])); } @@ -972,22 +998,17 @@ ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, in static int ubsec_process(device_t dev, struct cryptop *crp, int hint) { + const struct crypto_session_params *csp; struct ubsec_softc *sc = device_get_softc(dev); struct ubsec_q *q = NULL; int err = 0, i, j, nicealign; - struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; - int encoffset = 0, macoffset = 0, cpskip, cpoffset; + int cpskip, cpoffset; int sskip, dskip, stheend, dtheend; int16_t coffset; struct ubsec_session *ses; struct ubsec_pktctx ctx; struct ubsec_dma *dmap = NULL; - if (crp == NULL || crp->crp_callback == NULL || sc == NULL) { - ubsecstats.hst_invalid++; - return (EINVAL); - } - mtx_lock(&sc->sc_freeqlock); if (SIMPLEQ_EMPTY(&sc->sc_freequeue)) { ubsecstats.hst_queuefull++; @@ -1006,103 +1027,34 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) q->q_dma = dmap; ses = crypto_get_driver_session(crp->crp_session); - if (crp->crp_flags & CRYPTO_F_IMBUF) { - q->q_src_m = (struct mbuf *)crp->crp_buf; - q->q_dst_m = (struct mbuf *)crp->crp_buf; - } else if (crp->crp_flags & CRYPTO_F_IOV) { - q->q_src_io = (struct uio *)crp->crp_buf; - q->q_dst_io = (struct uio *)crp->crp_buf; - } else { - ubsecstats.hst_badflags++; - err = EINVAL; - goto errout; /* XXX we don't handle contiguous blocks! */ - } - bzero(&dmap->d_dma->d_mcr, sizeof(struct ubsec_mcr)); dmap->d_dma->d_mcr.mcr_pkts = htole16(1); dmap->d_dma->d_mcr.mcr_flags = 0; q->q_crp = crp; - crd1 = crp->crp_desc; - if (crd1 == NULL) { - ubsecstats.hst_nodesc++; - err = EINVAL; - goto errout; - } - crd2 = crd1->crd_next; + csp = crypto_get_params(crp->crp_session); - if (crd2 == NULL) { - if (crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC) { - maccrd = crd1; - enccrd = NULL; - } else if (crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_3DES_CBC) { - maccrd = NULL; - enccrd = crd1; - } else { - ubsecstats.hst_badalg++; - err = EINVAL; - goto errout; - } - } else { - if ((crd1->crd_alg == CRYPTO_MD5_HMAC || - crd1->crd_alg == CRYPTO_SHA1_HMAC) && - (crd2->crd_alg == CRYPTO_DES_CBC || - crd2->crd_alg == CRYPTO_3DES_CBC) && - ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) { - maccrd = crd1; - enccrd = crd2; - } else if ((crd1->crd_alg == CRYPTO_DES_CBC || - crd1->crd_alg == CRYPTO_3DES_CBC) && - (crd2->crd_alg == CRYPTO_MD5_HMAC || - crd2->crd_alg == CRYPTO_SHA1_HMAC) && - (crd1->crd_flags & CRD_F_ENCRYPT)) { - enccrd = crd1; - maccrd = crd2; - } else { - /* - * We cannot order the ubsec as requested - */ - ubsecstats.hst_badalg++; - err = EINVAL; - goto errout; + if (csp->csp_cipher_alg != 0) { + if (crp->crp_cipher_key != NULL) { + ubsec_setup_enckey(ses, csp->csp_cipher_alg, + crp->crp_cipher_key); } - } - if (enccrd) { - if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) { - ubsec_setup_enckey(ses, enccrd->crd_alg, - enccrd->crd_key); - } - - encoffset = enccrd->crd_skip; ctx.pc_flags |= htole16(UBS_PKTCTX_ENC_3DES); - if (enccrd->crd_flags & CRD_F_ENCRYPT) { - q->q_flags |= UBSEC_QFLAGS_COPYOUTIV; - - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(enccrd->crd_iv, ctx.pc_iv, 8); - else { - ctx.pc_iv[0] = ses->ses_iv[0]; - ctx.pc_iv[1] = ses->ses_iv[1]; - } + if (crp->crp_flags & CRYPTO_F_IV_GENERATE) { + arc4rand(ctx.pc_iv, csp->csp_ivlen, 0); + crypto_copyback(crp, crp->crp_iv_start, + csp->csp_ivlen, ctx.pc_iv); + } else if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) + memcpy(ctx.pc_iv, crp->crp_iv, csp->csp_ivlen); + else + crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen, + ctx.pc_iv); - if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) { - crypto_copyback(crp->crp_flags, crp->crp_buf, - enccrd->crd_inject, 8, (caddr_t)ctx.pc_iv); - } - } else { + if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { ctx.pc_flags |= htole16(UBS_PKTCTX_INBOUND); - - if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) - bcopy(enccrd->crd_iv, ctx.pc_iv, 8); - else { - crypto_copydata(crp->crp_flags, crp->crp_buf, - enccrd->crd_inject, 8, (caddr_t)ctx.pc_iv); - } } ctx.pc_deskey[0] = ses->ses_deskey[0]; @@ -1115,15 +1067,13 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) SWAP32(ctx.pc_iv[1]); } - if (maccrd) { - if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) { - ubsec_setup_mackey(ses, maccrd->crd_alg, - maccrd->crd_key, maccrd->crd_klen / 8); + if (csp->csp_auth_alg != 0) { + if (crp->crp_auth_key != NULL) { + ubsec_setup_mackey(ses, csp->csp_auth_alg, + crp->crp_auth_key, csp->csp_auth_klen); } - macoffset = maccrd->crd_skip; - - if (maccrd->crd_alg == CRYPTO_MD5_HMAC) + if (csp->csp_auth_alg == CRYPTO_MD5_HMAC) ctx.pc_flags |= htole16(UBS_PKTCTX_AUTH_MD5); else ctx.pc_flags |= htole16(UBS_PKTCTX_AUTH_SHA1); @@ -1137,35 +1087,37 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) } } - if (enccrd && maccrd) { + if (csp->csp_mode == CSP_MODE_ETA) { /* - * ubsec cannot handle packets where the end of encryption - * and authentication are not the same, or where the - * encrypted part begins before the authenticated part. + * ubsec only supports ETA requests where there is no + * gap between the AAD and payload. */ - if ((encoffset + enccrd->crd_len) != - (macoffset + maccrd->crd_len)) { + if (crp->crp_aad_length != 0 && + crp->crp_aad_start + crp->crp_aad_length != + crp->crp_payload_start) { ubsecstats.hst_lenmismatch++; err = EINVAL; goto errout; } - if (enccrd->crd_skip < maccrd->crd_skip) { - ubsecstats.hst_skipmismatch++; - err = EINVAL; - goto errout; + + if (crp->crp_aad_length != 0) { + sskip = crp->crp_aad_start; + } else { + sskip = crp->crp_payload_start; } - sskip = maccrd->crd_skip; - cpskip = dskip = enccrd->crd_skip; - stheend = maccrd->crd_len; - dtheend = enccrd->crd_len; - coffset = enccrd->crd_skip - maccrd->crd_skip; + cpskip = dskip = crp->crp_payload_start; + stheend = crp->crp_aad_length + crp->crp_payload_length; + dtheend = crp->crp_payload_length; + coffset = crp->crp_aad_length; cpoffset = cpskip + dtheend; #ifdef UBSEC_DEBUG if (ubsec_debug) { - printf("mac: skip %d, len %d, inject %d\n", - maccrd->crd_skip, maccrd->crd_len, maccrd->crd_inject); - printf("enc: skip %d, len %d, inject %d\n", - enccrd->crd_skip, enccrd->crd_len, enccrd->crd_inject); + printf("AAD: start %d, len %d, digest %d\n", + crp->crp_aad_start, crp->crp_aad_length, + crp->crp_digest_start); + printf("payload: start %d, len %d, IV %d\n", + crp->crp_payload_start, crp->crp_payload_length, + crp->crp_iv_start); printf("src: skip %d, len %d\n", sskip, stheend); printf("dst: skip %d, len %d\n", dskip, dtheend); printf("ubs: coffset %d, pktlen %d, cpskip %d, cpoffset %d\n", @@ -1173,8 +1125,8 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) } #endif } else { - cpskip = dskip = sskip = macoffset + encoffset; - dtheend = stheend = (enccrd)?enccrd->crd_len:maccrd->crd_len; + cpskip = dskip = sskip = crp->crp_payload_start; + dtheend = stheend = crp->crp_payload_length; cpoffset = cpskip + dtheend; coffset = 0; } @@ -1185,25 +1137,15 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) err = ENOMEM; goto errout; } - if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (bus_dmamap_load_mbuf(sc->sc_dmat, q->q_src_map, - q->q_src_m, ubsec_op_cb, &q->q_src, BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); - q->q_src_map = NULL; - ubsecstats.hst_noload++; - err = ENOMEM; - goto errout; - } - } else if (crp->crp_flags & CRYPTO_F_IOV) { - if (bus_dmamap_load_uio(sc->sc_dmat, q->q_src_map, - q->q_src_io, ubsec_op_cb, &q->q_src, BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); - q->q_src_map = NULL; - ubsecstats.hst_noload++; - err = ENOMEM; - goto errout; - } + if (bus_dmamap_load_crp(sc->sc_dmat, q->q_src_map, crp, ubsec_op_cb, + &q->q_src, BUS_DMA_NOWAIT) != 0) { + bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); + q->q_src_map = NULL; + ubsecstats.hst_noload++; + err = ENOMEM; + goto errout; } + q->q_src_mapsize = ubsec_crp_length(crp); nicealign = ubsec_dmamap_aligned(&q->q_src); dmap->d_dma->d_mcr.mcr_pktlen = htole16(stheend); @@ -1257,7 +1199,7 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) j++; } - if (enccrd == NULL && maccrd != NULL) { + if (csp->csp_mode == CSP_MODE_DIGEST) { dmap->d_dma->d_mcr.mcr_opktbuf.pb_addr = 0; dmap->d_dma->d_mcr.mcr_opktbuf.pb_len = 0; dmap->d_dma->d_mcr.mcr_opktbuf.pb_next = htole32(dmap->d_alloc.dma_paddr + @@ -1270,104 +1212,79 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) dmap->d_dma->d_mcr.mcr_opktbuf.pb_next); #endif } else { - if (crp->crp_flags & CRYPTO_F_IOV) { - if (!nicealign) { - ubsecstats.hst_iovmisaligned++; - err = EINVAL; - goto errout; + if (nicealign) { + q->q_dst = q->q_src; + } else if (crp->crp_buf_type == CRYPTO_BUF_MBUF) { + int totlen, len; + struct mbuf *m, *top, **mp; + + ubsecstats.hst_unaligned++; + totlen = q->q_src_mapsize; + if (totlen >= MINCLSIZE) { + m = m_getcl(M_NOWAIT, MT_DATA, + crp->crp_mbuf->m_flags & M_PKTHDR); + len = MCLBYTES; + } else if (crp->crp_mbuf->m_flags & M_PKTHDR) { + m = m_gethdr(M_NOWAIT, MT_DATA); + len = MHLEN; + } else { + m = m_get(M_NOWAIT, MT_DATA); + len = MLEN; } - if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, - &q->q_dst_map)) { - ubsecstats.hst_nomap++; - err = ENOMEM; - goto errout; + if (m && crp->crp_mbuf->m_flags & M_PKTHDR && + !m_dup_pkthdr(m, crp->crp_mbuf, M_NOWAIT)) { + m_free(m); + m = NULL; } - if (bus_dmamap_load_uio(sc->sc_dmat, q->q_dst_map, - q->q_dst_io, ubsec_op_cb, &q->q_dst, BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map); - q->q_dst_map = NULL; - ubsecstats.hst_noload++; - err = ENOMEM; + if (m == NULL) { + ubsecstats.hst_nombuf++; + err = sc->sc_nqueue ? ERESTART : ENOMEM; goto errout; } - } else if (crp->crp_flags & CRYPTO_F_IMBUF) { - if (nicealign) { - q->q_dst = q->q_src; - } else { - int totlen, len; - struct mbuf *m, *top, **mp; + m->m_len = len = min(totlen, len); + totlen -= len; + top = m; + mp = ⊤ - ubsecstats.hst_unaligned++; - totlen = q->q_src_mapsize; + while (totlen > 0) { if (totlen >= MINCLSIZE) { - m = m_getcl(M_NOWAIT, MT_DATA, - q->q_src_m->m_flags & M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, 0); len = MCLBYTES; - } else if (q->q_src_m->m_flags & M_PKTHDR) { - m = m_gethdr(M_NOWAIT, MT_DATA); - len = MHLEN; } else { m = m_get(M_NOWAIT, MT_DATA); len = MLEN; } - if (m && q->q_src_m->m_flags & M_PKTHDR && - !m_dup_pkthdr(m, q->q_src_m, M_NOWAIT)) { - m_free(m); - m = NULL; - } if (m == NULL) { + m_freem(top); ubsecstats.hst_nombuf++; err = sc->sc_nqueue ? ERESTART : ENOMEM; goto errout; } m->m_len = len = min(totlen, len); totlen -= len; - top = m; - mp = ⊤ - - while (totlen > 0) { - if (totlen >= MINCLSIZE) { - m = m_getcl(M_NOWAIT, - MT_DATA, 0); - len = MCLBYTES; - } else { - m = m_get(M_NOWAIT, MT_DATA); - len = MLEN; - } - if (m == NULL) { - m_freem(top); - ubsecstats.hst_nombuf++; - err = sc->sc_nqueue ? ERESTART : ENOMEM; - goto errout; - } - m->m_len = len = min(totlen, len); - totlen -= len; - *mp = m; - mp = &m->m_next; - } - q->q_dst_m = top; - ubsec_mcopy(q->q_src_m, q->q_dst_m, - cpskip, cpoffset); - if (bus_dmamap_create(sc->sc_dmat, - BUS_DMA_NOWAIT, &q->q_dst_map) != 0) { - ubsecstats.hst_nomap++; - err = ENOMEM; - goto errout; - } - if (bus_dmamap_load_mbuf(sc->sc_dmat, - q->q_dst_map, q->q_dst_m, - ubsec_op_cb, &q->q_dst, - BUS_DMA_NOWAIT) != 0) { - bus_dmamap_destroy(sc->sc_dmat, - q->q_dst_map); - q->q_dst_map = NULL; - ubsecstats.hst_noload++; - err = ENOMEM; - goto errout; - } + *mp = m; + mp = &m->m_next; + } + q->q_dst_m = top; + ubsec_mcopy(crp->crp_mbuf, q->q_dst_m, cpskip, cpoffset); + if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, + &q->q_dst_map) != 0) { + ubsecstats.hst_nomap++; + err = ENOMEM; + goto errout; + } + if (bus_dmamap_load_mbuf_sg(sc->sc_dmat, + q->q_dst_map, q->q_dst_m, q->q_dst_segs, + &q->q_dst_nsegs, 0) != 0) { + bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map); + q->q_dst_map = NULL; + ubsecstats.hst_noload++; + err = ENOMEM; + goto errout; } + q->q_dst_mapsize = q->q_src_mapsize; } else { - ubsecstats.hst_badflags++; + ubsecstats.hst_iovmisaligned++; err = EINVAL; goto errout; } @@ -1414,7 +1331,7 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) pb->pb_len = htole32(packl); if ((i + 1) == q->q_dst_nsegs) { - if (maccrd) + if (csp->csp_auth_alg != 0) pb->pb_next = htole32(dmap->d_alloc.dma_paddr + offsetof(struct ubsec_dmachunk, d_macbuf[0])); else @@ -1465,7 +1382,7 @@ ubsec_process(device_t dev, struct cryptop *crp, int hint) errout: if (q != NULL) { - if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m)) + if (q->q_dst_m != NULL) m_freem(q->q_dst_m); if (q->q_dst_map != NULL && q->q_dst_map != q->q_src_map) { @@ -1495,12 +1412,14 @@ errout: static void ubsec_callback(struct ubsec_softc *sc, struct ubsec_q *q) { + const struct crypto_session_params *csp; struct cryptop *crp = (struct cryptop *)q->q_crp; struct ubsec_session *ses; - struct cryptodesc *crd; struct ubsec_dma *dmap = q->q_dma; + char hash[SHA1_HASH_LEN]; ses = crypto_get_driver_session(crp->crp_session); + csp = crypto_get_params(crp->crp_session); ubsecstats.hst_opackets++; ubsecstats.hst_obytes += dmap->d_alloc.dma_size; @@ -1517,31 +1436,21 @@ ubsec_callback(struct ubsec_softc *sc, struct ubsec_q *q) bus_dmamap_unload(sc->sc_dmat, q->q_src_map); bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); - if ((crp->crp_flags & CRYPTO_F_IMBUF) && (q->q_src_m != q->q_dst_m)) { - m_freem(q->q_src_m); - crp->crp_buf = (caddr_t)q->q_dst_m; - } - - /* copy out IV for future use */ - if (q->q_flags & UBSEC_QFLAGS_COPYOUTIV) { - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - if (crd->crd_alg != CRYPTO_DES_CBC && - crd->crd_alg != CRYPTO_3DES_CBC) - continue; - crypto_copydata(crp->crp_flags, crp->crp_buf, - crd->crd_skip + crd->crd_len - 8, 8, - (caddr_t)ses->ses_iv); - break; - } + if (q->q_dst_m != NULL) { + m_freem(crp->crp_mbuf); + crp->crp_mbuf = q->q_dst_m; } - for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - if (crd->crd_alg != CRYPTO_MD5_HMAC && - crd->crd_alg != CRYPTO_SHA1_HMAC) - continue; - crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, - ses->ses_mlen, (caddr_t)dmap->d_dma->d_macbuf); - break; + if (csp->csp_auth_alg != 0) { + if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { + crypto_copydata(crp, crp->crp_digest_start, + ses->ses_mlen, hash); + if (timingsafe_bcmp(dmap->d_dma->d_macbuf, hash, + ses->ses_mlen) != 0) + crp->crp_etype = EBADMSG; + } else + crypto_copyback(crp, crp->crp_digest_start, + ses->ses_mlen, dmap->d_dma->d_macbuf); } mtx_lock(&sc->sc_freeqlock); SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next); @@ -1942,7 +1851,7 @@ ubsec_free_q(struct ubsec_softc *sc, struct ubsec_q *q) if(q->q_stacked_mcr[i]) { q2 = q->q_stacked_mcr[i]; - if ((q2->q_dst_m != NULL) && (q2->q_src_m != q2->q_dst_m)) + if (q2->q_dst_m != NULL) m_freem(q2->q_dst_m); crp = (struct cryptop *)q2->q_crp; @@ -1959,7 +1868,7 @@ ubsec_free_q(struct ubsec_softc *sc, struct ubsec_q *q) /* * Free header MCR */ - if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m)) + if (q->q_dst_m != NULL) m_freem(q->q_dst_m); crp = (struct cryptop *)q->q_crp; diff --git a/sys/dev/ubsec/ubsecvar.h b/sys/dev/ubsec/ubsecvar.h index ae6d5e2cb6bc..b857061be5c0 100644 --- a/sys/dev/ubsec/ubsecvar.h +++ b/sys/dev/ubsec/ubsecvar.h @@ -134,10 +134,6 @@ struct ubsec_dma { #define UBS_FLAGS_RNG 0x10 /* hardware rng */ struct ubsec_operand { - union { - struct mbuf *m; - struct uio *io; - } u; bus_dmamap_t map; bus_size_t mapsize; int nsegs; @@ -153,19 +149,16 @@ struct ubsec_q { struct ubsec_operand q_src; struct ubsec_operand q_dst; + struct mbuf *q_dst_m; int q_flags; }; -#define q_src_m q_src.u.m -#define q_src_io q_src.u.io #define q_src_map q_src.map #define q_src_nsegs q_src.nsegs #define q_src_segs q_src.segs #define q_src_mapsize q_src.mapsize -#define q_dst_m q_dst.u.m -#define q_dst_io q_dst.u.io #define q_dst_map q_dst.map #define q_dst_nsegs q_dst.nsegs #define q_dst_segs q_dst.segs @@ -215,7 +208,6 @@ struct ubsec_session { u_int32_t ses_mlen; /* hmac length */ u_int32_t ses_hminner[5]; /* hmac inner state */ u_int32_t ses_hmouter[5]; /* hmac outer state */ - u_int32_t ses_iv[2]; /* [3]DES iv */ }; #endif /* _KERNEL */ |
