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 1208fca7a5SJohn-Mark Gurney * Copyright (c) 2014 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 * 19091d81d1SSam Leffler * Permission to use, copy, and modify this software with or without fee 20091d81d1SSam Leffler * is hereby granted, provided that this entire notice is included in 21091d81d1SSam Leffler * all source code copies of any software which is or includes a copy or 22091d81d1SSam Leffler * modification of this software. 23091d81d1SSam Leffler * 24091d81d1SSam Leffler * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 25091d81d1SSam Leffler * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 26091d81d1SSam Leffler * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 27091d81d1SSam Leffler * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 28091d81d1SSam Leffler * PURPOSE. 29091d81d1SSam Leffler */ 30091d81d1SSam Leffler 312c446514SDavid E. O'Brien #include <sys/cdefs.h> 322c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 332c446514SDavid E. O'Brien 34091d81d1SSam Leffler #include <sys/param.h> 35091d81d1SSam Leffler #include <sys/systm.h> 36091d81d1SSam Leffler #include <sys/malloc.h> 37091d81d1SSam Leffler #include <sys/mbuf.h> 386810ad6fSSam Leffler #include <sys/module.h> 39091d81d1SSam Leffler #include <sys/sysctl.h> 40091d81d1SSam Leffler #include <sys/errno.h> 41091d81d1SSam Leffler #include <sys/random.h> 42091d81d1SSam Leffler #include <sys/kernel.h> 43091d81d1SSam Leffler #include <sys/uio.h> 44109919c6SBenno Rice #include <sys/lock.h> 45109919c6SBenno Rice #include <sys/rwlock.h> 4608fca7a5SJohn-Mark Gurney #include <sys/endian.h> 4708fca7a5SJohn-Mark Gurney #include <sys/limits.h> 48a7fcb1afSSean Eric Fagan #include <sys/mutex.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; 63*d8787d4fSMark Johnston const struct auth_hash *sw_axf; 64c0341432SJohn Baldwin uint16_t sw_mlen; 65c0341432SJohn Baldwin }; 66c0341432SJohn Baldwin 67c0341432SJohn Baldwin struct swcr_encdec { 683e947048SJohn Baldwin void *sw_kschedule; 69*d8787d4fSMark Johnston const struct enc_xform *sw_exf; 70c0341432SJohn Baldwin }; 71c0341432SJohn Baldwin 72c0341432SJohn Baldwin struct swcr_compdec { 73*d8787d4fSMark Johnston const struct comp_algo *sw_cxf; 74c0341432SJohn Baldwin }; 75c0341432SJohn Baldwin 76c0341432SJohn Baldwin struct swcr_session { 77c0341432SJohn Baldwin struct mtx swcr_lock; 78c0341432SJohn Baldwin int (*swcr_process)(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 91c0341432SJohn Baldwin swcr_null(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 101c0341432SJohn Baldwin swcr_encdec(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; 106*d8787d4fSMark Johnston const struct enc_xform *exf; 107c0341432SJohn Baldwin struct swcr_encdec *sw; 10886be314dSJohn Baldwin size_t inlen, outlen; 10986be314dSJohn Baldwin int i, blks, ivlen, resid; 1109c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 11126d292d3SJohn Baldwin const unsigned char *inblk; 11226d292d3SJohn Baldwin unsigned char *outblk; 11308fca7a5SJohn-Mark Gurney int error; 114c0341432SJohn Baldwin bool encrypting; 11508fca7a5SJohn-Mark Gurney 11608fca7a5SJohn-Mark Gurney error = 0; 117091d81d1SSam Leffler 118c0341432SJohn Baldwin sw = &ses->swcr_encdec; 119091d81d1SSam Leffler exf = sw->sw_exf; 12008fca7a5SJohn-Mark Gurney ivlen = exf->ivsize; 121091d81d1SSam Leffler 122723d8764SJohn Baldwin if (exf->native_blocksize == 0) { 123091d81d1SSam Leffler /* Check for non-padded data */ 124723d8764SJohn Baldwin if ((crp->crp_payload_length % exf->blocksize) != 0) 125723d8764SJohn Baldwin return (EINVAL); 126723d8764SJohn Baldwin 127723d8764SJohn Baldwin blks = exf->blocksize; 128723d8764SJohn Baldwin } else 129723d8764SJohn Baldwin blks = exf->native_blocksize; 130091d81d1SSam Leffler 131c0341432SJohn Baldwin if (exf == &enc_xform_aes_icm && 132c0341432SJohn Baldwin (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 13308fca7a5SJohn-Mark Gurney return (EINVAL); 13408fca7a5SJohn-Mark Gurney 135c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) { 136c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 1373e947048SJohn Baldwin error = exf->setkey(sw->sw_kschedule, 138c0341432SJohn Baldwin crp->crp_cipher_key, csp->csp_cipher_klen); 139c740ae4bSPoul-Henning Kamp if (error) 140c740ae4bSPoul-Henning Kamp return (error); 141c740ae4bSPoul-Henning Kamp } 142d295bdeeSPawel Jakub Dawidek 14320c128daSJohn Baldwin crypto_read_iv(crp, iv); 14420c128daSJohn Baldwin 14508fca7a5SJohn-Mark Gurney if (exf->reinit) { 146d295bdeeSPawel Jakub Dawidek /* 147d295bdeeSPawel Jakub Dawidek * xforms that provide a reinit method perform all IV 148d295bdeeSPawel Jakub Dawidek * handling themselves. 149d295bdeeSPawel Jakub Dawidek */ 150d295bdeeSPawel Jakub Dawidek exf->reinit(sw->sw_kschedule, iv); 151091d81d1SSam Leffler } 152091d81d1SSam Leffler 1539c0e3d3aSJohn Baldwin ivp = iv; 154091d81d1SSam Leffler 1559c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1569c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 15786be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 1589c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 1599c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 1609c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 1619c0e3d3aSJohn Baldwin } else 1629c0e3d3aSJohn Baldwin cc_out = cc_in; 16386be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 1649c0e3d3aSJohn Baldwin 1659c0e3d3aSJohn Baldwin resid = crp->crp_payload_length; 166c0341432SJohn Baldwin encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 167091d81d1SSam Leffler 168091d81d1SSam Leffler /* 1699c0e3d3aSJohn Baldwin * Loop through encrypting blocks. 'inlen' is the remaining 1709c0e3d3aSJohn Baldwin * length of the current segment in the input buffer. 1719c0e3d3aSJohn Baldwin * 'outlen' is the remaining length of current segment in the 1729c0e3d3aSJohn Baldwin * output buffer. 173091d81d1SSam Leffler */ 1749c0e3d3aSJohn Baldwin while (resid >= blks) { 1759c0e3d3aSJohn Baldwin /* 1769c0e3d3aSJohn Baldwin * If the current block is not contained within the 1779c0e3d3aSJohn Baldwin * current input/output segment, use 'blk' as a local 1789c0e3d3aSJohn Baldwin * buffer. 1799c0e3d3aSJohn Baldwin */ 1809c0e3d3aSJohn Baldwin if (inlen < blks) { 1819c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, blks, blk); 1829c0e3d3aSJohn Baldwin inblk = blk; 183d295bdeeSPawel Jakub Dawidek } 1849c0e3d3aSJohn Baldwin if (outlen < blks) 1859c0e3d3aSJohn Baldwin outblk = blk; 1869c0e3d3aSJohn Baldwin 1879c0e3d3aSJohn Baldwin /* 1889c0e3d3aSJohn Baldwin * Ciphers without a 'reinit' hook are assumed to be 1899c0e3d3aSJohn Baldwin * used in CBC mode where the chaining is done here. 1909c0e3d3aSJohn Baldwin */ 1919c0e3d3aSJohn Baldwin if (exf->reinit != NULL) { 1929c0e3d3aSJohn Baldwin if (encrypting) 1939c0e3d3aSJohn Baldwin exf->encrypt(sw->sw_kschedule, inblk, outblk); 1949c0e3d3aSJohn Baldwin else 1959c0e3d3aSJohn Baldwin exf->decrypt(sw->sw_kschedule, inblk, outblk); 196c0341432SJohn Baldwin } else if (encrypting) { 197091d81d1SSam Leffler /* XOR with previous block */ 1989c0e3d3aSJohn Baldwin for (i = 0; i < blks; i++) 1999c0e3d3aSJohn Baldwin outblk[i] = inblk[i] ^ ivp[i]; 200091d81d1SSam Leffler 2019c0e3d3aSJohn Baldwin exf->encrypt(sw->sw_kschedule, outblk, outblk); 202091d81d1SSam Leffler 203091d81d1SSam Leffler /* 204091d81d1SSam Leffler * Keep encrypted block for XOR'ing 205091d81d1SSam Leffler * with next block 206091d81d1SSam Leffler */ 2079c0e3d3aSJohn Baldwin memcpy(iv, outblk, blks); 208091d81d1SSam Leffler ivp = iv; 209091d81d1SSam Leffler } else { /* decrypt */ 210091d81d1SSam Leffler /* 211091d81d1SSam Leffler * Keep encrypted block for XOR'ing 212091d81d1SSam Leffler * with next block 213091d81d1SSam Leffler */ 21408fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 2159c0e3d3aSJohn Baldwin memcpy(nivp, inblk, blks); 216091d81d1SSam Leffler 2179c0e3d3aSJohn Baldwin exf->decrypt(sw->sw_kschedule, inblk, outblk); 218091d81d1SSam Leffler 219091d81d1SSam Leffler /* XOR with previous block */ 2209c0e3d3aSJohn Baldwin for (i = 0; i < blks; i++) 2219c0e3d3aSJohn Baldwin outblk[i] ^= ivp[i]; 222091d81d1SSam Leffler 22308fca7a5SJohn-Mark Gurney ivp = nivp; 224091d81d1SSam Leffler } 225091d81d1SSam Leffler 2269c0e3d3aSJohn Baldwin if (inlen < blks) { 22786be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 2289c0e3d3aSJohn Baldwin } else { 2299c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, blks); 2309c0e3d3aSJohn Baldwin inlen -= blks; 2319c0e3d3aSJohn Baldwin inblk += blks; 23208fca7a5SJohn-Mark Gurney } 233091d81d1SSam Leffler 2349c0e3d3aSJohn Baldwin if (outlen < blks) { 2359c0e3d3aSJohn Baldwin crypto_cursor_copyback(&cc_out, blks, blk); 23686be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2379c0e3d3aSJohn Baldwin } else { 2389c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, blks); 2399c0e3d3aSJohn Baldwin outlen -= blks; 2409c0e3d3aSJohn Baldwin outblk += blks; 241091d81d1SSam Leffler } 242091d81d1SSam Leffler 2439c0e3d3aSJohn Baldwin resid -= blks; 244f34a967bSPawel Jakub Dawidek } 245f34a967bSPawel Jakub Dawidek 246723d8764SJohn Baldwin /* Handle trailing partial block for stream ciphers. */ 2479c0e3d3aSJohn Baldwin if (resid > 0) { 248723d8764SJohn Baldwin KASSERT(exf->native_blocksize != 0, 249723d8764SJohn Baldwin ("%s: partial block of %d bytes for cipher %s", 250723d8764SJohn Baldwin __func__, i, exf->name)); 251723d8764SJohn Baldwin KASSERT(exf->reinit != NULL, 252723d8764SJohn Baldwin ("%s: partial block cipher %s without reinit hook", 253723d8764SJohn Baldwin __func__, exf->name)); 2549c0e3d3aSJohn Baldwin KASSERT(resid < blks, ("%s: partial block too big", __func__)); 255723d8764SJohn Baldwin 25686be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 25786be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2589c0e3d3aSJohn Baldwin if (inlen < resid) { 2599c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 2609c0e3d3aSJohn Baldwin inblk = blk; 26186be314dSJohn Baldwin } 2629c0e3d3aSJohn Baldwin if (outlen < resid) 2639c0e3d3aSJohn Baldwin outblk = blk; 2649c0e3d3aSJohn Baldwin if (encrypting) 2659c0e3d3aSJohn Baldwin exf->encrypt_last(sw->sw_kschedule, inblk, outblk, 2669c0e3d3aSJohn Baldwin resid); 2679c0e3d3aSJohn Baldwin else 2689c0e3d3aSJohn Baldwin exf->decrypt_last(sw->sw_kschedule, inblk, outblk, 2699c0e3d3aSJohn Baldwin resid); 2709c0e3d3aSJohn Baldwin if (outlen < resid) 2719c0e3d3aSJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 272723d8764SJohn Baldwin } 273723d8764SJohn Baldwin 27420c128daSJohn Baldwin explicit_bzero(blk, sizeof(blk)); 27520c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 27620c128daSJohn Baldwin explicit_bzero(iv2, sizeof(iv2)); 2779c0e3d3aSJohn Baldwin return (0); 278091d81d1SSam Leffler } 279091d81d1SSam Leffler 280c0341432SJohn Baldwin static void 281*d8787d4fSMark Johnston swcr_authprepare(const struct auth_hash *axf, struct swcr_auth *sw, 282c0341432SJohn Baldwin const uint8_t *key, int klen) 283f6c4bc3bSPawel Jakub Dawidek { 284f6c4bc3bSPawel Jakub Dawidek 285f6c4bc3bSPawel Jakub Dawidek switch (axf->type) { 286f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_HMAC: 287c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 288f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 289f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 290f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 291f6c4bc3bSPawel Jakub Dawidek case CRYPTO_NULL_HMAC: 292f6c4bc3bSPawel Jakub Dawidek case CRYPTO_RIPEMD160_HMAC: 293c0341432SJohn Baldwin hmac_init_ipad(axf, key, klen, sw->sw_ictx); 294c0341432SJohn Baldwin hmac_init_opad(axf, key, klen, sw->sw_octx); 295f6c4bc3bSPawel Jakub Dawidek break; 29625b7033bSConrad Meyer case CRYPTO_POLY1305: 2970e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 2980e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 2990e33efe4SConrad Meyer axf->Setkey(sw->sw_ictx, key, klen); 3000e33efe4SConrad Meyer axf->Init(sw->sw_ictx); 3010e33efe4SConrad Meyer break; 302f6c4bc3bSPawel Jakub Dawidek default: 303c0341432SJohn Baldwin panic("%s: algorithm %d doesn't use keys", __func__, axf->type); 304f6c4bc3bSPawel Jakub Dawidek } 305f6c4bc3bSPawel Jakub Dawidek } 306f6c4bc3bSPawel Jakub Dawidek 307091d81d1SSam Leffler /* 308c0341432SJohn Baldwin * Compute or verify hash. 309091d81d1SSam Leffler */ 310091d81d1SSam Leffler static int 311c0341432SJohn Baldwin swcr_authcompute(struct swcr_session *ses, struct cryptop *crp) 312091d81d1SSam Leffler { 313c0341432SJohn Baldwin u_char aalg[HASH_MAX_LEN]; 314c0341432SJohn Baldwin const struct crypto_session_params *csp; 315c0341432SJohn Baldwin struct swcr_auth *sw; 316*d8787d4fSMark Johnston const struct auth_hash *axf; 317091d81d1SSam Leffler union authctx ctx; 318091d81d1SSam Leffler int err; 319091d81d1SSam Leffler 320c0341432SJohn Baldwin sw = &ses->swcr_auth; 321091d81d1SSam Leffler 322091d81d1SSam Leffler axf = sw->sw_axf; 323091d81d1SSam Leffler 324c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 3256038018aSMarcin Wojtas if (crp->crp_auth_key != NULL) { 326c0341432SJohn Baldwin swcr_authprepare(axf, sw, crp->crp_auth_key, 327c0341432SJohn Baldwin csp->csp_auth_klen); 32825b7033bSConrad Meyer } 329f6c4bc3bSPawel Jakub Dawidek 330091d81d1SSam Leffler bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 331091d81d1SSam Leffler 3329b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 3339b774dc0SJohn Baldwin err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 3349b774dc0SJohn Baldwin else 335c0341432SJohn Baldwin err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 3369b6b2f86SJohn Baldwin axf->Update, &ctx); 337091d81d1SSam Leffler if (err) 338e0b155feSJohn Baldwin goto out; 339091d81d1SSam Leffler 3409c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && 3419c0e3d3aSJohn Baldwin CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 3429c0e3d3aSJohn Baldwin err = crypto_apply_buf(&crp->crp_obuf, 3439c0e3d3aSJohn Baldwin crp->crp_payload_output_start, crp->crp_payload_length, 3449b6b2f86SJohn Baldwin axf->Update, &ctx); 3459c0e3d3aSJohn Baldwin else 3469c0e3d3aSJohn Baldwin err = crypto_apply(crp, crp->crp_payload_start, 3479b6b2f86SJohn Baldwin crp->crp_payload_length, axf->Update, &ctx); 348c0341432SJohn Baldwin if (err) 349e0b155feSJohn Baldwin goto out; 350091d81d1SSam Leffler 3516038018aSMarcin Wojtas if (csp->csp_flags & CSP_F_ESN) 3526038018aSMarcin Wojtas axf->Update(&ctx, crp->crp_esn, 4); 3536038018aSMarcin Wojtas 354091d81d1SSam Leffler axf->Final(aalg, &ctx); 355e0b155feSJohn Baldwin if (sw->sw_octx != NULL) { 356091d81d1SSam Leffler bcopy(sw->sw_octx, &ctx, axf->ctxsize); 357091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 358091d81d1SSam Leffler axf->Final(aalg, &ctx); 359091d81d1SSam Leffler } 360091d81d1SSam Leffler 361c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 36220c128daSJohn Baldwin u_char uaalg[HASH_MAX_LEN]; 36320c128daSJohn Baldwin 364c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg); 365c0341432SJohn Baldwin if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0) 36620c128daSJohn Baldwin err = EBADMSG; 36720c128daSJohn Baldwin explicit_bzero(uaalg, sizeof(uaalg)); 368c0341432SJohn Baldwin } else { 369091d81d1SSam Leffler /* Inject the authentication data */ 370c0341432SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg); 371c0341432SJohn Baldwin } 37220c128daSJohn Baldwin explicit_bzero(aalg, sizeof(aalg)); 373e0b155feSJohn Baldwin out: 374e0b155feSJohn Baldwin explicit_bzero(&ctx, sizeof(ctx)); 37520c128daSJohn Baldwin return (err); 376091d81d1SSam Leffler } 377091d81d1SSam Leffler 37808fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 37908fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 38008fca7a5SJohn-Mark Gurney 38108fca7a5SJohn-Mark Gurney static int 382c0341432SJohn Baldwin swcr_gmac(struct swcr_session *ses, struct cryptop *crp) 38308fca7a5SJohn-Mark Gurney { 38426d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 38508fca7a5SJohn-Mark Gurney u_char *blk = (u_char *)blkbuf; 38626d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 38726d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 3889c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc; 38926d292d3SJohn Baldwin const u_char *inblk; 39008fca7a5SJohn-Mark Gurney union authctx ctx; 391c0341432SJohn Baldwin struct swcr_auth *swa; 392*d8787d4fSMark Johnston const struct auth_hash *axf; 39308fca7a5SJohn-Mark Gurney uint32_t *blkp; 39486be314dSJohn Baldwin size_t len; 39586be314dSJohn Baldwin int blksz, error, ivlen, resid; 39608fca7a5SJohn-Mark Gurney 397c0341432SJohn Baldwin swa = &ses->swcr_auth; 39808fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 399c0341432SJohn Baldwin 40008fca7a5SJohn-Mark Gurney bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 40126d292d3SJohn Baldwin blksz = GMAC_BLOCK_LEN; 40226d292d3SJohn Baldwin KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", 40326d292d3SJohn Baldwin __func__)); 40408fca7a5SJohn-Mark Gurney 40508fca7a5SJohn-Mark Gurney /* Initialize the IV */ 406c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 40729fe41ddSJohn Baldwin crypto_read_iv(crp, iv); 40808fca7a5SJohn-Mark Gurney 40908fca7a5SJohn-Mark Gurney axf->Reinit(&ctx, iv, ivlen); 4109c0e3d3aSJohn Baldwin crypto_cursor_init(&cc, &crp->crp_buf); 4119c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc, crp->crp_payload_start); 41226d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) { 41386be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc, &len); 41426d292d3SJohn Baldwin if (len >= blksz) { 41526d292d3SJohn Baldwin len = rounddown(MIN(len, resid), blksz); 41626d292d3SJohn Baldwin crypto_cursor_advance(&cc, len); 41726d292d3SJohn Baldwin } else { 41826d292d3SJohn Baldwin len = blksz; 4199c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc, len, blk); 42026d292d3SJohn Baldwin inblk = blk; 42126d292d3SJohn Baldwin } 42226d292d3SJohn Baldwin axf->Update(&ctx, inblk, len); 42326d292d3SJohn Baldwin } 42426d292d3SJohn Baldwin if (resid > 0) { 42526d292d3SJohn Baldwin memset(blk, 0, blksz); 42626d292d3SJohn Baldwin crypto_cursor_copydata(&cc, resid, blk); 42708fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 42808fca7a5SJohn-Mark Gurney } 42908fca7a5SJohn-Mark Gurney 43008fca7a5SJohn-Mark Gurney /* length block */ 43126d292d3SJohn Baldwin memset(blk, 0, blksz); 43208fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 433c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 43408fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 435c0341432SJohn Baldwin 436c0341432SJohn Baldwin /* Finalize MAC */ 43726d292d3SJohn Baldwin axf->Final(tag, &ctx); 438c0341432SJohn Baldwin 43920c128daSJohn Baldwin error = 0; 440c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 44126d292d3SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 44220c128daSJohn Baldwin 443c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 44426d292d3SJohn Baldwin tag2); 44526d292d3SJohn Baldwin if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) 44620c128daSJohn Baldwin error = EBADMSG; 44726d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 448c0341432SJohn Baldwin } else { 449c0341432SJohn Baldwin /* Inject the authentication data */ 45026d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 451c0341432SJohn Baldwin } 45220c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 45326d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 45420c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 45520c128daSJohn Baldwin return (error); 456c0341432SJohn Baldwin } 457c0341432SJohn Baldwin 458c0341432SJohn Baldwin static int 459c0341432SJohn Baldwin swcr_gcm(struct swcr_session *ses, struct cryptop *crp) 460c0341432SJohn Baldwin { 46126d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 462c0341432SJohn Baldwin u_char *blk = (u_char *)blkbuf; 46326d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 46426d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 4659c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 46626d292d3SJohn Baldwin const u_char *inblk; 46726d292d3SJohn Baldwin u_char *outblk; 468c0341432SJohn Baldwin union authctx ctx; 469c0341432SJohn Baldwin struct swcr_auth *swa; 470c0341432SJohn Baldwin struct swcr_encdec *swe; 471*d8787d4fSMark Johnston const struct auth_hash *axf; 472*d8787d4fSMark Johnston const struct enc_xform *exf; 473c0341432SJohn Baldwin uint32_t *blkp; 47486be314dSJohn Baldwin size_t len; 47586be314dSJohn Baldwin int blksz, error, ivlen, r, resid; 476c0341432SJohn Baldwin 477c0341432SJohn Baldwin swa = &ses->swcr_auth; 478c0341432SJohn Baldwin axf = swa->sw_axf; 479c0341432SJohn Baldwin 480c0341432SJohn Baldwin bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 48126d292d3SJohn Baldwin blksz = GMAC_BLOCK_LEN; 48226d292d3SJohn Baldwin KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", 48326d292d3SJohn Baldwin __func__)); 484c0341432SJohn Baldwin 485c0341432SJohn Baldwin swe = &ses->swcr_encdec; 486c0341432SJohn Baldwin exf = swe->sw_exf; 487723d8764SJohn Baldwin KASSERT(axf->blocksize == exf->native_blocksize, 488723d8764SJohn Baldwin ("%s: blocksize mismatch", __func__)); 489c0341432SJohn Baldwin 490c0341432SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 491c0341432SJohn Baldwin return (EINVAL); 492c0341432SJohn Baldwin 493c0341432SJohn Baldwin /* Initialize the IV */ 494c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 495c0341432SJohn Baldwin bcopy(crp->crp_iv, iv, ivlen); 496c0341432SJohn Baldwin 497c0341432SJohn Baldwin /* Supply MAC with IV */ 498c0341432SJohn Baldwin axf->Reinit(&ctx, iv, ivlen); 499c0341432SJohn Baldwin 500c0341432SJohn Baldwin /* Supply MAC with AAD */ 5019b774dc0SJohn Baldwin if (crp->crp_aad != NULL) { 5029b774dc0SJohn Baldwin len = rounddown(crp->crp_aad_length, blksz); 5039b774dc0SJohn Baldwin if (len != 0) 5049b774dc0SJohn Baldwin axf->Update(&ctx, crp->crp_aad, len); 5059b774dc0SJohn Baldwin if (crp->crp_aad_length != len) { 5069b774dc0SJohn Baldwin memset(blk, 0, blksz); 5079b774dc0SJohn Baldwin memcpy(blk, (char *)crp->crp_aad + len, 5089b774dc0SJohn Baldwin crp->crp_aad_length - len); 5099b774dc0SJohn Baldwin axf->Update(&ctx, blk, blksz); 5109b774dc0SJohn Baldwin } 5119b774dc0SJohn Baldwin } else { 5129c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 5139c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_aad_start); 5149b774dc0SJohn Baldwin for (resid = crp->crp_aad_length; resid >= blksz; 5159b774dc0SJohn Baldwin resid -= len) { 51686be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 51726d292d3SJohn Baldwin if (len >= blksz) { 51826d292d3SJohn Baldwin len = rounddown(MIN(len, resid), blksz); 51926d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, len); 52026d292d3SJohn Baldwin } else { 52126d292d3SJohn Baldwin len = blksz; 5229c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, len, blk); 52326d292d3SJohn Baldwin inblk = blk; 52426d292d3SJohn Baldwin } 52526d292d3SJohn Baldwin axf->Update(&ctx, inblk, len); 52626d292d3SJohn Baldwin } 52726d292d3SJohn Baldwin if (resid > 0) { 52826d292d3SJohn Baldwin memset(blk, 0, blksz); 52926d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 530c0341432SJohn Baldwin axf->Update(&ctx, blk, blksz); 531c0341432SJohn Baldwin } 5329b774dc0SJohn Baldwin } 533c0341432SJohn Baldwin 534a10020cfSJohn Baldwin if (crp->crp_cipher_key != NULL) 535a10020cfSJohn Baldwin exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, 536a10020cfSJohn Baldwin crypto_get_params(crp->crp_session)->csp_cipher_klen); 537c0341432SJohn Baldwin exf->reinit(swe->sw_kschedule, iv); 538c0341432SJohn Baldwin 539c0341432SJohn Baldwin /* Do encryption with MAC */ 5409c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 5419c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 5429c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 5439c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 5449c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 5459c0e3d3aSJohn Baldwin } else 5469c0e3d3aSJohn Baldwin cc_out = cc_in; 54726d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 54886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 54986be314dSJohn Baldwin if (len < blksz) { 55026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 55126d292d3SJohn Baldwin inblk = blk; 552c0341432SJohn Baldwin } else { 55326d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 554c0341432SJohn Baldwin } 55526d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 55686be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 55786be314dSJohn Baldwin if (len < blksz) 55826d292d3SJohn Baldwin outblk = blk; 55926d292d3SJohn Baldwin exf->encrypt(swe->sw_kschedule, inblk, outblk); 56026d292d3SJohn Baldwin axf->Update(&ctx, outblk, blksz); 56126d292d3SJohn Baldwin if (outblk == blk) 56226d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 56326d292d3SJohn Baldwin else 56426d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 56526d292d3SJohn Baldwin } else { 56626d292d3SJohn Baldwin axf->Update(&ctx, inblk, blksz); 56726d292d3SJohn Baldwin } 56826d292d3SJohn Baldwin } 56926d292d3SJohn Baldwin if (resid > 0) { 57026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 57126d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 57226d292d3SJohn Baldwin exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); 57326d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 57426d292d3SJohn Baldwin } 57526d292d3SJohn Baldwin axf->Update(&ctx, blk, resid); 576c0341432SJohn Baldwin } 577c0341432SJohn Baldwin 578c0341432SJohn Baldwin /* length block */ 57926d292d3SJohn Baldwin memset(blk, 0, blksz); 580c0341432SJohn Baldwin blkp = (uint32_t *)blk + 1; 581c0341432SJohn Baldwin *blkp = htobe32(crp->crp_aad_length * 8); 582c0341432SJohn Baldwin blkp = (uint32_t *)blk + 3; 583c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 584c0341432SJohn Baldwin axf->Update(&ctx, blk, blksz); 585c0341432SJohn Baldwin 586c0341432SJohn Baldwin /* Finalize MAC */ 58726d292d3SJohn Baldwin axf->Final(tag, &ctx); 588c0341432SJohn Baldwin 589c0341432SJohn Baldwin /* Validate tag */ 59020c128daSJohn Baldwin error = 0; 591c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 59226d292d3SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 59320c128daSJohn Baldwin 59426d292d3SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); 595c0341432SJohn Baldwin 59626d292d3SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 59726d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 59820c128daSJohn Baldwin if (r != 0) { 59920c128daSJohn Baldwin error = EBADMSG; 60020c128daSJohn Baldwin goto out; 60120c128daSJohn Baldwin } 602c0341432SJohn Baldwin 603c0341432SJohn Baldwin /* tag matches, decrypt data */ 6049c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 6059c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 60626d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 60726d292d3SJohn Baldwin resid -= blksz) { 60886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 60986be314dSJohn Baldwin if (len < blksz) { 61026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 61126d292d3SJohn Baldwin inblk = blk; 61286be314dSJohn Baldwin } else 61326d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 61486be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 61586be314dSJohn Baldwin if (len < blksz) 61626d292d3SJohn Baldwin outblk = blk; 61726d292d3SJohn Baldwin exf->decrypt(swe->sw_kschedule, inblk, outblk); 61826d292d3SJohn Baldwin if (outblk == blk) 61926d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 62026d292d3SJohn Baldwin else 62126d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 62226d292d3SJohn Baldwin } 62326d292d3SJohn Baldwin if (resid > 0) { 62426d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 62526d292d3SJohn Baldwin exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); 62626d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 627c0341432SJohn Baldwin } 628c0341432SJohn Baldwin } else { 629c0341432SJohn Baldwin /* Inject the authentication data */ 63026d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 631c0341432SJohn Baldwin } 632c0341432SJohn Baldwin 63320c128daSJohn Baldwin out: 63420c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 63526d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 63620c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 63720c128daSJohn Baldwin 63820c128daSJohn Baldwin return (error); 639c0341432SJohn Baldwin } 640c0341432SJohn Baldwin 641c0341432SJohn Baldwin static int 642c0341432SJohn Baldwin swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp) 643c0341432SJohn Baldwin { 64426d292d3SJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 64526d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 646c0341432SJohn Baldwin union authctx ctx; 647c0341432SJohn Baldwin struct swcr_auth *swa; 648*d8787d4fSMark Johnston const struct auth_hash *axf; 64926d292d3SJohn Baldwin int error, ivlen; 650c0341432SJohn Baldwin 651c0341432SJohn Baldwin swa = &ses->swcr_auth; 652c0341432SJohn Baldwin axf = swa->sw_axf; 653c0341432SJohn Baldwin 654c0341432SJohn Baldwin bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 655c0341432SJohn Baldwin 656c0341432SJohn Baldwin /* Initialize the IV */ 657c0341432SJohn Baldwin ivlen = AES_CCM_IV_LEN; 65829fe41ddSJohn Baldwin crypto_read_iv(crp, iv); 659c0341432SJohn Baldwin 660c0341432SJohn Baldwin /* 661c0341432SJohn Baldwin * AES CCM-CBC-MAC needs to know the length of both the auth 662c0341432SJohn Baldwin * data and payload data before doing the auth computation. 663c0341432SJohn Baldwin */ 664c0341432SJohn Baldwin ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_payload_length; 665c0341432SJohn Baldwin ctx.aes_cbc_mac_ctx.cryptDataLength = 0; 666c0341432SJohn Baldwin 667c0341432SJohn Baldwin axf->Reinit(&ctx, iv, ivlen); 6689b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 6699b774dc0SJohn Baldwin error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 6709b774dc0SJohn Baldwin else 67126d292d3SJohn Baldwin error = crypto_apply(crp, crp->crp_payload_start, 67226d292d3SJohn Baldwin crp->crp_payload_length, axf->Update, &ctx); 67326d292d3SJohn Baldwin if (error) 67426d292d3SJohn Baldwin return (error); 675c0341432SJohn Baldwin 676c0341432SJohn Baldwin /* Finalize MAC */ 67726d292d3SJohn Baldwin axf->Final(tag, &ctx); 678c0341432SJohn Baldwin 679c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 68026d292d3SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 68120c128daSJohn Baldwin 682c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 68326d292d3SJohn Baldwin tag2); 68426d292d3SJohn Baldwin if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) 68520c128daSJohn Baldwin error = EBADMSG; 68626d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag)); 687c0341432SJohn Baldwin } else { 688c0341432SJohn Baldwin /* Inject the authentication data */ 68926d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 690c0341432SJohn Baldwin } 69126d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 69220c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 69320c128daSJohn Baldwin return (error); 694c0341432SJohn Baldwin } 695c0341432SJohn Baldwin 696c0341432SJohn Baldwin static int 697c0341432SJohn Baldwin swcr_ccm(struct swcr_session *ses, struct cryptop *crp) 698c0341432SJohn Baldwin { 69926d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 700c0341432SJohn Baldwin u_char *blk = (u_char *)blkbuf; 70126d292d3SJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 70226d292d3SJohn Baldwin u_char iv[AES_BLOCK_LEN]; 7039c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 70426d292d3SJohn Baldwin const u_char *inblk; 70526d292d3SJohn Baldwin u_char *outblk; 706c0341432SJohn Baldwin union authctx ctx; 707c0341432SJohn Baldwin struct swcr_auth *swa; 708c0341432SJohn Baldwin struct swcr_encdec *swe; 709*d8787d4fSMark Johnston const struct auth_hash *axf; 710*d8787d4fSMark Johnston const struct enc_xform *exf; 71186be314dSJohn Baldwin size_t len; 71226d292d3SJohn Baldwin int blksz, error, ivlen, r, resid; 713c0341432SJohn Baldwin 714c0341432SJohn Baldwin swa = &ses->swcr_auth; 715c0341432SJohn Baldwin axf = swa->sw_axf; 716c0341432SJohn Baldwin 717c0341432SJohn Baldwin bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 71826d292d3SJohn Baldwin blksz = AES_BLOCK_LEN; 71926d292d3SJohn Baldwin KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", 72026d292d3SJohn Baldwin __func__)); 721c0341432SJohn Baldwin 722c0341432SJohn Baldwin swe = &ses->swcr_encdec; 723c0341432SJohn Baldwin exf = swe->sw_exf; 724723d8764SJohn Baldwin KASSERT(axf->blocksize == exf->native_blocksize, 725723d8764SJohn Baldwin ("%s: blocksize mismatch", __func__)); 726c0341432SJohn Baldwin 727c0341432SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 728c0341432SJohn Baldwin return (EINVAL); 729c0341432SJohn Baldwin 730c0341432SJohn Baldwin /* Initialize the IV */ 731c0341432SJohn Baldwin ivlen = AES_CCM_IV_LEN; 732c0341432SJohn Baldwin bcopy(crp->crp_iv, iv, ivlen); 733c0341432SJohn Baldwin 734c0341432SJohn Baldwin /* 735c0341432SJohn Baldwin * AES CCM-CBC-MAC needs to know the length of both the auth 736c0341432SJohn Baldwin * data and payload data before doing the auth computation. 737c0341432SJohn Baldwin */ 738c0341432SJohn Baldwin ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length; 739c0341432SJohn Baldwin ctx.aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length; 740c0341432SJohn Baldwin 741c0341432SJohn Baldwin /* Supply MAC with IV */ 742c0341432SJohn Baldwin axf->Reinit(&ctx, iv, ivlen); 743c0341432SJohn Baldwin 744c0341432SJohn Baldwin /* Supply MAC with AAD */ 7459b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 7469b774dc0SJohn Baldwin error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 7479b774dc0SJohn Baldwin else 7489b774dc0SJohn Baldwin error = crypto_apply(crp, crp->crp_aad_start, 7499b774dc0SJohn Baldwin crp->crp_aad_length, axf->Update, &ctx); 75026d292d3SJohn Baldwin if (error) 75126d292d3SJohn Baldwin return (error); 752c0341432SJohn Baldwin 753a10020cfSJohn Baldwin if (crp->crp_cipher_key != NULL) 754a10020cfSJohn Baldwin exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, 755a10020cfSJohn Baldwin crypto_get_params(crp->crp_session)->csp_cipher_klen); 756c0341432SJohn Baldwin exf->reinit(swe->sw_kschedule, iv); 757c0341432SJohn Baldwin 758c0341432SJohn Baldwin /* Do encryption/decryption with MAC */ 7599c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 7609c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 7619c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 7629c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 7639c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 7649c0e3d3aSJohn Baldwin } else 7659c0e3d3aSJohn Baldwin cc_out = cc_in; 76626d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 76786be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 76886be314dSJohn Baldwin if (len < blksz) { 76926d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 77026d292d3SJohn Baldwin inblk = blk; 77186be314dSJohn Baldwin } else 77226d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 773c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 77486be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 77586be314dSJohn Baldwin if (len < blksz) 77626d292d3SJohn Baldwin outblk = blk; 77726d292d3SJohn Baldwin axf->Update(&ctx, inblk, blksz); 77826d292d3SJohn Baldwin exf->encrypt(swe->sw_kschedule, inblk, outblk); 77926d292d3SJohn Baldwin if (outblk == blk) 78026d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 78126d292d3SJohn Baldwin else 78226d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 783c0341432SJohn Baldwin } else { 784c0341432SJohn Baldwin /* 785c0341432SJohn Baldwin * One of the problems with CCM+CBC is that 786c0341432SJohn Baldwin * the authentication is done on the 78726d292d3SJohn Baldwin * unencrypted data. As a result, we have to 788c0341432SJohn Baldwin * decrypt the data twice: once to generate 789c0341432SJohn Baldwin * the tag and a second time after the tag is 790c0341432SJohn Baldwin * verified. 791c0341432SJohn Baldwin */ 79226d292d3SJohn Baldwin exf->decrypt(swe->sw_kschedule, inblk, blk); 79326d292d3SJohn Baldwin axf->Update(&ctx, blk, blksz); 79426d292d3SJohn Baldwin } 79526d292d3SJohn Baldwin } 79626d292d3SJohn Baldwin if (resid > 0) { 79726d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 79826d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 79926d292d3SJohn Baldwin axf->Update(&ctx, blk, resid); 80026d292d3SJohn Baldwin exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); 80126d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 80226d292d3SJohn Baldwin } else { 80326d292d3SJohn Baldwin exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); 80426d292d3SJohn Baldwin axf->Update(&ctx, blk, resid); 805c0341432SJohn Baldwin } 80608fca7a5SJohn-Mark Gurney } 80708fca7a5SJohn-Mark Gurney 80808fca7a5SJohn-Mark Gurney /* Finalize MAC */ 80926d292d3SJohn Baldwin axf->Final(tag, &ctx); 81008fca7a5SJohn-Mark Gurney 81108fca7a5SJohn-Mark Gurney /* Validate tag */ 81220c128daSJohn Baldwin error = 0; 813c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 81426d292d3SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 81520c128daSJohn Baldwin 816c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 81726d292d3SJohn Baldwin tag2); 81808fca7a5SJohn-Mark Gurney 81926d292d3SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 82026d292d3SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 82120c128daSJohn Baldwin if (r != 0) { 82220c128daSJohn Baldwin error = EBADMSG; 82320c128daSJohn Baldwin goto out; 82420c128daSJohn Baldwin } 825c0341432SJohn Baldwin 82608fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 827507281e5SSean Eric Fagan exf->reinit(swe->sw_kschedule, iv); 8289c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 8299c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 83026d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 83126d292d3SJohn Baldwin resid -= blksz) { 83286be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 83386be314dSJohn Baldwin if (len < blksz) { 83426d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 83526d292d3SJohn Baldwin inblk = blk; 83686be314dSJohn Baldwin } else 83726d292d3SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 83886be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 83986be314dSJohn Baldwin if (len < blksz) 84026d292d3SJohn Baldwin outblk = blk; 84126d292d3SJohn Baldwin exf->decrypt(swe->sw_kschedule, inblk, outblk); 84226d292d3SJohn Baldwin if (outblk == blk) 84326d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 84426d292d3SJohn Baldwin else 84526d292d3SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 84626d292d3SJohn Baldwin } 84726d292d3SJohn Baldwin if (resid > 0) { 84826d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 84926d292d3SJohn Baldwin exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); 85026d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 85108fca7a5SJohn-Mark Gurney } 85208fca7a5SJohn-Mark Gurney } else { 85308fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 85426d292d3SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 85508fca7a5SJohn-Mark Gurney } 85608fca7a5SJohn-Mark Gurney 85720c128daSJohn Baldwin out: 85820c128daSJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 85926d292d3SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 86020c128daSJohn Baldwin explicit_bzero(iv, sizeof(iv)); 86120c128daSJohn Baldwin return (error); 86208fca7a5SJohn-Mark Gurney } 86308fca7a5SJohn-Mark Gurney 864dd2e1352SJohn Baldwin static int 865dd2e1352SJohn Baldwin swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp) 866dd2e1352SJohn Baldwin { 867dd2e1352SJohn Baldwin const struct crypto_session_params *csp; 868dd2e1352SJohn Baldwin uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; 869dd2e1352SJohn Baldwin u_char *blk = (u_char *)blkbuf; 870dd2e1352SJohn Baldwin u_char tag[POLY1305_HASH_LEN]; 871dd2e1352SJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 872dd2e1352SJohn Baldwin const u_char *inblk; 873dd2e1352SJohn Baldwin u_char *outblk; 874dd2e1352SJohn Baldwin uint64_t *blkp; 875dd2e1352SJohn Baldwin union authctx ctx; 876dd2e1352SJohn Baldwin struct swcr_auth *swa; 877dd2e1352SJohn Baldwin struct swcr_encdec *swe; 878*d8787d4fSMark Johnston const struct auth_hash *axf; 879*d8787d4fSMark Johnston const struct enc_xform *exf; 88086be314dSJohn Baldwin size_t len; 881dd2e1352SJohn Baldwin int blksz, error, r, resid; 882dd2e1352SJohn Baldwin 883dd2e1352SJohn Baldwin swa = &ses->swcr_auth; 884dd2e1352SJohn Baldwin axf = swa->sw_axf; 885dd2e1352SJohn Baldwin 886dd2e1352SJohn Baldwin swe = &ses->swcr_encdec; 887dd2e1352SJohn Baldwin exf = swe->sw_exf; 888dd2e1352SJohn Baldwin blksz = exf->native_blocksize; 889dd2e1352SJohn Baldwin KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__)); 890dd2e1352SJohn Baldwin 891dd2e1352SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 892dd2e1352SJohn Baldwin return (EINVAL); 893dd2e1352SJohn Baldwin 894dd2e1352SJohn Baldwin csp = crypto_get_params(crp->crp_session); 895dd2e1352SJohn Baldwin 896dd2e1352SJohn Baldwin /* Generate Poly1305 key. */ 897dd2e1352SJohn Baldwin if (crp->crp_cipher_key != NULL) 898dd2e1352SJohn Baldwin axf->Setkey(&ctx, crp->crp_cipher_key, csp->csp_cipher_klen); 899dd2e1352SJohn Baldwin else 900dd2e1352SJohn Baldwin axf->Setkey(&ctx, csp->csp_cipher_key, csp->csp_cipher_klen); 901dd2e1352SJohn Baldwin axf->Reinit(&ctx, crp->crp_iv, csp->csp_ivlen); 902dd2e1352SJohn Baldwin 903dd2e1352SJohn Baldwin /* Supply MAC with AAD */ 904dd2e1352SJohn Baldwin if (crp->crp_aad != NULL) 905dd2e1352SJohn Baldwin axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 906dd2e1352SJohn Baldwin else 907dd2e1352SJohn Baldwin crypto_apply(crp, crp->crp_aad_start, 908dd2e1352SJohn Baldwin crp->crp_aad_length, axf->Update, &ctx); 909dd2e1352SJohn Baldwin if (crp->crp_aad_length % 16 != 0) { 910dd2e1352SJohn Baldwin /* padding1 */ 911dd2e1352SJohn Baldwin memset(blk, 0, 16); 912dd2e1352SJohn Baldwin axf->Update(&ctx, blk, 16 - crp->crp_aad_length % 16); 913dd2e1352SJohn Baldwin } 914dd2e1352SJohn Baldwin 915dd2e1352SJohn Baldwin if (crp->crp_cipher_key != NULL) 916dd2e1352SJohn Baldwin exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, 917dd2e1352SJohn Baldwin csp->csp_cipher_klen); 918dd2e1352SJohn Baldwin exf->reinit(swe->sw_kschedule, crp->crp_iv); 919dd2e1352SJohn Baldwin 920dd2e1352SJohn Baldwin /* Do encryption with MAC */ 921dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 922dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 923dd2e1352SJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 924dd2e1352SJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 925dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 926dd2e1352SJohn Baldwin } else 927dd2e1352SJohn Baldwin cc_out = cc_in; 928dd2e1352SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { 92986be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 93086be314dSJohn Baldwin if (len < blksz) { 931dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 932dd2e1352SJohn Baldwin inblk = blk; 93386be314dSJohn Baldwin } else 934dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 935dd2e1352SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 93686be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 93786be314dSJohn Baldwin if (len < blksz) 938dd2e1352SJohn Baldwin outblk = blk; 939dd2e1352SJohn Baldwin exf->encrypt(swe->sw_kschedule, inblk, outblk); 940dd2e1352SJohn Baldwin axf->Update(&ctx, outblk, blksz); 941dd2e1352SJohn Baldwin if (outblk == blk) 942dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 943dd2e1352SJohn Baldwin else 944dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 945dd2e1352SJohn Baldwin } else { 946dd2e1352SJohn Baldwin axf->Update(&ctx, inblk, blksz); 947dd2e1352SJohn Baldwin } 948dd2e1352SJohn Baldwin } 949dd2e1352SJohn Baldwin if (resid > 0) { 950dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 951dd2e1352SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 952dd2e1352SJohn Baldwin exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); 953dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 954dd2e1352SJohn Baldwin } 955dd2e1352SJohn Baldwin axf->Update(&ctx, blk, resid); 956dd2e1352SJohn Baldwin if (resid % 16 != 0) { 957dd2e1352SJohn Baldwin /* padding2 */ 958dd2e1352SJohn Baldwin memset(blk, 0, 16); 959dd2e1352SJohn Baldwin axf->Update(&ctx, blk, 16 - resid % 16); 960dd2e1352SJohn Baldwin } 961dd2e1352SJohn Baldwin } 962dd2e1352SJohn Baldwin 963dd2e1352SJohn Baldwin /* lengths */ 964dd2e1352SJohn Baldwin blkp = (uint64_t *)blk; 965dd2e1352SJohn Baldwin blkp[0] = htole64(crp->crp_aad_length); 966dd2e1352SJohn Baldwin blkp[1] = htole64(crp->crp_payload_length); 967dd2e1352SJohn Baldwin axf->Update(&ctx, blk, sizeof(uint64_t) * 2); 968dd2e1352SJohn Baldwin 969dd2e1352SJohn Baldwin /* Finalize MAC */ 970dd2e1352SJohn Baldwin axf->Final(tag, &ctx); 971dd2e1352SJohn Baldwin 972dd2e1352SJohn Baldwin /* Validate tag */ 973dd2e1352SJohn Baldwin error = 0; 974dd2e1352SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 975dd2e1352SJohn Baldwin u_char tag2[POLY1305_HASH_LEN]; 976dd2e1352SJohn Baldwin 977dd2e1352SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); 978dd2e1352SJohn Baldwin 979dd2e1352SJohn Baldwin r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); 980dd2e1352SJohn Baldwin explicit_bzero(tag2, sizeof(tag2)); 981dd2e1352SJohn Baldwin if (r != 0) { 982dd2e1352SJohn Baldwin error = EBADMSG; 983dd2e1352SJohn Baldwin goto out; 984dd2e1352SJohn Baldwin } 985dd2e1352SJohn Baldwin 986dd2e1352SJohn Baldwin /* tag matches, decrypt data */ 987dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 988dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 989dd2e1352SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 990dd2e1352SJohn Baldwin resid -= blksz) { 99186be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &len); 99286be314dSJohn Baldwin if (len < blksz) { 993dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 994dd2e1352SJohn Baldwin inblk = blk; 99586be314dSJohn Baldwin } else 996dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, blksz); 99786be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &len); 99886be314dSJohn Baldwin if (len < blksz) 999dd2e1352SJohn Baldwin outblk = blk; 1000dd2e1352SJohn Baldwin exf->decrypt(swe->sw_kschedule, inblk, outblk); 1001dd2e1352SJohn Baldwin if (outblk == blk) 1002dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 1003dd2e1352SJohn Baldwin else 1004dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, blksz); 1005dd2e1352SJohn Baldwin } 1006dd2e1352SJohn Baldwin if (resid > 0) { 1007dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 1008dd2e1352SJohn Baldwin exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); 1009dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 1010dd2e1352SJohn Baldwin } 1011dd2e1352SJohn Baldwin } else { 1012dd2e1352SJohn Baldwin /* Inject the authentication data */ 1013dd2e1352SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); 1014dd2e1352SJohn Baldwin } 1015dd2e1352SJohn Baldwin 1016dd2e1352SJohn Baldwin out: 1017dd2e1352SJohn Baldwin explicit_bzero(blkbuf, sizeof(blkbuf)); 1018dd2e1352SJohn Baldwin explicit_bzero(tag, sizeof(tag)); 1019dd2e1352SJohn Baldwin explicit_bzero(&ctx, sizeof(ctx)); 1020dd2e1352SJohn Baldwin return (error); 1021dd2e1352SJohn Baldwin } 1022dd2e1352SJohn Baldwin 1023091d81d1SSam Leffler /* 1024c0341432SJohn Baldwin * Apply a cipher and a digest to perform EtA. 1025c0341432SJohn Baldwin */ 1026c0341432SJohn Baldwin static int 1027c0341432SJohn Baldwin swcr_eta(struct swcr_session *ses, struct cryptop *crp) 1028c0341432SJohn Baldwin { 1029c0341432SJohn Baldwin int error; 1030c0341432SJohn Baldwin 1031c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1032c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1033c0341432SJohn Baldwin if (error == 0) 1034c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1035c0341432SJohn Baldwin } else { 1036c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1037c0341432SJohn Baldwin if (error == 0) 1038c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1039c0341432SJohn Baldwin } 1040c0341432SJohn Baldwin return (error); 1041c0341432SJohn Baldwin } 1042c0341432SJohn Baldwin 1043c0341432SJohn Baldwin /* 1044091d81d1SSam Leffler * Apply a compression/decompression algorithm 1045091d81d1SSam Leffler */ 1046091d81d1SSam Leffler static int 1047c0341432SJohn Baldwin swcr_compdec(struct swcr_session *ses, struct cryptop *crp) 1048091d81d1SSam Leffler { 1049*d8787d4fSMark Johnston const struct comp_algo *cxf; 1050d3d79e96SJohn Baldwin uint8_t *data, *out; 1051091d81d1SSam Leffler int adj; 1052d3d79e96SJohn Baldwin uint32_t result; 1053091d81d1SSam Leffler 1054c0341432SJohn Baldwin cxf = ses->swcr_compdec.sw_cxf; 1055091d81d1SSam Leffler 1056091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 1057091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 1058091d81d1SSam Leffler * copy in a buffer. 1059091d81d1SSam Leffler */ 1060091d81d1SSam Leffler 1061c0341432SJohn Baldwin data = malloc(crp->crp_payload_length, M_CRYPTO_DATA, M_NOWAIT); 1062091d81d1SSam Leffler if (data == NULL) 1063091d81d1SSam Leffler return (EINVAL); 1064c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length, 1065c0341432SJohn Baldwin data); 1066091d81d1SSam Leffler 1067c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) 1068c0341432SJohn Baldwin result = cxf->compress(data, crp->crp_payload_length, &out); 1069091d81d1SSam Leffler else 1070c0341432SJohn Baldwin result = cxf->decompress(data, crp->crp_payload_length, &out); 1071091d81d1SSam Leffler 10721ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 1073091d81d1SSam Leffler if (result == 0) 1074c0341432SJohn Baldwin return (EINVAL); 1075c0341432SJohn Baldwin crp->crp_olen = result; 1076c0341432SJohn Baldwin 1077c0341432SJohn Baldwin /* Check the compressed size when doing compression */ 1078c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) { 1079c0341432SJohn Baldwin if (result >= crp->crp_payload_length) { 1080c0341432SJohn Baldwin /* Compression was useless, we lost time */ 1081c0341432SJohn Baldwin free(out, M_CRYPTO_DATA); 1082c0341432SJohn Baldwin return (0); 1083c0341432SJohn Baldwin } 1084c0341432SJohn Baldwin } 1085091d81d1SSam Leffler 1086091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 1087091d81d1SSam Leffler * extending the mbuf as necessary. 1088091d81d1SSam Leffler */ 1089c0341432SJohn Baldwin crypto_copyback(crp, crp->crp_payload_start, result, out); 1090c0341432SJohn Baldwin if (result < crp->crp_payload_length) { 10919c0e3d3aSJohn Baldwin switch (crp->crp_buf.cb_type) { 1092c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 1093883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 1094c0341432SJohn Baldwin adj = result - crp->crp_payload_length; 10959c0e3d3aSJohn Baldwin m_adj(crp->crp_buf.cb_mbuf, adj); 1096c0341432SJohn Baldwin break; 1097c0341432SJohn Baldwin case CRYPTO_BUF_UIO: { 10989c0e3d3aSJohn Baldwin struct uio *uio = crp->crp_buf.cb_uio; 1099091d81d1SSam Leffler int ind; 1100091d81d1SSam Leffler 1101c0341432SJohn Baldwin adj = crp->crp_payload_length - result; 1102091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 1103091d81d1SSam Leffler 1104091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 1105091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 1106091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 1107091d81d1SSam Leffler break; 1108091d81d1SSam Leffler } 1109091d81d1SSam Leffler 1110091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 1111091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 1112091d81d1SSam Leffler ind--; 1113091d81d1SSam Leffler uio->uio_iovcnt--; 1114091d81d1SSam Leffler } 1115091d81d1SSam Leffler } 1116c0341432SJohn Baldwin break; 1117e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 1118e6f6d0c9SAlan Somers adj = crp->crp_payload_length - result; 1119e6f6d0c9SAlan Somers crp->crp_buf.cb_vm_page_len -= adj; 1120e6f6d0c9SAlan Somers break; 11219c0e3d3aSJohn Baldwin default: 11229c0e3d3aSJohn Baldwin break; 1123c0341432SJohn Baldwin } 1124091d81d1SSam Leffler } 11251ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 1126091d81d1SSam Leffler return 0; 1127091d81d1SSam Leffler } 1128091d81d1SSam Leffler 1129091d81d1SSam Leffler static int 11303e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses, 1131c0341432SJohn Baldwin const struct crypto_session_params *csp) 1132091d81d1SSam Leffler { 1133c0341432SJohn Baldwin struct swcr_encdec *swe; 1134*d8787d4fSMark Johnston const struct enc_xform *txf; 1135f6c4bc3bSPawel Jakub Dawidek int error; 1136091d81d1SSam Leffler 1137c0341432SJohn Baldwin swe = &ses->swcr_encdec; 1138c0341432SJohn Baldwin txf = crypto_cipher(csp); 1139c0341432SJohn Baldwin MPASS(txf->ivsize == csp->csp_ivlen); 11403e947048SJohn Baldwin if (txf->ctxsize != 0) { 11413e947048SJohn Baldwin swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA, 11423e947048SJohn Baldwin M_NOWAIT); 11433e947048SJohn Baldwin if (swe->sw_kschedule == NULL) 11443e947048SJohn Baldwin return (ENOMEM); 11453e947048SJohn Baldwin } 1146c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) { 11473e947048SJohn Baldwin error = txf->setkey(swe->sw_kschedule, 1148c0341432SJohn Baldwin csp->csp_cipher_key, csp->csp_cipher_klen); 1149c0341432SJohn Baldwin if (error) 1150c0341432SJohn Baldwin return (error); 1151091d81d1SSam Leffler } 1152c0341432SJohn Baldwin swe->sw_exf = txf; 1153c0341432SJohn Baldwin return (0); 1154f6c4bc3bSPawel Jakub Dawidek } 1155091d81d1SSam Leffler 1156c0341432SJohn Baldwin static int 1157c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses, 1158c0341432SJohn Baldwin const struct crypto_session_params *csp) 1159c0341432SJohn Baldwin { 1160c0341432SJohn Baldwin struct swcr_auth *swa; 1161*d8787d4fSMark Johnston const struct auth_hash *axf; 1162c0341432SJohn Baldwin 1163c0341432SJohn Baldwin swa = &ses->swcr_auth; 1164c0341432SJohn Baldwin 1165c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1166c0341432SJohn Baldwin swa->sw_axf = axf; 1167c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1168c0341432SJohn Baldwin return (EINVAL); 1169c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1170c0341432SJohn Baldwin swa->sw_mlen = axf->hashsize; 1171c0341432SJohn Baldwin else 1172c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1173c0341432SJohn Baldwin swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); 1174c0341432SJohn Baldwin if (swa->sw_ictx == NULL) 1175c0341432SJohn Baldwin return (ENOBUFS); 1176c0341432SJohn Baldwin 1177c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1178091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1179c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1180f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1181f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1182f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1183091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1184091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 11853a0b6a93SJohn Baldwin swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 1186091d81d1SSam Leffler M_NOWAIT); 1187c0341432SJohn Baldwin if (swa->sw_octx == NULL) 1188c0341432SJohn Baldwin return (ENOBUFS); 1189c0341432SJohn Baldwin 1190c0341432SJohn Baldwin if (csp->csp_auth_key != NULL) { 1191c0341432SJohn Baldwin swcr_authprepare(axf, swa, csp->csp_auth_key, 1192c0341432SJohn Baldwin csp->csp_auth_klen); 1193091d81d1SSam Leffler } 1194091d81d1SSam Leffler 1195c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) 1196c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1197091d81d1SSam Leffler break; 1198091d81d1SSam Leffler case CRYPTO_SHA1: 1199c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1200c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1201c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1202c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 1203c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1204c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) 1205c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1206c0341432SJohn Baldwin break; 1207c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1208c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1209c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1210c0341432SJohn Baldwin csp->csp_auth_klen); 1211c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) 1212c0341432SJohn Baldwin ses->swcr_process = swcr_gmac; 1213c0341432SJohn Baldwin break; 1214c0341432SJohn Baldwin case CRYPTO_POLY1305: 1215c0341432SJohn Baldwin case CRYPTO_BLAKE2B: 1216c0341432SJohn Baldwin case CRYPTO_BLAKE2S: 1217c0341432SJohn Baldwin /* 1218c0341432SJohn Baldwin * Blake2b and Blake2s support an optional key but do 1219c0341432SJohn Baldwin * not require one. 1220c0341432SJohn Baldwin */ 1221c0341432SJohn Baldwin if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) 1222c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1223c0341432SJohn Baldwin csp->csp_auth_klen); 1224c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1225c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) 1226c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1227c0341432SJohn Baldwin break; 1228c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1229c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1230c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1231c0341432SJohn Baldwin csp->csp_auth_klen); 1232c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) 1233c0341432SJohn Baldwin ses->swcr_process = swcr_ccm_cbc_mac; 1234c0341432SJohn Baldwin break; 1235091d81d1SSam Leffler } 1236091d81d1SSam Leffler 1237c0341432SJohn Baldwin return (0); 1238c0341432SJohn Baldwin } 123908fca7a5SJohn-Mark Gurney 1240c0341432SJohn Baldwin static int 1241c0341432SJohn Baldwin swcr_setup_gcm(struct swcr_session *ses, 1242c0341432SJohn Baldwin const struct crypto_session_params *csp) 1243c0341432SJohn Baldwin { 1244c0341432SJohn Baldwin struct swcr_auth *swa; 1245*d8787d4fSMark Johnston const struct auth_hash *axf; 1246c0341432SJohn Baldwin 1247c0341432SJohn Baldwin if (csp->csp_ivlen != AES_GCM_IV_LEN) 1248c0341432SJohn Baldwin return (EINVAL); 1249c0341432SJohn Baldwin 1250c0341432SJohn Baldwin /* First, setup the auth side. */ 1251c0341432SJohn Baldwin swa = &ses->swcr_auth; 1252c0341432SJohn Baldwin switch (csp->csp_cipher_klen * 8) { 1253c0341432SJohn Baldwin case 128: 1254c0341432SJohn Baldwin axf = &auth_hash_nist_gmac_aes_128; 1255c0341432SJohn Baldwin break; 1256c0341432SJohn Baldwin case 192: 1257c0341432SJohn Baldwin axf = &auth_hash_nist_gmac_aes_192; 1258c0341432SJohn Baldwin break; 1259c0341432SJohn Baldwin case 256: 1260c0341432SJohn Baldwin axf = &auth_hash_nist_gmac_aes_256; 1261c0341432SJohn Baldwin break; 1262c0341432SJohn Baldwin default: 1263c0341432SJohn Baldwin return (EINVAL); 1264c0341432SJohn Baldwin } 1265c0341432SJohn Baldwin swa->sw_axf = axf; 1266c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1267c0341432SJohn Baldwin return (EINVAL); 1268c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1269c0341432SJohn Baldwin swa->sw_mlen = axf->hashsize; 1270c0341432SJohn Baldwin else 1271c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1272c0341432SJohn Baldwin swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); 1273c0341432SJohn Baldwin if (swa->sw_ictx == NULL) 1274c0341432SJohn Baldwin return (ENOBUFS); 1275c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1276c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) 1277c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, 1278c0341432SJohn Baldwin csp->csp_cipher_klen); 1279c0341432SJohn Baldwin 1280c0341432SJohn Baldwin /* Second, setup the cipher side. */ 12813e947048SJohn Baldwin return (swcr_setup_cipher(ses, csp)); 1282c0341432SJohn Baldwin } 1283c0341432SJohn Baldwin 1284c0341432SJohn Baldwin static int 1285c0341432SJohn Baldwin swcr_setup_ccm(struct swcr_session *ses, 1286c0341432SJohn Baldwin const struct crypto_session_params *csp) 1287c0341432SJohn Baldwin { 1288c0341432SJohn Baldwin struct swcr_auth *swa; 1289*d8787d4fSMark Johnston const struct auth_hash *axf; 1290c0341432SJohn Baldwin 1291c0341432SJohn Baldwin if (csp->csp_ivlen != AES_CCM_IV_LEN) 1292c0341432SJohn Baldwin return (EINVAL); 1293c0341432SJohn Baldwin 1294c0341432SJohn Baldwin /* First, setup the auth side. */ 1295c0341432SJohn Baldwin swa = &ses->swcr_auth; 1296c0341432SJohn Baldwin switch (csp->csp_cipher_klen * 8) { 1297507281e5SSean Eric Fagan case 128: 1298507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_128; 1299507281e5SSean Eric Fagan break; 1300507281e5SSean Eric Fagan case 192: 1301507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_192; 1302507281e5SSean Eric Fagan break; 1303507281e5SSean Eric Fagan case 256: 1304507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_256; 1305507281e5SSean Eric Fagan break; 1306507281e5SSean Eric Fagan default: 1307c0341432SJohn Baldwin return (EINVAL); 1308507281e5SSean Eric Fagan } 1309c0341432SJohn Baldwin swa->sw_axf = axf; 1310c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1311c0341432SJohn Baldwin return (EINVAL); 1312c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1313c0341432SJohn Baldwin swa->sw_mlen = axf->hashsize; 1314c0341432SJohn Baldwin else 1315c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1316c0341432SJohn Baldwin swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); 1317c0341432SJohn Baldwin if (swa->sw_ictx == NULL) 1318c0341432SJohn Baldwin return (ENOBUFS); 1319c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1320c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) 1321c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, 1322c0341432SJohn Baldwin csp->csp_cipher_klen); 132308fca7a5SJohn-Mark Gurney 1324c0341432SJohn Baldwin /* Second, setup the cipher side. */ 13253e947048SJohn Baldwin return (swcr_setup_cipher(ses, csp)); 13262e2e26d1SJohn Baldwin } 1327a2bc81bfSJohn-Mark Gurney 1328dd2e1352SJohn Baldwin static int 1329dd2e1352SJohn Baldwin swcr_setup_chacha20_poly1305(struct swcr_session *ses, 1330dd2e1352SJohn Baldwin const struct crypto_session_params *csp) 1331dd2e1352SJohn Baldwin { 1332dd2e1352SJohn Baldwin struct swcr_auth *swa; 1333*d8787d4fSMark Johnston const struct auth_hash *axf; 1334dd2e1352SJohn Baldwin 1335dd2e1352SJohn Baldwin if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN) 1336dd2e1352SJohn Baldwin return (EINVAL); 1337dd2e1352SJohn Baldwin 1338dd2e1352SJohn Baldwin /* First, setup the auth side. */ 1339dd2e1352SJohn Baldwin swa = &ses->swcr_auth; 1340dd2e1352SJohn Baldwin axf = &auth_hash_chacha20_poly1305; 1341dd2e1352SJohn Baldwin swa->sw_axf = axf; 1342dd2e1352SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1343dd2e1352SJohn Baldwin return (EINVAL); 1344dd2e1352SJohn Baldwin if (csp->csp_auth_mlen == 0) 1345dd2e1352SJohn Baldwin swa->sw_mlen = axf->hashsize; 1346dd2e1352SJohn Baldwin else 1347dd2e1352SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1348dd2e1352SJohn Baldwin 1349dd2e1352SJohn Baldwin /* The auth state is regenerated for each nonce. */ 1350dd2e1352SJohn Baldwin 1351dd2e1352SJohn Baldwin /* Second, setup the cipher side. */ 1352dd2e1352SJohn Baldwin return (swcr_setup_cipher(ses, csp)); 1353dd2e1352SJohn Baldwin } 1354dd2e1352SJohn Baldwin 1355c0341432SJohn Baldwin static bool 1356c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp) 1357109919c6SBenno Rice { 1358*d8787d4fSMark Johnston const struct auth_hash *axf; 1359091d81d1SSam Leffler 1360c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1361c0341432SJohn Baldwin if (axf == NULL) 1362c0341432SJohn Baldwin return (false); 1363c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1364091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1365c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1366f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1367f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1368f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1369091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1370c0341432SJohn Baldwin case CRYPTO_RIPEMD160_HMAC: 1371091d81d1SSam Leffler break; 1372c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1373c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1374c0341432SJohn Baldwin case 128: 1375c0341432SJohn Baldwin case 192: 1376c0341432SJohn Baldwin case 256: 1377c0341432SJohn Baldwin break; 1378c0341432SJohn Baldwin default: 1379c0341432SJohn Baldwin return (false); 1380c0341432SJohn Baldwin } 1381c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1382c0341432SJohn Baldwin return (false); 1383c0341432SJohn Baldwin if (csp->csp_ivlen != AES_GCM_IV_LEN) 1384c0341432SJohn Baldwin return (false); 1385c0341432SJohn Baldwin break; 138625b7033bSConrad Meyer case CRYPTO_POLY1305: 1387c0341432SJohn Baldwin if (csp->csp_auth_klen != POLY1305_KEY_LEN) 1388c0341432SJohn Baldwin return (false); 1389c0341432SJohn Baldwin break; 1390c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1391c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1392c0341432SJohn Baldwin case 128: 1393c0341432SJohn Baldwin case 192: 1394c0341432SJohn Baldwin case 256: 1395c0341432SJohn Baldwin break; 1396c0341432SJohn Baldwin default: 1397c0341432SJohn Baldwin return (false); 1398c0341432SJohn Baldwin } 1399c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1400c0341432SJohn Baldwin return (false); 1401c0341432SJohn Baldwin if (csp->csp_ivlen != AES_CCM_IV_LEN) 1402c0341432SJohn Baldwin return (false); 1403c0341432SJohn Baldwin break; 1404c0341432SJohn Baldwin } 1405c0341432SJohn Baldwin return (true); 1406c0341432SJohn Baldwin } 1407091d81d1SSam Leffler 1408c0341432SJohn Baldwin static bool 1409c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp) 1410c0341432SJohn Baldwin { 1411*d8787d4fSMark Johnston const struct enc_xform *txf; 1412c0341432SJohn Baldwin 1413c0341432SJohn Baldwin txf = crypto_cipher(csp); 1414c0341432SJohn Baldwin if (txf == NULL) 1415c0341432SJohn Baldwin return (false); 1416c0341432SJohn Baldwin if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && 1417c0341432SJohn Baldwin txf->ivsize != csp->csp_ivlen) 1418c0341432SJohn Baldwin return (false); 1419c0341432SJohn Baldwin return (true); 1420c0341432SJohn Baldwin } 1421c0341432SJohn Baldwin 14226038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN) 14236038018aSMarcin Wojtas 1424c0341432SJohn Baldwin static int 1425c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp) 1426c0341432SJohn Baldwin { 14276038018aSMarcin Wojtas if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0) 1428c0341432SJohn Baldwin return (EINVAL); 1429c0341432SJohn Baldwin switch (csp->csp_mode) { 1430c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1431c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1432c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1433c0341432SJohn Baldwin break; 1434c0341432SJohn Baldwin default: 1435c0341432SJohn Baldwin return (EINVAL); 14365fbc5b5aSConrad Meyer } 1437091d81d1SSam Leffler break; 1438c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1439c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1440c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1441c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1442dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1443c0341432SJohn Baldwin return (EINVAL); 1444c0341432SJohn Baldwin default: 1445c0341432SJohn Baldwin if (!swcr_cipher_supported(csp)) 1446c0341432SJohn Baldwin return (EINVAL); 1447091d81d1SSam Leffler break; 1448091d81d1SSam Leffler } 1449c0341432SJohn Baldwin break; 1450c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1451c0341432SJohn Baldwin if (!swcr_auth_supported(csp)) 1452c0341432SJohn Baldwin return (EINVAL); 1453c0341432SJohn Baldwin break; 1454c0341432SJohn Baldwin case CSP_MODE_AEAD: 1455c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1456c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1457c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1458dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1459c0341432SJohn Baldwin break; 1460c0341432SJohn Baldwin default: 1461c0341432SJohn Baldwin return (EINVAL); 1462c0341432SJohn Baldwin } 1463c0341432SJohn Baldwin break; 1464c0341432SJohn Baldwin case CSP_MODE_ETA: 1465c0341432SJohn Baldwin /* AEAD algorithms cannot be used for EtA. */ 1466c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1467c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1468c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1469dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1470c0341432SJohn Baldwin return (EINVAL); 1471c0341432SJohn Baldwin } 1472c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1473c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1474c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1475c0341432SJohn Baldwin return (EINVAL); 1476c0341432SJohn Baldwin } 1477c0341432SJohn Baldwin 1478c0341432SJohn Baldwin if (!swcr_cipher_supported(csp) || 1479c0341432SJohn Baldwin !swcr_auth_supported(csp)) 1480c0341432SJohn Baldwin return (EINVAL); 1481c0341432SJohn Baldwin break; 1482c0341432SJohn Baldwin default: 1483c0341432SJohn Baldwin return (EINVAL); 1484c0341432SJohn Baldwin } 1485c0341432SJohn Baldwin 1486c0341432SJohn Baldwin return (CRYPTODEV_PROBE_SOFTWARE); 1487c0341432SJohn Baldwin } 1488c0341432SJohn Baldwin 1489c0341432SJohn Baldwin /* 1490c0341432SJohn Baldwin * Generate a new software session. 1491c0341432SJohn Baldwin */ 1492c0341432SJohn Baldwin static int 1493c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses, 1494c0341432SJohn Baldwin const struct crypto_session_params *csp) 1495c0341432SJohn Baldwin { 1496c0341432SJohn Baldwin struct swcr_session *ses; 1497c0341432SJohn Baldwin struct swcr_encdec *swe; 1498c0341432SJohn Baldwin struct swcr_auth *swa; 1499*d8787d4fSMark Johnston const struct comp_algo *cxf; 1500c0341432SJohn Baldwin int error; 1501c0341432SJohn Baldwin 1502c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1503c0341432SJohn Baldwin mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF); 1504c0341432SJohn Baldwin 1505c0341432SJohn Baldwin error = 0; 1506c0341432SJohn Baldwin swe = &ses->swcr_encdec; 1507c0341432SJohn Baldwin swa = &ses->swcr_auth; 1508c0341432SJohn Baldwin switch (csp->csp_mode) { 1509c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1510c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1511c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1512c0341432SJohn Baldwin cxf = &comp_algo_deflate; 1513c0341432SJohn Baldwin break; 1514c0341432SJohn Baldwin #ifdef INVARIANTS 1515c0341432SJohn Baldwin default: 1516c0341432SJohn Baldwin panic("bad compression algo"); 1517c0341432SJohn Baldwin #endif 1518c0341432SJohn Baldwin } 1519c0341432SJohn Baldwin ses->swcr_compdec.sw_cxf = cxf; 1520c0341432SJohn Baldwin ses->swcr_process = swcr_compdec; 1521c0341432SJohn Baldwin break; 1522c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1523c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1524c0341432SJohn Baldwin case CRYPTO_NULL_CBC: 1525c0341432SJohn Baldwin ses->swcr_process = swcr_null; 1526c0341432SJohn Baldwin break; 1527c0341432SJohn Baldwin #ifdef INVARIANTS 1528c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1529c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1530dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1531c0341432SJohn Baldwin panic("bad cipher algo"); 1532c0341432SJohn Baldwin #endif 1533c0341432SJohn Baldwin default: 15343e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1535c0341432SJohn Baldwin if (error == 0) 1536c0341432SJohn Baldwin ses->swcr_process = swcr_encdec; 1537c0341432SJohn Baldwin } 1538c0341432SJohn Baldwin break; 1539c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1540c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1541c0341432SJohn Baldwin break; 1542c0341432SJohn Baldwin case CSP_MODE_AEAD: 1543c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1544c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1545c0341432SJohn Baldwin error = swcr_setup_gcm(ses, csp); 1546c0341432SJohn Baldwin if (error == 0) 1547c0341432SJohn Baldwin ses->swcr_process = swcr_gcm; 1548c0341432SJohn Baldwin break; 1549c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1550c0341432SJohn Baldwin error = swcr_setup_ccm(ses, csp); 1551c0341432SJohn Baldwin if (error == 0) 1552c0341432SJohn Baldwin ses->swcr_process = swcr_ccm; 1553c0341432SJohn Baldwin break; 1554dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1555dd2e1352SJohn Baldwin error = swcr_setup_chacha20_poly1305(ses, csp); 1556dd2e1352SJohn Baldwin if (error == 0) 1557dd2e1352SJohn Baldwin ses->swcr_process = swcr_chacha20_poly1305; 1558dd2e1352SJohn Baldwin break; 1559c0341432SJohn Baldwin #ifdef INVARIANTS 1560c0341432SJohn Baldwin default: 1561c0341432SJohn Baldwin panic("bad aead algo"); 1562c0341432SJohn Baldwin #endif 1563c0341432SJohn Baldwin } 1564c0341432SJohn Baldwin break; 1565c0341432SJohn Baldwin case CSP_MODE_ETA: 1566c0341432SJohn Baldwin #ifdef INVARIANTS 1567c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1568c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1569c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1570dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 1571c0341432SJohn Baldwin panic("bad eta cipher algo"); 1572c0341432SJohn Baldwin } 1573c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1574c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1575c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1576c0341432SJohn Baldwin panic("bad eta auth algo"); 1577c0341432SJohn Baldwin } 1578c0341432SJohn Baldwin #endif 1579c0341432SJohn Baldwin 1580c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1581c0341432SJohn Baldwin if (error) 1582c0341432SJohn Baldwin break; 1583c0341432SJohn Baldwin if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) { 1584c0341432SJohn Baldwin /* Effectively degrade to digest mode. */ 1585c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1586c0341432SJohn Baldwin break; 1587c0341432SJohn Baldwin } 1588c0341432SJohn Baldwin 15893e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1590c0341432SJohn Baldwin if (error == 0) 1591c0341432SJohn Baldwin ses->swcr_process = swcr_eta; 1592c0341432SJohn Baldwin break; 1593c0341432SJohn Baldwin default: 1594c0341432SJohn Baldwin error = EINVAL; 1595c0341432SJohn Baldwin } 1596c0341432SJohn Baldwin 1597c0341432SJohn Baldwin if (error) 1598c0341432SJohn Baldwin swcr_freesession(dev, cses); 1599c0341432SJohn Baldwin return (error); 1600c0341432SJohn Baldwin } 1601c0341432SJohn Baldwin 1602c0341432SJohn Baldwin static void 1603c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses) 1604c0341432SJohn Baldwin { 1605c0341432SJohn Baldwin struct swcr_session *ses; 1606c0341432SJohn Baldwin 1607c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1608c0341432SJohn Baldwin 1609c0341432SJohn Baldwin mtx_destroy(&ses->swcr_lock); 1610c0341432SJohn Baldwin 16113e947048SJohn Baldwin zfree(ses->swcr_encdec.sw_kschedule, M_CRYPTO_DATA); 16124a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA); 16134a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA); 1614091d81d1SSam Leffler } 1615091d81d1SSam Leffler 1616091d81d1SSam Leffler /* 1617091d81d1SSam Leffler * Process a software request. 1618091d81d1SSam Leffler */ 1619091d81d1SSam Leffler static int 16206810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1621091d81d1SSam Leffler { 1622c0341432SJohn Baldwin struct swcr_session *ses; 1623091d81d1SSam Leffler 16241b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1625a7fcb1afSSean Eric Fagan mtx_lock(&ses->swcr_lock); 1626091d81d1SSam Leffler 1627c0341432SJohn Baldwin crp->crp_etype = ses->swcr_process(ses, crp); 1628091d81d1SSam Leffler 1629a7fcb1afSSean Eric Fagan mtx_unlock(&ses->swcr_lock); 1630091d81d1SSam Leffler crypto_done(crp); 1631c0341432SJohn Baldwin return (0); 1632091d81d1SSam Leffler } 1633091d81d1SSam Leffler 1634091d81d1SSam Leffler static void 16353f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1636091d81d1SSam Leffler { 16376810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 16386810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 163986c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 16406810ad6fSSam Leffler panic("cryptosoft: could not attach"); 16416810ad6fSSam Leffler } 1642f6c4bc3bSPawel Jakub Dawidek 16436810ad6fSSam Leffler static int 16446810ad6fSSam Leffler swcr_probe(device_t dev) 16456810ad6fSSam Leffler { 16466810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 16474fc60fa9SMark Johnston device_quiet(dev); 164886c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 16496810ad6fSSam Leffler } 1650f6c4bc3bSPawel Jakub Dawidek 16516810ad6fSSam Leffler static int 16526810ad6fSSam Leffler swcr_attach(device_t dev) 16536810ad6fSSam Leffler { 16546810ad6fSSam Leffler 16559ebbebe4SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), 16566810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 16576810ad6fSSam Leffler if (swcr_id < 0) { 16586810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 1659c0341432SJohn Baldwin return (ENXIO); 16606810ad6fSSam Leffler } 16616810ad6fSSam Leffler 1662c0341432SJohn Baldwin return (0); 1663091d81d1SSam Leffler } 16644b465da2SPawel Jakub Dawidek 16653f147ab2SWarner Losh static int 16666810ad6fSSam Leffler swcr_detach(device_t dev) 16674b465da2SPawel Jakub Dawidek { 16686810ad6fSSam Leffler crypto_unregister_all(swcr_id); 16693f147ab2SWarner Losh return 0; 16704b465da2SPawel Jakub Dawidek } 16716810ad6fSSam Leffler 16726810ad6fSSam Leffler static device_method_t swcr_methods[] = { 16736810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 16746810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 16756810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 16766810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 16776810ad6fSSam Leffler 1678c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, swcr_probesession), 16796810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 16806810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 16816810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 16826810ad6fSSam Leffler 16836810ad6fSSam Leffler {0, 0}, 16846810ad6fSSam Leffler }; 16856810ad6fSSam Leffler 16866810ad6fSSam Leffler static driver_t swcr_driver = { 16876810ad6fSSam Leffler "cryptosoft", 16886810ad6fSSam Leffler swcr_methods, 16896810ad6fSSam Leffler 0, /* NB: no softc */ 16906810ad6fSSam Leffler }; 16916810ad6fSSam Leffler static devclass_t swcr_devclass; 16926810ad6fSSam Leffler 16936810ad6fSSam Leffler /* 16946810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 16956810ad6fSSam Leffler * get the necessary ordering when built as a loadable 16966810ad6fSSam Leffler * module. This is required because we bundle the crypto 16976810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 16986810ad6fSSam Leffler * normal module dependencies would handle things). 16996810ad6fSSam Leffler */ 17006810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 17016810ad6fSSam Leffler /* XXX where to attach */ 17026810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 17036810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 17046810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1705