1091d81d1SSam Leffler /* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */ 2091d81d1SSam Leffler 360727d8bSWarner Losh /*- 4091d81d1SSam Leffler * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) 56810ad6fSSam Leffler * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting 6091d81d1SSam Leffler * 7091d81d1SSam Leffler * This code was written by Angelos D. Keromytis in Athens, Greece, in 8091d81d1SSam Leffler * February 2000. Network Security Technologies Inc. (NSTI) kindly 9091d81d1SSam Leffler * supported the development of this code. 10091d81d1SSam Leffler * 11091d81d1SSam Leffler * Copyright (c) 2000, 2001 Angelos D. Keromytis 121833d604SJohn Baldwin * Copyright (c) 2014-2021 The FreeBSD Foundation 1308fca7a5SJohn-Mark Gurney * All rights reserved. 1408fca7a5SJohn-Mark Gurney * 1508fca7a5SJohn-Mark Gurney * Portions of this software were developed by John-Mark Gurney 1608fca7a5SJohn-Mark Gurney * under sponsorship of the FreeBSD Foundation and 1708fca7a5SJohn-Mark Gurney * Rubicon Communications, LLC (Netgate). 18091d81d1SSam Leffler * 191833d604SJohn Baldwin * Portions of this software were developed by Ararat River 201833d604SJohn Baldwin * Consulting, LLC under sponsorship of the FreeBSD Foundation. 211833d604SJohn Baldwin * 22091d81d1SSam Leffler * Permission to use, copy, and modify this software with or without fee 23091d81d1SSam Leffler * is hereby granted, provided that this entire notice is included in 24091d81d1SSam Leffler * all source code copies of any software which is or includes a copy or 25091d81d1SSam Leffler * modification of this software. 26091d81d1SSam Leffler * 27091d81d1SSam Leffler * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 28091d81d1SSam Leffler * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 29091d81d1SSam Leffler * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 30091d81d1SSam Leffler * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 31091d81d1SSam Leffler * PURPOSE. 32091d81d1SSam Leffler */ 33091d81d1SSam Leffler 342c446514SDavid E. O'Brien #include <sys/cdefs.h> 352c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 362c446514SDavid E. O'Brien 37091d81d1SSam Leffler #include <sys/param.h> 38091d81d1SSam Leffler #include <sys/systm.h> 39091d81d1SSam Leffler #include <sys/malloc.h> 40091d81d1SSam Leffler #include <sys/mbuf.h> 416810ad6fSSam Leffler #include <sys/module.h> 42091d81d1SSam Leffler #include <sys/sysctl.h> 43091d81d1SSam Leffler #include <sys/errno.h> 44091d81d1SSam Leffler #include <sys/random.h> 45091d81d1SSam Leffler #include <sys/kernel.h> 46091d81d1SSam Leffler #include <sys/uio.h> 4708fca7a5SJohn-Mark Gurney #include <sys/endian.h> 4808fca7a5SJohn-Mark Gurney #include <sys/limits.h> 49091d81d1SSam Leffler 50091d81d1SSam Leffler #include <crypto/sha1.h> 51091d81d1SSam Leffler #include <opencrypto/rmd160.h> 52091d81d1SSam Leffler 53091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 54091d81d1SSam Leffler #include <opencrypto/xform.h> 55091d81d1SSam Leffler 566810ad6fSSam Leffler #include <sys/kobj.h> 576810ad6fSSam Leffler #include <sys/bus.h> 586810ad6fSSam Leffler #include "cryptodev_if.h" 59091d81d1SSam Leffler 60c0341432SJohn Baldwin struct swcr_auth { 61c0341432SJohn Baldwin void *sw_ictx; 62c0341432SJohn Baldwin void *sw_octx; 63d8787d4fSMark Johnston const struct auth_hash *sw_axf; 64c0341432SJohn Baldwin uint16_t sw_mlen; 656113a08bSJohn Baldwin bool sw_hmac; 66c0341432SJohn Baldwin }; 67c0341432SJohn Baldwin 68c0341432SJohn Baldwin struct swcr_encdec { 69f313909aSJohn Baldwin void *sw_ctx; 70d8787d4fSMark Johnston const struct enc_xform *sw_exf; 71c0341432SJohn Baldwin }; 72c0341432SJohn Baldwin 73c0341432SJohn Baldwin struct swcr_compdec { 74d8787d4fSMark Johnston const struct comp_algo *sw_cxf; 75c0341432SJohn Baldwin }; 76c0341432SJohn Baldwin 77c0341432SJohn Baldwin struct swcr_session { 78dc475c9bSJohn Baldwin int (*swcr_process)(const struct swcr_session *, struct cryptop *); 79c0341432SJohn Baldwin 80c0341432SJohn Baldwin struct swcr_auth swcr_auth; 81c0341432SJohn Baldwin struct swcr_encdec swcr_encdec; 82c0341432SJohn Baldwin struct swcr_compdec swcr_compdec; 83c0341432SJohn Baldwin }; 84507281e5SSean Eric Fagan 856810ad6fSSam Leffler static int32_t swcr_id; 866810ad6fSSam Leffler 871b0909d5SConrad Meyer static void swcr_freesession(device_t dev, crypto_session_t cses); 88091d81d1SSam Leffler 89c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */ 90c0341432SJohn Baldwin static int 91dc475c9bSJohn Baldwin swcr_null(const struct swcr_session *ses, struct cryptop *crp) 92c0341432SJohn Baldwin { 93c0341432SJohn Baldwin 94c0341432SJohn Baldwin return (0); 95c0341432SJohn Baldwin } 96c0341432SJohn Baldwin 97091d81d1SSam Leffler /* 98091d81d1SSam Leffler * Apply a symmetric encryption/decryption algorithm. 99091d81d1SSam Leffler */ 100091d81d1SSam Leffler static int 101dc475c9bSJohn Baldwin swcr_encdec(const struct swcr_session *ses, struct cryptop *crp) 102091d81d1SSam Leffler { 1035d7ae54aSConrad Meyer unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; 10408fca7a5SJohn-Mark Gurney unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; 105c0341432SJohn Baldwin const struct crypto_session_params *csp; 106d8787d4fSMark Johnston const struct enc_xform *exf; 107b54d1284SJohn Baldwin const struct swcr_encdec *sw; 108b54d1284SJohn Baldwin void *ctx; 10986be314dSJohn Baldwin size_t inlen, outlen; 1101833d604SJohn Baldwin int i, blks, resid; 1119c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 11226d292d3SJohn Baldwin const unsigned char *inblk; 11326d292d3SJohn Baldwin unsigned char *outblk; 11408fca7a5SJohn-Mark Gurney int error; 115c0341432SJohn Baldwin bool encrypting; 11608fca7a5SJohn-Mark Gurney 11708fca7a5SJohn-Mark Gurney error = 0; 118091d81d1SSam Leffler 119c0341432SJohn Baldwin sw = &ses->swcr_encdec; 120091d81d1SSam Leffler exf = sw->sw_exf; 1211833d604SJohn Baldwin csp = crypto_get_params(crp->crp_session); 122091d81d1SSam Leffler 123723d8764SJohn Baldwin if (exf->native_blocksize == 0) { 124091d81d1SSam Leffler /* Check for non-padded data */ 125723d8764SJohn Baldwin if ((crp->crp_payload_length % exf->blocksize) != 0) 126723d8764SJohn Baldwin return (EINVAL); 127723d8764SJohn Baldwin 128723d8764SJohn Baldwin blks = exf->blocksize; 129723d8764SJohn Baldwin } else 130723d8764SJohn Baldwin blks = exf->native_blocksize; 131091d81d1SSam Leffler 132c0341432SJohn Baldwin if (exf == &enc_xform_aes_icm && 133c0341432SJohn Baldwin (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 13408fca7a5SJohn-Mark Gurney return (EINVAL); 13508fca7a5SJohn-Mark Gurney 136b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 137c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) { 138b54d1284SJohn Baldwin error = exf->setkey(ctx, crp->crp_cipher_key, 139b54d1284SJohn Baldwin csp->csp_cipher_klen); 140c740ae4bSPoul-Henning Kamp if (error) 141c740ae4bSPoul-Henning Kamp return (error); 142b54d1284SJohn Baldwin } else 143b54d1284SJohn Baldwin memcpy(ctx, sw->sw_ctx, exf->ctxsize); 144d295bdeeSPawel Jakub Dawidek 14520c128daSJohn Baldwin crypto_read_iv(crp, iv); 14620c128daSJohn Baldwin 14708fca7a5SJohn-Mark Gurney if (exf->reinit) { 148d295bdeeSPawel Jakub Dawidek /* 149d295bdeeSPawel Jakub Dawidek * xforms that provide a reinit method perform all IV 150d295bdeeSPawel Jakub Dawidek * handling themselves. 151d295bdeeSPawel Jakub Dawidek */ 152b54d1284SJohn Baldwin exf->reinit(ctx, iv, csp->csp_ivlen); 153091d81d1SSam Leffler } 154091d81d1SSam Leffler 1559c0e3d3aSJohn Baldwin ivp = iv; 156091d81d1SSam Leffler 1579c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1589c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 15986be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 1609c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 1619c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 1629c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 1639c0e3d3aSJohn Baldwin } else 1649c0e3d3aSJohn Baldwin cc_out = cc_in; 16586be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 1669c0e3d3aSJohn Baldwin 1679c0e3d3aSJohn Baldwin resid = crp->crp_payload_length; 168c0341432SJohn Baldwin encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 169091d81d1SSam Leffler 170091d81d1SSam Leffler /* 1719c0e3d3aSJohn Baldwin * Loop through encrypting blocks. 'inlen' is the remaining 1729c0e3d3aSJohn Baldwin * length of the current segment in the input buffer. 1739c0e3d3aSJohn Baldwin * 'outlen' is the remaining length of current segment in the 1749c0e3d3aSJohn Baldwin * output buffer. 175091d81d1SSam Leffler */ 1769c0e3d3aSJohn Baldwin while (resid >= blks) { 1779c0e3d3aSJohn Baldwin /* 1789c0e3d3aSJohn Baldwin * If the current block is not contained within the 1799c0e3d3aSJohn Baldwin * current input/output segment, use 'blk' as a local 1809c0e3d3aSJohn Baldwin * buffer. 1819c0e3d3aSJohn Baldwin */ 1829c0e3d3aSJohn Baldwin if (inlen < blks) { 1839c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, blks, blk); 1849c0e3d3aSJohn Baldwin inblk = blk; 185d295bdeeSPawel Jakub Dawidek } 1869c0e3d3aSJohn Baldwin if (outlen < blks) 1879c0e3d3aSJohn Baldwin outblk = blk; 1889c0e3d3aSJohn Baldwin 1899c0e3d3aSJohn Baldwin /* 1909c0e3d3aSJohn Baldwin * Ciphers without a 'reinit' hook are assumed to be 1919c0e3d3aSJohn Baldwin * used in CBC mode where the chaining is done here. 1929c0e3d3aSJohn Baldwin */ 1939c0e3d3aSJohn Baldwin if (exf->reinit != NULL) { 1949c0e3d3aSJohn Baldwin if (encrypting) 195b54d1284SJohn Baldwin exf->encrypt(ctx, inblk, outblk); 1969c0e3d3aSJohn Baldwin else 197b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, outblk); 198c0341432SJohn Baldwin } else if (encrypting) { 199091d81d1SSam Leffler /* XOR with previous block */ 2009c0e3d3aSJohn Baldwin for (i = 0; i < blks; i++) 2019c0e3d3aSJohn Baldwin outblk[i] = inblk[i] ^ ivp[i]; 202091d81d1SSam Leffler 203b54d1284SJohn Baldwin exf->encrypt(ctx, outblk, outblk); 204091d81d1SSam Leffler 205091d81d1SSam Leffler /* 206091d81d1SSam Leffler * Keep encrypted block for XOR'ing 207091d81d1SSam Leffler * with next block 208091d81d1SSam Leffler */ 2099c0e3d3aSJohn Baldwin memcpy(iv, outblk, blks); 210091d81d1SSam Leffler ivp = iv; 211091d81d1SSam Leffler } else { /* decrypt */ 212091d81d1SSam Leffler /* 213091d81d1SSam Leffler * Keep encrypted block for XOR'ing 214091d81d1SSam Leffler * with next block 215091d81d1SSam Leffler */ 21608fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 2179c0e3d3aSJohn Baldwin memcpy(nivp, inblk, blks); 218091d81d1SSam Leffler 219b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, outblk); 220091d81d1SSam Leffler 221091d81d1SSam Leffler /* XOR with previous block */ 2229c0e3d3aSJohn Baldwin for (i = 0; i < blks; i++) 2239c0e3d3aSJohn Baldwin outblk[i] ^= ivp[i]; 224091d81d1SSam Leffler 22508fca7a5SJohn-Mark Gurney ivp = nivp; 226091d81d1SSam Leffler } 227091d81d1SSam Leffler 2289c0e3d3aSJohn Baldwin if (inlen < blks) { 22986be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 2309c0e3d3aSJohn Baldwin } else { 2319c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, blks); 2329c0e3d3aSJohn Baldwin inlen -= blks; 2339c0e3d3aSJohn Baldwin inblk += blks; 23408fca7a5SJohn-Mark Gurney } 235091d81d1SSam Leffler 2369c0e3d3aSJohn Baldwin if (outlen < blks) { 2379c0e3d3aSJohn Baldwin crypto_cursor_copyback(&cc_out, blks, blk); 23886be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2399c0e3d3aSJohn Baldwin } else { 2409c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, blks); 2419c0e3d3aSJohn Baldwin outlen -= blks; 2429c0e3d3aSJohn Baldwin outblk += blks; 243091d81d1SSam Leffler } 244091d81d1SSam Leffler 2459c0e3d3aSJohn Baldwin resid -= blks; 246f34a967bSPawel Jakub Dawidek } 247f34a967bSPawel Jakub Dawidek 248723d8764SJohn Baldwin /* Handle trailing partial block for stream ciphers. */ 2499c0e3d3aSJohn Baldwin if (resid > 0) { 250723d8764SJohn Baldwin KASSERT(exf->native_blocksize != 0, 251723d8764SJohn Baldwin ("%s: partial block of %d bytes for cipher %s", 252723d8764SJohn Baldwin __func__, i, exf->name)); 253723d8764SJohn Baldwin KASSERT(exf->reinit != NULL, 254723d8764SJohn Baldwin ("%s: partial block cipher %s without reinit hook", 255723d8764SJohn Baldwin __func__, exf->name)); 2569c0e3d3aSJohn Baldwin KASSERT(resid < blks, ("%s: partial block too big", __func__)); 257723d8764SJohn Baldwin 25886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 25986be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2609c0e3d3aSJohn Baldwin if (inlen < resid) { 2619c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 2629c0e3d3aSJohn Baldwin inblk = blk; 26386be314dSJohn Baldwin } 2649c0e3d3aSJohn Baldwin if (outlen < resid) 2659c0e3d3aSJohn Baldwin outblk = blk; 2669c0e3d3aSJohn Baldwin if (encrypting) 267b54d1284SJohn Baldwin exf->encrypt_last(ctx, inblk, outblk, 2689c0e3d3aSJohn Baldwin resid); 2699c0e3d3aSJohn Baldwin else 270b54d1284SJohn Baldwin exf->decrypt_last(ctx, inblk, outblk, 2719c0e3d3aSJohn Baldwin resid); 2729c0e3d3aSJohn Baldwin if (outlen < resid) 2739c0e3d3aSJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 274723d8764SJohn Baldwin } 275723d8764SJohn Baldwin 276b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 27720c128daSJohn Baldwin explicit_bzero(blk, sizeof(blk)); 27820c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 27920c128daSJohn Baldwin explicit_bzero(iv2, sizeof(iv2)); 2809c0e3d3aSJohn Baldwin return (0); 281091d81d1SSam Leffler } 282091d81d1SSam Leffler 283091d81d1SSam Leffler /* 284c0341432SJohn Baldwin * Compute or verify hash. 285091d81d1SSam Leffler */ 286091d81d1SSam Leffler static int 287dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp) 288091d81d1SSam Leffler { 289c0341432SJohn Baldwin u_char aalg[HASH_MAX_LEN]; 290c0341432SJohn Baldwin const struct crypto_session_params *csp; 2916113a08bSJohn Baldwin const struct swcr_auth *sw; 292d8787d4fSMark Johnston const struct auth_hash *axf; 293091d81d1SSam Leffler union authctx ctx; 294091d81d1SSam Leffler int err; 295091d81d1SSam Leffler 296c0341432SJohn Baldwin sw = &ses->swcr_auth; 297091d81d1SSam Leffler 298091d81d1SSam Leffler axf = sw->sw_axf; 299091d81d1SSam Leffler 300c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 3016038018aSMarcin Wojtas if (crp->crp_auth_key != NULL) { 3026113a08bSJohn Baldwin if (sw->sw_hmac) { 3036113a08bSJohn Baldwin hmac_init_ipad(axf, crp->crp_auth_key, 3046113a08bSJohn Baldwin csp->csp_auth_klen, &ctx); 3056113a08bSJohn Baldwin } else { 3066113a08bSJohn Baldwin axf->Init(&ctx); 3076113a08bSJohn Baldwin axf->Setkey(&ctx, crp->crp_auth_key, 308c0341432SJohn Baldwin csp->csp_auth_klen); 30925b7033bSConrad Meyer } 3106113a08bSJohn Baldwin } else 3116113a08bSJohn Baldwin memcpy(&ctx, sw->sw_ictx, axf->ctxsize); 312091d81d1SSam Leffler 3139b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 3149b774dc0SJohn Baldwin err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 3159b774dc0SJohn Baldwin else 316c0341432SJohn Baldwin err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 3179b6b2f86SJohn Baldwin axf->Update, &ctx); 318091d81d1SSam Leffler if (err) 319e0b155feSJohn Baldwin goto out; 320091d81d1SSam Leffler 3219c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && 3229c0e3d3aSJohn Baldwin CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 3239c0e3d3aSJohn Baldwin err = crypto_apply_buf(&crp->crp_obuf, 3249c0e3d3aSJohn Baldwin crp->crp_payload_output_start, crp->crp_payload_length, 3259b6b2f86SJohn Baldwin axf->Update, &ctx); 3269c0e3d3aSJohn Baldwin else 3279c0e3d3aSJohn Baldwin err = crypto_apply(crp, crp->crp_payload_start, 3289b6b2f86SJohn Baldwin crp->crp_payload_length, axf->Update, &ctx); 329c0341432SJohn Baldwin if (err) 330e0b155feSJohn Baldwin goto out; 331091d81d1SSam Leffler 3326038018aSMarcin Wojtas if (csp->csp_flags & CSP_F_ESN) 3336038018aSMarcin Wojtas axf->Update(&ctx, crp->crp_esn, 4); 3346038018aSMarcin Wojtas 335091d81d1SSam Leffler axf->Final(aalg, &ctx); 3366113a08bSJohn Baldwin if (sw->sw_hmac) { 3376113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) 3386113a08bSJohn Baldwin hmac_init_opad(axf, crp->crp_auth_key, 3396113a08bSJohn Baldwin csp->csp_auth_klen, &ctx); 3406113a08bSJohn Baldwin else 3416113a08bSJohn Baldwin memcpy(&ctx, sw->sw_octx, axf->ctxsize); 342091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 343091d81d1SSam Leffler axf->Final(aalg, &ctx); 344091d81d1SSam Leffler } 345091d81d1SSam Leffler 346c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 34720c128daSJohn Baldwin u_char uaalg[HASH_MAX_LEN]; 34820c128daSJohn Baldwin 349c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg); 350c0341432SJohn Baldwin if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0) 35120c128daSJohn Baldwin err = EBADMSG; 35220c128daSJohn Baldwin explicit_bzero(uaalg, sizeof(uaalg)); 353c0341432SJohn Baldwin } else { 354091d81d1SSam Leffler /* Inject the authentication data */ 355c0341432SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg); 356c0341432SJohn Baldwin } 35720c128daSJohn Baldwin explicit_bzero(aalg, sizeof(aalg)); 358e0b155feSJohn Baldwin out: 359e0b155feSJohn Baldwin explicit_bzero(&ctx, sizeof(ctx)); 36020c128daSJohn Baldwin return (err); 361091d81d1SSam Leffler } 362091d81d1SSam Leffler 36308fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 36408fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 36508fca7a5SJohn-Mark Gurney 36608fca7a5SJohn-Mark Gurney static int 367dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp) 36808fca7a5SJohn-Mark Gurney { 36926d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 37008fca7a5SJohn-Mark Gurney u_char *blk = (u_char *)blkbuf; 37126d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 37226d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 3739c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc; 37426d292d3SJohn Baldwin const u_char *inblk; 37508fca7a5SJohn-Mark Gurney union authctx ctx; 3766113a08bSJohn Baldwin const struct swcr_auth *swa; 377d8787d4fSMark Johnston const struct auth_hash *axf; 37808fca7a5SJohn-Mark Gurney uint32_t *blkp; 37986be314dSJohn Baldwin size_t len; 38086be314dSJohn Baldwin int blksz, error, ivlen, resid; 38108fca7a5SJohn-Mark Gurney 382c0341432SJohn Baldwin swa = &ses->swcr_auth; 38308fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 38426d292d3SJohn Baldwin blksz = GMAC_BLOCK_LEN; 38526d292d3SJohn Baldwin KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", 38626d292d3SJohn Baldwin __func__)); 38708fca7a5SJohn-Mark Gurney 3886113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) { 3896113a08bSJohn Baldwin axf->Init(&ctx); 3906113a08bSJohn Baldwin axf->Setkey(&ctx, crp->crp_auth_key, 3916113a08bSJohn Baldwin crypto_get_params(crp->crp_session)->csp_auth_klen); 3926113a08bSJohn Baldwin } else 3936113a08bSJohn Baldwin memcpy(&ctx, swa->sw_ictx, axf->ctxsize); 3946113a08bSJohn Baldwin 39508fca7a5SJohn-Mark Gurney /* Initialize the IV */ 396c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 39729fe41ddSJohn Baldwin crypto_read_iv(crp, iv); 39808fca7a5SJohn-Mark Gurney 39908fca7a5SJohn-Mark Gurney axf->Reinit(&ctx, iv, ivlen); 4009c0e3d3aSJohn Baldwin crypto_cursor_init(&cc, &crp->crp_buf); 4019c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc, crp->crp_payload_start); 40226d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) { 40386be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc, &len); 40426d292d3SJohn Baldwin if (len >= blksz) { 40526d292d3SJohn Baldwin len = rounddown(MIN(len, resid), blksz); 40626d292d3SJohn Baldwin crypto_cursor_advance(&cc, len); 40726d292d3SJohn Baldwin } else { 40826d292d3SJohn Baldwin len = blksz; 4099c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc, len, blk); 41026d292d3SJohn Baldwin inblk = blk; 41126d292d3SJohn Baldwin } 41226d292d3SJohn Baldwin axf->Update(&ctx, inblk, len); 41326d292d3SJohn Baldwin } 41426d292d3SJohn Baldwin if (resid > 0) { 41526d292d3SJohn Baldwin memset(blk, 0, blksz); 41626d292d3SJohn Baldwin crypto_cursor_copydata(&cc, resid, blk); 41708fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 41808fca7a5SJohn-Mark Gurney } 41908fca7a5SJohn-Mark Gurney 42008fca7a5SJohn-Mark Gurney /* length block */ 42126d292d3SJohn Baldwin memset(blk, 0, blksz); 42208fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 423c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 42408fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 425c0341432SJohn Baldwin 426c0341432SJohn Baldwin /* Finalize MAC */ 42726d292d3SJohn Baldwin axf->Final(tag, &ctx); 428c0341432SJohn Baldwin 42920c128daSJohn Baldwin error = 0; 430c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 43126d292d3SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 43220c128daSJohn Baldwin 433c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 43426d292d3SJohn Baldwin tag2); 43526d292d3SJohn Baldwin if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) 43620c128daSJohn Baldwin error = EBADMSG; 43726d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 438c0341432SJohn Baldwin } else { 439c0341432SJohn Baldwin /* Inject the authentication data */ 44026d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 441c0341432SJohn Baldwin } 44220c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 44326d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 44420c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 44520c128daSJohn Baldwin return (error); 446c0341432SJohn Baldwin } 447c0341432SJohn Baldwin 448c0341432SJohn Baldwin static int 449dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp) 450c0341432SJohn Baldwin { 45126d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 452c0341432SJohn Baldwin u_char *blk = (u_char *)blkbuf; 45326d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 4549c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 45526d292d3SJohn Baldwin const u_char *inblk; 45626d292d3SJohn Baldwin u_char *outblk; 457b54d1284SJohn Baldwin const struct swcr_auth *swa; 458b54d1284SJohn Baldwin const struct swcr_encdec *swe; 459d8787d4fSMark Johnston const struct enc_xform *exf; 460b54d1284SJohn Baldwin void *ctx; 461c0341432SJohn Baldwin uint32_t *blkp; 46286be314dSJohn Baldwin size_t len; 46386be314dSJohn Baldwin int blksz, error, ivlen, r, resid; 464c0341432SJohn Baldwin 465c0341432SJohn Baldwin swa = &ses->swcr_auth; 466c0341432SJohn Baldwin swe = &ses->swcr_encdec; 467c0341432SJohn Baldwin exf = swe->sw_exf; 468ab91fb6cSJohn Baldwin blksz = GMAC_BLOCK_LEN; 469ab91fb6cSJohn Baldwin KASSERT(blksz == exf->native_blocksize, 470723d8764SJohn Baldwin ("%s: blocksize mismatch", __func__)); 471c0341432SJohn Baldwin 472c0341432SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 473c0341432SJohn Baldwin return (EINVAL); 474c0341432SJohn Baldwin 475c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 476c0341432SJohn Baldwin 477b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 478ab91fb6cSJohn Baldwin if (crp->crp_cipher_key != NULL) 479b54d1284SJohn Baldwin exf->setkey(ctx, crp->crp_cipher_key, 480ab91fb6cSJohn Baldwin crypto_get_params(crp->crp_session)->csp_cipher_klen); 481b54d1284SJohn Baldwin else 482b54d1284SJohn Baldwin memcpy(ctx, swe->sw_ctx, exf->ctxsize); 483b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, ivlen); 484c0341432SJohn Baldwin 485c0341432SJohn Baldwin /* Supply MAC with AAD */ 4869b774dc0SJohn Baldwin if (crp->crp_aad != NULL) { 4879b774dc0SJohn Baldwin len = rounddown(crp->crp_aad_length, blksz); 4889b774dc0SJohn Baldwin if (len != 0) 489b54d1284SJohn Baldwin exf->update(ctx, crp->crp_aad, len); 4909b774dc0SJohn Baldwin if (crp->crp_aad_length != len) { 4919b774dc0SJohn Baldwin memset(blk, 0, blksz); 4929b774dc0SJohn Baldwin memcpy(blk, (char *)crp->crp_aad + len, 4939b774dc0SJohn Baldwin crp->crp_aad_length - len); 494b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 4959b774dc0SJohn Baldwin } 4969b774dc0SJohn Baldwin } else { 4979c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 4989c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_aad_start); 4999b774dc0SJohn Baldwin for (resid = crp->crp_aad_length; resid >= blksz; 5009b774dc0SJohn Baldwin resid -= len) { 50186be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 50226d292d3SJohn Baldwin if (len >= blksz) { 50326d292d3SJohn Baldwin len = rounddown(MIN(len, resid), blksz); 50426d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, len); 50526d292d3SJohn Baldwin } else { 50626d292d3SJohn Baldwin len = blksz; 5079c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, len, blk); 50826d292d3SJohn Baldwin inblk = blk; 50926d292d3SJohn Baldwin } 510b54d1284SJohn Baldwin exf->update(ctx, inblk, len); 51126d292d3SJohn Baldwin } 51226d292d3SJohn Baldwin if (resid > 0) { 51326d292d3SJohn Baldwin memset(blk, 0, blksz); 51426d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 515b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 516c0341432SJohn Baldwin } 5179b774dc0SJohn Baldwin } 518c0341432SJohn Baldwin 519c0341432SJohn Baldwin /* Do encryption with MAC */ 5209c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 5219c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 5229c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 5239c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 5249c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 5259c0e3d3aSJohn Baldwin } else 5269c0e3d3aSJohn Baldwin cc_out = cc_in; 52726d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 52886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 52986be314dSJohn Baldwin if (len < blksz) { 53026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 53126d292d3SJohn Baldwin inblk = blk; 532c0341432SJohn Baldwin } else { 53326d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 534c0341432SJohn Baldwin } 53526d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 53686be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 53786be314dSJohn Baldwin if (len < blksz) 53826d292d3SJohn Baldwin outblk = blk; 539b54d1284SJohn Baldwin exf->encrypt(ctx, inblk, outblk); 540b54d1284SJohn Baldwin exf->update(ctx, outblk, blksz); 54126d292d3SJohn Baldwin if (outblk == blk) 54226d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 54326d292d3SJohn Baldwin else 54426d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 54526d292d3SJohn Baldwin } else { 546b54d1284SJohn Baldwin exf->update(ctx, inblk, blksz); 54726d292d3SJohn Baldwin } 54826d292d3SJohn Baldwin } 54926d292d3SJohn Baldwin if (resid > 0) { 55026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 55126d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 552b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 55326d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 55426d292d3SJohn Baldwin } 555b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 556c0341432SJohn Baldwin } 557c0341432SJohn Baldwin 558c0341432SJohn Baldwin /* length block */ 55926d292d3SJohn Baldwin memset(blk, 0, blksz); 560c0341432SJohn Baldwin blkp = (uint32_t *)blk + 1; 561c0341432SJohn Baldwin *blkp = htobe32(crp->crp_aad_length * 8); 562c0341432SJohn Baldwin blkp = (uint32_t *)blk + 3; 563c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 564b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 565c0341432SJohn Baldwin 566c0341432SJohn Baldwin /* Finalize MAC */ 567b54d1284SJohn Baldwin exf->final(tag, ctx); 568c0341432SJohn Baldwin 569c0341432SJohn Baldwin /* Validate tag */ 57020c128daSJohn Baldwin error = 0; 571c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 57226d292d3SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 57320c128daSJohn Baldwin 57426d292d3SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); 575c0341432SJohn Baldwin 57626d292d3SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 57726d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 57820c128daSJohn Baldwin if (r != 0) { 57920c128daSJohn Baldwin error = EBADMSG; 58020c128daSJohn Baldwin goto out; 58120c128daSJohn Baldwin } 582c0341432SJohn Baldwin 583c0341432SJohn Baldwin /* tag matches, decrypt data */ 5849c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 5859c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 58626d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 58726d292d3SJohn Baldwin resid -= blksz) { 58886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 58986be314dSJohn Baldwin if (len < blksz) { 59026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 59126d292d3SJohn Baldwin inblk = blk; 59286be314dSJohn Baldwin } else 59326d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 59486be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 59586be314dSJohn Baldwin if (len < blksz) 59626d292d3SJohn Baldwin outblk = blk; 597b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, outblk); 59826d292d3SJohn Baldwin if (outblk == blk) 59926d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 60026d292d3SJohn Baldwin else 60126d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 60226d292d3SJohn Baldwin } 60326d292d3SJohn Baldwin if (resid > 0) { 60426d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 605b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 60626d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 607c0341432SJohn Baldwin } 608c0341432SJohn Baldwin } else { 609c0341432SJohn Baldwin /* Inject the authentication data */ 61026d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 611c0341432SJohn Baldwin } 612c0341432SJohn Baldwin 61320c128daSJohn Baldwin out: 614b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 61520c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 61626d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 61720c128daSJohn Baldwin 61820c128daSJohn Baldwin return (error); 619c0341432SJohn Baldwin } 620c0341432SJohn Baldwin 6214361c4ebSJohn Baldwin static void 6224361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length, 6234361c4ebSJohn Baldwin u_int data_length, u_int tag_length, uint8_t *b0) 6244361c4ebSJohn Baldwin { 6254361c4ebSJohn Baldwin uint8_t *bp; 6264361c4ebSJohn Baldwin uint8_t flags, L; 6274361c4ebSJohn Baldwin 6284361c4ebSJohn Baldwin KASSERT(nonce_length >= 7 && nonce_length <= 13, 6294361c4ebSJohn Baldwin ("nonce_length must be between 7 and 13 bytes")); 6304361c4ebSJohn Baldwin 6314361c4ebSJohn Baldwin /* 6324361c4ebSJohn Baldwin * Need to determine the L field value. This is the number of 6334361c4ebSJohn Baldwin * bytes needed to specify the length of the message; the length 6344361c4ebSJohn Baldwin * is whatever is left in the 16 bytes after specifying flags and 6354361c4ebSJohn Baldwin * the nonce. 6364361c4ebSJohn Baldwin */ 6374361c4ebSJohn Baldwin L = 15 - nonce_length; 6384361c4ebSJohn Baldwin 6394361c4ebSJohn Baldwin flags = ((aad_length > 0) << 6) + 6404361c4ebSJohn Baldwin (((tag_length - 2) / 2) << 3) + 6414361c4ebSJohn Baldwin L - 1; 6424361c4ebSJohn Baldwin 6434361c4ebSJohn Baldwin /* 6444361c4ebSJohn Baldwin * Now we need to set up the first block, which has flags, nonce, 6454361c4ebSJohn Baldwin * and the message length. 6464361c4ebSJohn Baldwin */ 6474361c4ebSJohn Baldwin b0[0] = flags; 6484361c4ebSJohn Baldwin memcpy(b0 + 1, nonce, nonce_length); 6494361c4ebSJohn Baldwin bp = b0 + 1 + nonce_length; 6504361c4ebSJohn Baldwin 6514361c4ebSJohn Baldwin /* Need to copy L' [aka L-1] bytes of data_length */ 6524361c4ebSJohn Baldwin for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) { 6534361c4ebSJohn Baldwin *dst = data_length; 6544361c4ebSJohn Baldwin data_length >>= 8; 6554361c4ebSJohn Baldwin } 6564361c4ebSJohn Baldwin } 6574361c4ebSJohn Baldwin 6584361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */ 6594361c4ebSJohn Baldwin static int 6604361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk) 6614361c4ebSJohn Baldwin { 6624361c4ebSJohn Baldwin if (aad_length < ((1 << 16) - (1 << 8))) { 6634361c4ebSJohn Baldwin be16enc(blk, aad_length); 6644361c4ebSJohn Baldwin return (sizeof(uint16_t)); 6654361c4ebSJohn Baldwin } else { 6664361c4ebSJohn Baldwin blk[0] = 0xff; 6674361c4ebSJohn Baldwin blk[1] = 0xfe; 6684361c4ebSJohn Baldwin be32enc(blk + 2, aad_length); 6694361c4ebSJohn Baldwin return (2 + sizeof(uint32_t)); 6704361c4ebSJohn Baldwin } 6714361c4ebSJohn Baldwin } 6724361c4ebSJohn Baldwin 673c0341432SJohn Baldwin static int 674dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp) 675c0341432SJohn Baldwin { 67626d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 6774361c4ebSJohn Baldwin u_char blk[CCM_CBC_BLOCK_LEN]; 6784361c4ebSJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 679c0341432SJohn Baldwin union authctx ctx; 680ae18720dSJohn Baldwin const struct crypto_session_params *csp; 6816113a08bSJohn Baldwin const struct swcr_auth *swa; 682d8787d4fSMark Johnston const struct auth_hash *axf; 6834361c4ebSJohn Baldwin int error, ivlen, len; 684c0341432SJohn Baldwin 685ae18720dSJohn Baldwin csp = crypto_get_params(crp->crp_session); 686c0341432SJohn Baldwin swa = &ses->swcr_auth; 687c0341432SJohn Baldwin axf = swa->sw_axf; 688c0341432SJohn Baldwin 6896113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) { 6906113a08bSJohn Baldwin axf->Init(&ctx); 6916113a08bSJohn Baldwin axf->Setkey(&ctx, crp->crp_auth_key, csp->csp_auth_klen); 6926113a08bSJohn Baldwin } else 6936113a08bSJohn Baldwin memcpy(&ctx, swa->sw_ictx, axf->ctxsize); 694c0341432SJohn Baldwin 695c0341432SJohn Baldwin /* Initialize the IV */ 696ae18720dSJohn Baldwin ivlen = csp->csp_ivlen; 69729fe41ddSJohn Baldwin crypto_read_iv(crp, iv); 698c0341432SJohn Baldwin 6994361c4ebSJohn Baldwin /* Supply MAC with IV */ 7004361c4ebSJohn Baldwin axf->Reinit(&ctx, crp->crp_iv, ivlen); 701c0341432SJohn Baldwin 7024361c4ebSJohn Baldwin /* Supply MAC with b0. */ 7034361c4ebSJohn Baldwin build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0, 7044361c4ebSJohn Baldwin swa->sw_mlen, blk); 7054361c4ebSJohn Baldwin axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN); 7064361c4ebSJohn Baldwin 7074361c4ebSJohn Baldwin len = build_ccm_aad_length(crp->crp_payload_length, blk); 7084361c4ebSJohn Baldwin axf->Update(&ctx, blk, len); 7094361c4ebSJohn Baldwin 7104361c4ebSJohn Baldwin crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, 7114361c4ebSJohn Baldwin axf->Update, &ctx); 712c0341432SJohn Baldwin 713c0341432SJohn Baldwin /* Finalize MAC */ 71426d292d3SJohn Baldwin axf->Final(tag, &ctx); 715c0341432SJohn Baldwin 7164361c4ebSJohn Baldwin error = 0; 717c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 71826d292d3SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 71920c128daSJohn Baldwin 720c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 72126d292d3SJohn Baldwin tag2); 72226d292d3SJohn Baldwin if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) 72320c128daSJohn Baldwin error = EBADMSG; 72426d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag)); 725c0341432SJohn Baldwin } else { 726c0341432SJohn Baldwin /* Inject the authentication data */ 72726d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 728c0341432SJohn Baldwin } 72926d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 7304361c4ebSJohn Baldwin explicit_bzero(blk, sizeof(blk)); 73120c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 73220c128daSJohn Baldwin return (error); 733c0341432SJohn Baldwin } 734c0341432SJohn Baldwin 735c0341432SJohn Baldwin static int 736dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp) 737c0341432SJohn Baldwin { 738ae18720dSJohn Baldwin const struct crypto_session_params *csp; 73926d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 740c0341432SJohn Baldwin u_char *blk = (u_char *)blkbuf; 74126d292d3SJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 7429c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 74326d292d3SJohn Baldwin const u_char *inblk; 74426d292d3SJohn Baldwin u_char *outblk; 745b54d1284SJohn Baldwin const struct swcr_auth *swa; 746b54d1284SJohn Baldwin const struct swcr_encdec *swe; 747d8787d4fSMark Johnston const struct enc_xform *exf; 748b54d1284SJohn Baldwin void *ctx; 74986be314dSJohn Baldwin size_t len; 75026d292d3SJohn Baldwin int blksz, error, ivlen, r, resid; 751c0341432SJohn Baldwin 752ae18720dSJohn Baldwin csp = crypto_get_params(crp->crp_session); 753c0341432SJohn Baldwin swa = &ses->swcr_auth; 754c0341432SJohn Baldwin swe = &ses->swcr_encdec; 755c0341432SJohn Baldwin exf = swe->sw_exf; 756ab91fb6cSJohn Baldwin blksz = AES_BLOCK_LEN; 757ab91fb6cSJohn Baldwin KASSERT(blksz == exf->native_blocksize, 758723d8764SJohn Baldwin ("%s: blocksize mismatch", __func__)); 759c0341432SJohn Baldwin 760ae18720dSJohn Baldwin if (crp->crp_payload_length > ccm_max_payload_length(csp)) 761ae18720dSJohn Baldwin return (EMSGSIZE); 762ae18720dSJohn Baldwin 763c0341432SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 764c0341432SJohn Baldwin return (EINVAL); 765c0341432SJohn Baldwin 766ae18720dSJohn Baldwin ivlen = csp->csp_ivlen; 767c0341432SJohn Baldwin 768b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 769ab91fb6cSJohn Baldwin if (crp->crp_cipher_key != NULL) 770b54d1284SJohn Baldwin exf->setkey(ctx, crp->crp_cipher_key, 771ab91fb6cSJohn Baldwin crypto_get_params(crp->crp_session)->csp_cipher_klen); 772b54d1284SJohn Baldwin else 773b54d1284SJohn Baldwin memcpy(ctx, swe->sw_ctx, exf->ctxsize); 774b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, ivlen); 775c0341432SJohn Baldwin 7764361c4ebSJohn Baldwin /* Supply MAC with b0. */ 7774361c4ebSJohn Baldwin _Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN, 7784361c4ebSJohn Baldwin "blkbuf too small for b0"); 7794361c4ebSJohn Baldwin build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length, 7804361c4ebSJohn Baldwin crp->crp_payload_length, swa->sw_mlen, blk); 781b54d1284SJohn Baldwin exf->update(ctx, blk, CCM_CBC_BLOCK_LEN); 7824361c4ebSJohn Baldwin 783c0341432SJohn Baldwin /* Supply MAC with AAD */ 7844361c4ebSJohn Baldwin if (crp->crp_aad_length != 0) { 7854361c4ebSJohn Baldwin len = build_ccm_aad_length(crp->crp_aad_length, blk); 786b54d1284SJohn Baldwin exf->update(ctx, blk, len); 7879b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 788b54d1284SJohn Baldwin exf->update(ctx, crp->crp_aad, crp->crp_aad_length); 7899b774dc0SJohn Baldwin else 7904361c4ebSJohn Baldwin crypto_apply(crp, crp->crp_aad_start, 791b54d1284SJohn Baldwin crp->crp_aad_length, exf->update, ctx); 7924361c4ebSJohn Baldwin 7934361c4ebSJohn Baldwin /* Pad the AAD (including length field) to a full block. */ 7944361c4ebSJohn Baldwin len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN; 7954361c4ebSJohn Baldwin if (len != 0) { 7964361c4ebSJohn Baldwin len = CCM_CBC_BLOCK_LEN - len; 7974361c4ebSJohn Baldwin memset(blk, 0, CCM_CBC_BLOCK_LEN); 798b54d1284SJohn Baldwin exf->update(ctx, blk, len); 7994361c4ebSJohn Baldwin } 8004361c4ebSJohn Baldwin } 801c0341432SJohn Baldwin 802c0341432SJohn Baldwin /* Do encryption/decryption with MAC */ 8039c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 8049c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 8059c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 8069c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 8079c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 8089c0e3d3aSJohn Baldwin } else 8099c0e3d3aSJohn Baldwin cc_out = cc_in; 81026d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 81186be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 81286be314dSJohn Baldwin if (len < blksz) { 81326d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 81426d292d3SJohn Baldwin inblk = blk; 81586be314dSJohn Baldwin } else 81626d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 817c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 81886be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 81986be314dSJohn Baldwin if (len < blksz) 82026d292d3SJohn Baldwin outblk = blk; 821b54d1284SJohn Baldwin exf->update(ctx, inblk, blksz); 822b54d1284SJohn Baldwin exf->encrypt(ctx, inblk, outblk); 82326d292d3SJohn Baldwin if (outblk == blk) 82426d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 82526d292d3SJohn Baldwin else 82626d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 827c0341432SJohn Baldwin } else { 828c0341432SJohn Baldwin /* 829c0341432SJohn Baldwin * One of the problems with CCM+CBC is that 830c0341432SJohn Baldwin * the authentication is done on the 83126d292d3SJohn Baldwin * unencrypted data. As a result, we have to 832c0341432SJohn Baldwin * decrypt the data twice: once to generate 833c0341432SJohn Baldwin * the tag and a second time after the tag is 834c0341432SJohn Baldwin * verified. 835c0341432SJohn Baldwin */ 836b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, blk); 837b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 83826d292d3SJohn Baldwin } 83926d292d3SJohn Baldwin } 84026d292d3SJohn Baldwin if (resid > 0) { 84126d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 84226d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 843b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 844b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 84526d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 84626d292d3SJohn Baldwin } else { 847b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 848b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 849c0341432SJohn Baldwin } 85008fca7a5SJohn-Mark Gurney } 85108fca7a5SJohn-Mark Gurney 85208fca7a5SJohn-Mark Gurney /* Finalize MAC */ 853b54d1284SJohn Baldwin exf->final(tag, ctx); 85408fca7a5SJohn-Mark Gurney 85508fca7a5SJohn-Mark Gurney /* Validate tag */ 85620c128daSJohn Baldwin error = 0; 857c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 85826d292d3SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 85920c128daSJohn Baldwin 860c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 86126d292d3SJohn Baldwin tag2); 86208fca7a5SJohn-Mark Gurney 86326d292d3SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 86426d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 86520c128daSJohn Baldwin if (r != 0) { 86620c128daSJohn Baldwin error = EBADMSG; 86720c128daSJohn Baldwin goto out; 86820c128daSJohn Baldwin } 869c0341432SJohn Baldwin 87008fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 871b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, ivlen); 8729c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 8739c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 87426d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 87526d292d3SJohn Baldwin resid -= blksz) { 87686be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 87786be314dSJohn Baldwin if (len < blksz) { 87826d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 87926d292d3SJohn Baldwin inblk = blk; 88086be314dSJohn Baldwin } else 88126d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 88286be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 88386be314dSJohn Baldwin if (len < blksz) 88426d292d3SJohn Baldwin outblk = blk; 885b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, outblk); 88626d292d3SJohn Baldwin if (outblk == blk) 88726d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 88826d292d3SJohn Baldwin else 88926d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 89026d292d3SJohn Baldwin } 89126d292d3SJohn Baldwin if (resid > 0) { 89226d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 893b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 89426d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 89508fca7a5SJohn-Mark Gurney } 89608fca7a5SJohn-Mark Gurney } else { 89708fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 89826d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 89908fca7a5SJohn-Mark Gurney } 90008fca7a5SJohn-Mark Gurney 90120c128daSJohn Baldwin out: 902b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 90320c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 90426d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 90520c128daSJohn Baldwin return (error); 90608fca7a5SJohn-Mark Gurney } 90708fca7a5SJohn-Mark Gurney 908dd2e1352SJohn Baldwin static int 909dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp) 910dd2e1352SJohn Baldwin { 911dd2e1352SJohn Baldwin const struct crypto_session_params *csp; 912dd2e1352SJohn Baldwin uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; 913dd2e1352SJohn Baldwin u_char *blk = (u_char *)blkbuf; 914dd2e1352SJohn Baldwin u_char tag[POLY1305_HASH_LEN]; 915dd2e1352SJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 916dd2e1352SJohn Baldwin const u_char *inblk; 917dd2e1352SJohn Baldwin u_char *outblk; 918dd2e1352SJohn Baldwin uint64_t *blkp; 919b54d1284SJohn Baldwin const struct swcr_auth *swa; 920b54d1284SJohn Baldwin const struct swcr_encdec *swe; 921d8787d4fSMark Johnston const struct enc_xform *exf; 922b54d1284SJohn Baldwin void *ctx; 92386be314dSJohn Baldwin size_t len; 924dd2e1352SJohn Baldwin int blksz, error, r, resid; 925dd2e1352SJohn Baldwin 926dd2e1352SJohn Baldwin swa = &ses->swcr_auth; 927dd2e1352SJohn Baldwin swe = &ses->swcr_encdec; 928dd2e1352SJohn Baldwin exf = swe->sw_exf; 929dd2e1352SJohn Baldwin blksz = exf->native_blocksize; 930dd2e1352SJohn Baldwin KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__)); 931dd2e1352SJohn Baldwin 932dd2e1352SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 933dd2e1352SJohn Baldwin return (EINVAL); 934dd2e1352SJohn Baldwin 935dd2e1352SJohn Baldwin csp = crypto_get_params(crp->crp_session); 936dd2e1352SJohn Baldwin 937b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 938dd2e1352SJohn Baldwin if (crp->crp_cipher_key != NULL) 939b54d1284SJohn Baldwin exf->setkey(ctx, crp->crp_cipher_key, 940dd2e1352SJohn Baldwin csp->csp_cipher_klen); 941b54d1284SJohn Baldwin else 942b54d1284SJohn Baldwin memcpy(ctx, swe->sw_ctx, exf->ctxsize); 943b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen); 944dd2e1352SJohn Baldwin 945ab91fb6cSJohn Baldwin /* Supply MAC with AAD */ 946ab91fb6cSJohn Baldwin if (crp->crp_aad != NULL) 947b54d1284SJohn Baldwin exf->update(ctx, crp->crp_aad, crp->crp_aad_length); 948ab91fb6cSJohn Baldwin else 949b54d1284SJohn Baldwin crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 950b54d1284SJohn Baldwin exf->update, ctx); 951ab91fb6cSJohn Baldwin if (crp->crp_aad_length % 16 != 0) { 952ab91fb6cSJohn Baldwin /* padding1 */ 953ab91fb6cSJohn Baldwin memset(blk, 0, 16); 954b54d1284SJohn Baldwin exf->update(ctx, blk, 16 - crp->crp_aad_length % 16); 955ab91fb6cSJohn Baldwin } 956ab91fb6cSJohn Baldwin 957dd2e1352SJohn Baldwin /* Do encryption with MAC */ 958dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 959dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 960dd2e1352SJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 961dd2e1352SJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 962dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 963dd2e1352SJohn Baldwin } else 964dd2e1352SJohn Baldwin cc_out = cc_in; 965dd2e1352SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 96686be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 96786be314dSJohn Baldwin if (len < blksz) { 968dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 969dd2e1352SJohn Baldwin inblk = blk; 97086be314dSJohn Baldwin } else 971dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 972dd2e1352SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 97386be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 97486be314dSJohn Baldwin if (len < blksz) 975dd2e1352SJohn Baldwin outblk = blk; 976b54d1284SJohn Baldwin exf->encrypt(ctx, inblk, outblk); 977b54d1284SJohn Baldwin exf->update(ctx, outblk, blksz); 978dd2e1352SJohn Baldwin if (outblk == blk) 979dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 980dd2e1352SJohn Baldwin else 981dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 982dd2e1352SJohn Baldwin } else { 983b54d1284SJohn Baldwin exf->update(ctx, inblk, blksz); 984dd2e1352SJohn Baldwin } 985dd2e1352SJohn Baldwin } 986dd2e1352SJohn Baldwin if (resid > 0) { 987dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 988dd2e1352SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 989b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 990dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 991dd2e1352SJohn Baldwin } 992b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 993dd2e1352SJohn Baldwin if (resid % 16 != 0) { 994dd2e1352SJohn Baldwin /* padding2 */ 995dd2e1352SJohn Baldwin memset(blk, 0, 16); 996b54d1284SJohn Baldwin exf->update(ctx, blk, 16 - resid % 16); 997dd2e1352SJohn Baldwin } 998dd2e1352SJohn Baldwin } 999dd2e1352SJohn Baldwin 1000dd2e1352SJohn Baldwin /* lengths */ 1001dd2e1352SJohn Baldwin blkp = (uint64_t *)blk; 1002dd2e1352SJohn Baldwin blkp[0] = htole64(crp->crp_aad_length); 1003dd2e1352SJohn Baldwin blkp[1] = htole64(crp->crp_payload_length); 1004b54d1284SJohn Baldwin exf->update(ctx, blk, sizeof(uint64_t) * 2); 1005dd2e1352SJohn Baldwin 1006dd2e1352SJohn Baldwin /* Finalize MAC */ 1007b54d1284SJohn Baldwin exf->final(tag, ctx); 1008dd2e1352SJohn Baldwin 1009dd2e1352SJohn Baldwin /* Validate tag */ 1010dd2e1352SJohn Baldwin error = 0; 1011dd2e1352SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1012dd2e1352SJohn Baldwin u_char tag2[POLY1305_HASH_LEN]; 1013dd2e1352SJohn Baldwin 1014dd2e1352SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); 1015dd2e1352SJohn Baldwin 1016dd2e1352SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 1017dd2e1352SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 1018dd2e1352SJohn Baldwin if (r != 0) { 1019dd2e1352SJohn Baldwin error = EBADMSG; 1020dd2e1352SJohn Baldwin goto out; 1021dd2e1352SJohn Baldwin } 1022dd2e1352SJohn Baldwin 1023dd2e1352SJohn Baldwin /* tag matches, decrypt data */ 1024dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1025dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 1026dd2e1352SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 1027dd2e1352SJohn Baldwin resid -= blksz) { 102886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 102986be314dSJohn Baldwin if (len < blksz) { 1030dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 1031dd2e1352SJohn Baldwin inblk = blk; 103286be314dSJohn Baldwin } else 1033dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 103486be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 103586be314dSJohn Baldwin if (len < blksz) 1036dd2e1352SJohn Baldwin outblk = blk; 1037b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, outblk); 1038dd2e1352SJohn Baldwin if (outblk == blk) 1039dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 1040dd2e1352SJohn Baldwin else 1041dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 1042dd2e1352SJohn Baldwin } 1043dd2e1352SJohn Baldwin if (resid > 0) { 1044dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 1045b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 1046dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 1047dd2e1352SJohn Baldwin } 1048dd2e1352SJohn Baldwin } else { 1049dd2e1352SJohn Baldwin /* Inject the authentication data */ 1050dd2e1352SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 1051dd2e1352SJohn Baldwin } 1052dd2e1352SJohn Baldwin 1053dd2e1352SJohn Baldwin out: 1054b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 1055dd2e1352SJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 1056dd2e1352SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 1057dd2e1352SJohn Baldwin return (error); 1058dd2e1352SJohn Baldwin } 1059dd2e1352SJohn Baldwin 1060091d81d1SSam Leffler /* 1061c0341432SJohn Baldwin * Apply a cipher and a digest to perform EtA. 1062c0341432SJohn Baldwin */ 1063c0341432SJohn Baldwin static int 1064dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp) 1065c0341432SJohn Baldwin { 1066c0341432SJohn Baldwin int error; 1067c0341432SJohn Baldwin 1068c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1069c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1070c0341432SJohn Baldwin if (error == 0) 1071c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1072c0341432SJohn Baldwin } else { 1073c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1074c0341432SJohn Baldwin if (error == 0) 1075c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1076c0341432SJohn Baldwin } 1077c0341432SJohn Baldwin return (error); 1078c0341432SJohn Baldwin } 1079c0341432SJohn Baldwin 1080c0341432SJohn Baldwin /* 1081091d81d1SSam Leffler * Apply a compression/decompression algorithm 1082091d81d1SSam Leffler */ 1083091d81d1SSam Leffler static int 1084dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp) 1085091d81d1SSam Leffler { 1086d8787d4fSMark Johnston const struct comp_algo *cxf; 1087d3d79e96SJohn Baldwin uint8_t *data, *out; 1088091d81d1SSam Leffler int adj; 1089d3d79e96SJohn Baldwin uint32_t result; 1090091d81d1SSam Leffler 1091c0341432SJohn Baldwin cxf = ses->swcr_compdec.sw_cxf; 1092091d81d1SSam Leffler 1093091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 1094091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 1095091d81d1SSam Leffler * copy in a buffer. 1096091d81d1SSam Leffler */ 1097091d81d1SSam Leffler 1098c0341432SJohn Baldwin data = malloc(crp->crp_payload_length, M_CRYPTO_DATA, M_NOWAIT); 1099091d81d1SSam Leffler if (data == NULL) 1100091d81d1SSam Leffler return (EINVAL); 1101c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length, 1102c0341432SJohn Baldwin data); 1103091d81d1SSam Leffler 1104c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) 1105c0341432SJohn Baldwin result = cxf->compress(data, crp->crp_payload_length, &out); 1106091d81d1SSam Leffler else 1107c0341432SJohn Baldwin result = cxf->decompress(data, crp->crp_payload_length, &out); 1108091d81d1SSam Leffler 11091ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 1110091d81d1SSam Leffler if (result == 0) 1111c0341432SJohn Baldwin return (EINVAL); 1112c0341432SJohn Baldwin crp->crp_olen = result; 1113c0341432SJohn Baldwin 1114c0341432SJohn Baldwin /* Check the compressed size when doing compression */ 1115c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) { 1116c0341432SJohn Baldwin if (result >= crp->crp_payload_length) { 1117c0341432SJohn Baldwin /* Compression was useless, we lost time */ 1118c0341432SJohn Baldwin free(out, M_CRYPTO_DATA); 1119c0341432SJohn Baldwin return (0); 1120c0341432SJohn Baldwin } 1121c0341432SJohn Baldwin } 1122091d81d1SSam Leffler 1123091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 1124091d81d1SSam Leffler * extending the mbuf as necessary. 1125091d81d1SSam Leffler */ 1126c0341432SJohn Baldwin crypto_copyback(crp, crp->crp_payload_start, result, out); 1127c0341432SJohn Baldwin if (result < crp->crp_payload_length) { 11289c0e3d3aSJohn Baldwin switch (crp->crp_buf.cb_type) { 1129c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 1130883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 1131c0341432SJohn Baldwin adj = result - crp->crp_payload_length; 11329c0e3d3aSJohn Baldwin m_adj(crp->crp_buf.cb_mbuf, adj); 1133c0341432SJohn Baldwin break; 1134c0341432SJohn Baldwin case CRYPTO_BUF_UIO: { 11359c0e3d3aSJohn Baldwin struct uio *uio = crp->crp_buf.cb_uio; 1136091d81d1SSam Leffler int ind; 1137091d81d1SSam Leffler 1138c0341432SJohn Baldwin adj = crp->crp_payload_length - result; 1139091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 1140091d81d1SSam Leffler 1141091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 1142091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 1143091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 1144091d81d1SSam Leffler break; 1145091d81d1SSam Leffler } 1146091d81d1SSam Leffler 1147091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 1148091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 1149091d81d1SSam Leffler ind--; 1150091d81d1SSam Leffler uio->uio_iovcnt--; 1151091d81d1SSam Leffler } 1152091d81d1SSam Leffler } 1153c0341432SJohn Baldwin break; 1154e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 1155e6f6d0c9SAlan Somers adj = crp->crp_payload_length - result; 1156e6f6d0c9SAlan Somers crp->crp_buf.cb_vm_page_len -= adj; 1157e6f6d0c9SAlan Somers break; 11589c0e3d3aSJohn Baldwin default: 11599c0e3d3aSJohn Baldwin break; 1160c0341432SJohn Baldwin } 1161091d81d1SSam Leffler } 11621ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 1163091d81d1SSam Leffler return 0; 1164091d81d1SSam Leffler } 1165091d81d1SSam Leffler 1166091d81d1SSam Leffler static int 11673e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses, 1168c0341432SJohn Baldwin const struct crypto_session_params *csp) 1169091d81d1SSam Leffler { 1170c0341432SJohn Baldwin struct swcr_encdec *swe; 1171d8787d4fSMark Johnston const struct enc_xform *txf; 1172f6c4bc3bSPawel Jakub Dawidek int error; 1173091d81d1SSam Leffler 1174c0341432SJohn Baldwin swe = &ses->swcr_encdec; 1175c0341432SJohn Baldwin txf = crypto_cipher(csp); 1176b54d1284SJohn Baldwin if (csp->csp_cipher_key != NULL) { 11773e947048SJohn Baldwin if (txf->ctxsize != 0) { 1178f313909aSJohn Baldwin swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA, 11793e947048SJohn Baldwin M_NOWAIT); 1180f313909aSJohn Baldwin if (swe->sw_ctx == NULL) 11813e947048SJohn Baldwin return (ENOMEM); 11823e947048SJohn Baldwin } 1183f313909aSJohn Baldwin error = txf->setkey(swe->sw_ctx, 1184c0341432SJohn Baldwin csp->csp_cipher_key, csp->csp_cipher_klen); 1185c0341432SJohn Baldwin if (error) 1186c0341432SJohn Baldwin return (error); 1187091d81d1SSam Leffler } 1188c0341432SJohn Baldwin swe->sw_exf = txf; 1189c0341432SJohn Baldwin return (0); 1190f6c4bc3bSPawel Jakub Dawidek } 1191091d81d1SSam Leffler 1192c0341432SJohn Baldwin static int 1193c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses, 1194c0341432SJohn Baldwin const struct crypto_session_params *csp) 1195c0341432SJohn Baldwin { 1196c0341432SJohn Baldwin struct swcr_auth *swa; 1197d8787d4fSMark Johnston const struct auth_hash *axf; 1198c0341432SJohn Baldwin 1199c0341432SJohn Baldwin swa = &ses->swcr_auth; 1200c0341432SJohn Baldwin 1201c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1202c0341432SJohn Baldwin swa->sw_axf = axf; 1203c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1204c0341432SJohn Baldwin return (EINVAL); 1205c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1206c0341432SJohn Baldwin swa->sw_mlen = axf->hashsize; 1207c0341432SJohn Baldwin else 1208c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 12096113a08bSJohn Baldwin if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) { 12106113a08bSJohn Baldwin swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 12116113a08bSJohn Baldwin M_NOWAIT); 1212c0341432SJohn Baldwin if (swa->sw_ictx == NULL) 1213c0341432SJohn Baldwin return (ENOBUFS); 12146113a08bSJohn Baldwin } 1215c0341432SJohn Baldwin 1216c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1217091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1218c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1219f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1220f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1221f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1222091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 12236113a08bSJohn Baldwin swa->sw_hmac = true; 12246113a08bSJohn Baldwin if (csp->csp_auth_key != NULL) { 12253a0b6a93SJohn Baldwin swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 1226091d81d1SSam Leffler M_NOWAIT); 1227c0341432SJohn Baldwin if (swa->sw_octx == NULL) 1228c0341432SJohn Baldwin return (ENOBUFS); 12296113a08bSJohn Baldwin hmac_init_ipad(axf, csp->csp_auth_key, 12306113a08bSJohn Baldwin csp->csp_auth_klen, swa->sw_ictx); 12316113a08bSJohn Baldwin hmac_init_opad(axf, csp->csp_auth_key, 12326113a08bSJohn Baldwin csp->csp_auth_klen, swa->sw_octx); 1233091d81d1SSam Leffler } 1234091d81d1SSam Leffler break; 1235091d81d1SSam Leffler case CRYPTO_SHA1: 1236c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1237c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1238c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1239c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 1240*aa268175SJohn Baldwin case CRYPTO_NULL_HMAC: 1241c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1242c0341432SJohn Baldwin break; 1243c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 12446113a08bSJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 12456113a08bSJohn Baldwin case CRYPTO_POLY1305: 12466113a08bSJohn Baldwin if (csp->csp_auth_key != NULL) { 1247c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1248c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1249c0341432SJohn Baldwin csp->csp_auth_klen); 12506113a08bSJohn Baldwin } 1251c0341432SJohn Baldwin break; 1252c0341432SJohn Baldwin case CRYPTO_BLAKE2B: 1253c0341432SJohn Baldwin case CRYPTO_BLAKE2S: 1254c0341432SJohn Baldwin /* 1255c0341432SJohn Baldwin * Blake2b and Blake2s support an optional key but do 1256c0341432SJohn Baldwin * not require one. 1257c0341432SJohn Baldwin */ 12586113a08bSJohn Baldwin if (csp->csp_auth_klen == 0) 12596113a08bSJohn Baldwin axf->Init(swa->sw_ictx); 12606113a08bSJohn Baldwin else if (csp->csp_auth_key != NULL) 1261c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1262c0341432SJohn Baldwin csp->csp_auth_klen); 12636113a08bSJohn Baldwin break; 12646113a08bSJohn Baldwin } 12656113a08bSJohn Baldwin 12666113a08bSJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) { 12676113a08bSJohn Baldwin switch (csp->csp_auth_alg) { 12686113a08bSJohn Baldwin case CRYPTO_AES_NIST_GMAC: 12696113a08bSJohn Baldwin ses->swcr_process = swcr_gmac; 1270c0341432SJohn Baldwin break; 1271c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1272c0341432SJohn Baldwin ses->swcr_process = swcr_ccm_cbc_mac; 1273c0341432SJohn Baldwin break; 12746113a08bSJohn Baldwin default: 12756113a08bSJohn Baldwin ses->swcr_process = swcr_authcompute; 12766113a08bSJohn Baldwin } 1277091d81d1SSam Leffler } 1278091d81d1SSam Leffler 1279c0341432SJohn Baldwin return (0); 1280c0341432SJohn Baldwin } 128108fca7a5SJohn-Mark Gurney 1282c0341432SJohn Baldwin static int 1283ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses, 1284c0341432SJohn Baldwin const struct crypto_session_params *csp) 1285c0341432SJohn Baldwin { 1286c0341432SJohn Baldwin struct swcr_auth *swa; 1287ab91fb6cSJohn Baldwin int error; 1288c0341432SJohn Baldwin 1289ab91fb6cSJohn Baldwin error = swcr_setup_cipher(ses, csp); 1290ab91fb6cSJohn Baldwin if (error) 1291ab91fb6cSJohn Baldwin return (error); 1292ab91fb6cSJohn Baldwin 1293c0341432SJohn Baldwin swa = &ses->swcr_auth; 1294c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1295ab91fb6cSJohn Baldwin swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize; 1296c0341432SJohn Baldwin else 1297c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1298ab91fb6cSJohn Baldwin return (0); 1299dd2e1352SJohn Baldwin } 1300dd2e1352SJohn Baldwin 1301c0341432SJohn Baldwin static bool 1302c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp) 1303109919c6SBenno Rice { 1304d8787d4fSMark Johnston const struct auth_hash *axf; 1305091d81d1SSam Leffler 1306c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1307c0341432SJohn Baldwin if (axf == NULL) 1308c0341432SJohn Baldwin return (false); 1309c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1310091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1311c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1312f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1313f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1314f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1315091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1316c0341432SJohn Baldwin case CRYPTO_RIPEMD160_HMAC: 1317091d81d1SSam Leffler break; 1318c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1319c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1320c0341432SJohn Baldwin case 128: 1321c0341432SJohn Baldwin case 192: 1322c0341432SJohn Baldwin case 256: 1323c0341432SJohn Baldwin break; 1324c0341432SJohn Baldwin default: 1325c0341432SJohn Baldwin return (false); 1326c0341432SJohn Baldwin } 1327c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1328c0341432SJohn Baldwin return (false); 1329c0341432SJohn Baldwin if (csp->csp_ivlen != AES_GCM_IV_LEN) 1330c0341432SJohn Baldwin return (false); 1331c0341432SJohn Baldwin break; 133225b7033bSConrad Meyer case CRYPTO_POLY1305: 1333c0341432SJohn Baldwin if (csp->csp_auth_klen != POLY1305_KEY_LEN) 1334c0341432SJohn Baldwin return (false); 1335c0341432SJohn Baldwin break; 1336c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1337c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1338c0341432SJohn Baldwin case 128: 1339c0341432SJohn Baldwin case 192: 1340c0341432SJohn Baldwin case 256: 1341c0341432SJohn Baldwin break; 1342c0341432SJohn Baldwin default: 1343c0341432SJohn Baldwin return (false); 1344c0341432SJohn Baldwin } 1345c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1346c0341432SJohn Baldwin return (false); 1347c0341432SJohn Baldwin break; 1348c0341432SJohn Baldwin } 1349c0341432SJohn Baldwin return (true); 1350c0341432SJohn Baldwin } 1351091d81d1SSam Leffler 1352c0341432SJohn Baldwin static bool 1353c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp) 1354c0341432SJohn Baldwin { 1355d8787d4fSMark Johnston const struct enc_xform *txf; 1356c0341432SJohn Baldwin 1357c0341432SJohn Baldwin txf = crypto_cipher(csp); 1358c0341432SJohn Baldwin if (txf == NULL) 1359c0341432SJohn Baldwin return (false); 1360c0341432SJohn Baldwin if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && 1361c0341432SJohn Baldwin txf->ivsize != csp->csp_ivlen) 1362c0341432SJohn Baldwin return (false); 1363c0341432SJohn Baldwin return (true); 1364c0341432SJohn Baldwin } 1365c0341432SJohn Baldwin 13666038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN) 13676038018aSMarcin Wojtas 1368c0341432SJohn Baldwin static int 1369c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp) 1370c0341432SJohn Baldwin { 13716038018aSMarcin Wojtas if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0) 1372c0341432SJohn Baldwin return (EINVAL); 1373c0341432SJohn Baldwin switch (csp->csp_mode) { 1374c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1375c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1376c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1377c0341432SJohn Baldwin break; 1378c0341432SJohn Baldwin default: 1379c0341432SJohn Baldwin return (EINVAL); 13805fbc5b5aSConrad Meyer } 1381091d81d1SSam Leffler break; 1382c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1383c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1384c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1385c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1386dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1387c0341432SJohn Baldwin return (EINVAL); 1388c0341432SJohn Baldwin default: 1389c0341432SJohn Baldwin if (!swcr_cipher_supported(csp)) 1390c0341432SJohn Baldwin return (EINVAL); 1391091d81d1SSam Leffler break; 1392091d81d1SSam Leffler } 1393c0341432SJohn Baldwin break; 1394c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1395c0341432SJohn Baldwin if (!swcr_auth_supported(csp)) 1396c0341432SJohn Baldwin return (EINVAL); 1397c0341432SJohn Baldwin break; 1398c0341432SJohn Baldwin case CSP_MODE_AEAD: 1399c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1400c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1401c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1402c172a407SJohn Baldwin switch (csp->csp_cipher_klen * 8) { 1403c172a407SJohn Baldwin case 128: 1404c172a407SJohn Baldwin case 192: 1405c172a407SJohn Baldwin case 256: 1406c172a407SJohn Baldwin break; 1407c172a407SJohn Baldwin default: 1408c172a407SJohn Baldwin return (EINVAL); 1409c172a407SJohn Baldwin } 1410c172a407SJohn Baldwin break; 1411dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1412c0341432SJohn Baldwin break; 1413c0341432SJohn Baldwin default: 1414c0341432SJohn Baldwin return (EINVAL); 1415c0341432SJohn Baldwin } 1416c0341432SJohn Baldwin break; 1417c0341432SJohn Baldwin case CSP_MODE_ETA: 1418c0341432SJohn Baldwin /* AEAD algorithms cannot be used for EtA. */ 1419c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1420c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1421c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1422dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1423c0341432SJohn Baldwin return (EINVAL); 1424c0341432SJohn Baldwin } 1425c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1426c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1427c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1428c0341432SJohn Baldwin return (EINVAL); 1429c0341432SJohn Baldwin } 1430c0341432SJohn Baldwin 1431c0341432SJohn Baldwin if (!swcr_cipher_supported(csp) || 1432c0341432SJohn Baldwin !swcr_auth_supported(csp)) 1433c0341432SJohn Baldwin return (EINVAL); 1434c0341432SJohn Baldwin break; 1435c0341432SJohn Baldwin default: 1436c0341432SJohn Baldwin return (EINVAL); 1437c0341432SJohn Baldwin } 1438c0341432SJohn Baldwin 1439c0341432SJohn Baldwin return (CRYPTODEV_PROBE_SOFTWARE); 1440c0341432SJohn Baldwin } 1441c0341432SJohn Baldwin 1442c0341432SJohn Baldwin /* 1443c0341432SJohn Baldwin * Generate a new software session. 1444c0341432SJohn Baldwin */ 1445c0341432SJohn Baldwin static int 1446c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses, 1447c0341432SJohn Baldwin const struct crypto_session_params *csp) 1448c0341432SJohn Baldwin { 1449c0341432SJohn Baldwin struct swcr_session *ses; 1450d8787d4fSMark Johnston const struct comp_algo *cxf; 1451c0341432SJohn Baldwin int error; 1452c0341432SJohn Baldwin 1453c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1454c0341432SJohn Baldwin 1455c0341432SJohn Baldwin error = 0; 1456c0341432SJohn Baldwin switch (csp->csp_mode) { 1457c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1458c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1459c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1460c0341432SJohn Baldwin cxf = &comp_algo_deflate; 1461c0341432SJohn Baldwin break; 1462c0341432SJohn Baldwin #ifdef INVARIANTS 1463c0341432SJohn Baldwin default: 1464c0341432SJohn Baldwin panic("bad compression algo"); 1465c0341432SJohn Baldwin #endif 1466c0341432SJohn Baldwin } 1467c0341432SJohn Baldwin ses->swcr_compdec.sw_cxf = cxf; 1468c0341432SJohn Baldwin ses->swcr_process = swcr_compdec; 1469c0341432SJohn Baldwin break; 1470c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1471c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1472c0341432SJohn Baldwin case CRYPTO_NULL_CBC: 1473c0341432SJohn Baldwin ses->swcr_process = swcr_null; 1474c0341432SJohn Baldwin break; 1475c0341432SJohn Baldwin #ifdef INVARIANTS 1476c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1477c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1478dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1479c0341432SJohn Baldwin panic("bad cipher algo"); 1480c0341432SJohn Baldwin #endif 1481c0341432SJohn Baldwin default: 14823e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1483c0341432SJohn Baldwin if (error == 0) 1484c0341432SJohn Baldwin ses->swcr_process = swcr_encdec; 1485c0341432SJohn Baldwin } 1486c0341432SJohn Baldwin break; 1487c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1488c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1489c0341432SJohn Baldwin break; 1490c0341432SJohn Baldwin case CSP_MODE_AEAD: 1491c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1492c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1493ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1494c0341432SJohn Baldwin if (error == 0) 1495c0341432SJohn Baldwin ses->swcr_process = swcr_gcm; 1496c0341432SJohn Baldwin break; 1497c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1498ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1499c0341432SJohn Baldwin if (error == 0) 1500c0341432SJohn Baldwin ses->swcr_process = swcr_ccm; 1501c0341432SJohn Baldwin break; 1502dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1503ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1504dd2e1352SJohn Baldwin if (error == 0) 1505dd2e1352SJohn Baldwin ses->swcr_process = swcr_chacha20_poly1305; 1506dd2e1352SJohn Baldwin break; 1507c0341432SJohn Baldwin #ifdef INVARIANTS 1508c0341432SJohn Baldwin default: 1509c0341432SJohn Baldwin panic("bad aead algo"); 1510c0341432SJohn Baldwin #endif 1511c0341432SJohn Baldwin } 1512c0341432SJohn Baldwin break; 1513c0341432SJohn Baldwin case CSP_MODE_ETA: 1514c0341432SJohn Baldwin #ifdef INVARIANTS 1515c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1516c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1517c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1518dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1519c0341432SJohn Baldwin panic("bad eta cipher algo"); 1520c0341432SJohn Baldwin } 1521c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1522c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1523c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1524c0341432SJohn Baldwin panic("bad eta auth algo"); 1525c0341432SJohn Baldwin } 1526c0341432SJohn Baldwin #endif 1527c0341432SJohn Baldwin 1528c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1529c0341432SJohn Baldwin if (error) 1530c0341432SJohn Baldwin break; 1531c0341432SJohn Baldwin if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) { 1532c0341432SJohn Baldwin /* Effectively degrade to digest mode. */ 1533c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1534c0341432SJohn Baldwin break; 1535c0341432SJohn Baldwin } 1536c0341432SJohn Baldwin 15373e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1538c0341432SJohn Baldwin if (error == 0) 1539c0341432SJohn Baldwin ses->swcr_process = swcr_eta; 1540c0341432SJohn Baldwin break; 1541c0341432SJohn Baldwin default: 1542c0341432SJohn Baldwin error = EINVAL; 1543c0341432SJohn Baldwin } 1544c0341432SJohn Baldwin 1545c0341432SJohn Baldwin if (error) 1546c0341432SJohn Baldwin swcr_freesession(dev, cses); 1547c0341432SJohn Baldwin return (error); 1548c0341432SJohn Baldwin } 1549c0341432SJohn Baldwin 1550c0341432SJohn Baldwin static void 1551c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses) 1552c0341432SJohn Baldwin { 1553c0341432SJohn Baldwin struct swcr_session *ses; 1554c0341432SJohn Baldwin 1555c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1556c0341432SJohn Baldwin 1557f313909aSJohn Baldwin zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA); 15584a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA); 15594a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA); 1560091d81d1SSam Leffler } 1561091d81d1SSam Leffler 1562091d81d1SSam Leffler /* 1563091d81d1SSam Leffler * Process a software request. 1564091d81d1SSam Leffler */ 1565091d81d1SSam Leffler static int 15666810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1567091d81d1SSam Leffler { 1568c0341432SJohn Baldwin struct swcr_session *ses; 1569091d81d1SSam Leffler 15701b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1571091d81d1SSam Leffler 1572c0341432SJohn Baldwin crp->crp_etype = ses->swcr_process(ses, crp); 1573091d81d1SSam Leffler 1574091d81d1SSam Leffler crypto_done(crp); 1575c0341432SJohn Baldwin return (0); 1576091d81d1SSam Leffler } 1577091d81d1SSam Leffler 1578091d81d1SSam Leffler static void 15793f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1580091d81d1SSam Leffler { 15816810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 15826810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 158386c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 15846810ad6fSSam Leffler panic("cryptosoft: could not attach"); 15856810ad6fSSam Leffler } 1586f6c4bc3bSPawel Jakub Dawidek 15876810ad6fSSam Leffler static int 15886810ad6fSSam Leffler swcr_probe(device_t dev) 15896810ad6fSSam Leffler { 15906810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 15914fc60fa9SMark Johnston device_quiet(dev); 159286c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 15936810ad6fSSam Leffler } 1594f6c4bc3bSPawel Jakub Dawidek 15956810ad6fSSam Leffler static int 15966810ad6fSSam Leffler swcr_attach(device_t dev) 15976810ad6fSSam Leffler { 15986810ad6fSSam Leffler 15999ebbebe4SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), 16006810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 16016810ad6fSSam Leffler if (swcr_id < 0) { 16026810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 1603c0341432SJohn Baldwin return (ENXIO); 16046810ad6fSSam Leffler } 16056810ad6fSSam Leffler 1606c0341432SJohn Baldwin return (0); 1607091d81d1SSam Leffler } 16084b465da2SPawel Jakub Dawidek 16093f147ab2SWarner Losh static int 16106810ad6fSSam Leffler swcr_detach(device_t dev) 16114b465da2SPawel Jakub Dawidek { 16126810ad6fSSam Leffler crypto_unregister_all(swcr_id); 16133f147ab2SWarner Losh return 0; 16144b465da2SPawel Jakub Dawidek } 16156810ad6fSSam Leffler 16166810ad6fSSam Leffler static device_method_t swcr_methods[] = { 16176810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 16186810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 16196810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 16206810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 16216810ad6fSSam Leffler 1622c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, swcr_probesession), 16236810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 16246810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 16256810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 16266810ad6fSSam Leffler 16276810ad6fSSam Leffler {0, 0}, 16286810ad6fSSam Leffler }; 16296810ad6fSSam Leffler 16306810ad6fSSam Leffler static driver_t swcr_driver = { 16316810ad6fSSam Leffler "cryptosoft", 16326810ad6fSSam Leffler swcr_methods, 16336810ad6fSSam Leffler 0, /* NB: no softc */ 16346810ad6fSSam Leffler }; 16356810ad6fSSam Leffler static devclass_t swcr_devclass; 16366810ad6fSSam Leffler 16376810ad6fSSam Leffler /* 16386810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 16396810ad6fSSam Leffler * get the necessary ordering when built as a loadable 16406810ad6fSSam Leffler * module. This is required because we bundle the crypto 16416810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 16426810ad6fSSam Leffler * normal module dependencies would handle things). 16436810ad6fSSam Leffler */ 16446810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 16456810ad6fSSam Leffler /* XXX where to attach */ 16466810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 16476810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 16486810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1649