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
swcr_null(const struct swcr_session * ses,struct cryptop * crp)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
swcr_encdec(const struct swcr_session * ses,struct cryptop * crp)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
swcr_authcompute(const struct swcr_session * ses,struct cryptop * crp)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
swcr_gmac(const struct swcr_session * ses,struct cryptop * crp)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
swcr_gcm(const struct swcr_session * ses,struct cryptop * crp)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
build_ccm_b0(const char * nonce,u_int nonce_length,u_int aad_length,u_int data_length,u_int tag_length,uint8_t * b0)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
build_ccm_aad_length(u_int aad_length,uint8_t * blk)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
swcr_ccm_cbc_mac(const struct swcr_session * ses,struct cryptop * crp)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
swcr_ccm(const struct swcr_session * ses,struct cryptop * crp)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
swcr_chacha20_poly1305(const struct swcr_session * ses,struct cryptop * crp)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
swcr_eta(const struct swcr_session * ses,struct cryptop * crp)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
swcr_compdec(const struct swcr_session * ses,struct cryptop * crp)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
swcr_setup_cipher(struct swcr_session * ses,const struct crypto_session_params * csp)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
swcr_setup_auth(struct swcr_session * ses,const struct crypto_session_params * csp)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
swcr_setup_aead(struct swcr_session * ses,const struct crypto_session_params * csp)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
swcr_auth_supported(const struct crypto_session_params * csp)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
swcr_cipher_supported(const struct crypto_session_params * csp)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
swcr_probesession(device_t dev,const struct crypto_session_params * csp)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
swcr_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)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
swcr_freesession(device_t dev,crypto_session_t cses)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
swcr_process(device_t dev,struct cryptop * crp,int hint)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
swcr_identify(driver_t * drv,device_t parent)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
swcr_probe(device_t dev)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
swcr_attach(device_t dev)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
swcr_detach(device_t dev)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