11160dcf7SMatt Barden /*
21160dcf7SMatt Barden  * This file and its contents are supplied under the terms of the
31160dcf7SMatt Barden  * Common Development and Distribution License ("CDDL"), version 1.0.
41160dcf7SMatt Barden  * You may only use this file in accordance with the terms of version
51160dcf7SMatt Barden  * 1.0 of the CDDL.
61160dcf7SMatt Barden  *
71160dcf7SMatt Barden  * A full copy of the text of the CDDL should have accompanied this
81160dcf7SMatt Barden  * source.  A copy of the CDDL is also available via the Internet at
91160dcf7SMatt Barden  * http://www.illumos.org/license/CDDL.
101160dcf7SMatt Barden  */
111160dcf7SMatt Barden 
121160dcf7SMatt Barden /*
13897907ceSGordon Ross  * Copyright 2017-2021 Tintri by DDN, Inc.  All rights reserved.
14a4568e19SAlexander Stetsenko  * Copyright 2022 RackTop Systems, Inc.
151160dcf7SMatt Barden  */
161160dcf7SMatt Barden 
171160dcf7SMatt Barden /*
181160dcf7SMatt Barden  * Routines for smb3 encryption.
191160dcf7SMatt Barden  */
201160dcf7SMatt Barden 
211160dcf7SMatt Barden #include <smbsrv/smb2_kproto.h>
221160dcf7SMatt Barden #include <smbsrv/smb_kcrypt.h>
231160dcf7SMatt Barden #include <sys/random.h>
241160dcf7SMatt Barden #include <sys/cmn_err.h>
251160dcf7SMatt Barden 
261160dcf7SMatt Barden #define	SMB3_NONCE_OFFS		20
271160dcf7SMatt Barden #define	SMB3_SIG_OFFS		4
281160dcf7SMatt Barden 
291160dcf7SMatt Barden /*
301160dcf7SMatt Barden  * Arbitrary value used to prevent nonce reuse via overflow. Currently
311160dcf7SMatt Barden  * 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
321160dcf7SMatt Barden  * 2^32 concurrent messages when we hit this number.
331160dcf7SMatt Barden  */
341160dcf7SMatt Barden static uint64_t smb3_max_nonce = 0xffffffff00000000ULL;
351160dcf7SMatt Barden 
361160dcf7SMatt Barden /*
371160dcf7SMatt Barden  * Nonce generation based on draft-mcgrew-iv-gen-01
381160dcf7SMatt Barden  * "Generation of Deterministic Initialization Vectors (IVs) and Nonces"
391160dcf7SMatt Barden  *
401160dcf7SMatt Barden  * Generate an 8-byte random salt and a 3-byte random 'fixed' value.
411160dcf7SMatt Barden  * then, nonce = (++counter ^ salt) || fixed
421160dcf7SMatt Barden  *
431160dcf7SMatt Barden  * This protects against nonce-reuse (8-byte counter), as well as known
441160dcf7SMatt Barden  * attacks on reusing nonces with different keys
451160dcf7SMatt Barden  */
461160dcf7SMatt Barden 
471160dcf7SMatt Barden void
smb3_encrypt_init_nonce(smb_user_t * user)481160dcf7SMatt Barden smb3_encrypt_init_nonce(smb_user_t *user)
491160dcf7SMatt Barden {
501160dcf7SMatt Barden 	user->u_nonce_cnt = 0;
511160dcf7SMatt Barden 	(void) random_get_pseudo_bytes(user->u_nonce_fixed,
521160dcf7SMatt Barden 	    sizeof (user->u_nonce_fixed));
531160dcf7SMatt Barden 	(void) random_get_pseudo_bytes((uint8_t *)&user->u_salt,
541160dcf7SMatt Barden 	    sizeof (user->u_salt));
551160dcf7SMatt Barden }
561160dcf7SMatt Barden 
57*4f0ce1daSGordon Ross static int
smb3_encrypt_gen_nonce(smb_user_t * user,uint8_t * buf,size_t len)581160dcf7SMatt Barden smb3_encrypt_gen_nonce(smb_user_t *user, uint8_t *buf, size_t len)
591160dcf7SMatt Barden {
60*4f0ce1daSGordon Ross 	uint64_t cnt;
611160dcf7SMatt Barden 
621160dcf7SMatt Barden 	/*
631160dcf7SMatt Barden 	 * Nonces must be unique per-key for the life of the key.
641160dcf7SMatt Barden 	 * Bail before we roll over to avoid breaking the crypto.
651160dcf7SMatt Barden 	 */
66*4f0ce1daSGordon Ross 	cnt = atomic_inc_64_nv(&user->u_nonce_cnt);
671160dcf7SMatt Barden 	if (cnt > smb3_max_nonce)
681160dcf7SMatt Barden 		return (-1);
691160dcf7SMatt Barden 
701160dcf7SMatt Barden 	cnt ^= user->u_salt;
71*4f0ce1daSGordon Ross 
721160dcf7SMatt Barden 	bcopy((uint8_t *)&cnt, buf, sizeof (cnt));
731160dcf7SMatt Barden 
74*4f0ce1daSGordon Ross 	ASSERT(len <= 16);	// th_nonce
751160dcf7SMatt Barden 	ASSERT(len > sizeof (cnt));
761160dcf7SMatt Barden 	bcopy(user->u_nonce_fixed, buf + sizeof (cnt), len - sizeof (cnt));
771160dcf7SMatt Barden 	return (0);
781160dcf7SMatt Barden }
791160dcf7SMatt Barden 
801160dcf7SMatt Barden int
smb3_encrypt_init_mech(smb_session_t * s)811160dcf7SMatt Barden smb3_encrypt_init_mech(smb_session_t *s)
821160dcf7SMatt Barden {
831160dcf7SMatt Barden 	smb_crypto_mech_t *mech;
841160dcf7SMatt Barden 	int rc;
851160dcf7SMatt Barden 
861160dcf7SMatt Barden 	if (s->enc_mech != NULL)
871160dcf7SMatt Barden 		return (0);
881160dcf7SMatt Barden 
891160dcf7SMatt Barden 	mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
904e065a9fSAlexander Stetsenko 
914e065a9fSAlexander Stetsenko 	switch (s->smb31_enc_cipherid) {
92a4568e19SAlexander Stetsenko 	case SMB3_CIPHER_AES256_GCM:
934e065a9fSAlexander Stetsenko 	case SMB3_CIPHER_AES128_GCM:
944e065a9fSAlexander Stetsenko 		rc = smb3_aes_gcm_getmech(mech);
954e065a9fSAlexander Stetsenko 		break;
96a4568e19SAlexander Stetsenko 	case SMB3_CIPHER_AES256_CCM:
974e065a9fSAlexander Stetsenko 	case SMB3_CIPHER_AES128_CCM:
984e065a9fSAlexander Stetsenko 		rc = smb3_aes_ccm_getmech(mech);
994e065a9fSAlexander Stetsenko 		break;
1004e065a9fSAlexander Stetsenko 	default:
1014e065a9fSAlexander Stetsenko 		rc = -1;
1024e065a9fSAlexander Stetsenko 		break;
1034e065a9fSAlexander Stetsenko 	}
1044e065a9fSAlexander Stetsenko 
1051160dcf7SMatt Barden 	if (rc != 0) {
1061160dcf7SMatt Barden 		kmem_free(mech, sizeof (*mech));
1071160dcf7SMatt Barden 		return (rc);
1081160dcf7SMatt Barden 	}
1091160dcf7SMatt Barden 	s->enc_mech = mech;
1101160dcf7SMatt Barden 
1111160dcf7SMatt Barden 	return (0);
1121160dcf7SMatt Barden }
1131160dcf7SMatt Barden 
1141160dcf7SMatt Barden /*
1151160dcf7SMatt Barden  * Initializes keys/state required for SMB3 Encryption.
1161160dcf7SMatt Barden  * Note: If a failure occurs here, don't fail the request.
1171160dcf7SMatt Barden  * Instead, return an error when we attempt to encrypt/decrypt.
1181160dcf7SMatt Barden  */
1191160dcf7SMatt Barden void
smb3_encrypt_begin(smb_user_t * u,smb_token_t * token)120*4f0ce1daSGordon Ross smb3_encrypt_begin(smb_user_t *u, smb_token_t *token)
1211160dcf7SMatt Barden {
122*4f0ce1daSGordon Ross 	smb_session_t *s = u->u_session;
1231160dcf7SMatt Barden 	struct smb_key *enc_key = &u->u_enc_key;
1241160dcf7SMatt Barden 	struct smb_key *dec_key = &u->u_dec_key;
125a4568e19SAlexander Stetsenko 	uint32_t derived_keylen, input_keylen;
1261160dcf7SMatt Barden 
1271160dcf7SMatt Barden 	/*
1281160dcf7SMatt Barden 	 * In order to enforce encryption, all users need to
1291160dcf7SMatt Barden 	 * have Session.EncryptData properly set, even anon/guest.
1301160dcf7SMatt Barden 	 */
1311160dcf7SMatt Barden 	u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
1321160dcf7SMatt Barden 	enc_key->len = 0;
1331160dcf7SMatt Barden 	dec_key->len = 0;
1341160dcf7SMatt Barden 
1351160dcf7SMatt Barden 	/*
1361160dcf7SMatt Barden 	 * If we don't have a session key, we'll fail later when a
1371160dcf7SMatt Barden 	 * request that requires (en/de)cryption can't be (en/de)crypted.
1381160dcf7SMatt Barden 	 * Also don't bother initializing if we don't have a mechanism.
1391160dcf7SMatt Barden 	 */
1401160dcf7SMatt Barden 	if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
1411160dcf7SMatt Barden 	    s->enc_mech == NULL)
1421160dcf7SMatt Barden 		return;
1431160dcf7SMatt Barden 
1441160dcf7SMatt Barden 	/*
1451160dcf7SMatt Barden 	 * Compute and store the encryption keys, which live in
1461160dcf7SMatt Barden 	 * the user structure.
1471160dcf7SMatt Barden 	 */
1481160dcf7SMatt Barden 
1491160dcf7SMatt Barden 	/*
1501160dcf7SMatt Barden 	 * For SMB3, the encrypt/decrypt keys are derived from
1511160dcf7SMatt Barden 	 * the session key using KDF in counter mode.
152a4568e19SAlexander Stetsenko 	 *
153a4568e19SAlexander Stetsenko 	 * AES256 Keys are derived from the 'FullSessionKey', which is the
154a4568e19SAlexander Stetsenko 	 * entirety of what we got in the token; AES128 Keys are derived from
155a4568e19SAlexander Stetsenko 	 * the 'SessionKey', which is the first 16 bytes of the key we got in
156a4568e19SAlexander Stetsenko 	 * the token.
1571160dcf7SMatt Barden 	 */
1584e065a9fSAlexander Stetsenko 	if (s->dialect >= SMB_VERS_3_11) {
159a4568e19SAlexander Stetsenko 		if (s->smb31_enc_cipherid == SMB3_CIPHER_AES256_GCM ||
160a4568e19SAlexander Stetsenko 		    s->smb31_enc_cipherid == SMB3_CIPHER_AES256_CCM) {
161a4568e19SAlexander Stetsenko 			derived_keylen = AES256_KEY_LENGTH;
162a4568e19SAlexander Stetsenko 			input_keylen = token->tkn_ssnkey.len;
163a4568e19SAlexander Stetsenko 		} else {
164a4568e19SAlexander Stetsenko 			derived_keylen = AES128_KEY_LENGTH;
165a4568e19SAlexander Stetsenko 			input_keylen = MIN(SMB2_SSN_KEYLEN,
166a4568e19SAlexander Stetsenko 			    token->tkn_ssnkey.len);
167a4568e19SAlexander Stetsenko 		}
168a4568e19SAlexander Stetsenko 
169a4568e19SAlexander Stetsenko 		if (smb3_kdf(enc_key->key, derived_keylen,
170a4568e19SAlexander Stetsenko 		    token->tkn_ssnkey.val, input_keylen,
1714e065a9fSAlexander Stetsenko 		    (uint8_t *)"SMBS2CCipherKey", 16,
1724e065a9fSAlexander Stetsenko 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
1734e065a9fSAlexander Stetsenko 			return;
1744e065a9fSAlexander Stetsenko 
175a4568e19SAlexander Stetsenko 		if (smb3_kdf(dec_key->key, derived_keylen,
176a4568e19SAlexander Stetsenko 		    token->tkn_ssnkey.val, input_keylen,
1774e065a9fSAlexander Stetsenko 		    (uint8_t *)"SMBC2SCipherKey", 16,
1784e065a9fSAlexander Stetsenko 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
1794e065a9fSAlexander Stetsenko 			return;
180a4568e19SAlexander Stetsenko 
181a4568e19SAlexander Stetsenko 		enc_key->len = derived_keylen;
182a4568e19SAlexander Stetsenko 		dec_key->len = derived_keylen;
1834e065a9fSAlexander Stetsenko 	} else {
184a4568e19SAlexander Stetsenko 		derived_keylen = AES128_KEY_LENGTH;
185a4568e19SAlexander Stetsenko 		input_keylen = MIN(SMB2_SSN_KEYLEN, token->tkn_ssnkey.len);
186a4568e19SAlexander Stetsenko 
187a4568e19SAlexander Stetsenko 		if (smb3_kdf(enc_key->key, derived_keylen,
188a4568e19SAlexander Stetsenko 		    token->tkn_ssnkey.val, input_keylen,
1894e065a9fSAlexander Stetsenko 		    (uint8_t *)"SMB2AESCCM", 11,
1904e065a9fSAlexander Stetsenko 		    (uint8_t *)"ServerOut", 10) != 0)
1914e065a9fSAlexander Stetsenko 			return;
1924e065a9fSAlexander Stetsenko 
193a4568e19SAlexander Stetsenko 		if (smb3_kdf(dec_key->key, derived_keylen,
194a4568e19SAlexander Stetsenko 		    token->tkn_ssnkey.val, input_keylen,
1954e065a9fSAlexander Stetsenko 		    (uint8_t *)"SMB2AESCCM", 11,
1964e065a9fSAlexander Stetsenko 		    (uint8_t *)"ServerIn ", 10) != 0)
1974e065a9fSAlexander Stetsenko 			return;
198a4568e19SAlexander Stetsenko 
199a4568e19SAlexander Stetsenko 		enc_key->len = derived_keylen;
200a4568e19SAlexander Stetsenko 		dec_key->len = derived_keylen;
2014e065a9fSAlexander Stetsenko 	}
2021160dcf7SMatt Barden 
2031160dcf7SMatt Barden 	smb3_encrypt_init_nonce(u);
204*4f0ce1daSGordon Ross 
205*4f0ce1daSGordon Ross 	/*
206*4f0ce1daSGordon Ross 	 * XXX todo: setup crypto context for enc_key, dec_key.
207*4f0ce1daSGordon Ross 	 * See crypto_create_ctx_template(mech, key, tmpl,...)
208*4f0ce1daSGordon Ross 	 *
209*4f0ce1daSGordon Ross 	 * Will need a new indirect functions eg.
210*4f0ce1daSGordon Ross 	 *	smb3_encrypt_init_templ(s->enc_mech, enc_key);
211*4f0ce1daSGordon Ross 	 *	smb3_encrypt_init_templ(s->enc_mech, dec_key);
212*4f0ce1daSGordon Ross 	 * where struct smb_key gains a new member:
213*4f0ce1daSGordon Ross 	 *	void *template;
214*4f0ce1daSGordon Ross 	 *
215*4f0ce1daSGordon Ross 	 * Already have s->enc_mech from smb3_encrypt_init_mech().
216*4f0ce1daSGordon Ross 	 */
217*4f0ce1daSGordon Ross }
218*4f0ce1daSGordon Ross 
219*4f0ce1daSGordon Ross static int
smb3_decode_tform_header(smb_request_t * sr,struct mbuf_chain * mbc)220*4f0ce1daSGordon Ross smb3_decode_tform_header(smb_request_t *sr, struct mbuf_chain *mbc)
221*4f0ce1daSGordon Ross {
222*4f0ce1daSGordon Ross 	uint32_t protocolid;
223*4f0ce1daSGordon Ross 	uint16_t flags;
224*4f0ce1daSGordon Ross 	int rc;
225*4f0ce1daSGordon Ross 
226*4f0ce1daSGordon Ross 	rc = smb_mbc_decodef(
227*4f0ce1daSGordon Ross 	    mbc, "l16c16cl..wq",
228*4f0ce1daSGordon Ross 	    &protocolid,	/*  l  */
229*4f0ce1daSGordon Ross 	    sr->smb2_sig,	/* 16c */
230*4f0ce1daSGordon Ross 	    sr->th_nonce,	/* 16c */
231*4f0ce1daSGordon Ross 	    &sr->th_msglen,	/* l */
232*4f0ce1daSGordon Ross 	    /* reserved	  .. */
233*4f0ce1daSGordon Ross 	    &flags,		/* w */
234*4f0ce1daSGordon Ross 	    &sr->th_ssnid);	/* q */
235*4f0ce1daSGordon Ross 	if (rc)
236*4f0ce1daSGordon Ross 		return (rc);
237*4f0ce1daSGordon Ross 
238*4f0ce1daSGordon Ross 	/* This was checked in smb2sr_newrq() */
239*4f0ce1daSGordon Ross 	ASSERT3U(protocolid, ==, SMB3_ENCRYPTED_MAGIC);
240*4f0ce1daSGordon Ross 
241*4f0ce1daSGordon Ross 	if (flags != 1) {
242*4f0ce1daSGordon Ross #ifdef DEBUG
243*4f0ce1daSGordon Ross 		cmn_err(CE_NOTE, "flags field not 1: %x", flags);
244*4f0ce1daSGordon Ross #endif
245*4f0ce1daSGordon Ross 		return (-1);
246*4f0ce1daSGordon Ross 	}
247*4f0ce1daSGordon Ross 
248*4f0ce1daSGordon Ross 	return (rc);
249*4f0ce1daSGordon Ross }
250*4f0ce1daSGordon Ross 
251*4f0ce1daSGordon Ross static int
smb3_encode_tform_header(smb_request_t * sr,struct mbuf_chain * mbc)252*4f0ce1daSGordon Ross smb3_encode_tform_header(smb_request_t *sr, struct mbuf_chain *mbc)
253*4f0ce1daSGordon Ross {
254*4f0ce1daSGordon Ross 	int rc;
255*4f0ce1daSGordon Ross 
256*4f0ce1daSGordon Ross 	rc = smb_mbc_encodef(
257*4f0ce1daSGordon Ross 	    mbc, "l16.16clwwq",
258*4f0ce1daSGordon Ross 	    SMB3_ENCRYPTED_MAGIC, /* l */
259*4f0ce1daSGordon Ross 	    /* signature(16)	   16. (filled in later) */
260*4f0ce1daSGordon Ross 	    sr->th_nonce,	/* 16c */
261*4f0ce1daSGordon Ross 	    sr->th_msglen,	/* l */
262*4f0ce1daSGordon Ross 	    0, /* reserved	   w */
263*4f0ce1daSGordon Ross 	    1, /* flags		   w */
264*4f0ce1daSGordon Ross 	    sr->th_ssnid); /* q */
265*4f0ce1daSGordon Ross 
266*4f0ce1daSGordon Ross 	return (rc);
267*4f0ce1daSGordon Ross }
268*4f0ce1daSGordon Ross 
269*4f0ce1daSGordon Ross /*
270*4f0ce1daSGordon Ross  * Get an smb_vdb_t and initialize it.
271*4f0ce1daSGordon Ross  * Free'd via smb_request_free
272*4f0ce1daSGordon Ross  */
273*4f0ce1daSGordon Ross static smb_vdb_t *
smb3_get_vdb(smb_request_t * sr)274*4f0ce1daSGordon Ross smb3_get_vdb(smb_request_t *sr)
275*4f0ce1daSGordon Ross {
276*4f0ce1daSGordon Ross 	smb_vdb_t *vdb;
277*4f0ce1daSGordon Ross 
278*4f0ce1daSGordon Ross 	vdb = smb_srm_zalloc(sr, sizeof (*vdb));
279*4f0ce1daSGordon Ross 	vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
280*4f0ce1daSGordon Ross 	vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
281*4f0ce1daSGordon Ross 	vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
282*4f0ce1daSGordon Ross 	vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
283*4f0ce1daSGordon Ross 
284*4f0ce1daSGordon Ross 	return (vdb);
2851160dcf7SMatt Barden }
2861160dcf7SMatt Barden 
2871160dcf7SMatt Barden /*
288*4f0ce1daSGordon Ross  * Decrypt the request in mbc_in into out_mbc which as been
289*4f0ce1daSGordon Ross  * setup by the caller.  The caller will replace sr->command
290*4f0ce1daSGordon Ross  * with out_mbc if this succeeds, or will free which ever one
291*4f0ce1daSGordon Ross  * ends up not being used as sr->command.
292*4f0ce1daSGordon Ross  *
293*4f0ce1daSGordon Ross  * The encrypted request in in_mbc is left unmodified here,
294*4f0ce1daSGordon Ross  * and free'd by the caller when appropriate.
295*4f0ce1daSGordon Ross  *
296*4f0ce1daSGordon Ross  * Error return values here are just for visibility in dtrace.
297*4f0ce1daSGordon Ross  * Anything non-zero results in a connection drop.
2981160dcf7SMatt Barden  */
2991160dcf7SMatt Barden int
smb3_decrypt_sr(smb_request_t * sr,struct mbuf_chain * in_mbc,struct mbuf_chain * out_mbc)300*4f0ce1daSGordon Ross smb3_decrypt_sr(smb_request_t *sr,
301*4f0ce1daSGordon Ross     struct mbuf_chain *in_mbc,	// transform header + ciphertext
302*4f0ce1daSGordon Ross     struct mbuf_chain *out_mbc)	// cleartext
3031160dcf7SMatt Barden {
304*4f0ce1daSGordon Ross 	smb_enc_ctx_t ctx;
305*4f0ce1daSGordon Ross 	uint8_t th_raw[SMB3_TFORM_HDR_SIZE];
306*4f0ce1daSGordon Ross 	uint8_t *authdata;
307*4f0ce1daSGordon Ross 	size_t authlen;
308*4f0ce1daSGordon Ross 	size_t cipherlen;
309*4f0ce1daSGordon Ross 	smb_vdb_t *in_vdb = NULL;
310*4f0ce1daSGordon Ross 	smb_vdb_t *out_vdb = NULL;
3111160dcf7SMatt Barden 	smb_session_t *s = sr->session;
312*4f0ce1daSGordon Ross 	smb_user_t *u;
313*4f0ce1daSGordon Ross 	struct smb_key *dec_key;
314*4f0ce1daSGordon Ross 	int cnt, rc;
315*4f0ce1daSGordon Ross 	boolean_t gcm;
316*4f0ce1daSGordon Ross 	size_t nonce_size;
317*4f0ce1daSGordon Ross 	uint_t keylen;
3181160dcf7SMatt Barden 
319*4f0ce1daSGordon Ross 	if (s->enc_mech == NULL)
320*4f0ce1daSGordon Ross 		return (SET_ERROR(-1));
3211160dcf7SMatt Barden 
322*4f0ce1daSGordon Ross 	switch (s->smb31_enc_cipherid) {
323*4f0ce1daSGordon Ross 	default:
324*4f0ce1daSGordon Ross 		ASSERT(0);
325*4f0ce1daSGordon Ross 		/* fallthrough */
326*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES128_CCM:	// 1
327*4f0ce1daSGordon Ross 		gcm = B_FALSE;
328*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_CCM_NONCE_SIZE;
329*4f0ce1daSGordon Ross 		keylen = AES128_KEY_LENGTH;
330*4f0ce1daSGordon Ross 		break;
331*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES128_GCM:	// 2
332*4f0ce1daSGordon Ross 		gcm = B_TRUE;
333*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_GCM_NONCE_SIZE;
334*4f0ce1daSGordon Ross 		keylen = AES128_KEY_LENGTH;
335*4f0ce1daSGordon Ross 		break;
336*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES256_CCM:	// 3
337*4f0ce1daSGordon Ross 		gcm = B_FALSE;
338*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_CCM_NONCE_SIZE;
339*4f0ce1daSGordon Ross 		keylen = AES256_KEY_LENGTH;
340*4f0ce1daSGordon Ross 		break;
341*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES256_GCM:	// 4
342*4f0ce1daSGordon Ross 		gcm = B_TRUE;
343*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_GCM_NONCE_SIZE;
344*4f0ce1daSGordon Ross 		keylen = AES256_KEY_LENGTH;
345*4f0ce1daSGordon Ross 		break;
3461160dcf7SMatt Barden 	}
3471160dcf7SMatt Barden 
348*4f0ce1daSGordon Ross 	/*
349*4f0ce1daSGordon Ross 	 * Get the transform header, in both raw form and decoded,
350*4f0ce1daSGordon Ross 	 * then remove the transform header from the message.
351*4f0ce1daSGordon Ross 	 * Note: the signature lands in sr->smb2_sig
352*4f0ce1daSGordon Ross 	 */
353*4f0ce1daSGordon Ross 	if (smb_mbc_peek(in_mbc, 0, "#c",
354*4f0ce1daSGordon Ross 	    SMB3_TFORM_HDR_SIZE, th_raw) != 0) {
355*4f0ce1daSGordon Ross 		return (SET_ERROR(-2));
356*4f0ce1daSGordon Ross 	}
357*4f0ce1daSGordon Ross 	rc = smb3_decode_tform_header(sr, in_mbc);
358*4f0ce1daSGordon Ross 	if (rc != 0) {
359*4f0ce1daSGordon Ross 		return (SET_ERROR(-3));
3601160dcf7SMatt Barden 	}
361*4f0ce1daSGordon Ross 	m_adjust(in_mbc->chain, SMB3_TFORM_HDR_SIZE);
362*4f0ce1daSGordon Ross 	ASSERT(in_mbc->max_bytes > SMB3_TFORM_HDR_SIZE);
363*4f0ce1daSGordon Ross 	in_mbc->max_bytes -= SMB3_TFORM_HDR_SIZE;
364*4f0ce1daSGordon Ross 	in_mbc->chain_offset = 0;
3651160dcf7SMatt Barden 
366*4f0ce1daSGordon Ross 	/*
367*4f0ce1daSGordon Ross 	 * Bounds-check the stated length of the encapsulated message.
368*4f0ce1daSGordon Ross 	 */
369*4f0ce1daSGordon Ross 	if (sr->th_msglen < SMB2_HDR_SIZE ||
370*4f0ce1daSGordon Ross 	    sr->th_msglen > in_mbc->max_bytes) {
371*4f0ce1daSGordon Ross 		return (SET_ERROR(-4));
372*4f0ce1daSGordon Ross 	}
373*4f0ce1daSGordon Ross 	cipherlen = sr->th_msglen + SMB2_SIG_SIZE;
3741160dcf7SMatt Barden 
3751160dcf7SMatt Barden 	/*
376*4f0ce1daSGordon Ross 	 * Lookup/validate the transform session ID so we'll
377*4f0ce1daSGordon Ross 	 * have the key we'll need.  Release for this happens
378*4f0ce1daSGordon Ross 	 * in smb_request_free().
3791160dcf7SMatt Barden 	 */
380*4f0ce1daSGordon Ross 	u = smb_session_lookup_ssnid(s, sr->th_ssnid);
381*4f0ce1daSGordon Ross 	if (u == NULL) {
382*4f0ce1daSGordon Ross 		return (SET_ERROR(-5));
383*4f0ce1daSGordon Ross 	}
384*4f0ce1daSGordon Ross 	sr->th_sid_user = u;
385*4f0ce1daSGordon Ross 	dec_key = &u->u_dec_key;
386*4f0ce1daSGordon Ross 	if (dec_key->len != keylen) {
387*4f0ce1daSGordon Ross 		return (SET_ERROR(-6));
388*4f0ce1daSGordon Ross 	}
3891160dcf7SMatt Barden 
3901160dcf7SMatt Barden 	/*
391*4f0ce1daSGordon Ross 	 * Initialize crypto I/F: mech, params, key
392*4f0ce1daSGordon Ross 	 *
3931160dcf7SMatt Barden 	 * Unlike signing, which uses one global mech struct,
3941160dcf7SMatt Barden 	 * encryption requires modifying the mech to add a
3951160dcf7SMatt Barden 	 * per-use param struct. Thus, we need to make a copy.
3961160dcf7SMatt Barden 	 */
397*4f0ce1daSGordon Ross 	bzero(&ctx, sizeof (ctx));
398*4f0ce1daSGordon Ross 	ctx.mech = *((smb_crypto_mech_t *)s->enc_mech);
3991160dcf7SMatt Barden 
4001160dcf7SMatt Barden 	/*
401*4f0ce1daSGordon Ross 	 * The transform header, minus the PROTOCOL_ID and the
402*4f0ce1daSGordon Ross 	 * SIGNATURE, is authenticated but not encrypted.
403*4f0ce1daSGordon Ross 	 * (That's the "auth data" passed to init)
4041160dcf7SMatt Barden 	 *
405*4f0ce1daSGordon Ross 	 * Param init for CCM also needs the cipher length, which is
406*4f0ce1daSGordon Ross 	 * the clear length + 16, but note that the last 16 bytes is
407*4f0ce1daSGordon Ross 	 * the signature in the transform header.
4081160dcf7SMatt Barden 	 */
409*4f0ce1daSGordon Ross 	authdata = th_raw + SMB3_NONCE_OFFS;
410*4f0ce1daSGordon Ross 	authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
411*4f0ce1daSGordon Ross 
412*4f0ce1daSGordon Ross 	if (gcm) {
413*4f0ce1daSGordon Ross 		smb3_crypto_init_gcm_param(&ctx,
414*4f0ce1daSGordon Ross 		    sr->th_nonce, nonce_size,
415*4f0ce1daSGordon Ross 		    authdata, authlen);
416*4f0ce1daSGordon Ross 	} else {
417*4f0ce1daSGordon Ross 		smb3_crypto_init_ccm_param(&ctx,
418*4f0ce1daSGordon Ross 		    sr->th_nonce, nonce_size,
419*4f0ce1daSGordon Ross 		    authdata, authlen, cipherlen);
4201160dcf7SMatt Barden 	}
4211160dcf7SMatt Barden 
422*4f0ce1daSGordon Ross 	rc = smb3_decrypt_init(&ctx,
423*4f0ce1daSGordon Ross 	    dec_key->key, dec_key->len);
424*4f0ce1daSGordon Ross 	if (rc != 0)
425*4f0ce1daSGordon Ross 		return (SET_ERROR(-7));
4261160dcf7SMatt Barden 
4271160dcf7SMatt Barden 	/*
428*4f0ce1daSGordon Ross 	 * Build a UIO vector for the ciphertext (in)
429*4f0ce1daSGordon Ross 	 * a: remainder of the 1s segment after the transform header
430*4f0ce1daSGordon Ross 	 * b: all subsequent segments of this message
431*4f0ce1daSGordon Ross 	 * c: final 16 byte signature from the transform header
4321160dcf7SMatt Barden 	 */
433*4f0ce1daSGordon Ross 	in_vdb = smb3_get_vdb(sr);
434*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_resid = sr->th_msglen;
435*4f0ce1daSGordon Ross 	rc = smb_mbuf_mkuio(in_mbc->chain, &in_vdb->vdb_uio);
436*4f0ce1daSGordon Ross 	if (rc != 0)
437*4f0ce1daSGordon Ross 		return (SET_ERROR(-8));
438*4f0ce1daSGordon Ross 
439*4f0ce1daSGordon Ross 	/* Add one more uio seg. for the signature. */
440*4f0ce1daSGordon Ross 	cnt = in_vdb->vdb_uio.uio_iovcnt;
441*4f0ce1daSGordon Ross 	if ((cnt + 1) > MAX_IOVEC)
442*4f0ce1daSGordon Ross 		return (SET_ERROR(-9));
443*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_iov[cnt].iov_base = (void *)sr->smb2_sig;
444*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_iov[cnt].iov_len = SMB2_SIG_SIZE;
445*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_iovcnt = cnt + 1;
446*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_resid += SMB2_SIG_SIZE;
4471160dcf7SMatt Barden 
4481160dcf7SMatt Barden 	/*
449*4f0ce1daSGordon Ross 	 * Build a UIO vector for the cleartext (out)
4501160dcf7SMatt Barden 	 */
451*4f0ce1daSGordon Ross 	out_vdb = smb3_get_vdb(sr);
452*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_resid = sr->th_msglen;
453*4f0ce1daSGordon Ross 	rc = smb_mbuf_mkuio(out_mbc->chain, &out_vdb->vdb_uio);
454*4f0ce1daSGordon Ross 	if (rc != 0)
455*4f0ce1daSGordon Ross 		return (SET_ERROR(-10));
4561160dcf7SMatt Barden 
4571160dcf7SMatt Barden 	/*
458*4f0ce1daSGordon Ross 	 * Have in/out UIO descriptors.  Decrypt!
4591160dcf7SMatt Barden 	 */
460*4f0ce1daSGordon Ross 	rc = smb3_decrypt_uio(&ctx, &in_vdb->vdb_uio, &out_vdb->vdb_uio);
4611160dcf7SMatt Barden 	if (rc != 0) {
462*4f0ce1daSGordon Ross #ifdef	DEBUG
463*4f0ce1daSGordon Ross 		cmn_err(CE_WARN, "smb3_decrypt_uio failed");
464*4f0ce1daSGordon Ross #endif
465*4f0ce1daSGordon Ross 		return (SET_ERROR(-11));
466897907ceSGordon Ross 	}
4671160dcf7SMatt Barden 
4681160dcf7SMatt Barden 	return (rc);
4691160dcf7SMatt Barden }
4701160dcf7SMatt Barden 
4711160dcf7SMatt Barden /*
472*4f0ce1daSGordon Ross  * Encrypt the response in in_mbc into out_mbc which as been
473*4f0ce1daSGordon Ross  * setup by the caller.  The caller will send out_mbc if this
474*4f0ce1daSGordon Ross  * returns success, and otherwise will free out_mbc.
475*4f0ce1daSGordon Ross  *
476*4f0ce1daSGordon Ross  * The cleartext response in in_mbc is left unmodified here,
477*4f0ce1daSGordon Ross  * and free'd in smb_request_free.
478*4f0ce1daSGordon Ross  *
479*4f0ce1daSGordon Ross  * Error return values here are just for visibility in dtrace.
480*4f0ce1daSGordon Ross  * Anything non-zero results in a connection drop.
4811160dcf7SMatt Barden  */
4821160dcf7SMatt Barden int
smb3_encrypt_sr(smb_request_t * sr,struct mbuf_chain * in_mbc,struct mbuf_chain * out_mbc)483*4f0ce1daSGordon Ross smb3_encrypt_sr(smb_request_t *sr,
484*4f0ce1daSGordon Ross     struct mbuf_chain *in_mbc,	// cleartext
485*4f0ce1daSGordon Ross     struct mbuf_chain *out_mbc)	// transform header + ciphertext
4861160dcf7SMatt Barden {
487*4f0ce1daSGordon Ross 	smb_enc_ctx_t ctx;
488*4f0ce1daSGordon Ross 	uint8_t th_raw[SMB3_TFORM_HDR_SIZE];
489*4f0ce1daSGordon Ross 	uint8_t *authdata;
490*4f0ce1daSGordon Ross 	size_t authlen;
491*4f0ce1daSGordon Ross 	smb_vdb_t *in_vdb = NULL;
492*4f0ce1daSGordon Ross 	smb_vdb_t *out_vdb = NULL;
4931160dcf7SMatt Barden 	smb_session_t *s = sr->session;
494*4f0ce1daSGordon Ross 	smb_user_t *u = sr->th_sid_user;
4951160dcf7SMatt Barden 	struct smb_key *enc_key = &u->u_enc_key;
496*4f0ce1daSGordon Ross 	int cnt, rc;
497*4f0ce1daSGordon Ross 	boolean_t gcm;
498*4f0ce1daSGordon Ross 	size_t nonce_size;
499*4f0ce1daSGordon Ross 	uint_t keylen;
500*4f0ce1daSGordon Ross 
501*4f0ce1daSGordon Ross 	VERIFY(u != NULL); // and have sr->th_ssnid
5021160dcf7SMatt Barden 
503*4f0ce1daSGordon Ross 	switch (s->smb31_enc_cipherid) {
504*4f0ce1daSGordon Ross 	default:
505*4f0ce1daSGordon Ross 		ASSERT(0);
506*4f0ce1daSGordon Ross 		/* fallthrough */
507*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES128_CCM:	// 1
508*4f0ce1daSGordon Ross 		gcm = B_FALSE;
509*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_CCM_NONCE_SIZE;
510*4f0ce1daSGordon Ross 		keylen = AES128_KEY_LENGTH;
511*4f0ce1daSGordon Ross 		break;
512*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES128_GCM:	// 2
513*4f0ce1daSGordon Ross 		gcm = B_TRUE;
514*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_GCM_NONCE_SIZE;
515*4f0ce1daSGordon Ross 		keylen = AES128_KEY_LENGTH;
516*4f0ce1daSGordon Ross 		break;
517*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES256_CCM:	// 3
518*4f0ce1daSGordon Ross 		gcm = B_FALSE;
519*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_CCM_NONCE_SIZE;
520*4f0ce1daSGordon Ross 		keylen = AES256_KEY_LENGTH;
521*4f0ce1daSGordon Ross 		break;
522*4f0ce1daSGordon Ross 	case SMB3_CIPHER_AES256_GCM:	// 4
523*4f0ce1daSGordon Ross 		gcm = B_TRUE;
524*4f0ce1daSGordon Ross 		nonce_size = SMB3_AES_GCM_NONCE_SIZE;
525*4f0ce1daSGordon Ross 		keylen = AES256_KEY_LENGTH;
526*4f0ce1daSGordon Ross 		break;
527*4f0ce1daSGordon Ross 	}
528*4f0ce1daSGordon Ross 	if (s->enc_mech == NULL || enc_key->len != keylen) {
529*4f0ce1daSGordon Ross 		return (SET_ERROR(-1));
530*4f0ce1daSGordon Ross 	}
5311160dcf7SMatt Barden 
532*4f0ce1daSGordon Ross 	/*
533*4f0ce1daSGordon Ross 	 * Need to fill in the transform header for everything
534*4f0ce1daSGordon Ross 	 * after the signature, needed as the "auth" data.
535*4f0ce1daSGordon Ross 	 * The signature is stuffed in later.  So we need:
536*4f0ce1daSGordon Ross 	 *   the nonce, msgsize, flags, th_ssnid
537*4f0ce1daSGordon Ross 	 */
538*4f0ce1daSGordon Ross 	rc = smb3_encrypt_gen_nonce(u, sr->th_nonce, nonce_size);
5391160dcf7SMatt Barden 	if (rc != 0) {
5401160dcf7SMatt Barden 		cmn_err(CE_WARN, "ran out of nonces");
541*4f0ce1daSGordon Ross 		return (SET_ERROR(-2));
542*4f0ce1daSGordon Ross 	}
543*4f0ce1daSGordon Ross 	if (smb3_encode_tform_header(sr, out_mbc) != 0) {
544*4f0ce1daSGordon Ross 		cmn_err(CE_WARN, "couldn't encode transform header");
545*4f0ce1daSGordon Ross 		return (SET_ERROR(-3));
5461160dcf7SMatt Barden 	}
5471160dcf7SMatt Barden 
548*4f0ce1daSGordon Ross 	/* Get the raw header to use as auth data */
549*4f0ce1daSGordon Ross 	if (smb_mbc_peek(out_mbc, 0, "#c",
550*4f0ce1daSGordon Ross 	    SMB3_TFORM_HDR_SIZE, th_raw) != 0)
551*4f0ce1daSGordon Ross 		return (SET_ERROR(-4));
5521160dcf7SMatt Barden 
553*4f0ce1daSGordon Ross 	/*
554*4f0ce1daSGordon Ross 	 * Initialize crypto I/F: mech, params, key
555*4f0ce1daSGordon Ross 	 *
556*4f0ce1daSGordon Ross 	 * Unlike signing, which uses one global mech struct,
557*4f0ce1daSGordon Ross 	 * encryption requires modifying the mech to add a
558*4f0ce1daSGordon Ross 	 * per-use param struct. Thus, we need to make a copy.
559*4f0ce1daSGordon Ross 	 */
560*4f0ce1daSGordon Ross 	bzero(&ctx, sizeof (ctx));
561*4f0ce1daSGordon Ross 	ctx.mech = *((smb_crypto_mech_t *)s->enc_mech);
5621160dcf7SMatt Barden 
5631160dcf7SMatt Barden 	/*
5641160dcf7SMatt Barden 	 * The transform header, minus the PROTOCOL_ID and the
5651160dcf7SMatt Barden 	 * SIGNATURE, is authenticated but not encrypted.
566*4f0ce1daSGordon Ross 	 * (That's the "auth data" passed to init)
567*4f0ce1daSGordon Ross 	 *
568*4f0ce1daSGordon Ross 	 * Param init for CCM also needs the cipher length, which is
569*4f0ce1daSGordon Ross 	 * the clear length + 16, but note that the last 16 bytes is
570*4f0ce1daSGordon Ross 	 * the signature in the transform header.
571*4f0ce1daSGordon Ross 	 *
572*4f0ce1daSGordon Ross 	 * Note: sr->th_msglen already set by caller
5731160dcf7SMatt Barden 	 */
574*4f0ce1daSGordon Ross 	authdata = th_raw + SMB3_NONCE_OFFS;
575*4f0ce1daSGordon Ross 	authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
576*4f0ce1daSGordon Ross 
577*4f0ce1daSGordon Ross 	if (gcm) {
578*4f0ce1daSGordon Ross 		smb3_crypto_init_gcm_param(&ctx,
579*4f0ce1daSGordon Ross 		    sr->th_nonce, nonce_size,
580*4f0ce1daSGordon Ross 		    authdata, authlen);
581*4f0ce1daSGordon Ross 	} else {
582*4f0ce1daSGordon Ross 		smb3_crypto_init_ccm_param(&ctx,
583*4f0ce1daSGordon Ross 		    sr->th_nonce, nonce_size,
584*4f0ce1daSGordon Ross 		    authdata, authlen, sr->th_msglen);
585*4f0ce1daSGordon Ross 	}
586*4f0ce1daSGordon Ross 
587*4f0ce1daSGordon Ross 	rc = smb3_encrypt_init(&ctx,
588*4f0ce1daSGordon Ross 	    enc_key->key, enc_key->len);
589*4f0ce1daSGordon Ross 	if (rc != 0)
590*4f0ce1daSGordon Ross 		return (SET_ERROR(-5));
5911160dcf7SMatt Barden 
5921160dcf7SMatt Barden 	/*
593*4f0ce1daSGordon Ross 	 * Build a UIO vector for the cleartext (in)
5941160dcf7SMatt Barden 	 */
595*4f0ce1daSGordon Ross 	in_vdb = smb3_get_vdb(sr);
596*4f0ce1daSGordon Ross 	in_vdb->vdb_uio.uio_resid = sr->th_msglen;
597*4f0ce1daSGordon Ross 	rc = smb_mbuf_mkuio(in_mbc->chain, &in_vdb->vdb_uio);
598*4f0ce1daSGordon Ross 	if (rc != 0)
599*4f0ce1daSGordon Ross 		return (SET_ERROR(-6));
6001160dcf7SMatt Barden 
6011160dcf7SMatt Barden 	/*
602*4f0ce1daSGordon Ross 	 * Build a UIO vector for the ciphertext (out)
603*4f0ce1daSGordon Ross 	 * a: remainder of the 1s segment after the transform header
604*4f0ce1daSGordon Ross 	 * b: all subsequent segments of this message
605*4f0ce1daSGordon Ross 	 * c: final 16 byte signature that will go in the TH
606*4f0ce1daSGordon Ross 	 *
607*4f0ce1daSGordon Ross 	 * Caller puts transform header in its own mblk so we can
608*4f0ce1daSGordon Ross 	 * just skip the first mlbk when building the uio.
6091160dcf7SMatt Barden 	 */
610*4f0ce1daSGordon Ross 	out_vdb = smb3_get_vdb(sr);
611*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_resid = sr->th_msglen;
612*4f0ce1daSGordon Ross 	rc = smb_mbuf_mkuio(out_mbc->chain->m_next, &out_vdb->vdb_uio);
613*4f0ce1daSGordon Ross 	if (rc != 0)
614*4f0ce1daSGordon Ross 		return (SET_ERROR(-7));
615*4f0ce1daSGordon Ross 
616*4f0ce1daSGordon Ross 	/* Add one more uio seg. for the signature. */
617*4f0ce1daSGordon Ross 	cnt = out_vdb->vdb_uio.uio_iovcnt;
618*4f0ce1daSGordon Ross 	if ((cnt + 1) > MAX_IOVEC)
619*4f0ce1daSGordon Ross 		return (SET_ERROR(-8));
620*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_iov[cnt].iov_base = (void *)sr->smb2_sig;
621*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_iov[cnt].iov_len = SMB2_SIG_SIZE;
622*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_iovcnt = cnt + 1;
623*4f0ce1daSGordon Ross 	out_vdb->vdb_uio.uio_resid += SMB2_SIG_SIZE;
6241160dcf7SMatt Barden 
625*4f0ce1daSGordon Ross 	/*
626*4f0ce1daSGordon Ross 	 * Have in/out UIO descriptors. Encrypt!
627*4f0ce1daSGordon Ross 	 */
628*4f0ce1daSGordon Ross 	rc = smb3_encrypt_uio(&ctx, &in_vdb->vdb_uio, &out_vdb->vdb_uio);
629*4f0ce1daSGordon Ross 	if (rc != 0) {
630*4f0ce1daSGordon Ross #ifdef	DEBUG
631*4f0ce1daSGordon Ross 		cmn_err(CE_WARN, "smb3_encrypt_uio failed");
632*4f0ce1daSGordon Ross #endif
633*4f0ce1daSGordon Ross 		return (SET_ERROR(-9));
6341160dcf7SMatt Barden 	}
6351160dcf7SMatt Barden 
636*4f0ce1daSGordon Ross 	/*
637*4f0ce1daSGordon Ross 	 * Now patch the final signature into the transform header
638*4f0ce1daSGordon Ross 	 */
639*4f0ce1daSGordon Ross 	(void) smb_mbc_poke(out_mbc, SMB3_SIG_OFFS, "#c",
640*4f0ce1daSGordon Ross 	    SMB2_SIG_SIZE, sr->smb2_sig);
6411160dcf7SMatt Barden 
6421160dcf7SMatt Barden 	return (rc);
6431160dcf7SMatt Barden }
6441160dcf7SMatt Barden 
6451160dcf7SMatt Barden void
smb3_encrypt_ssn_fini(smb_session_t * s)646*4f0ce1daSGordon Ross smb3_encrypt_ssn_fini(smb_session_t *s)
6471160dcf7SMatt Barden {
6481160dcf7SMatt Barden 	smb_crypto_mech_t *mech;
6491160dcf7SMatt Barden 
6501160dcf7SMatt Barden 	if ((mech = s->enc_mech) != NULL) {
6511160dcf7SMatt Barden 		kmem_free(mech, sizeof (*mech));
6521160dcf7SMatt Barden 		s->enc_mech = NULL;
6531160dcf7SMatt Barden 	}
6541160dcf7SMatt Barden }
655