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 /*
13*4f0ce1daSGordon Ross  * Copyright 2018-2021 Tintri by DDN, Inc. All rights reserved.
14*4f0ce1daSGordon Ross  * Copyright 2022 RackTop Systems, Inc.
151160dcf7SMatt Barden  */
161160dcf7SMatt Barden 
171160dcf7SMatt Barden /*
181160dcf7SMatt Barden  * Helper functions for SMB3 encryption using the
191160dcf7SMatt Barden  * Kernel Cryptographic Framework (KCF)
201160dcf7SMatt Barden  *
211160dcf7SMatt Barden  * There are two implementations of these functions:
221160dcf7SMatt Barden  * This one (for kernel) and another for user space:
231160dcf7SMatt Barden  * See: lib/smbsrv/libfksmbsrv/common/fksmb_encrypt_pkcs.c
24*4f0ce1daSGordon Ross  *
25*4f0ce1daSGordon Ross  * Contrary to what one might assume from the file name,
26*4f0ce1daSGordon Ross  * there should be NO SMB implementation knowledge here
27*4f0ce1daSGordon Ross  * beyond a few carefully selected things (smb_kcrypt.h).
281160dcf7SMatt Barden  */
291160dcf7SMatt Barden 
301160dcf7SMatt Barden #include <sys/crypto/api.h>
311160dcf7SMatt Barden #include <smbsrv/smb_kcrypt.h>
32*4f0ce1daSGordon Ross #include <sys/systm.h>
331160dcf7SMatt Barden #include <sys/cmn_err.h>
341160dcf7SMatt Barden 
351160dcf7SMatt Barden /*
364e065a9fSAlexander Stetsenko  * Common function to see if a mech is available.
371160dcf7SMatt Barden  */
384e065a9fSAlexander Stetsenko static int
find_mech(smb_crypto_mech_t * mech,const char * name)39eba274b9SToomas Soome find_mech(smb_crypto_mech_t *mech, const char *name)
401160dcf7SMatt Barden {
411160dcf7SMatt Barden 	crypto_mech_type_t t;
421160dcf7SMatt Barden 
434e065a9fSAlexander Stetsenko 	t = crypto_mech2id(name);
441160dcf7SMatt Barden 	if (t == CRYPTO_MECH_INVALID) {
454e065a9fSAlexander Stetsenko 		cmn_err(CE_NOTE, "smb: no kcf mech: %s", name);
461160dcf7SMatt Barden 		return (-1);
471160dcf7SMatt Barden 	}
481160dcf7SMatt Barden 	mech->cm_type = t;
491160dcf7SMatt Barden 	return (0);
501160dcf7SMatt Barden }
511160dcf7SMatt Barden 
524e065a9fSAlexander Stetsenko /*
534e065a9fSAlexander Stetsenko  * SMB3 encryption helpers:
544e065a9fSAlexander Stetsenko  * (getmech, init, update, final)
554e065a9fSAlexander Stetsenko  */
564e065a9fSAlexander Stetsenko 
574e065a9fSAlexander Stetsenko int
smb3_aes_ccm_getmech(smb_crypto_mech_t * mech)584e065a9fSAlexander Stetsenko smb3_aes_ccm_getmech(smb_crypto_mech_t *mech)
594e065a9fSAlexander Stetsenko {
604e065a9fSAlexander Stetsenko 	return (find_mech(mech, SUN_CKM_AES_CCM));
614e065a9fSAlexander Stetsenko }
624e065a9fSAlexander Stetsenko 
634e065a9fSAlexander Stetsenko int
smb3_aes_gcm_getmech(smb_crypto_mech_t * mech)644e065a9fSAlexander Stetsenko smb3_aes_gcm_getmech(smb_crypto_mech_t *mech)
654e065a9fSAlexander Stetsenko {
664e065a9fSAlexander Stetsenko 	return (find_mech(mech, SUN_CKM_AES_GCM));
674e065a9fSAlexander Stetsenko }
684e065a9fSAlexander Stetsenko 
691160dcf7SMatt Barden void
smb3_crypto_init_ccm_param(smb_enc_ctx_t * ctx,uint8_t * nonce,size_t noncesize,uint8_t * auth,size_t authsize,size_t datasize)70*4f0ce1daSGordon Ross smb3_crypto_init_ccm_param(smb_enc_ctx_t *ctx,
71*4f0ce1daSGordon Ross     uint8_t *nonce, size_t noncesize,
72*4f0ce1daSGordon Ross     uint8_t *auth, size_t authsize,
731160dcf7SMatt Barden     size_t datasize)
741160dcf7SMatt Barden {
751160dcf7SMatt Barden 
76*4f0ce1daSGordon Ross 	ASSERT3U(noncesize, >=, SMB3_AES_CCM_NONCE_SIZE);
771160dcf7SMatt Barden 
78*4f0ce1daSGordon Ross 	ctx->param.ccm.ulMACSize = SMB2_SIG_SIZE;
79*4f0ce1daSGordon Ross 	ctx->param.ccm.ulNonceSize = SMB3_AES_CCM_NONCE_SIZE;
80*4f0ce1daSGordon Ross 	ctx->param.ccm.nonce = nonce;
81*4f0ce1daSGordon Ross 	ctx->param.ccm.ulDataSize = datasize;
82*4f0ce1daSGordon Ross 	ctx->param.ccm.ulAuthDataSize = authsize;
83*4f0ce1daSGordon Ross 	ctx->param.ccm.authData = auth;
841160dcf7SMatt Barden 
85*4f0ce1daSGordon Ross 	ctx->mech.cm_param = (caddr_t)&ctx->param.ccm;
86*4f0ce1daSGordon Ross 	ctx->mech.cm_param_len = sizeof (ctx->param.ccm);
871160dcf7SMatt Barden }
881160dcf7SMatt Barden 
89*4f0ce1daSGordon Ross void
smb3_crypto_init_gcm_param(smb_enc_ctx_t * ctx,uint8_t * nonce,size_t noncesize,uint8_t * auth,size_t authsize)90*4f0ce1daSGordon Ross smb3_crypto_init_gcm_param(smb_enc_ctx_t *ctx,
91*4f0ce1daSGordon Ross     uint8_t *nonce, size_t noncesize,
92*4f0ce1daSGordon Ross     uint8_t *auth, size_t authsize)
931160dcf7SMatt Barden {
941160dcf7SMatt Barden 
95*4f0ce1daSGordon Ross 	ASSERT3U(noncesize, >=, SMB3_AES_GCM_NONCE_SIZE);
961160dcf7SMatt Barden 
97*4f0ce1daSGordon Ross 	ctx->param.gcm.pIv = nonce;
98*4f0ce1daSGordon Ross 	ctx->param.gcm.ulIvLen = SMB3_AES_GCM_NONCE_SIZE;
99*4f0ce1daSGordon Ross 	ctx->param.gcm.ulTagBits = SMB2_SIG_SIZE << 3;	/* bytes to bits */
100*4f0ce1daSGordon Ross 	ctx->param.gcm.pAAD = auth;			/* auth data */
101*4f0ce1daSGordon Ross 	ctx->param.gcm.ulAADLen = authsize;		/* auth data len */
1021160dcf7SMatt Barden 
103*4f0ce1daSGordon Ross 	ctx->mech.cm_param = (caddr_t)&ctx->param.gcm;
104*4f0ce1daSGordon Ross 	ctx->mech.cm_param_len = sizeof (ctx->param.gcm);
1051160dcf7SMatt Barden }
1061160dcf7SMatt Barden 
1071160dcf7SMatt Barden /*
108*4f0ce1daSGordon Ross  * KCF doesn't need anything to happen in this call, but
109*4f0ce1daSGordon Ross  * wants that key when we call encrypt or decrypt, so
110*4f0ce1daSGordon Ross  * just stash the key here.
111*4f0ce1daSGordon Ross  *
112*4f0ce1daSGordon Ross  * Todo: clone crypto context template here?
1131160dcf7SMatt Barden  */
1141160dcf7SMatt Barden int
smb3_encrypt_init(smb_enc_ctx_t * ctxp,uint8_t * key,size_t keylen)115*4f0ce1daSGordon Ross smb3_encrypt_init(smb_enc_ctx_t *ctxp,
116*4f0ce1daSGordon Ross     uint8_t *key, size_t keylen)
1171160dcf7SMatt Barden {
1181160dcf7SMatt Barden 
119*4f0ce1daSGordon Ross 	bzero(&ctxp->ckey, sizeof (ctxp->ckey));
120*4f0ce1daSGordon Ross 	ctxp->ckey.ck_format = CRYPTO_KEY_RAW;
121*4f0ce1daSGordon Ross 	ctxp->ckey.ck_data = key;
122*4f0ce1daSGordon Ross 	ctxp->ckey.ck_length = keylen * 8; /* in bits */
1231160dcf7SMatt Barden 
1241160dcf7SMatt Barden 	return (0);
1251160dcf7SMatt Barden }
1261160dcf7SMatt Barden 
1271160dcf7SMatt Barden int
smb3_decrypt_init(smb_enc_ctx_t * ctxp,uint8_t * key,size_t keylen)128*4f0ce1daSGordon Ross smb3_decrypt_init(smb_enc_ctx_t *ctxp,
129*4f0ce1daSGordon Ross     uint8_t *key, size_t keylen)
1301160dcf7SMatt Barden {
1311160dcf7SMatt Barden 
132*4f0ce1daSGordon Ross 	bzero(&ctxp->ckey, sizeof (ctxp->ckey));
133*4f0ce1daSGordon Ross 	ctxp->ckey.ck_format = CRYPTO_KEY_RAW;
134*4f0ce1daSGordon Ross 	ctxp->ckey.ck_data = key;
135*4f0ce1daSGordon Ross 	ctxp->ckey.ck_length = keylen * 8; /* in bits */
1361160dcf7SMatt Barden 
1371160dcf7SMatt Barden 	return (0);
1381160dcf7SMatt Barden }
1391160dcf7SMatt Barden 
140*4f0ce1daSGordon Ross /*
141*4f0ce1daSGordon Ross  * Encrypt a whole message with scatter/gather (UIO)
142*4f0ce1daSGordon Ross  */
1431160dcf7SMatt Barden int
smb3_encrypt_uio(smb_enc_ctx_t * ctxp,uio_t * in_uio,uio_t * out_uio)144*4f0ce1daSGordon Ross smb3_encrypt_uio(smb_enc_ctx_t *ctxp, uio_t *in_uio, uio_t *out_uio)
1451160dcf7SMatt Barden {
146*4f0ce1daSGordon Ross 	crypto_ctx_template_t tmpl = NULL;	// todo
147*4f0ce1daSGordon Ross 	crypto_data_t in_cd, out_cd;
1481160dcf7SMatt Barden 	int rv;
1491160dcf7SMatt Barden 
150*4f0ce1daSGordon Ross 	bzero(&in_cd, sizeof (crypto_data_t));
151*4f0ce1daSGordon Ross 	in_cd.cd_format = CRYPTO_DATA_UIO;
152*4f0ce1daSGordon Ross 	in_cd.cd_length = in_uio->uio_resid;
153*4f0ce1daSGordon Ross 	in_cd.cd_uio = in_uio;
1541160dcf7SMatt Barden 
155*4f0ce1daSGordon Ross 	bzero(&out_cd, sizeof (crypto_data_t));
156*4f0ce1daSGordon Ross 	out_cd.cd_format = CRYPTO_DATA_UIO;
157*4f0ce1daSGordon Ross 	out_cd.cd_length = out_uio->uio_resid;
158*4f0ce1daSGordon Ross 	out_cd.cd_uio = out_uio;
1591160dcf7SMatt Barden 
160*4f0ce1daSGordon Ross 	rv = crypto_encrypt(&ctxp->mech, &in_cd,
161*4f0ce1daSGordon Ross 	    &ctxp->ckey, tmpl, &out_cd, NULL);
1621160dcf7SMatt Barden 	if (rv != CRYPTO_SUCCESS) {
163*4f0ce1daSGordon Ross 		cmn_err(CE_WARN, "crypto_encrypt failed: 0x%x", rv);
1641160dcf7SMatt Barden 		return (-1);
1651160dcf7SMatt Barden 	}
1661160dcf7SMatt Barden 
1671160dcf7SMatt Barden 	return (0);
1681160dcf7SMatt Barden }
1691160dcf7SMatt Barden 
170*4f0ce1daSGordon Ross /*
171*4f0ce1daSGordon Ross  * Decrypt a whole message with scatter/gather (UIO)
172*4f0ce1daSGordon Ross  */
1731160dcf7SMatt Barden int
smb3_decrypt_uio(smb_enc_ctx_t * ctxp,uio_t * in_uio,uio_t * out_uio)174*4f0ce1daSGordon Ross smb3_decrypt_uio(smb_enc_ctx_t *ctxp, uio_t *in_uio, uio_t *out_uio)
1751160dcf7SMatt Barden {
176*4f0ce1daSGordon Ross 	crypto_ctx_template_t tmpl = NULL;	// todo
177*4f0ce1daSGordon Ross 	crypto_data_t in_cd, out_cd;
1781160dcf7SMatt Barden 	int rv;
1791160dcf7SMatt Barden 
180*4f0ce1daSGordon Ross 	/* In is ciphertext */
181*4f0ce1daSGordon Ross 	bzero(&in_cd, sizeof (crypto_data_t));
182*4f0ce1daSGordon Ross 	in_cd.cd_format = CRYPTO_DATA_UIO;
183*4f0ce1daSGordon Ross 	in_cd.cd_length = in_uio->uio_resid;
184*4f0ce1daSGordon Ross 	in_cd.cd_uio = in_uio;
1851160dcf7SMatt Barden 
186*4f0ce1daSGordon Ross 	/* Out is plaintext */
187*4f0ce1daSGordon Ross 	bzero(&out_cd, sizeof (crypto_data_t));
188*4f0ce1daSGordon Ross 	out_cd.cd_format = CRYPTO_DATA_UIO;
189*4f0ce1daSGordon Ross 	out_cd.cd_length = out_uio->uio_resid;
190*4f0ce1daSGordon Ross 	out_cd.cd_uio = out_uio;
1911160dcf7SMatt Barden 
192*4f0ce1daSGordon Ross 	rv = crypto_decrypt(&ctxp->mech, &in_cd,
193*4f0ce1daSGordon Ross 	    &ctxp->ckey, tmpl, &out_cd, NULL);
194*4f0ce1daSGordon Ross 	if (rv != CRYPTO_SUCCESS) {
195*4f0ce1daSGordon Ross 		cmn_err(CE_WARN, "crypto_decrypt failed: 0x%x", rv);
196*4f0ce1daSGordon Ross 		return (-1);
197*4f0ce1daSGordon Ross 	}
1981160dcf7SMatt Barden 
199*4f0ce1daSGordon Ross 	return (0);
2001160dcf7SMatt Barden }
2011160dcf7SMatt Barden 
2021160dcf7SMatt Barden void
smb3_enc_ctx_done(smb_enc_ctx_t * ctxp)203*4f0ce1daSGordon Ross smb3_enc_ctx_done(smb_enc_ctx_t *ctxp)
2041160dcf7SMatt Barden {
2051160dcf7SMatt Barden 	crypto_cancel_ctx(ctxp->ctx);
2061160dcf7SMatt Barden }
207