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 959c0e3d3aSJohn Baldwin ccp_populate_sglist(struct sglist *sg, struct crypto_buffer *cb) 96844d9543SConrad Meyer { 97844d9543SConrad Meyer int error; 98844d9543SConrad Meyer 99844d9543SConrad Meyer sglist_reset(sg); 1009c0e3d3aSJohn Baldwin switch (cb->cb_type) { 101c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 1029c0e3d3aSJohn Baldwin error = sglist_append_mbuf(sg, cb->cb_mbuf); 103c0341432SJohn Baldwin break; 104883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 105883a0196SJohn Baldwin error = sglist_append_single_mbuf(sg, cb->cb_mbuf); 106883a0196SJohn Baldwin break; 107c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 1089c0e3d3aSJohn Baldwin error = sglist_append_uio(sg, cb->cb_uio); 109c0341432SJohn Baldwin break; 110c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 1119c0e3d3aSJohn Baldwin error = sglist_append(sg, cb->cb_buf, cb->cb_buf_len); 112c0341432SJohn Baldwin break; 113e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 114e6f6d0c9SAlan Somers error = sglist_append_vmpages(sg, cb->cb_vm_page, 115e6f6d0c9SAlan Somers cb->cb_vm_page_len, cb->cb_vm_page_offset); 116e6f6d0c9SAlan Somers break; 117c0341432SJohn Baldwin default: 118c0341432SJohn Baldwin error = EINVAL; 119c0341432SJohn Baldwin } 120844d9543SConrad Meyer return (error); 121844d9543SConrad Meyer } 122844d9543SConrad Meyer 123844d9543SConrad Meyer static int 124844d9543SConrad Meyer ccp_probe(device_t dev) 125844d9543SConrad Meyer { 126844d9543SConrad Meyer struct pciid *ip; 127844d9543SConrad Meyer uint32_t id; 128844d9543SConrad Meyer 129844d9543SConrad Meyer id = pci_get_devid(dev); 130844d9543SConrad Meyer for (ip = ccp_ids; ip < &ccp_ids[nitems(ccp_ids)]; ip++) { 131844d9543SConrad Meyer if (id == ip->devid) { 132844d9543SConrad Meyer device_set_desc(dev, ip->desc); 133844d9543SConrad Meyer return (0); 134844d9543SConrad Meyer } 135844d9543SConrad Meyer } 136844d9543SConrad Meyer return (ENXIO); 137844d9543SConrad Meyer } 138844d9543SConrad Meyer 139844d9543SConrad Meyer static void 140844d9543SConrad Meyer ccp_initialize_queues(struct ccp_softc *sc) 141844d9543SConrad Meyer { 142844d9543SConrad Meyer struct ccp_queue *qp; 143844d9543SConrad Meyer size_t i; 144844d9543SConrad Meyer 145844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 146844d9543SConrad Meyer qp = &sc->queues[i]; 147844d9543SConrad Meyer 148844d9543SConrad Meyer qp->cq_softc = sc; 149844d9543SConrad Meyer qp->cq_qindex = i; 150844d9543SConrad Meyer mtx_init(&qp->cq_lock, "ccp queue", NULL, MTX_DEF); 151844d9543SConrad Meyer /* XXX - arbitrarily chosen sizes */ 152844d9543SConrad Meyer qp->cq_sg_crp = sglist_alloc(32, M_WAITOK); 153844d9543SConrad Meyer /* Two more SGEs than sg_crp to accommodate ipad. */ 154844d9543SConrad Meyer qp->cq_sg_ulptx = sglist_alloc(34, M_WAITOK); 155844d9543SConrad Meyer qp->cq_sg_dst = sglist_alloc(2, M_WAITOK); 156844d9543SConrad Meyer } 157844d9543SConrad Meyer } 158844d9543SConrad Meyer 159844d9543SConrad Meyer static void 160844d9543SConrad Meyer ccp_free_queues(struct ccp_softc *sc) 161844d9543SConrad Meyer { 162844d9543SConrad Meyer struct ccp_queue *qp; 163844d9543SConrad Meyer size_t i; 164844d9543SConrad Meyer 165844d9543SConrad Meyer for (i = 0; i < nitems(sc->queues); i++) { 166844d9543SConrad Meyer qp = &sc->queues[i]; 167844d9543SConrad Meyer 168844d9543SConrad Meyer mtx_destroy(&qp->cq_lock); 169844d9543SConrad Meyer sglist_free(qp->cq_sg_crp); 170844d9543SConrad Meyer sglist_free(qp->cq_sg_ulptx); 171844d9543SConrad Meyer sglist_free(qp->cq_sg_dst); 172844d9543SConrad Meyer } 173844d9543SConrad Meyer } 174844d9543SConrad Meyer 175844d9543SConrad Meyer static int 176844d9543SConrad Meyer ccp_attach(device_t dev) 177844d9543SConrad Meyer { 178844d9543SConrad Meyer struct ccp_softc *sc; 179844d9543SConrad Meyer int error; 180844d9543SConrad Meyer 181844d9543SConrad Meyer sc = device_get_softc(dev); 182844d9543SConrad Meyer sc->dev = dev; 183844d9543SConrad Meyer 1841b0909d5SConrad Meyer sc->cid = crypto_get_driverid(dev, sizeof(struct ccp_session), 1851b0909d5SConrad Meyer CRYPTOCAP_F_HARDWARE); 186844d9543SConrad Meyer if (sc->cid < 0) { 187844d9543SConrad Meyer device_printf(dev, "could not get crypto driver id\n"); 188844d9543SConrad Meyer return (ENXIO); 189844d9543SConrad Meyer } 190844d9543SConrad Meyer 191844d9543SConrad Meyer error = ccp_hw_attach(dev); 192844d9543SConrad Meyer if (error != 0) 193844d9543SConrad Meyer return (error); 194844d9543SConrad Meyer 195844d9543SConrad Meyer mtx_init(&sc->lock, "ccp", NULL, MTX_DEF); 196844d9543SConrad Meyer 197844d9543SConrad Meyer ccp_initialize_queues(sc); 198844d9543SConrad Meyer 199844d9543SConrad Meyer if (g_ccp_softc == NULL) { 200844d9543SConrad Meyer g_ccp_softc = sc; 201844d9543SConrad Meyer if ((sc->hw_features & VERSION_CAP_TRNG) != 0) 202844d9543SConrad Meyer random_source_register(&random_ccp); 203844d9543SConrad Meyer } 204844d9543SConrad Meyer 205844d9543SConrad Meyer return (0); 206844d9543SConrad Meyer } 207844d9543SConrad Meyer 208844d9543SConrad Meyer static int 209844d9543SConrad Meyer ccp_detach(device_t dev) 210844d9543SConrad Meyer { 211844d9543SConrad Meyer struct ccp_softc *sc; 212844d9543SConrad Meyer 213844d9543SConrad Meyer sc = device_get_softc(dev); 214844d9543SConrad Meyer 215844d9543SConrad Meyer mtx_lock(&sc->lock); 216844d9543SConrad Meyer sc->detaching = true; 217844d9543SConrad Meyer mtx_unlock(&sc->lock); 218844d9543SConrad Meyer 219844d9543SConrad Meyer crypto_unregister_all(sc->cid); 220844d9543SConrad Meyer if (g_ccp_softc == sc && (sc->hw_features & VERSION_CAP_TRNG) != 0) 221844d9543SConrad Meyer random_source_deregister(&random_ccp); 222844d9543SConrad Meyer 223844d9543SConrad Meyer ccp_hw_detach(dev); 224844d9543SConrad Meyer ccp_free_queues(sc); 225844d9543SConrad Meyer 226844d9543SConrad Meyer if (g_ccp_softc == sc) 227844d9543SConrad Meyer g_ccp_softc = NULL; 228844d9543SConrad Meyer 229844d9543SConrad Meyer mtx_destroy(&sc->lock); 230844d9543SConrad Meyer return (0); 231844d9543SConrad Meyer } 232844d9543SConrad Meyer 233844d9543SConrad Meyer static void 234c0341432SJohn Baldwin ccp_init_hmac_digest(struct ccp_session *s, const char *key, int klen) 235844d9543SConrad Meyer { 236844d9543SConrad Meyer union authctx auth_ctx; 237d8787d4fSMark Johnston const struct auth_hash *axf; 238844d9543SConrad Meyer u_int i; 239844d9543SConrad Meyer 240844d9543SConrad Meyer /* 241844d9543SConrad Meyer * If the key is larger than the block size, use the digest of 242844d9543SConrad Meyer * the key as the key instead. 243844d9543SConrad Meyer */ 244844d9543SConrad Meyer axf = s->hmac.auth_hash; 245844d9543SConrad Meyer if (klen > axf->blocksize) { 246844d9543SConrad Meyer axf->Init(&auth_ctx); 247844d9543SConrad Meyer axf->Update(&auth_ctx, key, klen); 248844d9543SConrad Meyer axf->Final(s->hmac.ipad, &auth_ctx); 249844d9543SConrad Meyer explicit_bzero(&auth_ctx, sizeof(auth_ctx)); 250844d9543SConrad Meyer klen = axf->hashsize; 251844d9543SConrad Meyer } else 252844d9543SConrad Meyer memcpy(s->hmac.ipad, key, klen); 253844d9543SConrad Meyer 254844d9543SConrad Meyer memset(s->hmac.ipad + klen, 0, axf->blocksize - klen); 255844d9543SConrad Meyer memcpy(s->hmac.opad, s->hmac.ipad, axf->blocksize); 256844d9543SConrad Meyer 257844d9543SConrad Meyer for (i = 0; i < axf->blocksize; i++) { 258844d9543SConrad Meyer s->hmac.ipad[i] ^= HMAC_IPAD_VAL; 259844d9543SConrad Meyer s->hmac.opad[i] ^= HMAC_OPAD_VAL; 260844d9543SConrad Meyer } 261844d9543SConrad Meyer } 262844d9543SConrad Meyer 263c0341432SJohn Baldwin static bool 264844d9543SConrad Meyer ccp_aes_check_keylen(int alg, int klen) 265844d9543SConrad Meyer { 266844d9543SConrad Meyer 267c0341432SJohn Baldwin switch (klen * 8) { 268844d9543SConrad Meyer case 128: 269844d9543SConrad Meyer case 192: 270844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 271c0341432SJohn Baldwin return (false); 272844d9543SConrad Meyer break; 273844d9543SConrad Meyer case 256: 274844d9543SConrad Meyer break; 275844d9543SConrad Meyer case 512: 276844d9543SConrad Meyer if (alg != CRYPTO_AES_XTS) 277c0341432SJohn Baldwin return (false); 278844d9543SConrad Meyer break; 279844d9543SConrad Meyer default: 280c0341432SJohn Baldwin return (false); 281844d9543SConrad Meyer } 282c0341432SJohn Baldwin return (true); 283844d9543SConrad Meyer } 284844d9543SConrad Meyer 285844d9543SConrad Meyer static void 286844d9543SConrad Meyer ccp_aes_setkey(struct ccp_session *s, int alg, const void *key, int klen) 287844d9543SConrad Meyer { 288844d9543SConrad Meyer unsigned kbits; 289844d9543SConrad Meyer 290844d9543SConrad Meyer if (alg == CRYPTO_AES_XTS) 291c0341432SJohn Baldwin kbits = (klen / 2) * 8; 292844d9543SConrad Meyer else 293c0341432SJohn Baldwin kbits = klen * 8; 294844d9543SConrad Meyer 295844d9543SConrad Meyer switch (kbits) { 296844d9543SConrad Meyer case 128: 297844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_128; 298844d9543SConrad Meyer break; 299844d9543SConrad Meyer case 192: 300844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_192; 301844d9543SConrad Meyer break; 302844d9543SConrad Meyer case 256: 303844d9543SConrad Meyer s->blkcipher.cipher_type = CCP_AES_TYPE_256; 304844d9543SConrad Meyer break; 305844d9543SConrad Meyer default: 306844d9543SConrad Meyer panic("should not get here"); 307844d9543SConrad Meyer } 308844d9543SConrad Meyer 309c0341432SJohn Baldwin s->blkcipher.key_len = klen; 310844d9543SConrad Meyer memcpy(s->blkcipher.enckey, key, s->blkcipher.key_len); 311844d9543SConrad Meyer } 312844d9543SConrad Meyer 313c0341432SJohn Baldwin static bool 314c0341432SJohn Baldwin ccp_auth_supported(struct ccp_softc *sc, 315c0341432SJohn Baldwin const struct crypto_session_params *csp) 316c0341432SJohn Baldwin { 317c0341432SJohn Baldwin 318c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_SHA) == 0) 319c0341432SJohn Baldwin return (false); 320c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 321c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC: 322c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 323c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 324c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 325c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 326c0341432SJohn Baldwin return (false); 327c0341432SJohn Baldwin break; 328c0341432SJohn Baldwin default: 329c0341432SJohn Baldwin return (false); 330c0341432SJohn Baldwin } 331c0341432SJohn Baldwin return (true); 332c0341432SJohn Baldwin } 333c0341432SJohn Baldwin 334c0341432SJohn Baldwin static bool 335c0341432SJohn Baldwin ccp_cipher_supported(struct ccp_softc *sc, 336c0341432SJohn Baldwin const struct crypto_session_params *csp) 337c0341432SJohn Baldwin { 338c0341432SJohn Baldwin 339c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_AES) == 0) 340c0341432SJohn Baldwin return (false); 341c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 342c0341432SJohn Baldwin case CRYPTO_AES_CBC: 343c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN) 344c0341432SJohn Baldwin return (false); 345c0341432SJohn Baldwin break; 346c0341432SJohn Baldwin case CRYPTO_AES_ICM: 347c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN) 348c0341432SJohn Baldwin return (false); 349c0341432SJohn Baldwin break; 350c0341432SJohn Baldwin case CRYPTO_AES_XTS: 351c0341432SJohn Baldwin if (csp->csp_ivlen != AES_XTS_IV_LEN) 352c0341432SJohn Baldwin return (false); 353c0341432SJohn Baldwin break; 354c0341432SJohn Baldwin default: 355c0341432SJohn Baldwin return (false); 356c0341432SJohn Baldwin } 357c0341432SJohn Baldwin return (ccp_aes_check_keylen(csp->csp_cipher_alg, 358c0341432SJohn Baldwin csp->csp_cipher_klen)); 359c0341432SJohn Baldwin } 360c0341432SJohn Baldwin 361844d9543SConrad Meyer static int 362c0341432SJohn Baldwin ccp_probesession(device_t dev, const struct crypto_session_params *csp) 363844d9543SConrad Meyer { 364844d9543SConrad Meyer struct ccp_softc *sc; 365844d9543SConrad Meyer 366c0341432SJohn Baldwin if (csp->csp_flags != 0) 367844d9543SConrad Meyer return (EINVAL); 368c0341432SJohn Baldwin sc = device_get_softc(dev); 369c0341432SJohn Baldwin switch (csp->csp_mode) { 370c0341432SJohn Baldwin case CSP_MODE_DIGEST: 371c0341432SJohn Baldwin if (!ccp_auth_supported(sc, csp)) 372844d9543SConrad Meyer return (EINVAL); 373844d9543SConrad Meyer break; 374c0341432SJohn Baldwin case CSP_MODE_CIPHER: 375c0341432SJohn Baldwin if (!ccp_cipher_supported(sc, csp)) 376c0341432SJohn Baldwin return (EINVAL); 377844d9543SConrad Meyer break; 378c0341432SJohn Baldwin case CSP_MODE_AEAD: 379c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 380844d9543SConrad Meyer case CRYPTO_AES_NIST_GCM_16: 381c0341432SJohn Baldwin if ((sc->hw_features & VERSION_CAP_AES) == 0) 382c0341432SJohn Baldwin return (EINVAL); 383844d9543SConrad Meyer break; 384844d9543SConrad Meyer default: 385844d9543SConrad Meyer return (EINVAL); 386844d9543SConrad Meyer } 387c0341432SJohn Baldwin break; 388c0341432SJohn Baldwin case CSP_MODE_ETA: 389c0341432SJohn Baldwin if (!ccp_auth_supported(sc, csp) || 390c0341432SJohn Baldwin !ccp_cipher_supported(sc, csp)) 391c0341432SJohn Baldwin return (EINVAL); 392c0341432SJohn Baldwin break; 393c0341432SJohn Baldwin default: 394c0341432SJohn Baldwin return (EINVAL); 395844d9543SConrad Meyer } 396c0341432SJohn Baldwin 397c0341432SJohn Baldwin return (CRYPTODEV_PROBE_HARDWARE); 398c0341432SJohn Baldwin } 399c0341432SJohn Baldwin 400c0341432SJohn Baldwin static int 401c0341432SJohn Baldwin ccp_newsession(device_t dev, crypto_session_t cses, 402c0341432SJohn Baldwin const struct crypto_session_params *csp) 403c0341432SJohn Baldwin { 404c0341432SJohn Baldwin struct ccp_softc *sc; 405c0341432SJohn Baldwin struct ccp_session *s; 406d8787d4fSMark Johnston const struct auth_hash *auth_hash; 407c0341432SJohn Baldwin enum ccp_aes_mode cipher_mode; 408c0341432SJohn Baldwin unsigned auth_mode; 409c0341432SJohn Baldwin unsigned q; 410c0341432SJohn Baldwin 411c0341432SJohn Baldwin /* XXX reconcile auth_mode with use by ccp_sha */ 412c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 413c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC: 414c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha1; 415c0341432SJohn Baldwin auth_mode = SHA1; 416c0341432SJohn Baldwin break; 417c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 418c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_256; 419c0341432SJohn Baldwin auth_mode = SHA2_256; 420c0341432SJohn Baldwin break; 421c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 422c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_384; 423c0341432SJohn Baldwin auth_mode = SHA2_384; 424c0341432SJohn Baldwin break; 425c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 426c0341432SJohn Baldwin auth_hash = &auth_hash_hmac_sha2_512; 427c0341432SJohn Baldwin auth_mode = SHA2_512; 428c0341432SJohn Baldwin break; 429c0341432SJohn Baldwin default: 430c0341432SJohn Baldwin auth_hash = NULL; 431c0341432SJohn Baldwin auth_mode = 0; 432c0341432SJohn Baldwin break; 433c0341432SJohn Baldwin } 434c0341432SJohn Baldwin 435c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 436c0341432SJohn Baldwin case CRYPTO_AES_CBC: 437c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_CBC; 438c0341432SJohn Baldwin break; 439c0341432SJohn Baldwin case CRYPTO_AES_ICM: 440c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_CTR; 441c0341432SJohn Baldwin break; 442c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 443c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_GCTR; 444c0341432SJohn Baldwin break; 445c0341432SJohn Baldwin case CRYPTO_AES_XTS: 446c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_XTS; 447c0341432SJohn Baldwin break; 448c0341432SJohn Baldwin default: 449c0341432SJohn Baldwin cipher_mode = CCP_AES_MODE_ECB; 450c0341432SJohn Baldwin break; 451c0341432SJohn Baldwin } 452844d9543SConrad Meyer 453844d9543SConrad Meyer sc = device_get_softc(dev); 454844d9543SConrad Meyer mtx_lock(&sc->lock); 455844d9543SConrad Meyer if (sc->detaching) { 456844d9543SConrad Meyer mtx_unlock(&sc->lock); 457844d9543SConrad Meyer return (ENXIO); 458844d9543SConrad Meyer } 459844d9543SConrad Meyer 460c0341432SJohn Baldwin s = crypto_get_driver_session(cses); 461c0341432SJohn Baldwin 462844d9543SConrad Meyer /* Just grab the first usable queue for now. */ 463844d9543SConrad Meyer for (q = 0; q < nitems(sc->queues); q++) 464844d9543SConrad Meyer if ((sc->valid_queues & (1 << q)) != 0) 465844d9543SConrad Meyer break; 466844d9543SConrad Meyer if (q == nitems(sc->queues)) { 467844d9543SConrad Meyer mtx_unlock(&sc->lock); 468844d9543SConrad Meyer return (ENXIO); 469844d9543SConrad Meyer } 470844d9543SConrad Meyer s->queue = q; 471844d9543SConrad Meyer 472c0341432SJohn Baldwin switch (csp->csp_mode) { 473c0341432SJohn Baldwin case CSP_MODE_AEAD: 474844d9543SConrad Meyer s->mode = GCM; 475c0341432SJohn Baldwin break; 476c0341432SJohn Baldwin case CSP_MODE_ETA: 477844d9543SConrad Meyer s->mode = AUTHENC; 478c0341432SJohn Baldwin break; 479c0341432SJohn Baldwin case CSP_MODE_DIGEST: 480844d9543SConrad Meyer s->mode = HMAC; 481c0341432SJohn Baldwin break; 482c0341432SJohn Baldwin case CSP_MODE_CIPHER: 483844d9543SConrad Meyer s->mode = BLKCIPHER; 484c0341432SJohn Baldwin break; 485844d9543SConrad Meyer } 486c0341432SJohn Baldwin 487c0341432SJohn Baldwin if (s->mode == GCM) { 488c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 489844d9543SConrad Meyer s->gmac.hash_len = AES_GMAC_HASH_LEN; 490844d9543SConrad Meyer else 491c0341432SJohn Baldwin s->gmac.hash_len = csp->csp_auth_mlen; 492c0341432SJohn Baldwin } else if (auth_hash != NULL) { 493844d9543SConrad Meyer s->hmac.auth_hash = auth_hash; 494844d9543SConrad Meyer s->hmac.auth_mode = auth_mode; 495c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 496844d9543SConrad Meyer s->hmac.hash_len = auth_hash->hashsize; 497844d9543SConrad Meyer else 498c0341432SJohn Baldwin s->hmac.hash_len = csp->csp_auth_mlen; 499c0341432SJohn Baldwin ccp_init_hmac_digest(s, csp->csp_auth_key, csp->csp_auth_klen); 500844d9543SConrad Meyer } 501c0341432SJohn Baldwin if (cipher_mode != CCP_AES_MODE_ECB) { 502844d9543SConrad Meyer s->blkcipher.cipher_mode = cipher_mode; 503c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) 504c0341432SJohn Baldwin ccp_aes_setkey(s, csp->csp_cipher_alg, 505c0341432SJohn Baldwin csp->csp_cipher_key, csp->csp_cipher_klen); 506844d9543SConrad Meyer } 507844d9543SConrad Meyer 508844d9543SConrad Meyer s->active = true; 509844d9543SConrad Meyer mtx_unlock(&sc->lock); 510844d9543SConrad Meyer 511844d9543SConrad Meyer return (0); 512844d9543SConrad Meyer } 513844d9543SConrad Meyer 5141b0909d5SConrad Meyer static void 5151b0909d5SConrad Meyer ccp_freesession(device_t dev, crypto_session_t cses) 516844d9543SConrad Meyer { 5171b0909d5SConrad Meyer struct ccp_session *s; 518844d9543SConrad Meyer 5191b0909d5SConrad Meyer s = crypto_get_driver_session(cses); 5201b0909d5SConrad Meyer 5211b0909d5SConrad Meyer if (s->pending != 0) 522844d9543SConrad Meyer device_printf(dev, 5231b0909d5SConrad Meyer "session %p freed with %d pending requests\n", s, 5241b0909d5SConrad Meyer s->pending); 5251b0909d5SConrad Meyer s->active = false; 526844d9543SConrad Meyer } 527844d9543SConrad Meyer 528844d9543SConrad Meyer static int 529844d9543SConrad Meyer ccp_process(device_t dev, struct cryptop *crp, int hint) 530844d9543SConrad Meyer { 531c0341432SJohn Baldwin const struct crypto_session_params *csp; 532844d9543SConrad Meyer struct ccp_softc *sc; 533844d9543SConrad Meyer struct ccp_queue *qp; 534844d9543SConrad Meyer struct ccp_session *s; 535844d9543SConrad Meyer int error; 536844d9543SConrad Meyer bool qpheld; 537844d9543SConrad Meyer 538844d9543SConrad Meyer qpheld = false; 539844d9543SConrad Meyer qp = NULL; 540844d9543SConrad Meyer 541c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 5421b0909d5SConrad Meyer s = crypto_get_driver_session(crp->crp_session); 543844d9543SConrad Meyer sc = device_get_softc(dev); 544844d9543SConrad Meyer mtx_lock(&sc->lock); 545844d9543SConrad Meyer qp = &sc->queues[s->queue]; 546844d9543SConrad Meyer mtx_unlock(&sc->lock); 547844d9543SConrad Meyer error = ccp_queue_acquire_reserve(qp, 1 /* placeholder */, M_NOWAIT); 548844d9543SConrad Meyer if (error != 0) 549844d9543SConrad Meyer goto out; 550844d9543SConrad Meyer qpheld = true; 551844d9543SConrad Meyer 5529c0e3d3aSJohn Baldwin error = ccp_populate_sglist(qp->cq_sg_crp, &crp->crp_buf); 553844d9543SConrad Meyer if (error != 0) 554844d9543SConrad Meyer goto out; 555844d9543SConrad Meyer 556c0341432SJohn Baldwin if (crp->crp_auth_key != NULL) { 557c0341432SJohn Baldwin KASSERT(s->hmac.auth_hash != NULL, ("auth key without HMAC")); 558c0341432SJohn Baldwin ccp_init_hmac_digest(s, crp->crp_auth_key, csp->csp_auth_klen); 559c0341432SJohn Baldwin } 560c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) 561c0341432SJohn Baldwin ccp_aes_setkey(s, csp->csp_cipher_alg, crp->crp_cipher_key, 562c0341432SJohn Baldwin csp->csp_cipher_klen); 563c0341432SJohn Baldwin 564844d9543SConrad Meyer switch (s->mode) { 565844d9543SConrad Meyer case HMAC: 566c0341432SJohn Baldwin if (s->pending != 0) { 567c0341432SJohn Baldwin error = EAGAIN; 568c0341432SJohn Baldwin break; 569c0341432SJohn Baldwin } 570844d9543SConrad Meyer error = ccp_hmac(qp, s, crp); 571844d9543SConrad Meyer break; 572844d9543SConrad Meyer case BLKCIPHER: 573c0341432SJohn Baldwin if (s->pending != 0) { 574c0341432SJohn Baldwin error = EAGAIN; 575844d9543SConrad Meyer break; 576844d9543SConrad Meyer } 577844d9543SConrad Meyer error = ccp_blkcipher(qp, s, crp); 578844d9543SConrad Meyer break; 579844d9543SConrad Meyer case AUTHENC: 580c0341432SJohn Baldwin if (s->pending != 0) { 581c0341432SJohn Baldwin error = EAGAIN; 582844d9543SConrad Meyer break; 583844d9543SConrad Meyer } 584c0341432SJohn Baldwin error = ccp_authenc(qp, s, crp); 585844d9543SConrad Meyer break; 586844d9543SConrad Meyer case GCM: 587c0341432SJohn Baldwin if (s->pending != 0) { 588c0341432SJohn Baldwin error = EAGAIN; 589c0341432SJohn Baldwin break; 590c0341432SJohn Baldwin } 591c0341432SJohn Baldwin error = ccp_gcm(qp, s, crp); 592844d9543SConrad Meyer break; 593844d9543SConrad Meyer } 594844d9543SConrad Meyer 595844d9543SConrad Meyer if (error == 0) 596844d9543SConrad Meyer s->pending++; 597844d9543SConrad Meyer 598844d9543SConrad Meyer out: 599844d9543SConrad Meyer if (qpheld) { 600844d9543SConrad Meyer if (error != 0) { 601844d9543SConrad Meyer /* 602844d9543SConrad Meyer * Squash EAGAIN so callers don't uselessly and 603844d9543SConrad Meyer * expensively retry if the ring was full. 604844d9543SConrad Meyer */ 605844d9543SConrad Meyer if (error == EAGAIN) 606844d9543SConrad Meyer error = ENOMEM; 607844d9543SConrad Meyer ccp_queue_abort(qp); 608844d9543SConrad Meyer } else 609844d9543SConrad Meyer ccp_queue_release(qp); 610844d9543SConrad Meyer } 611844d9543SConrad Meyer 612844d9543SConrad Meyer if (error != 0) { 613844d9543SConrad Meyer DPRINTF(dev, "%s: early error:%d\n", __func__, error); 614844d9543SConrad Meyer crp->crp_etype = error; 615844d9543SConrad Meyer crypto_done(crp); 616844d9543SConrad Meyer } 617844d9543SConrad Meyer return (0); 618844d9543SConrad Meyer } 619844d9543SConrad Meyer 620844d9543SConrad Meyer static device_method_t ccp_methods[] = { 621844d9543SConrad Meyer DEVMETHOD(device_probe, ccp_probe), 622844d9543SConrad Meyer DEVMETHOD(device_attach, ccp_attach), 623844d9543SConrad Meyer DEVMETHOD(device_detach, ccp_detach), 624844d9543SConrad Meyer 625c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, ccp_probesession), 626844d9543SConrad Meyer DEVMETHOD(cryptodev_newsession, ccp_newsession), 627844d9543SConrad Meyer DEVMETHOD(cryptodev_freesession, ccp_freesession), 628844d9543SConrad Meyer DEVMETHOD(cryptodev_process, ccp_process), 629844d9543SConrad Meyer 630844d9543SConrad Meyer DEVMETHOD_END 631844d9543SConrad Meyer }; 632844d9543SConrad Meyer 633844d9543SConrad Meyer static driver_t ccp_driver = { 634844d9543SConrad Meyer "ccp", 635844d9543SConrad Meyer ccp_methods, 636844d9543SConrad Meyer sizeof(struct ccp_softc) 637844d9543SConrad Meyer }; 638844d9543SConrad Meyer 639844d9543SConrad Meyer static devclass_t ccp_devclass; 640844d9543SConrad Meyer DRIVER_MODULE(ccp, pci, ccp_driver, ccp_devclass, NULL, NULL); 641844d9543SConrad Meyer MODULE_VERSION(ccp, 1); 642844d9543SConrad Meyer MODULE_DEPEND(ccp, crypto, 1, 1, 1); 643844d9543SConrad Meyer MODULE_DEPEND(ccp, random_device, 1, 1, 1); 64491eeadc5SWarner Losh #if 0 /* There are enough known issues that we shouldn't load automatically */ 645329e817fSWarner Losh MODULE_PNP_INFO("W32:vendor/device", pci, ccp, ccp_ids, 646b7220273SWarner Losh nitems(ccp_ids)); 64791eeadc5SWarner Losh #endif 648844d9543SConrad Meyer 649844d9543SConrad Meyer static int 650844d9543SConrad Meyer ccp_queue_reserve_space(struct ccp_queue *qp, unsigned n, int mflags) 651844d9543SConrad Meyer { 652844d9543SConrad Meyer struct ccp_softc *sc; 653844d9543SConrad Meyer 654844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 655844d9543SConrad Meyer sc = qp->cq_softc; 656844d9543SConrad Meyer 657844d9543SConrad Meyer if (n < 1 || n >= (1 << sc->ring_size_order)) 658844d9543SConrad Meyer return (EINVAL); 659844d9543SConrad Meyer 660844d9543SConrad Meyer while (true) { 661844d9543SConrad Meyer if (ccp_queue_get_ring_space(qp) >= n) 662844d9543SConrad Meyer return (0); 663844d9543SConrad Meyer if ((mflags & M_WAITOK) == 0) 664844d9543SConrad Meyer return (EAGAIN); 665844d9543SConrad Meyer qp->cq_waiting = true; 666844d9543SConrad Meyer msleep(&qp->cq_tail, &qp->cq_lock, 0, "ccpqfull", 0); 667844d9543SConrad Meyer } 668844d9543SConrad Meyer } 669844d9543SConrad Meyer 670844d9543SConrad Meyer int 671844d9543SConrad Meyer ccp_queue_acquire_reserve(struct ccp_queue *qp, unsigned n, int mflags) 672844d9543SConrad Meyer { 673844d9543SConrad Meyer int error; 674844d9543SConrad Meyer 675844d9543SConrad Meyer mtx_lock(&qp->cq_lock); 676844d9543SConrad Meyer qp->cq_acq_tail = qp->cq_tail; 677844d9543SConrad Meyer error = ccp_queue_reserve_space(qp, n, mflags); 678844d9543SConrad Meyer if (error != 0) 679844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 680844d9543SConrad Meyer return (error); 681844d9543SConrad Meyer } 682844d9543SConrad Meyer 683844d9543SConrad Meyer void 684844d9543SConrad Meyer ccp_queue_release(struct ccp_queue *qp) 685844d9543SConrad Meyer { 686844d9543SConrad Meyer 687844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 688844d9543SConrad Meyer if (qp->cq_tail != qp->cq_acq_tail) { 689844d9543SConrad Meyer wmb(); 690844d9543SConrad Meyer ccp_queue_write_tail(qp); 691844d9543SConrad Meyer } 692844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 693844d9543SConrad Meyer } 694844d9543SConrad Meyer 695844d9543SConrad Meyer void 696844d9543SConrad Meyer ccp_queue_abort(struct ccp_queue *qp) 697844d9543SConrad Meyer { 698844d9543SConrad Meyer unsigned i; 699844d9543SConrad Meyer 700844d9543SConrad Meyer mtx_assert(&qp->cq_lock, MA_OWNED); 701844d9543SConrad Meyer 702844d9543SConrad Meyer /* Wipe out any descriptors associated with this aborted txn. */ 703844d9543SConrad Meyer for (i = qp->cq_acq_tail; i != qp->cq_tail; 704844d9543SConrad Meyer i = (i + 1) % (1 << qp->cq_softc->ring_size_order)) { 705844d9543SConrad Meyer memset(&qp->desc_ring[i], 0, sizeof(qp->desc_ring[i])); 706844d9543SConrad Meyer } 707844d9543SConrad Meyer qp->cq_tail = qp->cq_acq_tail; 708844d9543SConrad Meyer 709844d9543SConrad Meyer mtx_unlock(&qp->cq_lock); 710844d9543SConrad Meyer } 711844d9543SConrad Meyer 712844d9543SConrad Meyer #ifdef DDB 713844d9543SConrad Meyer #define _db_show_lock(lo) LOCK_CLASS(lo)->lc_ddb_show(lo) 714844d9543SConrad Meyer #define db_show_lock(lk) _db_show_lock(&(lk)->lock_object) 715844d9543SConrad Meyer static void 716844d9543SConrad Meyer db_show_ccp_sc(struct ccp_softc *sc) 717844d9543SConrad Meyer { 718844d9543SConrad Meyer 719844d9543SConrad Meyer db_printf("ccp softc at %p\n", sc); 720844d9543SConrad Meyer db_printf(" cid: %d\n", (int)sc->cid); 721844d9543SConrad Meyer 722844d9543SConrad Meyer db_printf(" lock: "); 723844d9543SConrad Meyer db_show_lock(&sc->lock); 724844d9543SConrad Meyer 725844d9543SConrad Meyer db_printf(" detaching: %d\n", (int)sc->detaching); 726844d9543SConrad Meyer db_printf(" ring_size_order: %u\n", sc->ring_size_order); 727844d9543SConrad Meyer 728844d9543SConrad Meyer db_printf(" hw_version: %d\n", (int)sc->hw_version); 729844d9543SConrad Meyer db_printf(" hw_features: %b\n", (int)sc->hw_features, 730844d9543SConrad Meyer "\20\24ELFC\23TRNG\22Zip_Compress\16Zip_Decompress\13ECC\12RSA" 731844d9543SConrad Meyer "\11SHA\0103DES\07AES"); 732844d9543SConrad Meyer 733844d9543SConrad Meyer db_printf(" hw status:\n"); 734844d9543SConrad Meyer db_ccp_show_hw(sc); 735844d9543SConrad Meyer } 736844d9543SConrad Meyer 737844d9543SConrad Meyer static void 738844d9543SConrad Meyer db_show_ccp_qp(struct ccp_queue *qp) 739844d9543SConrad Meyer { 740844d9543SConrad Meyer 741844d9543SConrad Meyer db_printf(" lock: "); 742844d9543SConrad Meyer db_show_lock(&qp->cq_lock); 743844d9543SConrad Meyer 744844d9543SConrad Meyer db_printf(" cq_qindex: %u\n", qp->cq_qindex); 745844d9543SConrad Meyer db_printf(" cq_softc: %p\n", qp->cq_softc); 746844d9543SConrad Meyer 747844d9543SConrad Meyer db_printf(" head: %u\n", qp->cq_head); 748844d9543SConrad Meyer db_printf(" tail: %u\n", qp->cq_tail); 749844d9543SConrad Meyer db_printf(" acq_tail: %u\n", qp->cq_acq_tail); 750844d9543SConrad Meyer db_printf(" desc_ring: %p\n", qp->desc_ring); 751844d9543SConrad Meyer db_printf(" completions_ring: %p\n", qp->completions_ring); 752844d9543SConrad Meyer db_printf(" descriptors (phys): 0x%jx\n", 753844d9543SConrad Meyer (uintmax_t)qp->desc_ring_bus_addr); 754844d9543SConrad Meyer 755844d9543SConrad Meyer db_printf(" hw status:\n"); 756844d9543SConrad Meyer db_ccp_show_queue_hw(qp); 757844d9543SConrad Meyer } 758844d9543SConrad Meyer 759844d9543SConrad Meyer DB_SHOW_COMMAND(ccp, db_show_ccp) 760844d9543SConrad Meyer { 761844d9543SConrad Meyer struct ccp_softc *sc; 762844d9543SConrad Meyer unsigned unit, qindex; 763844d9543SConrad Meyer 764844d9543SConrad Meyer if (!have_addr) 765844d9543SConrad Meyer goto usage; 766844d9543SConrad Meyer 767844d9543SConrad Meyer unit = (unsigned)addr; 768844d9543SConrad Meyer 769*907f35efSJohn Baldwin sc = devclass_get_softc(devclass_find("ccp"), unit); 770844d9543SConrad Meyer if (sc == NULL) { 771844d9543SConrad Meyer db_printf("No such device ccp%u\n", unit); 772844d9543SConrad Meyer goto usage; 773844d9543SConrad Meyer } 774844d9543SConrad Meyer 775844d9543SConrad Meyer if (count == -1) { 776844d9543SConrad Meyer db_show_ccp_sc(sc); 777844d9543SConrad Meyer return; 778844d9543SConrad Meyer } 779844d9543SConrad Meyer 780844d9543SConrad Meyer qindex = (unsigned)count; 781844d9543SConrad Meyer if (qindex >= nitems(sc->queues)) { 782844d9543SConrad Meyer db_printf("No such queue %u\n", qindex); 783844d9543SConrad Meyer goto usage; 784844d9543SConrad Meyer } 785844d9543SConrad Meyer db_show_ccp_qp(&sc->queues[qindex]); 786844d9543SConrad Meyer return; 787844d9543SConrad Meyer 788844d9543SConrad Meyer usage: 789844d9543SConrad Meyer db_printf("usage: show ccp <unit>[,<qindex>]\n"); 790844d9543SConrad Meyer return; 791844d9543SConrad Meyer } 792844d9543SConrad Meyer #endif /* DDB */ 793