1844d9543SConrad Meyer /*- 2844d9543SConrad Meyer * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3844d9543SConrad Meyer * 4844d9543SConrad Meyer * Copyright (c) 2017 Chelsio Communications, Inc. 5844d9543SConrad Meyer * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org> 6844d9543SConrad Meyer * All rights reserved. 7844d9543SConrad Meyer * Largely borrowed from ccr(4), Written by: John Baldwin <jhb@FreeBSD.org> 8844d9543SConrad Meyer * 9844d9543SConrad Meyer * Redistribution and use in source and binary forms, with or without 10844d9543SConrad Meyer * modification, are permitted provided that the following conditions 11844d9543SConrad Meyer * are met: 12844d9543SConrad Meyer * 1. Redistributions of source code must retain the above copyright 13844d9543SConrad Meyer * notice, this list of conditions and the following disclaimer. 14844d9543SConrad Meyer * 2. Redistributions in binary form must reproduce the above copyright 15844d9543SConrad Meyer * notice, this list of conditions and the following disclaimer in the 16844d9543SConrad Meyer * documentation and/or other materials provided with the distribution. 17844d9543SConrad Meyer * 18844d9543SConrad Meyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19844d9543SConrad Meyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20844d9543SConrad Meyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21844d9543SConrad Meyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22844d9543SConrad Meyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23844d9543SConrad Meyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24844d9543SConrad Meyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25844d9543SConrad Meyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26844d9543SConrad Meyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27844d9543SConrad Meyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28844d9543SConrad Meyer * SUCH DAMAGE. 29844d9543SConrad Meyer */ 30844d9543SConrad Meyer 31844d9543SConrad Meyer #include <sys/cdefs.h> 32844d9543SConrad Meyer __FBSDID("$FreeBSD$"); 33844d9543SConrad Meyer 34844d9543SConrad Meyer #include "opt_ddb.h" 35844d9543SConrad Meyer 36e2e050c8SConrad Meyer #include <sys/param.h> 37844d9543SConrad Meyer #include <sys/bus.h> 38844d9543SConrad Meyer #include <sys/lock.h> 39844d9543SConrad Meyer #include <sys/kernel.h> 40844d9543SConrad Meyer #include <sys/malloc.h> 41844d9543SConrad Meyer #include <sys/mutex.h> 42844d9543SConrad Meyer #include <sys/module.h> 43844d9543SConrad Meyer #include <sys/random.h> 44844d9543SConrad Meyer #include <sys/sglist.h> 45844d9543SConrad Meyer #include <sys/sysctl.h> 46844d9543SConrad Meyer 47844d9543SConrad Meyer #ifdef DDB 48844d9543SConrad Meyer #include <ddb/ddb.h> 49844d9543SConrad Meyer #endif 50844d9543SConrad Meyer 51844d9543SConrad Meyer #include <dev/pci/pcivar.h> 52844d9543SConrad Meyer 53844d9543SConrad Meyer #include <dev/random/randomdev.h> 54844d9543SConrad Meyer 55844d9543SConrad Meyer #include <opencrypto/cryptodev.h> 56844d9543SConrad Meyer #include <opencrypto/xform.h> 57844d9543SConrad Meyer 58844d9543SConrad Meyer #include "cryptodev_if.h" 59844d9543SConrad Meyer 60844d9543SConrad Meyer #include "ccp.h" 61844d9543SConrad Meyer #include "ccp_hardware.h" 62844d9543SConrad Meyer 63844d9543SConrad Meyer MALLOC_DEFINE(M_CCP, "ccp", "AMD CCP crypto"); 64844d9543SConrad Meyer 65844d9543SConrad Meyer /* 66844d9543SConrad Meyer * Need a global softc available for garbage random_source API, which lacks any 67844d9543SConrad Meyer * context pointer. It's also handy for debugging. 68844d9543SConrad Meyer */ 69844d9543SConrad Meyer struct ccp_softc *g_ccp_softc; 70844d9543SConrad Meyer 71844d9543SConrad Meyer bool g_debug_print = false; 72844d9543SConrad Meyer SYSCTL_BOOL(_hw_ccp, OID_AUTO, debug, CTLFLAG_RWTUN, &g_debug_print, 0, 73844d9543SConrad Meyer "Set to enable debugging log messages"); 74844d9543SConrad Meyer 75844d9543SConrad Meyer static struct pciid { 76844d9543SConrad Meyer uint32_t devid; 77844d9543SConrad Meyer const char *desc; 78844d9543SConrad Meyer } ccp_ids[] = { 79844d9543SConrad Meyer { 0x14561022, "AMD CCP-5a" }, 80844d9543SConrad Meyer { 0x14681022, "AMD CCP-5b" }, 81a481fc91SAndriy Gapon { 0x15df1022, "AMD CCP-5a" }, 82844d9543SConrad Meyer }; 83844d9543SConrad Meyer 84844d9543SConrad Meyer static struct random_source random_ccp = { 85844d9543SConrad Meyer .rs_ident = "AMD CCP TRNG", 86844d9543SConrad Meyer .rs_source = RANDOM_PURE_CCP, 87844d9543SConrad Meyer .rs_read = random_ccp_read, 88844d9543SConrad Meyer }; 89844d9543SConrad Meyer 90844d9543SConrad Meyer /* 91844d9543SConrad Meyer * ccp_populate_sglist() generates a scatter/gather list that covers the entire 92844d9543SConrad Meyer * crypto operation buffer. 93844d9543SConrad Meyer */ 94844d9543SConrad Meyer static int 95*9c0e3d3aSJohn Baldwin ccp_populate_sglist(struct sglist *sg, struct crypto_buffer *cb) 96844d9543SConrad Meyer { 97844d9543SConrad Meyer int error; 98844d9543SConrad Meyer 99844d9543SConrad Meyer sglist_reset(sg); 100*9c0e3d3aSJohn Baldwin switch (cb->cb_type) { 101c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 102*9c0e3d3aSJohn Baldwin error = sglist_append_mbuf(sg, cb->cb_mbuf); 103c0341432SJohn Baldwin break; 104c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 105*9c0e3d3aSJohn Baldwin error = sglist_append_uio(sg, cb->cb_uio); 106c0341432SJohn Baldwin break; 107c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 108*9c0e3d3aSJohn Baldwin error = sglist_append(sg, cb->cb_buf, cb->cb_buf_len); 109c0341432SJohn Baldwin break; 110c0341432SJohn Baldwin default: 111c0341432SJohn Baldwin error = EINVAL; 112c0341432SJohn Baldwin } 113844d9543SConrad Meyer return (error); 114844d9543SConrad Meyer } 115844d9543SConrad Meyer 116844d9543SConrad Meyer static int 117844d9543SConrad Meyer ccp_probe(device_t dev) 118844d9543SConrad Meyer { 119844d9543SConrad Meyer struct pciid *ip; 120844d9543SConrad Meyer uint32_t id; 121844d9543SConrad Meyer 122844d9543SConrad Meyer id = pci_get_devid(dev); 123844d9543SConrad Meyer for (ip = ccp_ids; ip < &ccp_ids[nitems(ccp_ids)]; ip++) { 124844d9543SConrad Meyer if (id == ip->devid) { 125844d9543SConrad Meyer device_set_desc(dev, ip->desc); 126844d9543SConrad Meyer return (0); 127844d9543SConrad Meyer } 128844d9543SConrad Meyer } 129844d9543SConrad Meyer return (ENXIO); 130844d9543SConrad Meyer } 131844d9543SConrad Meyer 132844d9543SConrad Meyer static void 133844d9543SConrad Meyer ccp_initialize_queues(struct ccp_softc *sc) 134844d9543SConrad Meyer { 135844d9543SConrad Meyer struct ccp_queue *qp; 136844d9543SConrad Meyer size_t i; 137844d9543SConrad Meyer 138844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 139844d9543SConrad Meyer qp = &sc->queues[i]; 140844d9543SConrad Meyer 141844d9543SConrad Meyer qp->cq_softc = sc; 142844d9543SConrad Meyer qp->cq_qindex = i; 143844d9543SConrad Meyer mtx_init(&qp->cq_lock, "ccp queue", NULL, MTX_DEF); 144844d9543SConrad Meyer /* XXX - arbitrarily chosen sizes */ 145844d9543SConrad Meyer qp->cq_sg_crp = sglist_alloc(32, M_WAITOK); 146844d9543SConrad Meyer /* Two more SGEs than sg_crp to accommodate ipad. */ 147844d9543SConrad Meyer qp->cq_sg_ulptx = sglist_alloc(34, M_WAITOK); 148844d9543SConrad Meyer qp->cq_sg_dst = sglist_alloc(2, M_WAITOK); 149844d9543SConrad Meyer } 150844d9543SConrad Meyer } 151844d9543SConrad Meyer 152844d9543SConrad Meyer static void 153844d9543SConrad Meyer ccp_free_queues(struct ccp_softc *sc) 154844d9543SConrad Meyer { 155844d9543SConrad Meyer struct ccp_queue *qp; 156844d9543SConrad Meyer size_t i; 157844d9543SConrad Meyer 158844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 159844d9543SConrad Meyer qp = &sc->queues[i]; 160844d9543SConrad Meyer 161844d9543SConrad Meyer mtx_destroy(&qp->cq_lock); 162844d9543SConrad Meyer sglist_free(qp->cq_sg_crp); 163844d9543SConrad Meyer sglist_free(qp->cq_sg_ulptx); 164844d9543SConrad Meyer sglist_free(qp->cq_sg_dst); 165844d9543SConrad Meyer } 166844d9543SConrad Meyer } 167844d9543SConrad Meyer 168844d9543SConrad Meyer static int 169844d9543SConrad Meyer ccp_attach(device_t dev) 170844d9543SConrad Meyer { 171844d9543SConrad Meyer struct ccp_softc *sc; 172844d9543SConrad Meyer int error; 173844d9543SConrad Meyer 174844d9543SConrad Meyer sc = device_get_softc(dev); 175844d9543SConrad Meyer sc->dev = dev; 176844d9543SConrad Meyer 1771b0909d5SConrad Meyer sc->cid = crypto_get_driverid(dev, sizeof(struct ccp_session), 1781b0909d5SConrad Meyer CRYPTOCAP_F_HARDWARE); 179844d9543SConrad Meyer if (sc->cid < 0) { 180844d9543SConrad Meyer device_printf(dev, "could not get crypto driver id\n"); 181844d9543SConrad Meyer return (ENXIO); 182844d9543SConrad Meyer } 183844d9543SConrad Meyer 184844d9543SConrad Meyer error = ccp_hw_attach(dev); 185844d9543SConrad Meyer if (error != 0) 186844d9543SConrad Meyer return (error); 187844d9543SConrad Meyer 188844d9543SConrad Meyer mtx_init(&sc->lock, "ccp", NULL, MTX_DEF); 189844d9543SConrad Meyer 190844d9543SConrad Meyer ccp_initialize_queues(sc); 191844d9543SConrad Meyer 192844d9543SConrad Meyer if (g_ccp_softc == NULL) { 193844d9543SConrad Meyer g_ccp_softc = sc; 194844d9543SConrad Meyer if ((sc->hw_features & VERSION_CAP_TRNG) != 0) 195844d9543SConrad Meyer random_source_register(&random_ccp); 196844d9543SConrad Meyer } 197844d9543SConrad Meyer 198844d9543SConrad Meyer return (0); 199844d9543SConrad Meyer } 200844d9543SConrad Meyer 201844d9543SConrad Meyer static int 202844d9543SConrad Meyer ccp_detach(device_t dev) 203844d9543SConrad Meyer { 204844d9543SConrad Meyer struct ccp_softc *sc; 205844d9543SConrad Meyer 206844d9543SConrad Meyer sc = device_get_softc(dev); 207844d9543SConrad Meyer 208844d9543SConrad Meyer mtx_lock(&sc->lock); 209844d9543SConrad Meyer sc->detaching = true; 210844d9543SConrad Meyer mtx_unlock(&sc->lock); 211844d9543SConrad Meyer 212844d9543SConrad Meyer crypto_unregister_all(sc->cid); 213844d9543SConrad Meyer if (g_ccp_softc == sc && (sc->hw_features & VERSION_CAP_TRNG) != 0) 214844d9543SConrad Meyer random_source_deregister(&random_ccp); 215844d9543SConrad Meyer 216844d9543SConrad Meyer ccp_hw_detach(dev); 217844d9543SConrad Meyer ccp_free_queues(sc); 218844d9543SConrad Meyer 219844d9543SConrad Meyer if (g_ccp_softc == sc) 220844d9543SConrad Meyer g_ccp_softc = NULL; 221844d9543SConrad Meyer 222844d9543SConrad Meyer mtx_destroy(&sc->lock); 223844d9543SConrad Meyer return (0); 224844d9543SConrad Meyer } 225844d9543SConrad Meyer 226844d9543SConrad Meyer static void 227c0341432SJohn Baldwin ccp_init_hmac_digest(struct ccp_session *s, const char *key, int klen) 228844d9543SConrad Meyer { 229844d9543SConrad Meyer union authctx auth_ctx; 230844d9543SConrad Meyer struct auth_hash *axf; 231844d9543SConrad Meyer u_int i; 232844d9543SConrad Meyer 233844d9543SConrad Meyer /* 234844d9543SConrad Meyer * If the key is larger than the block size, use the digest of 235844d9543SConrad Meyer * the key as the key instead. 236844d9543SConrad Meyer */ 237844d9543SConrad Meyer axf = s->hmac.auth_hash; 238844d9543SConrad Meyer if (klen > axf->blocksize) { 239844d9543SConrad Meyer axf->Init(&auth_ctx); 240844d9543SConrad Meyer axf->Update(&auth_ctx, key, klen); 241844d9543SConrad Meyer axf->Final(s->hmac.ipad, &auth_ctx); 242844d9543SConrad Meyer explicit_bzero(&auth_ctx, sizeof(auth_ctx)); 243844d9543SConrad Meyer klen = axf->hashsize; 244844d9543SConrad Meyer } else 245844d9543SConrad Meyer memcpy(s->hmac.ipad, key, klen); 246844d9543SConrad Meyer 247844d9543SConrad Meyer memset(s->hmac.ipad + klen, 0, axf->blocksize - klen); 248844d9543SConrad Meyer memcpy(s->hmac.opad, s->hmac.ipad, axf->blocksize); 249844d9543SConrad Meyer 250844d9543SConrad Meyer for (i = 0; i < axf->blocksize; i++) { 251844d9543SConrad Meyer s->hmac.ipad[i] ^= HMAC_IPAD_VAL; 252844d9543SConrad Meyer s->hmac.opad[i] ^= HMAC_OPAD_VAL; 253844d9543SConrad Meyer } 254844d9543SConrad Meyer } 255844d9543SConrad Meyer 256c0341432SJohn Baldwin static bool 257844d9543SConrad Meyer ccp_aes_check_keylen(int alg, int klen) 258844d9543SConrad Meyer { 259844d9543SConrad Meyer 260c0341432SJohn Baldwin switch (klen * 8) { 261844d9543SConrad Meyer case 128: 262844d9543SConrad Meyer case 192: 263844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 264c0341432SJohn Baldwin return (false); 265844d9543SConrad Meyer break; 266844d9543SConrad Meyer case 256: 267844d9543SConrad Meyer break; 268844d9543SConrad Meyer case 512: 269844d9543SConrad Meyer if (alg != CRYPTO_AES_XTS) 270c0341432SJohn Baldwin return (false); 271844d9543SConrad Meyer break; 272844d9543SConrad Meyer default: 273c0341432SJohn Baldwin return (false); 274844d9543SConrad Meyer } 275c0341432SJohn Baldwin return (true); 276844d9543SConrad Meyer } 277844d9543SConrad Meyer 278844d9543SConrad Meyer static void 279844d9543SConrad Meyer ccp_aes_setkey(struct ccp_session *s, int alg, const void *key, int klen) 280844d9543SConrad Meyer { 281844d9543SConrad Meyer unsigned kbits; 282844d9543SConrad Meyer 283844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 284c0341432SJohn Baldwin kbits = (klen / 2) * 8; 285844d9543SConrad Meyer else 286c0341432SJohn Baldwin kbits = klen * 8; 287844d9543SConrad Meyer 288844d9543SConrad Meyer switch (kbits) { 289844d9543SConrad Meyer case 128: 290844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_128; 291844d9543SConrad Meyer break; 292844d9543SConrad Meyer case 192: 293844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_192; 294844d9543SConrad Meyer break; 295844d9543SConrad Meyer case 256: 296844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_256; 297844d9543SConrad Meyer break; 298844d9543SConrad Meyer default: 299844d9543SConrad Meyer panic("should not get here"); 300844d9543SConrad Meyer } 301844d9543SConrad Meyer 302c0341432SJohn Baldwin s->blkcipher.key_len = klen; 303844d9543SConrad Meyer memcpy(s->blkcipher.enckey, key, s->blkcipher.key_len); 304844d9543SConrad Meyer } 305844d9543SConrad Meyer 306c0341432SJohn Baldwin static bool 307c0341432SJohn Baldwin ccp_auth_supported(struct ccp_softc *sc, 308c0341432SJohn Baldwin const struct crypto_session_params *csp) 309c0341432SJohn Baldwin { 310c0341432SJohn Baldwin 311c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_SHA) == 0) 312c0341432SJohn Baldwin return (false); 313c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 314c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC: 315c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 316c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 317c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 318c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 319c0341432SJohn Baldwin return (false); 320c0341432SJohn Baldwin break; 321c0341432SJohn Baldwin default: 322c0341432SJohn Baldwin return (false); 323c0341432SJohn Baldwin } 324c0341432SJohn Baldwin return (true); 325c0341432SJohn Baldwin } 326c0341432SJohn Baldwin 327c0341432SJohn Baldwin static bool 328c0341432SJohn Baldwin ccp_cipher_supported(struct ccp_softc *sc, 329c0341432SJohn Baldwin const struct crypto_session_params *csp) 330c0341432SJohn Baldwin { 331c0341432SJohn Baldwin 332c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_AES) == 0) 333c0341432SJohn Baldwin return (false); 334c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 335c0341432SJohn Baldwin case CRYPTO_AES_CBC: 336c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN) 337c0341432SJohn Baldwin return (false); 338c0341432SJohn Baldwin break; 339c0341432SJohn Baldwin case CRYPTO_AES_ICM: 340c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN) 341c0341432SJohn Baldwin return (false); 342c0341432SJohn Baldwin break; 343c0341432SJohn Baldwin case CRYPTO_AES_XTS: 344c0341432SJohn Baldwin if (csp->csp_ivlen != AES_XTS_IV_LEN) 345c0341432SJohn Baldwin return (false); 346c0341432SJohn Baldwin break; 347c0341432SJohn Baldwin default: 348c0341432SJohn Baldwin return (false); 349c0341432SJohn Baldwin } 350c0341432SJohn Baldwin return (ccp_aes_check_keylen(csp->csp_cipher_alg, 351c0341432SJohn Baldwin csp->csp_cipher_klen)); 352c0341432SJohn Baldwin } 353c0341432SJohn Baldwin 354844d9543SConrad Meyer static int 355c0341432SJohn Baldwin ccp_probesession(device_t dev, const struct crypto_session_params *csp) 356844d9543SConrad Meyer { 357844d9543SConrad Meyer struct ccp_softc *sc; 358844d9543SConrad Meyer 359c0341432SJohn Baldwin if (csp->csp_flags != 0) 360844d9543SConrad Meyer return (EINVAL); 361c0341432SJohn Baldwin sc = device_get_softc(dev); 362c0341432SJohn Baldwin switch (csp->csp_mode) { 363c0341432SJohn Baldwin case CSP_MODE_DIGEST: 364c0341432SJohn Baldwin if (!ccp_auth_supported(sc, csp)) 365844d9543SConrad Meyer return (EINVAL); 366844d9543SConrad Meyer break; 367c0341432SJohn Baldwin case CSP_MODE_CIPHER: 368c0341432SJohn Baldwin if (!ccp_cipher_supported(sc, csp)) 369c0341432SJohn Baldwin return (EINVAL); 370844d9543SConrad Meyer break; 371c0341432SJohn Baldwin case CSP_MODE_AEAD: 372c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 373844d9543SConrad Meyer case CRYPTO_AES_NIST_GCM_16: 374c0341432SJohn Baldwin if (csp->csp_ivlen != AES_GCM_IV_LEN) 375844d9543SConrad Meyer return (EINVAL); 376c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || 377c0341432SJohn Baldwin csp->csp_auth_mlen > AES_GMAC_HASH_LEN) 378c0341432SJohn Baldwin return (EINVAL); 379c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_AES) == 0) 380c0341432SJohn Baldwin return (EINVAL); 381844d9543SConrad Meyer break; 382844d9543SConrad Meyer default: 383844d9543SConrad Meyer return (EINVAL); 384844d9543SConrad Meyer } 385c0341432SJohn Baldwin break; 386c0341432SJohn Baldwin case CSP_MODE_ETA: 387c0341432SJohn Baldwin if (!ccp_auth_supported(sc, csp) || 388c0341432SJohn Baldwin !ccp_cipher_supported(sc, csp)) 389c0341432SJohn Baldwin return (EINVAL); 390c0341432SJohn Baldwin break; 391c0341432SJohn Baldwin default: 392c0341432SJohn Baldwin return (EINVAL); 393844d9543SConrad Meyer } 394c0341432SJohn Baldwin 395c0341432SJohn Baldwin return (CRYPTODEV_PROBE_HARDWARE); 396c0341432SJohn Baldwin } 397c0341432SJohn Baldwin 398c0341432SJohn Baldwin static int 399c0341432SJohn Baldwin ccp_newsession(device_t dev, crypto_session_t cses, 400c0341432SJohn Baldwin const struct crypto_session_params *csp) 401c0341432SJohn Baldwin { 402c0341432SJohn Baldwin struct ccp_softc *sc; 403c0341432SJohn Baldwin struct ccp_session *s; 404c0341432SJohn Baldwin struct auth_hash *auth_hash; 405c0341432SJohn Baldwin enum ccp_aes_mode cipher_mode; 406c0341432SJohn Baldwin unsigned auth_mode; 407c0341432SJohn Baldwin unsigned q; 408c0341432SJohn Baldwin 409c0341432SJohn Baldwin /* XXX reconcile auth_mode with use by ccp_sha */ 410c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 411c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC: 412c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha1; 413c0341432SJohn Baldwin auth_mode = SHA1; 414c0341432SJohn Baldwin break; 415c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 416c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_256; 417c0341432SJohn Baldwin auth_mode = SHA2_256; 418c0341432SJohn Baldwin break; 419c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 420c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_384; 421c0341432SJohn Baldwin auth_mode = SHA2_384; 422c0341432SJohn Baldwin break; 423c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 424c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_512; 425c0341432SJohn Baldwin auth_mode = SHA2_512; 426c0341432SJohn Baldwin break; 427c0341432SJohn Baldwin default: 428c0341432SJohn Baldwin auth_hash = NULL; 429c0341432SJohn Baldwin auth_mode = 0; 430c0341432SJohn Baldwin break; 431c0341432SJohn Baldwin } 432c0341432SJohn Baldwin 433c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 434c0341432SJohn Baldwin case CRYPTO_AES_CBC: 435c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_CBC; 436c0341432SJohn Baldwin break; 437c0341432SJohn Baldwin case CRYPTO_AES_ICM: 438c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_CTR; 439c0341432SJohn Baldwin break; 440c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 441c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_GCTR; 442c0341432SJohn Baldwin break; 443c0341432SJohn Baldwin case CRYPTO_AES_XTS: 444c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_XTS; 445c0341432SJohn Baldwin break; 446c0341432SJohn Baldwin default: 447c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_ECB; 448c0341432SJohn Baldwin break; 449c0341432SJohn Baldwin } 450844d9543SConrad Meyer 451844d9543SConrad Meyer sc = device_get_softc(dev); 452844d9543SConrad Meyer mtx_lock(&sc->lock); 453844d9543SConrad Meyer if (sc->detaching) { 454844d9543SConrad Meyer mtx_unlock(&sc->lock); 455844d9543SConrad Meyer return (ENXIO); 456844d9543SConrad Meyer } 457844d9543SConrad Meyer 458c0341432SJohn Baldwin s = crypto_get_driver_session(cses); 459c0341432SJohn Baldwin 460844d9543SConrad Meyer /* Just grab the first usable queue for now. */ 461844d9543SConrad Meyer for (q = 0; q < nitems(sc->queues); q++) 462844d9543SConrad Meyer if ((sc->valid_queues & (1 << q)) != 0) 463844d9543SConrad Meyer break; 464844d9543SConrad Meyer if (q == nitems(sc->queues)) { 465844d9543SConrad Meyer mtx_unlock(&sc->lock); 466844d9543SConrad Meyer return (ENXIO); 467844d9543SConrad Meyer } 468844d9543SConrad Meyer s->queue = q; 469844d9543SConrad Meyer 470c0341432SJohn Baldwin switch (csp->csp_mode) { 471c0341432SJohn Baldwin case CSP_MODE_AEAD: 472844d9543SConrad Meyer s->mode = GCM; 473c0341432SJohn Baldwin break; 474c0341432SJohn Baldwin case CSP_MODE_ETA: 475844d9543SConrad Meyer s->mode = AUTHENC; 476c0341432SJohn Baldwin break; 477c0341432SJohn Baldwin case CSP_MODE_DIGEST: 478844d9543SConrad Meyer s->mode = HMAC; 479c0341432SJohn Baldwin break; 480c0341432SJohn Baldwin case CSP_MODE_CIPHER: 481844d9543SConrad Meyer s->mode = BLKCIPHER; 482c0341432SJohn Baldwin break; 483844d9543SConrad Meyer } 484c0341432SJohn Baldwin 485c0341432SJohn Baldwin if (s->mode == GCM) { 486c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 487844d9543SConrad Meyer s->gmac.hash_len = AES_GMAC_HASH_LEN; 488844d9543SConrad Meyer else 489c0341432SJohn Baldwin s->gmac.hash_len = csp->csp_auth_mlen; 490c0341432SJohn Baldwin } else if (auth_hash != NULL) { 491844d9543SConrad Meyer s->hmac.auth_hash = auth_hash; 492844d9543SConrad Meyer s->hmac.auth_mode = auth_mode; 493c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 494844d9543SConrad Meyer s->hmac.hash_len = auth_hash->hashsize; 495844d9543SConrad Meyer else 496c0341432SJohn Baldwin s->hmac.hash_len = csp->csp_auth_mlen; 497c0341432SJohn Baldwin ccp_init_hmac_digest(s, csp->csp_auth_key, csp->csp_auth_klen); 498844d9543SConrad Meyer } 499c0341432SJohn Baldwin if (cipher_mode != CCP_AES_MODE_ECB) { 500844d9543SConrad Meyer s->blkcipher.cipher_mode = cipher_mode; 501c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) 502c0341432SJohn Baldwin ccp_aes_setkey(s, csp->csp_cipher_alg, 503c0341432SJohn Baldwin csp->csp_cipher_key, csp->csp_cipher_klen); 504844d9543SConrad Meyer } 505844d9543SConrad Meyer 506844d9543SConrad Meyer s->active = true; 507844d9543SConrad Meyer mtx_unlock(&sc->lock); 508844d9543SConrad Meyer 509844d9543SConrad Meyer return (0); 510844d9543SConrad Meyer } 511844d9543SConrad Meyer 5121b0909d5SConrad Meyer static void 5131b0909d5SConrad Meyer ccp_freesession(device_t dev, crypto_session_t cses) 514844d9543SConrad Meyer { 5151b0909d5SConrad Meyer struct ccp_session *s; 516844d9543SConrad Meyer 5171b0909d5SConrad Meyer s = crypto_get_driver_session(cses); 5181b0909d5SConrad Meyer 5191b0909d5SConrad Meyer if (s->pending != 0) 520844d9543SConrad Meyer device_printf(dev, 5211b0909d5SConrad Meyer "session %p freed with %d pending requests\n", s, 5221b0909d5SConrad Meyer s->pending); 5231b0909d5SConrad Meyer s->active = false; 524844d9543SConrad Meyer } 525844d9543SConrad Meyer 526844d9543SConrad Meyer static int 527844d9543SConrad Meyer ccp_process(device_t dev, struct cryptop *crp, int hint) 528844d9543SConrad Meyer { 529c0341432SJohn Baldwin const struct crypto_session_params *csp; 530844d9543SConrad Meyer struct ccp_softc *sc; 531844d9543SConrad Meyer struct ccp_queue *qp; 532844d9543SConrad Meyer struct ccp_session *s; 533844d9543SConrad Meyer int error; 534844d9543SConrad Meyer bool qpheld; 535844d9543SConrad Meyer 536844d9543SConrad Meyer qpheld = false; 537844d9543SConrad Meyer qp = NULL; 538844d9543SConrad Meyer 539c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 5401b0909d5SConrad Meyer s = crypto_get_driver_session(crp->crp_session); 541844d9543SConrad Meyer sc = device_get_softc(dev); 542844d9543SConrad Meyer mtx_lock(&sc->lock); 543844d9543SConrad Meyer qp = &sc->queues[s->queue]; 544844d9543SConrad Meyer mtx_unlock(&sc->lock); 545844d9543SConrad Meyer error = ccp_queue_acquire_reserve(qp, 1 /* placeholder */, M_NOWAIT); 546844d9543SConrad Meyer if (error != 0) 547844d9543SConrad Meyer goto out; 548844d9543SConrad Meyer qpheld = true; 549844d9543SConrad Meyer 550*9c0e3d3aSJohn Baldwin error = ccp_populate_sglist(qp->cq_sg_crp, &crp->crp_buf); 551844d9543SConrad Meyer if (error != 0) 552844d9543SConrad Meyer goto out; 553844d9543SConrad Meyer 554c0341432SJohn Baldwin if (crp->crp_auth_key != NULL) { 555c0341432SJohn Baldwin KASSERT(s->hmac.auth_hash != NULL, ("auth key without HMAC")); 556c0341432SJohn Baldwin ccp_init_hmac_digest(s, crp->crp_auth_key, csp->csp_auth_klen); 557c0341432SJohn Baldwin } 558c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) 559c0341432SJohn Baldwin ccp_aes_setkey(s, csp->csp_cipher_alg, crp->crp_cipher_key, 560c0341432SJohn Baldwin csp->csp_cipher_klen); 561c0341432SJohn Baldwin 562844d9543SConrad Meyer switch (s->mode) { 563844d9543SConrad Meyer case HMAC: 564c0341432SJohn Baldwin if (s->pending != 0) { 565c0341432SJohn Baldwin error = EAGAIN; 566c0341432SJohn Baldwin break; 567c0341432SJohn Baldwin } 568844d9543SConrad Meyer error = ccp_hmac(qp, s, crp); 569844d9543SConrad Meyer break; 570844d9543SConrad Meyer case BLKCIPHER: 571c0341432SJohn Baldwin if (s->pending != 0) { 572c0341432SJohn Baldwin error = EAGAIN; 573844d9543SConrad Meyer break; 574844d9543SConrad Meyer } 575844d9543SConrad Meyer error = ccp_blkcipher(qp, s, crp); 576844d9543SConrad Meyer break; 577844d9543SConrad Meyer case AUTHENC: 578c0341432SJohn Baldwin if (s->pending != 0) { 579c0341432SJohn Baldwin error = EAGAIN; 580844d9543SConrad Meyer break; 581844d9543SConrad Meyer } 582c0341432SJohn Baldwin error = ccp_authenc(qp, s, crp); 583844d9543SConrad Meyer break; 584844d9543SConrad Meyer case GCM: 585c0341432SJohn Baldwin if (s->pending != 0) { 586c0341432SJohn Baldwin error = EAGAIN; 587c0341432SJohn Baldwin break; 588c0341432SJohn Baldwin } 589c0341432SJohn Baldwin error = ccp_gcm(qp, s, crp); 590844d9543SConrad Meyer break; 591844d9543SConrad Meyer } 592844d9543SConrad Meyer 593844d9543SConrad Meyer if (error == 0) 594844d9543SConrad Meyer s->pending++; 595844d9543SConrad Meyer 596844d9543SConrad Meyer out: 597844d9543SConrad Meyer if (qpheld) { 598844d9543SConrad Meyer if (error != 0) { 599844d9543SConrad Meyer /* 600844d9543SConrad Meyer * Squash EAGAIN so callers don't uselessly and 601844d9543SConrad Meyer * expensively retry if the ring was full. 602844d9543SConrad Meyer */ 603844d9543SConrad Meyer if (error == EAGAIN) 604844d9543SConrad Meyer error = ENOMEM; 605844d9543SConrad Meyer ccp_queue_abort(qp); 606844d9543SConrad Meyer } else 607844d9543SConrad Meyer ccp_queue_release(qp); 608844d9543SConrad Meyer } 609844d9543SConrad Meyer 610844d9543SConrad Meyer if (error != 0) { 611844d9543SConrad Meyer DPRINTF(dev, "%s: early error:%d\n", __func__, error); 612844d9543SConrad Meyer crp->crp_etype = error; 613844d9543SConrad Meyer crypto_done(crp); 614844d9543SConrad Meyer } 615844d9543SConrad Meyer return (0); 616844d9543SConrad Meyer } 617844d9543SConrad Meyer 618844d9543SConrad Meyer static device_method_t ccp_methods[] = { 619844d9543SConrad Meyer DEVMETHOD(device_probe, ccp_probe), 620844d9543SConrad Meyer DEVMETHOD(device_attach, ccp_attach), 621844d9543SConrad Meyer DEVMETHOD(device_detach, ccp_detach), 622844d9543SConrad Meyer 623c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, ccp_probesession), 624844d9543SConrad Meyer DEVMETHOD(cryptodev_newsession, ccp_newsession), 625844d9543SConrad Meyer DEVMETHOD(cryptodev_freesession, ccp_freesession), 626844d9543SConrad Meyer DEVMETHOD(cryptodev_process, ccp_process), 627844d9543SConrad Meyer 628844d9543SConrad Meyer DEVMETHOD_END 629844d9543SConrad Meyer }; 630844d9543SConrad Meyer 631844d9543SConrad Meyer static driver_t ccp_driver = { 632844d9543SConrad Meyer "ccp", 633844d9543SConrad Meyer ccp_methods, 634844d9543SConrad Meyer sizeof(struct ccp_softc) 635844d9543SConrad Meyer }; 636844d9543SConrad Meyer 637844d9543SConrad Meyer static devclass_t ccp_devclass; 638844d9543SConrad Meyer DRIVER_MODULE(ccp, pci, ccp_driver, ccp_devclass, NULL, NULL); 639844d9543SConrad Meyer MODULE_VERSION(ccp, 1); 640844d9543SConrad Meyer MODULE_DEPEND(ccp, crypto, 1, 1, 1); 641844d9543SConrad Meyer MODULE_DEPEND(ccp, random_device, 1, 1, 1); 64291eeadc5SWarner Losh #if 0 /* There are enough known issues that we shouldn't load automatically */ 643329e817fSWarner Losh MODULE_PNP_INFO("W32:vendor/device", pci, ccp, ccp_ids, 644b7220273SWarner Losh nitems(ccp_ids)); 64591eeadc5SWarner Losh #endif 646844d9543SConrad Meyer 647844d9543SConrad Meyer static int 648844d9543SConrad Meyer ccp_queue_reserve_space(struct ccp_queue *qp, unsigned n, int mflags) 649844d9543SConrad Meyer { 650844d9543SConrad Meyer struct ccp_softc *sc; 651844d9543SConrad Meyer 652844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 653844d9543SConrad Meyer sc = qp->cq_softc; 654844d9543SConrad Meyer 655844d9543SConrad Meyer if (n < 1 || n >= (1 << sc->ring_size_order)) 656844d9543SConrad Meyer return (EINVAL); 657844d9543SConrad Meyer 658844d9543SConrad Meyer while (true) { 659844d9543SConrad Meyer if (ccp_queue_get_ring_space(qp) >= n) 660844d9543SConrad Meyer return (0); 661844d9543SConrad Meyer if ((mflags & M_WAITOK) == 0) 662844d9543SConrad Meyer return (EAGAIN); 663844d9543SConrad Meyer qp->cq_waiting = true; 664844d9543SConrad Meyer msleep(&qp->cq_tail, &qp->cq_lock, 0, "ccpqfull", 0); 665844d9543SConrad Meyer } 666844d9543SConrad Meyer } 667844d9543SConrad Meyer 668844d9543SConrad Meyer int 669844d9543SConrad Meyer ccp_queue_acquire_reserve(struct ccp_queue *qp, unsigned n, int mflags) 670844d9543SConrad Meyer { 671844d9543SConrad Meyer int error; 672844d9543SConrad Meyer 673844d9543SConrad Meyer mtx_lock(&qp->cq_lock); 674844d9543SConrad Meyer qp->cq_acq_tail = qp->cq_tail; 675844d9543SConrad Meyer error = ccp_queue_reserve_space(qp, n, mflags); 676844d9543SConrad Meyer if (error != 0) 677844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 678844d9543SConrad Meyer return (error); 679844d9543SConrad Meyer } 680844d9543SConrad Meyer 681844d9543SConrad Meyer void 682844d9543SConrad Meyer ccp_queue_release(struct ccp_queue *qp) 683844d9543SConrad Meyer { 684844d9543SConrad Meyer 685844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 686844d9543SConrad Meyer if (qp->cq_tail != qp->cq_acq_tail) { 687844d9543SConrad Meyer wmb(); 688844d9543SConrad Meyer ccp_queue_write_tail(qp); 689844d9543SConrad Meyer } 690844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 691844d9543SConrad Meyer } 692844d9543SConrad Meyer 693844d9543SConrad Meyer void 694844d9543SConrad Meyer ccp_queue_abort(struct ccp_queue *qp) 695844d9543SConrad Meyer { 696844d9543SConrad Meyer unsigned i; 697844d9543SConrad Meyer 698844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 699844d9543SConrad Meyer 700844d9543SConrad Meyer /* Wipe out any descriptors associated with this aborted txn. */ 701844d9543SConrad Meyer for (i = qp->cq_acq_tail; i != qp->cq_tail; 702844d9543SConrad Meyer i = (i + 1) % (1 << qp->cq_softc->ring_size_order)) { 703844d9543SConrad Meyer memset(&qp->desc_ring[i], 0, sizeof(qp->desc_ring[i])); 704844d9543SConrad Meyer } 705844d9543SConrad Meyer qp->cq_tail = qp->cq_acq_tail; 706844d9543SConrad Meyer 707844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 708844d9543SConrad Meyer } 709844d9543SConrad Meyer 710844d9543SConrad Meyer #ifdef DDB 711844d9543SConrad Meyer #define _db_show_lock(lo) LOCK_CLASS(lo)->lc_ddb_show(lo) 712844d9543SConrad Meyer #define db_show_lock(lk) _db_show_lock(&(lk)->lock_object) 713844d9543SConrad Meyer static void 714844d9543SConrad Meyer db_show_ccp_sc(struct ccp_softc *sc) 715844d9543SConrad Meyer { 716844d9543SConrad Meyer 717844d9543SConrad Meyer db_printf("ccp softc at %p\n", sc); 718844d9543SConrad Meyer db_printf(" cid: %d\n", (int)sc->cid); 719844d9543SConrad Meyer 720844d9543SConrad Meyer db_printf(" lock: "); 721844d9543SConrad Meyer db_show_lock(&sc->lock); 722844d9543SConrad Meyer 723844d9543SConrad Meyer db_printf(" detaching: %d\n", (int)sc->detaching); 724844d9543SConrad Meyer db_printf(" ring_size_order: %u\n", sc->ring_size_order); 725844d9543SConrad Meyer 726844d9543SConrad Meyer db_printf(" hw_version: %d\n", (int)sc->hw_version); 727844d9543SConrad Meyer db_printf(" hw_features: %b\n", (int)sc->hw_features, 728844d9543SConrad Meyer "\20\24ELFC\23TRNG\22Zip_Compress\16Zip_Decompress\13ECC\12RSA" 729844d9543SConrad Meyer "\11SHA\0103DES\07AES"); 730844d9543SConrad Meyer 731844d9543SConrad Meyer db_printf(" hw status:\n"); 732844d9543SConrad Meyer db_ccp_show_hw(sc); 733844d9543SConrad Meyer } 734844d9543SConrad Meyer 735844d9543SConrad Meyer static void 736844d9543SConrad Meyer db_show_ccp_qp(struct ccp_queue *qp) 737844d9543SConrad Meyer { 738844d9543SConrad Meyer 739844d9543SConrad Meyer db_printf(" lock: "); 740844d9543SConrad Meyer db_show_lock(&qp->cq_lock); 741844d9543SConrad Meyer 742844d9543SConrad Meyer db_printf(" cq_qindex: %u\n", qp->cq_qindex); 743844d9543SConrad Meyer db_printf(" cq_softc: %p\n", qp->cq_softc); 744844d9543SConrad Meyer 745844d9543SConrad Meyer db_printf(" head: %u\n", qp->cq_head); 746844d9543SConrad Meyer db_printf(" tail: %u\n", qp->cq_tail); 747844d9543SConrad Meyer db_printf(" acq_tail: %u\n", qp->cq_acq_tail); 748844d9543SConrad Meyer db_printf(" desc_ring: %p\n", qp->desc_ring); 749844d9543SConrad Meyer db_printf(" completions_ring: %p\n", qp->completions_ring); 750844d9543SConrad Meyer db_printf(" descriptors (phys): 0x%jx\n", 751844d9543SConrad Meyer (uintmax_t)qp->desc_ring_bus_addr); 752844d9543SConrad Meyer 753844d9543SConrad Meyer db_printf(" hw status:\n"); 754844d9543SConrad Meyer db_ccp_show_queue_hw(qp); 755844d9543SConrad Meyer } 756844d9543SConrad Meyer 757844d9543SConrad Meyer DB_SHOW_COMMAND(ccp, db_show_ccp) 758844d9543SConrad Meyer { 759844d9543SConrad Meyer struct ccp_softc *sc; 760844d9543SConrad Meyer unsigned unit, qindex; 761844d9543SConrad Meyer 762844d9543SConrad Meyer if (!have_addr) 763844d9543SConrad Meyer goto usage; 764844d9543SConrad Meyer 765844d9543SConrad Meyer unit = (unsigned)addr; 766844d9543SConrad Meyer 767844d9543SConrad Meyer sc = devclass_get_softc(ccp_devclass, unit); 768844d9543SConrad Meyer if (sc == NULL) { 769844d9543SConrad Meyer db_printf("No such device ccp%u\n", unit); 770844d9543SConrad Meyer goto usage; 771844d9543SConrad Meyer } 772844d9543SConrad Meyer 773844d9543SConrad Meyer if (count == -1) { 774844d9543SConrad Meyer db_show_ccp_sc(sc); 775844d9543SConrad Meyer return; 776844d9543SConrad Meyer } 777844d9543SConrad Meyer 778844d9543SConrad Meyer qindex = (unsigned)count; 779844d9543SConrad Meyer if (qindex >= nitems(sc->queues)) { 780844d9543SConrad Meyer db_printf("No such queue %u\n", qindex); 781844d9543SConrad Meyer goto usage; 782844d9543SConrad Meyer } 783844d9543SConrad Meyer db_show_ccp_qp(&sc->queues[qindex]); 784844d9543SConrad Meyer return; 785844d9543SConrad Meyer 786844d9543SConrad Meyer usage: 787844d9543SConrad Meyer db_printf("usage: show ccp <unit>[,<qindex>]\n"); 788844d9543SConrad Meyer return; 789844d9543SConrad Meyer } 790844d9543SConrad Meyer #endif /* DDB */ 791