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 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> 4408fca7a5SJohn-Mark Gurney #include <sys/endian.h> 4508fca7a5SJohn-Mark Gurney #include <sys/limits.h> 46091d81d1SSam Leffler 47091d81d1SSam Leffler #include <crypto/sha1.h> 48091d81d1SSam Leffler #include <opencrypto/rmd160.h> 49091d81d1SSam Leffler 50091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 51091d81d1SSam Leffler #include <opencrypto/xform.h> 52091d81d1SSam Leffler 536810ad6fSSam Leffler #include <sys/kobj.h> 546810ad6fSSam Leffler #include <sys/bus.h> 556810ad6fSSam Leffler #include "cryptodev_if.h" 56091d81d1SSam Leffler 57c0341432SJohn Baldwin struct swcr_auth { 58c0341432SJohn Baldwin void *sw_ictx; 59c0341432SJohn Baldwin void *sw_octx; 60d8787d4fSMark Johnston const struct auth_hash *sw_axf; 61c0341432SJohn Baldwin uint16_t sw_mlen; 626113a08bSJohn Baldwin bool sw_hmac; 63c0341432SJohn Baldwin }; 64c0341432SJohn Baldwin 65c0341432SJohn Baldwin struct swcr_encdec { 66f313909aSJohn Baldwin void *sw_ctx; 67d8787d4fSMark Johnston const struct enc_xform *sw_exf; 68c0341432SJohn Baldwin }; 69c0341432SJohn Baldwin 70c0341432SJohn Baldwin struct swcr_compdec { 71d8787d4fSMark Johnston const struct comp_algo *sw_cxf; 72c0341432SJohn Baldwin }; 73c0341432SJohn Baldwin 74c0341432SJohn Baldwin struct swcr_session { 75dc475c9bSJohn Baldwin int (*swcr_process)(const struct swcr_session *, struct cryptop *); 76c0341432SJohn Baldwin 77c0341432SJohn Baldwin struct swcr_auth swcr_auth; 78c0341432SJohn Baldwin struct swcr_encdec swcr_encdec; 79c0341432SJohn Baldwin struct swcr_compdec swcr_compdec; 80c0341432SJohn Baldwin }; 81507281e5SSean Eric Fagan 826810ad6fSSam Leffler static int32_t swcr_id; 836810ad6fSSam Leffler 841b0909d5SConrad Meyer static void swcr_freesession(device_t dev, crypto_session_t cses); 85091d81d1SSam Leffler 86c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */ 87c0341432SJohn Baldwin static int 88dc475c9bSJohn Baldwin swcr_null(const struct swcr_session *ses, struct cryptop *crp) 89c0341432SJohn Baldwin { 90c0341432SJohn Baldwin 91c0341432SJohn Baldwin return (0); 92c0341432SJohn Baldwin } 93c0341432SJohn Baldwin 94091d81d1SSam Leffler /* 95091d81d1SSam Leffler * Apply a symmetric encryption/decryption algorithm. 96091d81d1SSam Leffler */ 97091d81d1SSam Leffler static int 98dc475c9bSJohn Baldwin swcr_encdec(const struct swcr_session *ses, struct cryptop *crp) 99091d81d1SSam Leffler { 1002cd83828SJohn Baldwin unsigned char blk[EALG_MAX_BLOCK_LEN]; 101c0341432SJohn Baldwin const struct crypto_session_params *csp; 102d8787d4fSMark Johnston const struct enc_xform *exf; 103b54d1284SJohn Baldwin const struct swcr_encdec *sw; 104b54d1284SJohn Baldwin void *ctx; 105cfb7b942SJohn Baldwin size_t inlen, outlen, todo; 10669e533c3SJohn Baldwin int blksz, resid; 1079c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 10826d292d3SJohn Baldwin const unsigned char *inblk; 10926d292d3SJohn Baldwin unsigned char *outblk; 11008fca7a5SJohn-Mark Gurney int error; 111c0341432SJohn Baldwin bool encrypting; 11208fca7a5SJohn-Mark Gurney 11308fca7a5SJohn-Mark Gurney error = 0; 114091d81d1SSam Leffler 115c0341432SJohn Baldwin sw = &ses->swcr_encdec; 116091d81d1SSam Leffler exf = sw->sw_exf; 1171833d604SJohn Baldwin csp = crypto_get_params(crp->crp_session); 118091d81d1SSam Leffler 119723d8764SJohn Baldwin if (exf->native_blocksize == 0) { 120091d81d1SSam Leffler /* Check for non-padded data */ 121723d8764SJohn Baldwin if ((crp->crp_payload_length % exf->blocksize) != 0) 122723d8764SJohn Baldwin return (EINVAL); 123723d8764SJohn Baldwin 12469e533c3SJohn Baldwin blksz = exf->blocksize; 125723d8764SJohn Baldwin } else 12669e533c3SJohn Baldwin blksz = exf->native_blocksize; 127091d81d1SSam Leffler 128c0341432SJohn Baldwin if (exf == &enc_xform_aes_icm && 129c0341432SJohn Baldwin (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 13008fca7a5SJohn-Mark Gurney return (EINVAL); 13108fca7a5SJohn-Mark Gurney 132b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 133c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) { 134b54d1284SJohn Baldwin error = exf->setkey(ctx, crp->crp_cipher_key, 135b54d1284SJohn Baldwin csp->csp_cipher_klen); 136c740ae4bSPoul-Henning Kamp if (error) 137c740ae4bSPoul-Henning Kamp return (error); 138b54d1284SJohn Baldwin } else 139b54d1284SJohn Baldwin memcpy(ctx, sw->sw_ctx, exf->ctxsize); 140d295bdeeSPawel Jakub Dawidek 1412cd83828SJohn Baldwin crypto_read_iv(crp, blk); 1422cd83828SJohn Baldwin exf->reinit(ctx, blk, csp->csp_ivlen); 143091d81d1SSam Leffler 1449c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1459c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 1469c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 1479c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 1489c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 1499c0e3d3aSJohn Baldwin } else 1509c0e3d3aSJohn Baldwin cc_out = cc_in; 1519c0e3d3aSJohn Baldwin 152c0341432SJohn Baldwin encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); 153091d81d1SSam Leffler 154091d81d1SSam Leffler /* 1559c0e3d3aSJohn Baldwin * Loop through encrypting blocks. 'inlen' is the remaining 1569c0e3d3aSJohn Baldwin * length of the current segment in the input buffer. 1579c0e3d3aSJohn Baldwin * 'outlen' is the remaining length of current segment in the 1589c0e3d3aSJohn Baldwin * output buffer. 159091d81d1SSam Leffler */ 16050722514SMark Johnston inlen = outlen = 0; 16169e533c3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) { 16250722514SMark Johnston if (inlen == 0) 16350722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 16450722514SMark Johnston if (outlen == 0) 16550722514SMark Johnston outblk = crypto_cursor_segment(&cc_out, &outlen); 16650722514SMark Johnston 1679c0e3d3aSJohn Baldwin /* 1689c0e3d3aSJohn Baldwin * If the current block is not contained within the 1699c0e3d3aSJohn Baldwin * current input/output segment, use 'blk' as a local 1709c0e3d3aSJohn Baldwin * buffer. 1719c0e3d3aSJohn Baldwin */ 17269e533c3SJohn Baldwin if (inlen < blksz) { 17369e533c3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 1749c0e3d3aSJohn Baldwin inblk = blk; 17569e533c3SJohn Baldwin inlen = blksz; 176d295bdeeSPawel Jakub Dawidek } 17769e533c3SJohn Baldwin if (outlen < blksz) { 1789c0e3d3aSJohn Baldwin outblk = blk; 17969e533c3SJohn Baldwin outlen = blksz; 180cfb7b942SJohn Baldwin } 181cfb7b942SJohn Baldwin 18269e533c3SJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), blksz); 1839c0e3d3aSJohn Baldwin 1849c0e3d3aSJohn Baldwin if (encrypting) 185cfb7b942SJohn Baldwin exf->encrypt_multi(ctx, inblk, outblk, todo); 1869c0e3d3aSJohn Baldwin else 187cfb7b942SJohn Baldwin exf->decrypt_multi(ctx, inblk, outblk, todo); 188091d81d1SSam Leffler 189cfb7b942SJohn Baldwin if (inblk == blk) { 19086be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 1919c0e3d3aSJohn Baldwin } else { 192cfb7b942SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 193cfb7b942SJohn Baldwin inlen -= todo; 194cfb7b942SJohn Baldwin inblk += todo; 19508fca7a5SJohn-Mark Gurney } 196091d81d1SSam Leffler 197cfb7b942SJohn Baldwin if (outblk == blk) { 19869e533c3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 19986be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2009c0e3d3aSJohn Baldwin } else { 201cfb7b942SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 202cfb7b942SJohn Baldwin outlen -= todo; 203cfb7b942SJohn Baldwin outblk += todo; 204091d81d1SSam Leffler } 205f34a967bSPawel Jakub Dawidek } 206f34a967bSPawel Jakub Dawidek 207723d8764SJohn Baldwin /* Handle trailing partial block for stream ciphers. */ 2089c0e3d3aSJohn Baldwin if (resid > 0) { 209723d8764SJohn Baldwin KASSERT(exf->native_blocksize != 0, 210723d8764SJohn Baldwin ("%s: partial block of %d bytes for cipher %s", 2112cd83828SJohn Baldwin __func__, resid, exf->name)); 21269e533c3SJohn Baldwin KASSERT(resid < blksz, ("%s: partial block too big", __func__)); 213723d8764SJohn Baldwin 21486be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 21586be314dSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 2169c0e3d3aSJohn Baldwin if (inlen < resid) { 2179c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 2189c0e3d3aSJohn Baldwin inblk = blk; 21986be314dSJohn Baldwin } 2209c0e3d3aSJohn Baldwin if (outlen < resid) 2219c0e3d3aSJohn Baldwin outblk = blk; 2229c0e3d3aSJohn Baldwin if (encrypting) 223b54d1284SJohn Baldwin exf->encrypt_last(ctx, inblk, outblk, 2249c0e3d3aSJohn Baldwin resid); 2259c0e3d3aSJohn Baldwin else 226b54d1284SJohn Baldwin exf->decrypt_last(ctx, inblk, outblk, 2279c0e3d3aSJohn Baldwin resid); 2289c0e3d3aSJohn Baldwin if (outlen < resid) 2299c0e3d3aSJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 230723d8764SJohn Baldwin } 231723d8764SJohn Baldwin 232b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 23320c128daSJohn Baldwin explicit_bzero(blk, sizeof(blk)); 2349c0e3d3aSJohn Baldwin return (0); 235091d81d1SSam Leffler } 236091d81d1SSam Leffler 237091d81d1SSam Leffler /* 238c0341432SJohn Baldwin * Compute or verify hash. 239091d81d1SSam Leffler */ 240091d81d1SSam Leffler static int 241dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp) 242091d81d1SSam Leffler { 2437051c579SJohn Baldwin struct { 2447051c579SJohn Baldwin union authctx ctx; 245c0341432SJohn Baldwin u_char aalg[HASH_MAX_LEN]; 2467051c579SJohn Baldwin u_char uaalg[HASH_MAX_LEN]; 2477051c579SJohn Baldwin } s; 248c0341432SJohn Baldwin const struct crypto_session_params *csp; 2496113a08bSJohn Baldwin const struct swcr_auth *sw; 250d8787d4fSMark Johnston const struct auth_hash *axf; 251091d81d1SSam Leffler int err; 252091d81d1SSam Leffler 253c0341432SJohn Baldwin sw = &ses->swcr_auth; 254091d81d1SSam Leffler 255091d81d1SSam Leffler axf = sw->sw_axf; 256091d81d1SSam Leffler 257c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 2586038018aSMarcin Wojtas if (crp->crp_auth_key != NULL) { 2596113a08bSJohn Baldwin if (sw->sw_hmac) { 2606113a08bSJohn Baldwin hmac_init_ipad(axf, crp->crp_auth_key, 2617051c579SJohn Baldwin csp->csp_auth_klen, &s.ctx); 2626113a08bSJohn Baldwin } else { 2637051c579SJohn Baldwin axf->Init(&s.ctx); 2647051c579SJohn Baldwin axf->Setkey(&s.ctx, crp->crp_auth_key, 265c0341432SJohn Baldwin csp->csp_auth_klen); 26625b7033bSConrad Meyer } 2676113a08bSJohn Baldwin } else 2687051c579SJohn Baldwin memcpy(&s.ctx, sw->sw_ictx, axf->ctxsize); 269091d81d1SSam Leffler 2709b774dc0SJohn Baldwin if (crp->crp_aad != NULL) 2717051c579SJohn Baldwin err = axf->Update(&s.ctx, crp->crp_aad, crp->crp_aad_length); 2729b774dc0SJohn Baldwin else 273c0341432SJohn Baldwin err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 2747051c579SJohn Baldwin axf->Update, &s.ctx); 275091d81d1SSam Leffler if (err) 276e0b155feSJohn Baldwin goto out; 277091d81d1SSam Leffler 2789c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp) && 2799c0e3d3aSJohn Baldwin CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 2809c0e3d3aSJohn Baldwin err = crypto_apply_buf(&crp->crp_obuf, 2819c0e3d3aSJohn Baldwin crp->crp_payload_output_start, crp->crp_payload_length, 2827051c579SJohn Baldwin axf->Update, &s.ctx); 2839c0e3d3aSJohn Baldwin else 2849c0e3d3aSJohn Baldwin err = crypto_apply(crp, crp->crp_payload_start, 2857051c579SJohn Baldwin crp->crp_payload_length, axf->Update, &s.ctx); 286c0341432SJohn Baldwin if (err) 287e0b155feSJohn Baldwin goto out; 288091d81d1SSam Leffler 2896038018aSMarcin Wojtas if (csp->csp_flags & CSP_F_ESN) 2907051c579SJohn Baldwin axf->Update(&s.ctx, crp->crp_esn, 4); 2916038018aSMarcin Wojtas 2927051c579SJohn Baldwin axf->Final(s.aalg, &s.ctx); 2936113a08bSJohn Baldwin if (sw->sw_hmac) { 2946113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) 2956113a08bSJohn Baldwin hmac_init_opad(axf, crp->crp_auth_key, 2967051c579SJohn Baldwin csp->csp_auth_klen, &s.ctx); 2976113a08bSJohn Baldwin else 2987051c579SJohn Baldwin memcpy(&s.ctx, sw->sw_octx, axf->ctxsize); 2997051c579SJohn Baldwin axf->Update(&s.ctx, s.aalg, axf->hashsize); 3007051c579SJohn Baldwin axf->Final(s.aalg, &s.ctx); 301091d81d1SSam Leffler } 302091d81d1SSam Leffler 303c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 3047051c579SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, s.uaalg); 3057051c579SJohn Baldwin if (timingsafe_bcmp(s.aalg, s.uaalg, sw->sw_mlen) != 0) 30620c128daSJohn Baldwin err = EBADMSG; 307c0341432SJohn Baldwin } else { 308091d81d1SSam Leffler /* Inject the authentication data */ 3097051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, s.aalg); 310c0341432SJohn Baldwin } 311e0b155feSJohn Baldwin out: 3127051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 31320c128daSJohn Baldwin return (err); 314091d81d1SSam Leffler } 315091d81d1SSam Leffler 31608fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 31708fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 31808fca7a5SJohn-Mark Gurney 31908fca7a5SJohn-Mark Gurney static int 320dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp) 32108fca7a5SJohn-Mark Gurney { 3227051c579SJohn Baldwin struct { 3237051c579SJohn Baldwin union authctx ctx; 32426d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 32526d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 3267051c579SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 3277051c579SJohn Baldwin } s; 3287051c579SJohn Baldwin u_char *blk = (u_char *)s.blkbuf; 3299c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc; 33026d292d3SJohn Baldwin const u_char *inblk; 3316113a08bSJohn Baldwin const struct swcr_auth *swa; 332d8787d4fSMark Johnston const struct auth_hash *axf; 33308fca7a5SJohn-Mark Gurney uint32_t *blkp; 33486be314dSJohn Baldwin size_t len; 33586be314dSJohn Baldwin int blksz, error, ivlen, resid; 33608fca7a5SJohn-Mark Gurney 337c0341432SJohn Baldwin swa = &ses->swcr_auth; 33808fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 33926d292d3SJohn Baldwin blksz = GMAC_BLOCK_LEN; 34026d292d3SJohn Baldwin KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", 34126d292d3SJohn Baldwin __func__)); 34208fca7a5SJohn-Mark Gurney 3436113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) { 3447051c579SJohn Baldwin axf->Init(&s.ctx); 3457051c579SJohn Baldwin axf->Setkey(&s.ctx, crp->crp_auth_key, 3466113a08bSJohn Baldwin crypto_get_params(crp->crp_session)->csp_auth_klen); 3476113a08bSJohn Baldwin } else 3487051c579SJohn Baldwin memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize); 3496113a08bSJohn Baldwin 35008fca7a5SJohn-Mark Gurney /* Initialize the IV */ 351c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 3521c9b25a5SJohn Baldwin crypto_read_iv(crp, blk); 35308fca7a5SJohn-Mark Gurney 3547051c579SJohn Baldwin axf->Reinit(&s.ctx, blk, ivlen); 3559c0e3d3aSJohn Baldwin crypto_cursor_init(&cc, &crp->crp_buf); 3569c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc, crp->crp_payload_start); 35726d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) { 35886be314dSJohn Baldwin inblk = crypto_cursor_segment(&cc, &len); 35926d292d3SJohn Baldwin if (len >= blksz) { 36026d292d3SJohn Baldwin len = rounddown(MIN(len, resid), blksz); 36126d292d3SJohn Baldwin crypto_cursor_advance(&cc, len); 36226d292d3SJohn Baldwin } else { 36326d292d3SJohn Baldwin len = blksz; 3649c0e3d3aSJohn Baldwin crypto_cursor_copydata(&cc, len, blk); 36526d292d3SJohn Baldwin inblk = blk; 36626d292d3SJohn Baldwin } 3677051c579SJohn Baldwin axf->Update(&s.ctx, inblk, len); 36826d292d3SJohn Baldwin } 36926d292d3SJohn Baldwin if (resid > 0) { 37026d292d3SJohn Baldwin memset(blk, 0, blksz); 37126d292d3SJohn Baldwin crypto_cursor_copydata(&cc, resid, blk); 3727051c579SJohn Baldwin axf->Update(&s.ctx, blk, blksz); 37308fca7a5SJohn-Mark Gurney } 37408fca7a5SJohn-Mark Gurney 37508fca7a5SJohn-Mark Gurney /* length block */ 37626d292d3SJohn Baldwin memset(blk, 0, blksz); 37708fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 378c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 3797051c579SJohn Baldwin axf->Update(&s.ctx, blk, blksz); 380c0341432SJohn Baldwin 381c0341432SJohn Baldwin /* Finalize MAC */ 3827051c579SJohn Baldwin axf->Final(s.tag, &s.ctx); 383c0341432SJohn Baldwin 38420c128daSJohn Baldwin error = 0; 385c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 386c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 3877051c579SJohn Baldwin s.tag2); 3887051c579SJohn Baldwin if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0) 38920c128daSJohn Baldwin error = EBADMSG; 390c0341432SJohn Baldwin } else { 391c0341432SJohn Baldwin /* Inject the authentication data */ 3927051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, s.tag); 393c0341432SJohn Baldwin } 3947051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 39520c128daSJohn Baldwin return (error); 396c0341432SJohn Baldwin } 397c0341432SJohn Baldwin 398c0341432SJohn Baldwin static int 399dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp) 400c0341432SJohn Baldwin { 4017051c579SJohn Baldwin struct { 40226d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 40326d292d3SJohn Baldwin u_char tag[GMAC_DIGEST_LEN]; 4047051c579SJohn Baldwin u_char tag2[GMAC_DIGEST_LEN]; 4057051c579SJohn Baldwin } s; 4067051c579SJohn Baldwin u_char *blk = (u_char *)s.blkbuf; 4079c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 40826d292d3SJohn Baldwin const u_char *inblk; 40926d292d3SJohn Baldwin u_char *outblk; 410a221a8f4SJohn Baldwin size_t inlen, outlen, todo; 411b54d1284SJohn Baldwin const struct swcr_auth *swa; 412b54d1284SJohn Baldwin const struct swcr_encdec *swe; 413d8787d4fSMark Johnston const struct enc_xform *exf; 414b54d1284SJohn Baldwin void *ctx; 415c0341432SJohn Baldwin uint32_t *blkp; 41686be314dSJohn Baldwin int blksz, error, ivlen, r, resid; 417c0341432SJohn Baldwin 418c0341432SJohn Baldwin swa = &ses->swcr_auth; 419c0341432SJohn Baldwin swe = &ses->swcr_encdec; 420c0341432SJohn Baldwin exf = swe->sw_exf; 421ab91fb6cSJohn Baldwin blksz = GMAC_BLOCK_LEN; 422ab91fb6cSJohn Baldwin KASSERT(blksz == exf->native_blocksize, 423723d8764SJohn Baldwin ("%s: blocksize mismatch", __func__)); 424c0341432SJohn Baldwin 425c0341432SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 426c0341432SJohn Baldwin return (EINVAL); 427c0341432SJohn Baldwin 428c0341432SJohn Baldwin ivlen = AES_GCM_IV_LEN; 429c0341432SJohn Baldwin 430b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 431ab91fb6cSJohn Baldwin if (crp->crp_cipher_key != NULL) 432b54d1284SJohn Baldwin exf->setkey(ctx, crp->crp_cipher_key, 433ab91fb6cSJohn Baldwin crypto_get_params(crp->crp_session)->csp_cipher_klen); 434b54d1284SJohn Baldwin else 435b54d1284SJohn Baldwin memcpy(ctx, swe->sw_ctx, exf->ctxsize); 436b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, ivlen); 437c0341432SJohn Baldwin 438c0341432SJohn Baldwin /* Supply MAC with AAD */ 4399b774dc0SJohn Baldwin if (crp->crp_aad != NULL) { 440a221a8f4SJohn Baldwin inlen = rounddown2(crp->crp_aad_length, blksz); 441a221a8f4SJohn Baldwin if (inlen != 0) 442a221a8f4SJohn Baldwin exf->update(ctx, crp->crp_aad, inlen); 443a221a8f4SJohn Baldwin if (crp->crp_aad_length != inlen) { 4449b774dc0SJohn Baldwin memset(blk, 0, blksz); 445a221a8f4SJohn Baldwin memcpy(blk, (char *)crp->crp_aad + inlen, 446a221a8f4SJohn Baldwin crp->crp_aad_length - inlen); 447b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 4489b774dc0SJohn Baldwin } 4499b774dc0SJohn Baldwin } else { 4509c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 4519c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_aad_start); 4529b774dc0SJohn Baldwin for (resid = crp->crp_aad_length; resid >= blksz; 453a221a8f4SJohn Baldwin resid -= inlen) { 454a221a8f4SJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 455a221a8f4SJohn Baldwin if (inlen >= blksz) { 456a221a8f4SJohn Baldwin inlen = rounddown2(MIN(inlen, resid), blksz); 457a221a8f4SJohn Baldwin crypto_cursor_advance(&cc_in, inlen); 45826d292d3SJohn Baldwin } else { 459a221a8f4SJohn Baldwin inlen = blksz; 460a221a8f4SJohn Baldwin crypto_cursor_copydata(&cc_in, inlen, blk); 46126d292d3SJohn Baldwin inblk = blk; 46226d292d3SJohn Baldwin } 463a221a8f4SJohn Baldwin exf->update(ctx, inblk, inlen); 46426d292d3SJohn Baldwin } 46526d292d3SJohn Baldwin if (resid > 0) { 46626d292d3SJohn Baldwin memset(blk, 0, blksz); 46726d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 468b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 469c0341432SJohn Baldwin } 4709b774dc0SJohn Baldwin } 471c0341432SJohn Baldwin 472c0341432SJohn Baldwin /* Do encryption with MAC */ 4739c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 4749c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 4759c0e3d3aSJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 4769c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 4779c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 4789c0e3d3aSJohn Baldwin } else 4799c0e3d3aSJohn Baldwin cc_out = cc_in; 48050722514SMark Johnston 48150722514SMark Johnston inlen = outlen = 0; 48250722514SMark Johnston for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) { 48350722514SMark Johnston if (inlen == 0) 48450722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 48550722514SMark Johnston if (outlen == 0) 486a221a8f4SJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 487a221a8f4SJohn Baldwin 488a221a8f4SJohn Baldwin if (inlen < blksz) { 48926d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 49026d292d3SJohn Baldwin inblk = blk; 491a221a8f4SJohn Baldwin inlen = blksz; 492c0341432SJohn Baldwin } 493a221a8f4SJohn Baldwin 49426d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 495a221a8f4SJohn Baldwin if (outlen < blksz) { 49626d292d3SJohn Baldwin outblk = blk; 497a221a8f4SJohn Baldwin outlen = blksz; 498a221a8f4SJohn Baldwin } 499a221a8f4SJohn Baldwin 500a221a8f4SJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 501a221a8f4SJohn Baldwin blksz); 502a221a8f4SJohn Baldwin 503a221a8f4SJohn Baldwin exf->encrypt_multi(ctx, inblk, outblk, todo); 504a221a8f4SJohn Baldwin exf->update(ctx, outblk, todo); 505a221a8f4SJohn Baldwin 506a221a8f4SJohn Baldwin if (outblk == blk) { 50726d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 508a221a8f4SJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 50926d292d3SJohn Baldwin } else { 510a221a8f4SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 511a221a8f4SJohn Baldwin outlen -= todo; 512a221a8f4SJohn Baldwin outblk += todo; 513a221a8f4SJohn Baldwin } 514a221a8f4SJohn Baldwin } else { 515a221a8f4SJohn Baldwin todo = rounddown2(MIN(resid, inlen), blksz); 516a221a8f4SJohn Baldwin exf->update(ctx, inblk, todo); 517a221a8f4SJohn Baldwin } 518a221a8f4SJohn Baldwin 519a221a8f4SJohn Baldwin if (inblk == blk) { 520a221a8f4SJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 521a221a8f4SJohn Baldwin } else { 522a221a8f4SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 523a221a8f4SJohn Baldwin inlen -= todo; 524a221a8f4SJohn Baldwin inblk += todo; 52526d292d3SJohn Baldwin } 52626d292d3SJohn Baldwin } 52726d292d3SJohn Baldwin if (resid > 0) { 52826d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 52926d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 530b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 53126d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 53226d292d3SJohn Baldwin } 533b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 534c0341432SJohn Baldwin } 535c0341432SJohn Baldwin 536c0341432SJohn Baldwin /* length block */ 53726d292d3SJohn Baldwin memset(blk, 0, blksz); 538c0341432SJohn Baldwin blkp = (uint32_t *)blk + 1; 539c0341432SJohn Baldwin *blkp = htobe32(crp->crp_aad_length * 8); 540c0341432SJohn Baldwin blkp = (uint32_t *)blk + 3; 541c0341432SJohn Baldwin *blkp = htobe32(crp->crp_payload_length * 8); 542b54d1284SJohn Baldwin exf->update(ctx, blk, blksz); 543c0341432SJohn Baldwin 544c0341432SJohn Baldwin /* Finalize MAC */ 5457051c579SJohn Baldwin exf->final(s.tag, ctx); 546c0341432SJohn Baldwin 547c0341432SJohn Baldwin /* Validate tag */ 54820c128daSJohn Baldwin error = 0; 549c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 5507051c579SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 5517051c579SJohn Baldwin s.tag2); 5527051c579SJohn Baldwin r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen); 55320c128daSJohn Baldwin if (r != 0) { 55420c128daSJohn Baldwin error = EBADMSG; 55520c128daSJohn Baldwin goto out; 55620c128daSJohn Baldwin } 557c0341432SJohn Baldwin 558c0341432SJohn Baldwin /* tag matches, decrypt data */ 5599c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 5609c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 561a221a8f4SJohn Baldwin 56250722514SMark Johnston inlen = 0; 56326d292d3SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 564a221a8f4SJohn Baldwin resid -= todo) { 56550722514SMark Johnston if (inlen == 0) 56650722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 56750722514SMark Johnston if (outlen == 0) 56850722514SMark Johnston outblk = crypto_cursor_segment(&cc_out, &outlen); 569a221a8f4SJohn Baldwin if (inlen < blksz) { 57026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 57126d292d3SJohn Baldwin inblk = blk; 572a221a8f4SJohn Baldwin inlen = blksz; 573a221a8f4SJohn Baldwin } 574a221a8f4SJohn Baldwin if (outlen < blksz) { 57526d292d3SJohn Baldwin outblk = blk; 576a221a8f4SJohn Baldwin outlen = blksz; 577a221a8f4SJohn Baldwin } 578a221a8f4SJohn Baldwin 579a221a8f4SJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 580a221a8f4SJohn Baldwin blksz); 581a221a8f4SJohn Baldwin 582a221a8f4SJohn Baldwin exf->decrypt_multi(ctx, inblk, outblk, todo); 583a221a8f4SJohn Baldwin 584a221a8f4SJohn Baldwin if (inblk == blk) { 585a221a8f4SJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 586a221a8f4SJohn Baldwin } else { 587a221a8f4SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 588a221a8f4SJohn Baldwin inlen -= todo; 589a221a8f4SJohn Baldwin inblk += todo; 590a221a8f4SJohn Baldwin } 591a221a8f4SJohn Baldwin 592a221a8f4SJohn Baldwin if (outblk == blk) { 59326d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 594a221a8f4SJohn Baldwin outblk = crypto_cursor_segment(&cc_out, 595a221a8f4SJohn Baldwin &outlen); 596a221a8f4SJohn Baldwin } else { 597a221a8f4SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 598a221a8f4SJohn Baldwin outlen -= todo; 599a221a8f4SJohn Baldwin outblk += todo; 600a221a8f4SJohn Baldwin } 60126d292d3SJohn Baldwin } 60226d292d3SJohn Baldwin if (resid > 0) { 60326d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 604b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 60526d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 606c0341432SJohn Baldwin } 607c0341432SJohn Baldwin } else { 608c0341432SJohn Baldwin /* Inject the authentication data */ 6097051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, 6107051c579SJohn Baldwin s.tag); 611c0341432SJohn Baldwin } 612c0341432SJohn Baldwin 61320c128daSJohn Baldwin out: 614b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 6157051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 61620c128daSJohn Baldwin 61720c128daSJohn Baldwin return (error); 618c0341432SJohn Baldwin } 619c0341432SJohn Baldwin 6204361c4ebSJohn Baldwin static void 6214361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length, 6224361c4ebSJohn Baldwin u_int data_length, u_int tag_length, uint8_t *b0) 6234361c4ebSJohn Baldwin { 6244361c4ebSJohn Baldwin uint8_t *bp; 6254361c4ebSJohn Baldwin uint8_t flags, L; 6264361c4ebSJohn Baldwin 6274361c4ebSJohn Baldwin KASSERT(nonce_length >= 7 && nonce_length <= 13, 6284361c4ebSJohn Baldwin ("nonce_length must be between 7 and 13 bytes")); 6294361c4ebSJohn Baldwin 6304361c4ebSJohn Baldwin /* 6314361c4ebSJohn Baldwin * Need to determine the L field value. This is the number of 6324361c4ebSJohn Baldwin * bytes needed to specify the length of the message; the length 6334361c4ebSJohn Baldwin * is whatever is left in the 16 bytes after specifying flags and 6344361c4ebSJohn Baldwin * the nonce. 6354361c4ebSJohn Baldwin */ 6364361c4ebSJohn Baldwin L = 15 - nonce_length; 6374361c4ebSJohn Baldwin 6384361c4ebSJohn Baldwin flags = ((aad_length > 0) << 6) + 6394361c4ebSJohn Baldwin (((tag_length - 2) / 2) << 3) + 6404361c4ebSJohn Baldwin L - 1; 6414361c4ebSJohn Baldwin 6424361c4ebSJohn Baldwin /* 6434361c4ebSJohn Baldwin * Now we need to set up the first block, which has flags, nonce, 6444361c4ebSJohn Baldwin * and the message length. 6454361c4ebSJohn Baldwin */ 6464361c4ebSJohn Baldwin b0[0] = flags; 6474361c4ebSJohn Baldwin memcpy(b0 + 1, nonce, nonce_length); 6484361c4ebSJohn Baldwin bp = b0 + 1 + nonce_length; 6494361c4ebSJohn Baldwin 6504361c4ebSJohn Baldwin /* Need to copy L' [aka L-1] bytes of data_length */ 6514361c4ebSJohn Baldwin for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) { 6524361c4ebSJohn Baldwin *dst = data_length; 6534361c4ebSJohn Baldwin data_length >>= 8; 6544361c4ebSJohn Baldwin } 6554361c4ebSJohn Baldwin } 6564361c4ebSJohn Baldwin 6574361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */ 6584361c4ebSJohn Baldwin static int 6594361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk) 6604361c4ebSJohn Baldwin { 6614361c4ebSJohn Baldwin if (aad_length < ((1 << 16) - (1 << 8))) { 6624361c4ebSJohn Baldwin be16enc(blk, aad_length); 6634361c4ebSJohn Baldwin return (sizeof(uint16_t)); 6644361c4ebSJohn Baldwin } else { 6654361c4ebSJohn Baldwin blk[0] = 0xff; 6664361c4ebSJohn Baldwin blk[1] = 0xfe; 6674361c4ebSJohn Baldwin be32enc(blk + 2, aad_length); 6684361c4ebSJohn Baldwin return (2 + sizeof(uint32_t)); 6694361c4ebSJohn Baldwin } 6704361c4ebSJohn Baldwin } 6714361c4ebSJohn Baldwin 672c0341432SJohn Baldwin static int 673dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp) 674c0341432SJohn Baldwin { 6757051c579SJohn Baldwin struct { 6767051c579SJohn Baldwin union authctx ctx; 6774361c4ebSJohn Baldwin u_char blk[CCM_CBC_BLOCK_LEN]; 6784361c4ebSJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 6797051c579SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 6807051c579SJohn Baldwin } s; 681ae18720dSJohn Baldwin const struct crypto_session_params *csp; 6826113a08bSJohn Baldwin const struct swcr_auth *swa; 683d8787d4fSMark Johnston const struct auth_hash *axf; 6844361c4ebSJohn Baldwin int error, ivlen, len; 685c0341432SJohn Baldwin 686ae18720dSJohn Baldwin csp = crypto_get_params(crp->crp_session); 687c0341432SJohn Baldwin swa = &ses->swcr_auth; 688c0341432SJohn Baldwin axf = swa->sw_axf; 689c0341432SJohn Baldwin 6906113a08bSJohn Baldwin if (crp->crp_auth_key != NULL) { 6917051c579SJohn Baldwin axf->Init(&s.ctx); 6927051c579SJohn Baldwin axf->Setkey(&s.ctx, crp->crp_auth_key, csp->csp_auth_klen); 6936113a08bSJohn Baldwin } else 6947051c579SJohn Baldwin memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize); 695c0341432SJohn Baldwin 696c0341432SJohn Baldwin /* Initialize the IV */ 697ae18720dSJohn Baldwin ivlen = csp->csp_ivlen; 698c0341432SJohn Baldwin 6994361c4ebSJohn Baldwin /* Supply MAC with IV */ 7007051c579SJohn Baldwin axf->Reinit(&s.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, 7047051c579SJohn Baldwin swa->sw_mlen, s.blk); 7057051c579SJohn Baldwin axf->Update(&s.ctx, s.blk, CCM_CBC_BLOCK_LEN); 7064361c4ebSJohn Baldwin 7077051c579SJohn Baldwin len = build_ccm_aad_length(crp->crp_payload_length, s.blk); 7087051c579SJohn Baldwin axf->Update(&s.ctx, s.blk, len); 7094361c4ebSJohn Baldwin 7104361c4ebSJohn Baldwin crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, 7117051c579SJohn Baldwin axf->Update, &s.ctx); 712c0341432SJohn Baldwin 713c0341432SJohn Baldwin /* Finalize MAC */ 7147051c579SJohn Baldwin axf->Final(s.tag, &s.ctx); 715c0341432SJohn Baldwin 7164361c4ebSJohn Baldwin error = 0; 717c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 718c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 7197051c579SJohn Baldwin s.tag2); 7207051c579SJohn Baldwin if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0) 72120c128daSJohn Baldwin error = EBADMSG; 722c0341432SJohn Baldwin } else { 723c0341432SJohn Baldwin /* Inject the authentication data */ 7247051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, 7257051c579SJohn Baldwin s.tag); 726c0341432SJohn Baldwin } 7277051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 72820c128daSJohn Baldwin return (error); 729c0341432SJohn Baldwin } 730c0341432SJohn Baldwin 731c0341432SJohn Baldwin static int 732dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp) 733c0341432SJohn Baldwin { 734ae18720dSJohn Baldwin const struct crypto_session_params *csp; 7357051c579SJohn Baldwin struct { 73626d292d3SJohn Baldwin uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; 73726d292d3SJohn Baldwin u_char tag[AES_CBC_MAC_HASH_LEN]; 7387051c579SJohn Baldwin u_char tag2[AES_CBC_MAC_HASH_LEN]; 7397051c579SJohn Baldwin } s; 7407051c579SJohn Baldwin u_char *blk = (u_char *)s.blkbuf; 7419c0e3d3aSJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 74226d292d3SJohn Baldwin const u_char *inblk; 74326d292d3SJohn Baldwin u_char *outblk; 744f8580fcaSJohn Baldwin size_t inlen, outlen, todo; 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. */ 7777051c579SJohn Baldwin _Static_assert(sizeof(s.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; 81050722514SMark Johnston 81150722514SMark Johnston inlen = outlen = 0; 81250722514SMark Johnston for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) { 81350722514SMark Johnston if (inlen == 0) 81450722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 81550722514SMark Johnston if (outlen == 0) 816f8580fcaSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 817f8580fcaSJohn Baldwin 818f8580fcaSJohn Baldwin if (inlen < blksz) { 81926d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 82026d292d3SJohn Baldwin inblk = blk; 821f8580fcaSJohn Baldwin inlen = blksz; 822f8580fcaSJohn Baldwin } 823f8580fcaSJohn Baldwin 824c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 825f8580fcaSJohn Baldwin if (outlen < blksz) { 82626d292d3SJohn Baldwin outblk = blk; 827f8580fcaSJohn Baldwin outlen = blksz; 828f8580fcaSJohn Baldwin } 829f8580fcaSJohn Baldwin 830f8580fcaSJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 831f8580fcaSJohn Baldwin blksz); 832f8580fcaSJohn Baldwin 833f8580fcaSJohn Baldwin exf->update(ctx, inblk, todo); 834f8580fcaSJohn Baldwin exf->encrypt_multi(ctx, inblk, outblk, todo); 835f8580fcaSJohn Baldwin 836f8580fcaSJohn Baldwin if (outblk == blk) { 83726d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 838f8580fcaSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 839f8580fcaSJohn Baldwin } else { 840f8580fcaSJohn Baldwin crypto_cursor_advance(&cc_out, todo); 841f8580fcaSJohn Baldwin outlen -= todo; 842f8580fcaSJohn Baldwin outblk += todo; 843f8580fcaSJohn Baldwin } 844c0341432SJohn Baldwin } else { 845c0341432SJohn Baldwin /* 846c0341432SJohn Baldwin * One of the problems with CCM+CBC is that 847c0341432SJohn Baldwin * the authentication is done on the 84826d292d3SJohn Baldwin * unencrypted data. As a result, we have to 849c0341432SJohn Baldwin * decrypt the data twice: once to generate 850c0341432SJohn Baldwin * the tag and a second time after the tag is 851c0341432SJohn Baldwin * verified. 852c0341432SJohn Baldwin */ 853f8580fcaSJohn Baldwin todo = blksz; 854b54d1284SJohn Baldwin exf->decrypt(ctx, inblk, blk); 855f8580fcaSJohn Baldwin exf->update(ctx, blk, todo); 856f8580fcaSJohn Baldwin } 857f8580fcaSJohn Baldwin 858f8580fcaSJohn Baldwin if (inblk == blk) { 859f8580fcaSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 860f8580fcaSJohn Baldwin } else { 861f8580fcaSJohn Baldwin crypto_cursor_advance(&cc_in, todo); 862f8580fcaSJohn Baldwin inlen -= todo; 863f8580fcaSJohn Baldwin inblk += todo; 86426d292d3SJohn Baldwin } 86526d292d3SJohn Baldwin } 86626d292d3SJohn Baldwin if (resid > 0) { 86726d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 86826d292d3SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 869b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 870b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 87126d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 87226d292d3SJohn Baldwin } else { 873b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 874b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 875c0341432SJohn Baldwin } 87608fca7a5SJohn-Mark Gurney } 87708fca7a5SJohn-Mark Gurney 87808fca7a5SJohn-Mark Gurney /* Finalize MAC */ 8797051c579SJohn Baldwin exf->final(s.tag, ctx); 88008fca7a5SJohn-Mark Gurney 88108fca7a5SJohn-Mark Gurney /* Validate tag */ 88220c128daSJohn Baldwin error = 0; 883c0341432SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 884c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 8857051c579SJohn Baldwin s.tag2); 8867051c579SJohn Baldwin r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen); 88720c128daSJohn Baldwin if (r != 0) { 88820c128daSJohn Baldwin error = EBADMSG; 88920c128daSJohn Baldwin goto out; 89020c128daSJohn Baldwin } 891c0341432SJohn Baldwin 89208fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 893b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, ivlen); 8949c0e3d3aSJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 8959c0e3d3aSJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 896f8580fcaSJohn Baldwin 89750722514SMark Johnston inlen = 0; 898f8580fcaSJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; 899f8580fcaSJohn Baldwin resid -= todo) { 90050722514SMark Johnston if (inlen == 0) 90150722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 90250722514SMark Johnston if (outlen == 0) 90350722514SMark Johnston outblk = crypto_cursor_segment(&cc_out, 90450722514SMark Johnston &outlen); 90550722514SMark Johnston 906f8580fcaSJohn Baldwin if (inlen < blksz) { 90726d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 90826d292d3SJohn Baldwin inblk = blk; 909f8580fcaSJohn Baldwin inlen = blksz; 910f8580fcaSJohn Baldwin } 911f8580fcaSJohn Baldwin if (outlen < blksz) { 91226d292d3SJohn Baldwin outblk = blk; 913f8580fcaSJohn Baldwin outlen = blksz; 914f8580fcaSJohn Baldwin } 915f8580fcaSJohn Baldwin 916f8580fcaSJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 917f8580fcaSJohn Baldwin blksz); 918f8580fcaSJohn Baldwin 919f8580fcaSJohn Baldwin exf->decrypt_multi(ctx, inblk, outblk, todo); 920f8580fcaSJohn Baldwin 921f8580fcaSJohn Baldwin if (inblk == blk) { 922f8580fcaSJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 923f8580fcaSJohn Baldwin } else { 924f8580fcaSJohn Baldwin crypto_cursor_advance(&cc_in, todo); 925f8580fcaSJohn Baldwin inlen -= todo; 926f8580fcaSJohn Baldwin inblk += todo; 927f8580fcaSJohn Baldwin } 928f8580fcaSJohn Baldwin 929f8580fcaSJohn Baldwin if (outblk == blk) { 93026d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 931f8580fcaSJohn Baldwin outblk = crypto_cursor_segment(&cc_out, 932f8580fcaSJohn Baldwin &outlen); 933f8580fcaSJohn Baldwin } else { 934f8580fcaSJohn Baldwin crypto_cursor_advance(&cc_out, todo); 935f8580fcaSJohn Baldwin outlen -= todo; 936f8580fcaSJohn Baldwin outblk += todo; 937f8580fcaSJohn Baldwin } 93826d292d3SJohn Baldwin } 93926d292d3SJohn Baldwin if (resid > 0) { 94026d292d3SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 941b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 94226d292d3SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 94308fca7a5SJohn-Mark Gurney } 94408fca7a5SJohn-Mark Gurney } else { 94508fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 9467051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, 9477051c579SJohn Baldwin s.tag); 94808fca7a5SJohn-Mark Gurney } 94908fca7a5SJohn-Mark Gurney 95020c128daSJohn Baldwin out: 951b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 9527051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 95320c128daSJohn Baldwin return (error); 95408fca7a5SJohn-Mark Gurney } 95508fca7a5SJohn-Mark Gurney 956dd2e1352SJohn Baldwin static int 957dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp) 958dd2e1352SJohn Baldwin { 959dd2e1352SJohn Baldwin const struct crypto_session_params *csp; 9607051c579SJohn Baldwin struct { 961dd2e1352SJohn Baldwin uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; 962dd2e1352SJohn Baldwin u_char tag[POLY1305_HASH_LEN]; 9637051c579SJohn Baldwin u_char tag2[POLY1305_HASH_LEN]; 9647051c579SJohn Baldwin } s; 9657051c579SJohn Baldwin u_char *blk = (u_char *)s.blkbuf; 966dd2e1352SJohn Baldwin struct crypto_buffer_cursor cc_in, cc_out; 967dd2e1352SJohn Baldwin const u_char *inblk; 968dd2e1352SJohn Baldwin u_char *outblk; 9695022c687SJohn Baldwin size_t inlen, outlen, todo; 970dd2e1352SJohn Baldwin uint64_t *blkp; 971b54d1284SJohn Baldwin const struct swcr_auth *swa; 972b54d1284SJohn Baldwin const struct swcr_encdec *swe; 973d8787d4fSMark Johnston const struct enc_xform *exf; 974b54d1284SJohn Baldwin void *ctx; 975dd2e1352SJohn Baldwin int blksz, error, r, resid; 976dd2e1352SJohn Baldwin 977dd2e1352SJohn Baldwin swa = &ses->swcr_auth; 978dd2e1352SJohn Baldwin swe = &ses->swcr_encdec; 979dd2e1352SJohn Baldwin exf = swe->sw_exf; 980dd2e1352SJohn Baldwin blksz = exf->native_blocksize; 9817051c579SJohn Baldwin KASSERT(blksz <= sizeof(s.blkbuf), ("%s: blocksize mismatch", __func__)); 982dd2e1352SJohn Baldwin 983dd2e1352SJohn Baldwin if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) 984dd2e1352SJohn Baldwin return (EINVAL); 985dd2e1352SJohn Baldwin 986dd2e1352SJohn Baldwin csp = crypto_get_params(crp->crp_session); 987dd2e1352SJohn Baldwin 988b54d1284SJohn Baldwin ctx = __builtin_alloca(exf->ctxsize); 989dd2e1352SJohn Baldwin if (crp->crp_cipher_key != NULL) 990b54d1284SJohn Baldwin exf->setkey(ctx, crp->crp_cipher_key, 991dd2e1352SJohn Baldwin csp->csp_cipher_klen); 992b54d1284SJohn Baldwin else 993b54d1284SJohn Baldwin memcpy(ctx, swe->sw_ctx, exf->ctxsize); 994b54d1284SJohn Baldwin exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen); 995dd2e1352SJohn Baldwin 996ab91fb6cSJohn Baldwin /* Supply MAC with AAD */ 997ab91fb6cSJohn Baldwin if (crp->crp_aad != NULL) 998b54d1284SJohn Baldwin exf->update(ctx, crp->crp_aad, crp->crp_aad_length); 999ab91fb6cSJohn Baldwin else 1000b54d1284SJohn Baldwin crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length, 1001b54d1284SJohn Baldwin exf->update, ctx); 100204781697SJohn Baldwin if (crp->crp_aad_length % POLY1305_BLOCK_LEN != 0) { 1003ab91fb6cSJohn Baldwin /* padding1 */ 100404781697SJohn Baldwin memset(blk, 0, POLY1305_BLOCK_LEN); 100504781697SJohn Baldwin exf->update(ctx, blk, POLY1305_BLOCK_LEN - 100604781697SJohn Baldwin crp->crp_aad_length % POLY1305_BLOCK_LEN); 1007ab91fb6cSJohn Baldwin } 1008ab91fb6cSJohn Baldwin 1009dd2e1352SJohn Baldwin /* Do encryption with MAC */ 1010dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1011dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 1012dd2e1352SJohn Baldwin if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { 1013dd2e1352SJohn Baldwin crypto_cursor_init(&cc_out, &crp->crp_obuf); 1014dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); 1015dd2e1352SJohn Baldwin } else 1016dd2e1352SJohn Baldwin cc_out = cc_in; 10175022c687SJohn Baldwin 101850722514SMark Johnston inlen = outlen = 0; 10195022c687SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 10205022c687SJohn Baldwin for (resid = crp->crp_payload_length; resid >= blksz; 10215022c687SJohn Baldwin resid -= todo) { 102250722514SMark Johnston if (inlen == 0) 102350722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 102450722514SMark Johnston if (outlen == 0) 102550722514SMark Johnston outblk = crypto_cursor_segment(&cc_out, 102650722514SMark Johnston &outlen); 102750722514SMark Johnston 10285022c687SJohn Baldwin if (inlen < blksz) { 1029dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 1030dd2e1352SJohn Baldwin inblk = blk; 10315022c687SJohn Baldwin inlen = blksz; 10325022c687SJohn Baldwin } 10335022c687SJohn Baldwin 10345022c687SJohn Baldwin if (outlen < blksz) { 1035dd2e1352SJohn Baldwin outblk = blk; 10365022c687SJohn Baldwin outlen = blksz; 10375022c687SJohn Baldwin } 10385022c687SJohn Baldwin 10395022c687SJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 10405022c687SJohn Baldwin blksz); 10415022c687SJohn Baldwin 10425022c687SJohn Baldwin exf->encrypt_multi(ctx, inblk, outblk, todo); 10435022c687SJohn Baldwin exf->update(ctx, outblk, todo); 10445022c687SJohn Baldwin 10455022c687SJohn Baldwin if (inblk == blk) { 10465022c687SJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 1047dd2e1352SJohn Baldwin } else { 10485022c687SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 10495022c687SJohn Baldwin inlen -= todo; 10505022c687SJohn Baldwin inblk += todo; 10515022c687SJohn Baldwin } 10525022c687SJohn Baldwin 10535022c687SJohn Baldwin if (outblk == blk) { 10545022c687SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 10555022c687SJohn Baldwin outblk = crypto_cursor_segment(&cc_out, &outlen); 10565022c687SJohn Baldwin } else { 10575022c687SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 10585022c687SJohn Baldwin outlen -= todo; 10595022c687SJohn Baldwin outblk += todo; 1060dd2e1352SJohn Baldwin } 1061dd2e1352SJohn Baldwin } 1062dd2e1352SJohn Baldwin if (resid > 0) { 1063dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 1064b54d1284SJohn Baldwin exf->encrypt_last(ctx, blk, blk, resid); 1065dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 1066b54d1284SJohn Baldwin exf->update(ctx, blk, resid); 10675022c687SJohn Baldwin } 10685022c687SJohn Baldwin } else 10695022c687SJohn Baldwin crypto_apply(crp, crp->crp_payload_start, 10705022c687SJohn Baldwin crp->crp_payload_length, exf->update, ctx); 10715022c687SJohn Baldwin if (crp->crp_payload_length % POLY1305_BLOCK_LEN != 0) { 1072dd2e1352SJohn Baldwin /* padding2 */ 107304781697SJohn Baldwin memset(blk, 0, POLY1305_BLOCK_LEN); 107404781697SJohn Baldwin exf->update(ctx, blk, POLY1305_BLOCK_LEN - 10755022c687SJohn Baldwin crp->crp_payload_length % POLY1305_BLOCK_LEN); 1076dd2e1352SJohn Baldwin } 1077dd2e1352SJohn Baldwin 1078dd2e1352SJohn Baldwin /* lengths */ 1079dd2e1352SJohn Baldwin blkp = (uint64_t *)blk; 1080dd2e1352SJohn Baldwin blkp[0] = htole64(crp->crp_aad_length); 1081dd2e1352SJohn Baldwin blkp[1] = htole64(crp->crp_payload_length); 1082b54d1284SJohn Baldwin exf->update(ctx, blk, sizeof(uint64_t) * 2); 1083dd2e1352SJohn Baldwin 1084dd2e1352SJohn Baldwin /* Finalize MAC */ 10857051c579SJohn Baldwin exf->final(s.tag, ctx); 1086dd2e1352SJohn Baldwin 1087dd2e1352SJohn Baldwin /* Validate tag */ 1088dd2e1352SJohn Baldwin error = 0; 1089dd2e1352SJohn Baldwin if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 10907051c579SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, 10917051c579SJohn Baldwin s.tag2); 10927051c579SJohn Baldwin r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen); 1093dd2e1352SJohn Baldwin if (r != 0) { 1094dd2e1352SJohn Baldwin error = EBADMSG; 1095dd2e1352SJohn Baldwin goto out; 1096dd2e1352SJohn Baldwin } 1097dd2e1352SJohn Baldwin 1098dd2e1352SJohn Baldwin /* tag matches, decrypt data */ 1099dd2e1352SJohn Baldwin crypto_cursor_init(&cc_in, &crp->crp_buf); 1100dd2e1352SJohn Baldwin crypto_cursor_advance(&cc_in, crp->crp_payload_start); 11015022c687SJohn Baldwin 110250722514SMark Johnston inlen = 0; 1103dd2e1352SJohn Baldwin for (resid = crp->crp_payload_length; resid > blksz; 11045022c687SJohn Baldwin resid -= todo) { 110550722514SMark Johnston if (inlen == 0) 110650722514SMark Johnston inblk = crypto_cursor_segment(&cc_in, &inlen); 110750722514SMark Johnston if (outlen == 0) 110850722514SMark Johnston outblk = crypto_cursor_segment(&cc_out, 110950722514SMark Johnston &outlen); 11105022c687SJohn Baldwin if (inlen < blksz) { 1111dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, blksz, blk); 1112dd2e1352SJohn Baldwin inblk = blk; 11135022c687SJohn Baldwin inlen = blksz; 11145022c687SJohn Baldwin } 11155022c687SJohn Baldwin if (outlen < blksz) { 1116dd2e1352SJohn Baldwin outblk = blk; 11175022c687SJohn Baldwin outlen = blksz; 11185022c687SJohn Baldwin } 11195022c687SJohn Baldwin 11205022c687SJohn Baldwin todo = rounddown2(MIN(resid, MIN(inlen, outlen)), 11215022c687SJohn Baldwin blksz); 11225022c687SJohn Baldwin 11235022c687SJohn Baldwin exf->decrypt_multi(ctx, inblk, outblk, todo); 11245022c687SJohn Baldwin 11255022c687SJohn Baldwin if (inblk == blk) { 11265022c687SJohn Baldwin inblk = crypto_cursor_segment(&cc_in, &inlen); 11275022c687SJohn Baldwin } else { 11285022c687SJohn Baldwin crypto_cursor_advance(&cc_in, todo); 11295022c687SJohn Baldwin inlen -= todo; 11305022c687SJohn Baldwin inblk += todo; 11315022c687SJohn Baldwin } 11325022c687SJohn Baldwin 11335022c687SJohn Baldwin if (outblk == blk) { 1134dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, blksz, blk); 11355022c687SJohn Baldwin outblk = crypto_cursor_segment(&cc_out, 11365022c687SJohn Baldwin &outlen); 11375022c687SJohn Baldwin } else { 11385022c687SJohn Baldwin crypto_cursor_advance(&cc_out, todo); 11395022c687SJohn Baldwin outlen -= todo; 11405022c687SJohn Baldwin outblk += todo; 11415022c687SJohn Baldwin } 1142dd2e1352SJohn Baldwin } 1143dd2e1352SJohn Baldwin if (resid > 0) { 1144dd2e1352SJohn Baldwin crypto_cursor_copydata(&cc_in, resid, blk); 1145b54d1284SJohn Baldwin exf->decrypt_last(ctx, blk, blk, resid); 1146dd2e1352SJohn Baldwin crypto_cursor_copyback(&cc_out, resid, blk); 1147dd2e1352SJohn Baldwin } 1148dd2e1352SJohn Baldwin } else { 1149dd2e1352SJohn Baldwin /* Inject the authentication data */ 11507051c579SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, 11517051c579SJohn Baldwin s.tag); 1152dd2e1352SJohn Baldwin } 1153dd2e1352SJohn Baldwin 1154dd2e1352SJohn Baldwin out: 1155b54d1284SJohn Baldwin explicit_bzero(ctx, exf->ctxsize); 11567051c579SJohn Baldwin explicit_bzero(&s, sizeof(s)); 1157dd2e1352SJohn Baldwin return (error); 1158dd2e1352SJohn Baldwin } 1159dd2e1352SJohn Baldwin 1160091d81d1SSam Leffler /* 1161c0341432SJohn Baldwin * Apply a cipher and a digest to perform EtA. 1162c0341432SJohn Baldwin */ 1163c0341432SJohn Baldwin static int 1164dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp) 1165c0341432SJohn Baldwin { 1166c0341432SJohn Baldwin int error; 1167c0341432SJohn Baldwin 1168c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1169c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1170c0341432SJohn Baldwin if (error == 0) 1171c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1172c0341432SJohn Baldwin } else { 1173c0341432SJohn Baldwin error = swcr_authcompute(ses, crp); 1174c0341432SJohn Baldwin if (error == 0) 1175c0341432SJohn Baldwin error = swcr_encdec(ses, crp); 1176c0341432SJohn Baldwin } 1177c0341432SJohn Baldwin return (error); 1178c0341432SJohn Baldwin } 1179c0341432SJohn Baldwin 1180c0341432SJohn Baldwin /* 1181091d81d1SSam Leffler * Apply a compression/decompression algorithm 1182091d81d1SSam Leffler */ 1183091d81d1SSam Leffler static int 1184dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp) 1185091d81d1SSam Leffler { 1186d8787d4fSMark Johnston const struct comp_algo *cxf; 1187d3d79e96SJohn Baldwin uint8_t *data, *out; 1188091d81d1SSam Leffler int adj; 1189d3d79e96SJohn Baldwin uint32_t result; 1190091d81d1SSam Leffler 1191c0341432SJohn Baldwin cxf = ses->swcr_compdec.sw_cxf; 1192091d81d1SSam Leffler 1193091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 1194091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 1195091d81d1SSam Leffler * copy in a buffer. 1196091d81d1SSam Leffler */ 1197091d81d1SSam Leffler 1198c0341432SJohn Baldwin data = malloc(crp->crp_payload_length, M_CRYPTO_DATA, M_NOWAIT); 1199091d81d1SSam Leffler if (data == NULL) 1200091d81d1SSam Leffler return (EINVAL); 1201c0341432SJohn Baldwin crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length, 1202c0341432SJohn Baldwin data); 1203091d81d1SSam Leffler 1204c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) 1205c0341432SJohn Baldwin result = cxf->compress(data, crp->crp_payload_length, &out); 1206091d81d1SSam Leffler else 1207c0341432SJohn Baldwin result = cxf->decompress(data, crp->crp_payload_length, &out); 1208091d81d1SSam Leffler 12091ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 1210091d81d1SSam Leffler if (result == 0) 1211c0341432SJohn Baldwin return (EINVAL); 1212c0341432SJohn Baldwin crp->crp_olen = result; 1213c0341432SJohn Baldwin 1214c0341432SJohn Baldwin /* Check the compressed size when doing compression */ 1215c0341432SJohn Baldwin if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) { 1216c0341432SJohn Baldwin if (result >= crp->crp_payload_length) { 1217c0341432SJohn Baldwin /* Compression was useless, we lost time */ 1218c0341432SJohn Baldwin free(out, M_CRYPTO_DATA); 1219c0341432SJohn Baldwin return (0); 1220c0341432SJohn Baldwin } 1221c0341432SJohn Baldwin } 1222091d81d1SSam Leffler 1223091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 1224091d81d1SSam Leffler * extending the mbuf as necessary. 1225091d81d1SSam Leffler */ 1226c0341432SJohn Baldwin crypto_copyback(crp, crp->crp_payload_start, result, out); 1227c0341432SJohn Baldwin if (result < crp->crp_payload_length) { 12289c0e3d3aSJohn Baldwin switch (crp->crp_buf.cb_type) { 1229c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 1230883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 1231c0341432SJohn Baldwin adj = result - crp->crp_payload_length; 12329c0e3d3aSJohn Baldwin m_adj(crp->crp_buf.cb_mbuf, adj); 1233c0341432SJohn Baldwin break; 1234c0341432SJohn Baldwin case CRYPTO_BUF_UIO: { 12359c0e3d3aSJohn Baldwin struct uio *uio = crp->crp_buf.cb_uio; 1236091d81d1SSam Leffler int ind; 1237091d81d1SSam Leffler 1238c0341432SJohn Baldwin adj = crp->crp_payload_length - result; 1239091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 1240091d81d1SSam Leffler 1241091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 1242091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 1243091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 1244091d81d1SSam Leffler break; 1245091d81d1SSam Leffler } 1246091d81d1SSam Leffler 1247091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 1248091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 1249091d81d1SSam Leffler ind--; 1250091d81d1SSam Leffler uio->uio_iovcnt--; 1251091d81d1SSam Leffler } 1252091d81d1SSam Leffler } 1253c0341432SJohn Baldwin break; 1254e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 1255e6f6d0c9SAlan Somers adj = crp->crp_payload_length - result; 1256e6f6d0c9SAlan Somers crp->crp_buf.cb_vm_page_len -= adj; 1257e6f6d0c9SAlan Somers break; 12589c0e3d3aSJohn Baldwin default: 12599c0e3d3aSJohn Baldwin break; 1260c0341432SJohn Baldwin } 1261091d81d1SSam Leffler } 12621ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 1263091d81d1SSam Leffler return 0; 1264091d81d1SSam Leffler } 1265091d81d1SSam Leffler 1266091d81d1SSam Leffler static int 12673e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses, 1268c0341432SJohn Baldwin const struct crypto_session_params *csp) 1269091d81d1SSam Leffler { 1270c0341432SJohn Baldwin struct swcr_encdec *swe; 1271d8787d4fSMark Johnston const struct enc_xform *txf; 1272f6c4bc3bSPawel Jakub Dawidek int error; 1273091d81d1SSam Leffler 1274c0341432SJohn Baldwin swe = &ses->swcr_encdec; 1275c0341432SJohn Baldwin txf = crypto_cipher(csp); 1276b54d1284SJohn Baldwin if (csp->csp_cipher_key != NULL) { 12773e947048SJohn Baldwin if (txf->ctxsize != 0) { 1278f313909aSJohn Baldwin swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA, 12793e947048SJohn Baldwin M_NOWAIT); 1280f313909aSJohn Baldwin if (swe->sw_ctx == NULL) 12813e947048SJohn Baldwin return (ENOMEM); 12823e947048SJohn Baldwin } 1283f313909aSJohn Baldwin error = txf->setkey(swe->sw_ctx, 1284c0341432SJohn Baldwin csp->csp_cipher_key, csp->csp_cipher_klen); 1285c0341432SJohn Baldwin if (error) 1286c0341432SJohn Baldwin return (error); 1287091d81d1SSam Leffler } 1288c0341432SJohn Baldwin swe->sw_exf = txf; 1289c0341432SJohn Baldwin return (0); 1290f6c4bc3bSPawel Jakub Dawidek } 1291091d81d1SSam Leffler 1292c0341432SJohn Baldwin static int 1293c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses, 1294c0341432SJohn Baldwin const struct crypto_session_params *csp) 1295c0341432SJohn Baldwin { 1296c0341432SJohn Baldwin struct swcr_auth *swa; 1297d8787d4fSMark Johnston const struct auth_hash *axf; 1298c0341432SJohn Baldwin 1299c0341432SJohn Baldwin swa = &ses->swcr_auth; 1300c0341432SJohn Baldwin 1301c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1302c0341432SJohn Baldwin swa->sw_axf = axf; 1303c0341432SJohn Baldwin if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) 1304c0341432SJohn Baldwin return (EINVAL); 1305c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1306c0341432SJohn Baldwin swa->sw_mlen = axf->hashsize; 1307c0341432SJohn Baldwin else 1308c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 13096113a08bSJohn Baldwin if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) { 13106113a08bSJohn Baldwin swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 13116113a08bSJohn Baldwin M_NOWAIT); 1312c0341432SJohn Baldwin if (swa->sw_ictx == NULL) 1313c0341432SJohn Baldwin return (ENOBUFS); 13146113a08bSJohn Baldwin } 1315c0341432SJohn Baldwin 1316c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1317091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1318c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1319f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1320f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1321f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1322091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 13236113a08bSJohn Baldwin swa->sw_hmac = true; 13246113a08bSJohn Baldwin if (csp->csp_auth_key != NULL) { 13253a0b6a93SJohn Baldwin swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 1326091d81d1SSam Leffler M_NOWAIT); 1327c0341432SJohn Baldwin if (swa->sw_octx == NULL) 1328c0341432SJohn Baldwin return (ENOBUFS); 13296113a08bSJohn Baldwin hmac_init_ipad(axf, csp->csp_auth_key, 13306113a08bSJohn Baldwin csp->csp_auth_klen, swa->sw_ictx); 13316113a08bSJohn Baldwin hmac_init_opad(axf, csp->csp_auth_key, 13326113a08bSJohn Baldwin csp->csp_auth_klen, swa->sw_octx); 1333091d81d1SSam Leffler } 1334091d81d1SSam Leffler break; 1335c3a688efSJohn Baldwin case CRYPTO_RIPEMD160: 1336091d81d1SSam Leffler case CRYPTO_SHA1: 1337c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1338c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1339c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1340c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 1341aa268175SJohn Baldwin case CRYPTO_NULL_HMAC: 1342c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1343c0341432SJohn Baldwin break; 1344c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 13456113a08bSJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 13466113a08bSJohn Baldwin case CRYPTO_POLY1305: 13476113a08bSJohn Baldwin if (csp->csp_auth_key != NULL) { 1348c0341432SJohn Baldwin axf->Init(swa->sw_ictx); 1349c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1350c0341432SJohn Baldwin csp->csp_auth_klen); 13516113a08bSJohn Baldwin } 1352c0341432SJohn Baldwin break; 1353c0341432SJohn Baldwin case CRYPTO_BLAKE2B: 1354c0341432SJohn Baldwin case CRYPTO_BLAKE2S: 1355c0341432SJohn Baldwin /* 1356c0341432SJohn Baldwin * Blake2b and Blake2s support an optional key but do 1357c0341432SJohn Baldwin * not require one. 1358c0341432SJohn Baldwin */ 13596113a08bSJohn Baldwin if (csp->csp_auth_klen == 0) 13606113a08bSJohn Baldwin axf->Init(swa->sw_ictx); 13616113a08bSJohn Baldwin else if (csp->csp_auth_key != NULL) 1362c0341432SJohn Baldwin axf->Setkey(swa->sw_ictx, csp->csp_auth_key, 1363c0341432SJohn Baldwin csp->csp_auth_klen); 13646113a08bSJohn Baldwin break; 13656113a08bSJohn Baldwin } 13666113a08bSJohn Baldwin 13676113a08bSJohn Baldwin if (csp->csp_mode == CSP_MODE_DIGEST) { 13686113a08bSJohn Baldwin switch (csp->csp_auth_alg) { 13696113a08bSJohn Baldwin case CRYPTO_AES_NIST_GMAC: 13706113a08bSJohn Baldwin ses->swcr_process = swcr_gmac; 1371c0341432SJohn Baldwin break; 1372c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1373c0341432SJohn Baldwin ses->swcr_process = swcr_ccm_cbc_mac; 1374c0341432SJohn Baldwin break; 13756113a08bSJohn Baldwin default: 13766113a08bSJohn Baldwin ses->swcr_process = swcr_authcompute; 13776113a08bSJohn Baldwin } 1378091d81d1SSam Leffler } 1379091d81d1SSam Leffler 1380c0341432SJohn Baldwin return (0); 1381c0341432SJohn Baldwin } 138208fca7a5SJohn-Mark Gurney 1383c0341432SJohn Baldwin static int 1384ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses, 1385c0341432SJohn Baldwin const struct crypto_session_params *csp) 1386c0341432SJohn Baldwin { 1387c0341432SJohn Baldwin struct swcr_auth *swa; 1388ab91fb6cSJohn Baldwin int error; 1389c0341432SJohn Baldwin 1390ab91fb6cSJohn Baldwin error = swcr_setup_cipher(ses, csp); 1391ab91fb6cSJohn Baldwin if (error) 1392ab91fb6cSJohn Baldwin return (error); 1393ab91fb6cSJohn Baldwin 1394c0341432SJohn Baldwin swa = &ses->swcr_auth; 1395c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1396ab91fb6cSJohn Baldwin swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize; 1397c0341432SJohn Baldwin else 1398c0341432SJohn Baldwin swa->sw_mlen = csp->csp_auth_mlen; 1399ab91fb6cSJohn Baldwin return (0); 1400dd2e1352SJohn Baldwin } 1401dd2e1352SJohn Baldwin 1402c0341432SJohn Baldwin static bool 1403c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp) 1404109919c6SBenno Rice { 1405d8787d4fSMark Johnston const struct auth_hash *axf; 1406091d81d1SSam Leffler 1407c0341432SJohn Baldwin axf = crypto_auth_hash(csp); 1408c0341432SJohn Baldwin if (axf == NULL) 1409c0341432SJohn Baldwin return (false); 1410c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1411091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1412c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1413f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1414f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1415f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1416091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1417c0341432SJohn Baldwin case CRYPTO_RIPEMD160_HMAC: 1418091d81d1SSam Leffler break; 1419c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1420c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1421c0341432SJohn Baldwin case 128: 1422c0341432SJohn Baldwin case 192: 1423c0341432SJohn Baldwin case 256: 1424c0341432SJohn Baldwin break; 1425c0341432SJohn Baldwin default: 1426c0341432SJohn Baldwin return (false); 1427c0341432SJohn Baldwin } 1428c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1429c0341432SJohn Baldwin return (false); 1430c0341432SJohn Baldwin if (csp->csp_ivlen != AES_GCM_IV_LEN) 1431c0341432SJohn Baldwin return (false); 1432c0341432SJohn Baldwin break; 143325b7033bSConrad Meyer case CRYPTO_POLY1305: 1434c0341432SJohn Baldwin if (csp->csp_auth_klen != POLY1305_KEY_LEN) 1435c0341432SJohn Baldwin return (false); 1436c0341432SJohn Baldwin break; 1437c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1438c0341432SJohn Baldwin switch (csp->csp_auth_klen * 8) { 1439c0341432SJohn Baldwin case 128: 1440c0341432SJohn Baldwin case 192: 1441c0341432SJohn Baldwin case 256: 1442c0341432SJohn Baldwin break; 1443c0341432SJohn Baldwin default: 1444c0341432SJohn Baldwin return (false); 1445c0341432SJohn Baldwin } 1446c0341432SJohn Baldwin if (csp->csp_auth_key == NULL) 1447c0341432SJohn Baldwin return (false); 1448c0341432SJohn Baldwin break; 1449c0341432SJohn Baldwin } 1450c0341432SJohn Baldwin return (true); 1451c0341432SJohn Baldwin } 1452091d81d1SSam Leffler 1453c0341432SJohn Baldwin static bool 1454c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp) 1455c0341432SJohn Baldwin { 1456d8787d4fSMark Johnston const struct enc_xform *txf; 1457c0341432SJohn Baldwin 1458c0341432SJohn Baldwin txf = crypto_cipher(csp); 1459c0341432SJohn Baldwin if (txf == NULL) 1460c0341432SJohn Baldwin return (false); 1461c0341432SJohn Baldwin if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && 1462c0341432SJohn Baldwin txf->ivsize != csp->csp_ivlen) 1463c0341432SJohn Baldwin return (false); 1464c0341432SJohn Baldwin return (true); 1465c0341432SJohn Baldwin } 1466c0341432SJohn Baldwin 14676038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN) 14686038018aSMarcin Wojtas 1469c0341432SJohn Baldwin static int 1470c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp) 1471c0341432SJohn Baldwin { 14726038018aSMarcin Wojtas if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0) 1473c0341432SJohn Baldwin return (EINVAL); 1474c0341432SJohn Baldwin switch (csp->csp_mode) { 1475c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1476c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1477c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1478c0341432SJohn Baldwin break; 1479c0341432SJohn Baldwin default: 1480c0341432SJohn Baldwin return (EINVAL); 14815fbc5b5aSConrad Meyer } 1482091d81d1SSam Leffler break; 1483c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1484c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1485c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1486c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1487dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 14888f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1489c0341432SJohn Baldwin return (EINVAL); 1490c0341432SJohn Baldwin default: 1491c0341432SJohn Baldwin if (!swcr_cipher_supported(csp)) 1492c0341432SJohn Baldwin return (EINVAL); 1493091d81d1SSam Leffler break; 1494091d81d1SSam Leffler } 1495c0341432SJohn Baldwin break; 1496c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1497c0341432SJohn Baldwin if (!swcr_auth_supported(csp)) 1498c0341432SJohn Baldwin return (EINVAL); 1499c0341432SJohn Baldwin break; 1500c0341432SJohn Baldwin case CSP_MODE_AEAD: 1501c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1502c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1503c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1504c172a407SJohn Baldwin switch (csp->csp_cipher_klen * 8) { 1505c172a407SJohn Baldwin case 128: 1506c172a407SJohn Baldwin case 192: 1507c172a407SJohn Baldwin case 256: 1508c172a407SJohn Baldwin break; 1509c172a407SJohn Baldwin default: 1510c172a407SJohn Baldwin return (EINVAL); 1511c172a407SJohn Baldwin } 1512c172a407SJohn Baldwin break; 1513dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 15148f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1515c0341432SJohn Baldwin break; 1516c0341432SJohn Baldwin default: 1517c0341432SJohn Baldwin return (EINVAL); 1518c0341432SJohn Baldwin } 1519c0341432SJohn Baldwin break; 1520c0341432SJohn Baldwin case CSP_MODE_ETA: 1521c0341432SJohn Baldwin /* AEAD algorithms cannot be used for EtA. */ 1522c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1523c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1524c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1525dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 15268f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1527c0341432SJohn Baldwin return (EINVAL); 1528c0341432SJohn Baldwin } 1529c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1530c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1531c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1532c0341432SJohn Baldwin return (EINVAL); 1533c0341432SJohn Baldwin } 1534c0341432SJohn Baldwin 1535c0341432SJohn Baldwin if (!swcr_cipher_supported(csp) || 1536c0341432SJohn Baldwin !swcr_auth_supported(csp)) 1537c0341432SJohn Baldwin return (EINVAL); 1538c0341432SJohn Baldwin break; 1539c0341432SJohn Baldwin default: 1540c0341432SJohn Baldwin return (EINVAL); 1541c0341432SJohn Baldwin } 1542c0341432SJohn Baldwin 1543c0341432SJohn Baldwin return (CRYPTODEV_PROBE_SOFTWARE); 1544c0341432SJohn Baldwin } 1545c0341432SJohn Baldwin 1546c0341432SJohn Baldwin /* 1547c0341432SJohn Baldwin * Generate a new software session. 1548c0341432SJohn Baldwin */ 1549c0341432SJohn Baldwin static int 1550c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses, 1551c0341432SJohn Baldwin const struct crypto_session_params *csp) 1552c0341432SJohn Baldwin { 1553c0341432SJohn Baldwin struct swcr_session *ses; 1554d8787d4fSMark Johnston const struct comp_algo *cxf; 1555c0341432SJohn Baldwin int error; 1556c0341432SJohn Baldwin 1557c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1558c0341432SJohn Baldwin 1559c0341432SJohn Baldwin error = 0; 1560c0341432SJohn Baldwin switch (csp->csp_mode) { 1561c0341432SJohn Baldwin case CSP_MODE_COMPRESS: 1562c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1563c0341432SJohn Baldwin case CRYPTO_DEFLATE_COMP: 1564c0341432SJohn Baldwin cxf = &comp_algo_deflate; 1565c0341432SJohn Baldwin break; 1566c0341432SJohn Baldwin #ifdef INVARIANTS 1567c0341432SJohn Baldwin default: 1568c0341432SJohn Baldwin panic("bad compression algo"); 1569c0341432SJohn Baldwin #endif 1570c0341432SJohn Baldwin } 1571c0341432SJohn Baldwin ses->swcr_compdec.sw_cxf = cxf; 1572c0341432SJohn Baldwin ses->swcr_process = swcr_compdec; 1573c0341432SJohn Baldwin break; 1574c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1575c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1576c0341432SJohn Baldwin case CRYPTO_NULL_CBC: 1577c0341432SJohn Baldwin ses->swcr_process = swcr_null; 1578c0341432SJohn Baldwin break; 1579c0341432SJohn Baldwin #ifdef INVARIANTS 1580c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1581c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1582dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 15838f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1584c0341432SJohn Baldwin panic("bad cipher algo"); 1585c0341432SJohn Baldwin #endif 1586c0341432SJohn Baldwin default: 15873e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1588c0341432SJohn Baldwin if (error == 0) 1589c0341432SJohn Baldwin ses->swcr_process = swcr_encdec; 1590c0341432SJohn Baldwin } 1591c0341432SJohn Baldwin break; 1592c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1593c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1594c0341432SJohn Baldwin break; 1595c0341432SJohn Baldwin case CSP_MODE_AEAD: 1596c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1597c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1598ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1599c0341432SJohn Baldwin if (error == 0) 1600c0341432SJohn Baldwin ses->swcr_process = swcr_gcm; 1601c0341432SJohn Baldwin break; 1602c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1603ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1604c0341432SJohn Baldwin if (error == 0) 1605c0341432SJohn Baldwin ses->swcr_process = swcr_ccm; 1606c0341432SJohn Baldwin break; 1607dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 16088f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1609ab91fb6cSJohn Baldwin error = swcr_setup_aead(ses, csp); 1610dd2e1352SJohn Baldwin if (error == 0) 1611dd2e1352SJohn Baldwin ses->swcr_process = swcr_chacha20_poly1305; 1612dd2e1352SJohn Baldwin break; 1613c0341432SJohn Baldwin #ifdef INVARIANTS 1614c0341432SJohn Baldwin default: 1615c0341432SJohn Baldwin panic("bad aead algo"); 1616c0341432SJohn Baldwin #endif 1617c0341432SJohn Baldwin } 1618c0341432SJohn Baldwin break; 1619c0341432SJohn Baldwin case CSP_MODE_ETA: 1620c0341432SJohn Baldwin #ifdef INVARIANTS 1621c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1622c0341432SJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 1623c0341432SJohn Baldwin case CRYPTO_AES_CCM_16: 1624dd2e1352SJohn Baldwin case CRYPTO_CHACHA20_POLY1305: 16258f35841fSJohn Baldwin case CRYPTO_XCHACHA20_POLY1305: 1626c0341432SJohn Baldwin panic("bad eta cipher algo"); 1627c0341432SJohn Baldwin } 1628c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1629c0341432SJohn Baldwin case CRYPTO_AES_NIST_GMAC: 1630c0341432SJohn Baldwin case CRYPTO_AES_CCM_CBC_MAC: 1631c0341432SJohn Baldwin panic("bad eta auth algo"); 1632c0341432SJohn Baldwin } 1633c0341432SJohn Baldwin #endif 1634c0341432SJohn Baldwin 1635c0341432SJohn Baldwin error = swcr_setup_auth(ses, csp); 1636c0341432SJohn Baldwin if (error) 1637c0341432SJohn Baldwin break; 1638c0341432SJohn Baldwin if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) { 1639c0341432SJohn Baldwin /* Effectively degrade to digest mode. */ 1640c0341432SJohn Baldwin ses->swcr_process = swcr_authcompute; 1641c0341432SJohn Baldwin break; 1642c0341432SJohn Baldwin } 1643c0341432SJohn Baldwin 16443e947048SJohn Baldwin error = swcr_setup_cipher(ses, csp); 1645c0341432SJohn Baldwin if (error == 0) 1646c0341432SJohn Baldwin ses->swcr_process = swcr_eta; 1647c0341432SJohn Baldwin break; 1648c0341432SJohn Baldwin default: 1649c0341432SJohn Baldwin error = EINVAL; 1650c0341432SJohn Baldwin } 1651c0341432SJohn Baldwin 1652c0341432SJohn Baldwin if (error) 1653c0341432SJohn Baldwin swcr_freesession(dev, cses); 1654c0341432SJohn Baldwin return (error); 1655c0341432SJohn Baldwin } 1656c0341432SJohn Baldwin 1657c0341432SJohn Baldwin static void 1658c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses) 1659c0341432SJohn Baldwin { 1660c0341432SJohn Baldwin struct swcr_session *ses; 1661c0341432SJohn Baldwin 1662c0341432SJohn Baldwin ses = crypto_get_driver_session(cses); 1663c0341432SJohn Baldwin 1664f313909aSJohn Baldwin zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA); 16654a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA); 16664a711b8dSJohn Baldwin zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA); 1667091d81d1SSam Leffler } 1668091d81d1SSam Leffler 1669091d81d1SSam Leffler /* 1670091d81d1SSam Leffler * Process a software request. 1671091d81d1SSam Leffler */ 1672091d81d1SSam Leffler static int 16736810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1674091d81d1SSam Leffler { 1675c0341432SJohn Baldwin struct swcr_session *ses; 1676091d81d1SSam Leffler 16771b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1678091d81d1SSam Leffler 1679c0341432SJohn Baldwin crp->crp_etype = ses->swcr_process(ses, crp); 1680091d81d1SSam Leffler 1681091d81d1SSam Leffler crypto_done(crp); 1682c0341432SJohn Baldwin return (0); 1683091d81d1SSam Leffler } 1684091d81d1SSam Leffler 1685091d81d1SSam Leffler static void 16863f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1687091d81d1SSam Leffler { 16886810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 16896810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 169086c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 16916810ad6fSSam Leffler panic("cryptosoft: could not attach"); 16926810ad6fSSam Leffler } 1693f6c4bc3bSPawel Jakub Dawidek 16946810ad6fSSam Leffler static int 16956810ad6fSSam Leffler swcr_probe(device_t dev) 16966810ad6fSSam Leffler { 16976810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 16984fc60fa9SMark Johnston device_quiet(dev); 169986c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 17006810ad6fSSam Leffler } 1701f6c4bc3bSPawel Jakub Dawidek 17026810ad6fSSam Leffler static int 17036810ad6fSSam Leffler swcr_attach(device_t dev) 17046810ad6fSSam Leffler { 17056810ad6fSSam Leffler 17069ebbebe4SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), 17076810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 17086810ad6fSSam Leffler if (swcr_id < 0) { 17096810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 1710c0341432SJohn Baldwin return (ENXIO); 17116810ad6fSSam Leffler } 17126810ad6fSSam Leffler 1713c0341432SJohn Baldwin return (0); 1714091d81d1SSam Leffler } 17154b465da2SPawel Jakub Dawidek 17163f147ab2SWarner Losh static int 17176810ad6fSSam Leffler swcr_detach(device_t dev) 17184b465da2SPawel Jakub Dawidek { 17196810ad6fSSam Leffler crypto_unregister_all(swcr_id); 17203f147ab2SWarner Losh return 0; 17214b465da2SPawel Jakub Dawidek } 17226810ad6fSSam Leffler 17236810ad6fSSam Leffler static device_method_t swcr_methods[] = { 17246810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 17256810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 17266810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 17276810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 17286810ad6fSSam Leffler 1729c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, swcr_probesession), 17306810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 17316810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 17326810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 17336810ad6fSSam Leffler 17346810ad6fSSam Leffler {0, 0}, 17356810ad6fSSam Leffler }; 17366810ad6fSSam Leffler 17376810ad6fSSam Leffler static driver_t swcr_driver = { 17386810ad6fSSam Leffler "cryptosoft", 17396810ad6fSSam Leffler swcr_methods, 17406810ad6fSSam Leffler 0, /* NB: no softc */ 17416810ad6fSSam Leffler }; 17426810ad6fSSam Leffler 17436810ad6fSSam Leffler /* 17446810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 17456810ad6fSSam Leffler * get the necessary ordering when built as a loadable 17466810ad6fSSam Leffler * module. This is required because we bundle the crypto 17476810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 17486810ad6fSSam Leffler * normal module dependencies would handle things). 17496810ad6fSSam Leffler */ 17506810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 17516810ad6fSSam Leffler /* XXX where to attach */ 1752*ab050b2bSJohn Baldwin DRIVER_MODULE(cryptosoft, nexus, swcr_driver, crypto_modevent, NULL); 17536810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 17546810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1755