1*48e11a6eSGordon Ross /*
2*48e11a6eSGordon Ross * This file and its contents are supplied under the terms of the
3*48e11a6eSGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
4*48e11a6eSGordon Ross * You may only use this file in accordance with the terms of version
5*48e11a6eSGordon Ross * 1.0 of the CDDL.
6*48e11a6eSGordon Ross *
7*48e11a6eSGordon Ross * A full copy of the text of the CDDL should have accompanied this
8*48e11a6eSGordon Ross * source. A copy of the CDDL is also available via the Internet at
9*48e11a6eSGordon Ross * http://www.illumos.org/license/CDDL.
10*48e11a6eSGordon Ross */
11*48e11a6eSGordon Ross
12*48e11a6eSGordon Ross /*
13*48e11a6eSGordon Ross * Copyright 2018-2021 Tintri by DDN, Inc. All rights reserved.
14*48e11a6eSGordon Ross * Copyright 2021-2024 RackTop Systems, Inc.
15*48e11a6eSGordon Ross */
16*48e11a6eSGordon Ross
17*48e11a6eSGordon Ross /*
18*48e11a6eSGordon Ross * Helper functions for SMB3 encryption using PKCS#11
19*48e11a6eSGordon Ross *
20*48e11a6eSGordon Ross * There are two implementations of these functions:
21*48e11a6eSGordon Ross * This one (for user space) and another for kernel.
22*48e11a6eSGordon Ross * See: uts/common/fs/smbclnt/netsmb/smb_crypt_kcf.c
23*48e11a6eSGordon Ross *
24*48e11a6eSGordon Ross * Contrary to what one might assume from the file name,
25*48e11a6eSGordon Ross * there should be NO SMB implementation knowledge here
26*48e11a6eSGordon Ross * beyond a few carefully selected things (nsmb_kcrypt.h).
27*48e11a6eSGordon Ross */
28*48e11a6eSGordon Ross
29*48e11a6eSGordon Ross #include <security/cryptoki.h>
30*48e11a6eSGordon Ross #include <security/pkcs11.h>
31*48e11a6eSGordon Ross #include <netsmb/nsmb_kcrypt.h>
32*48e11a6eSGordon Ross
33*48e11a6eSGordon Ross #include <sys/cmn_err.h>
34*48e11a6eSGordon Ross #include <sys/debug.h>
35*48e11a6eSGordon Ross #include <sys/stream.h>
36*48e11a6eSGordon Ross #include <sys/strsun.h>
37*48e11a6eSGordon Ross #include <stdlib.h>
38*48e11a6eSGordon Ross #include <strings.h>
39*48e11a6eSGordon Ross
40*48e11a6eSGordon Ross size_t msgsize(mblk_t *);
41*48e11a6eSGordon Ross static int copy_mblks(void *buf, size_t buflen, enum uio_rw, mblk_t *m);
42*48e11a6eSGordon Ross
43*48e11a6eSGordon Ross /*
44*48e11a6eSGordon Ross * Common function to see if a mech is available.
45*48e11a6eSGordon Ross */
46*48e11a6eSGordon Ross static int
find_mech(CK_MECHANISM_TYPE id)47*48e11a6eSGordon Ross find_mech(CK_MECHANISM_TYPE id)
48*48e11a6eSGordon Ross {
49*48e11a6eSGordon Ross CK_SESSION_HANDLE hdl;
50*48e11a6eSGordon Ross CK_RV rv;
51*48e11a6eSGordon Ross
52*48e11a6eSGordon Ross rv = SUNW_C_GetMechSession(id, &hdl);
53*48e11a6eSGordon Ross if (rv != CKR_OK) {
54*48e11a6eSGordon Ross return (-1);
55*48e11a6eSGordon Ross }
56*48e11a6eSGordon Ross (void) C_CloseSession(hdl);
57*48e11a6eSGordon Ross
58*48e11a6eSGordon Ross return (0);
59*48e11a6eSGordon Ross }
60*48e11a6eSGordon Ross
61*48e11a6eSGordon Ross /*
62*48e11a6eSGordon Ross * SMB3 encryption helpers:
63*48e11a6eSGordon Ross * (getmech, init, update, final)
64*48e11a6eSGordon Ross */
65*48e11a6eSGordon Ross
66*48e11a6eSGordon Ross int
nsmb_aes_ccm_getmech(smb_crypto_mech_t * mech)67*48e11a6eSGordon Ross nsmb_aes_ccm_getmech(smb_crypto_mech_t *mech)
68*48e11a6eSGordon Ross {
69*48e11a6eSGordon Ross
70*48e11a6eSGordon Ross if (find_mech(CKM_AES_CCM) != 0) {
71*48e11a6eSGordon Ross cmn_err(CE_NOTE, "PKCS#11: no mech AES_CCM");
72*48e11a6eSGordon Ross return (-1);
73*48e11a6eSGordon Ross }
74*48e11a6eSGordon Ross
75*48e11a6eSGordon Ross mech->mechanism = CKM_AES_CCM;
76*48e11a6eSGordon Ross return (0);
77*48e11a6eSGordon Ross }
78*48e11a6eSGordon Ross
79*48e11a6eSGordon Ross int
nsmb_aes_gcm_getmech(smb_crypto_mech_t * mech)80*48e11a6eSGordon Ross nsmb_aes_gcm_getmech(smb_crypto_mech_t *mech)
81*48e11a6eSGordon Ross {
82*48e11a6eSGordon Ross
83*48e11a6eSGordon Ross if (find_mech(CKM_AES_GCM) != 0) {
84*48e11a6eSGordon Ross cmn_err(CE_NOTE, "PKCS#11: no mech AES_GCM");
85*48e11a6eSGordon Ross return (-1);
86*48e11a6eSGordon Ross }
87*48e11a6eSGordon Ross
88*48e11a6eSGordon Ross mech->mechanism = CKM_AES_GCM;
89*48e11a6eSGordon Ross return (0);
90*48e11a6eSGordon Ross }
91*48e11a6eSGordon Ross
92*48e11a6eSGordon Ross void
nsmb_crypto_init_ccm_param(smb_enc_ctx_t * ctx,uint8_t * nonce,size_t noncesize,uint8_t * auth,size_t authsize,size_t datasize)93*48e11a6eSGordon Ross nsmb_crypto_init_ccm_param(smb_enc_ctx_t *ctx,
94*48e11a6eSGordon Ross uint8_t *nonce, size_t noncesize,
95*48e11a6eSGordon Ross uint8_t *auth, size_t authsize,
96*48e11a6eSGordon Ross size_t datasize)
97*48e11a6eSGordon Ross {
98*48e11a6eSGordon Ross
99*48e11a6eSGordon Ross ASSERT3U(noncesize, >=, SMB3_AES_CCM_NONCE_SIZE);
100*48e11a6eSGordon Ross
101*48e11a6eSGordon Ross /* CK_CCM_PARAMS */
102*48e11a6eSGordon Ross ctx->param.ccm.ulDataLen = datasize;
103*48e11a6eSGordon Ross ctx->param.ccm.pNonce = nonce;
104*48e11a6eSGordon Ross ctx->param.ccm.ulNonceLen = SMB3_AES_CCM_NONCE_SIZE;
105*48e11a6eSGordon Ross ctx->param.ccm.pAAD = auth;
106*48e11a6eSGordon Ross ctx->param.ccm.ulAADLen = authsize;
107*48e11a6eSGordon Ross ctx->param.ccm.ulMACLen = SMB2_SIG_SIZE;
108*48e11a6eSGordon Ross
109*48e11a6eSGordon Ross ctx->mech.pParameter = (caddr_t)&ctx->param.ccm;
110*48e11a6eSGordon Ross ctx->mech.ulParameterLen = sizeof (ctx->param.ccm);
111*48e11a6eSGordon Ross }
112*48e11a6eSGordon Ross
113*48e11a6eSGordon Ross void
nsmb_crypto_init_gcm_param(smb_enc_ctx_t * ctx,uint8_t * nonce,size_t noncesize,uint8_t * auth,size_t authsize)114*48e11a6eSGordon Ross nsmb_crypto_init_gcm_param(smb_enc_ctx_t *ctx,
115*48e11a6eSGordon Ross uint8_t *nonce, size_t noncesize,
116*48e11a6eSGordon Ross uint8_t *auth, size_t authsize)
117*48e11a6eSGordon Ross {
118*48e11a6eSGordon Ross
119*48e11a6eSGordon Ross ASSERT3U(noncesize, >=, SMB3_AES_GCM_NONCE_SIZE);
120*48e11a6eSGordon Ross
121*48e11a6eSGordon Ross /* CK_GCM_PARAMS */
122*48e11a6eSGordon Ross ctx->param.gcm.pIv = nonce;
123*48e11a6eSGordon Ross ctx->param.gcm.ulIvLen = SMB3_AES_GCM_NONCE_SIZE;
124*48e11a6eSGordon Ross ctx->param.gcm.pAAD = auth; /* auth data */
125*48e11a6eSGordon Ross ctx->param.gcm.ulAADLen = authsize; /* auth data len */
126*48e11a6eSGordon Ross ctx->param.gcm.ulTagBits = SMB2_SIG_SIZE << 3; /* bytes to bits */
127*48e11a6eSGordon Ross
128*48e11a6eSGordon Ross ctx->mech.pParameter = (caddr_t)&ctx->param.gcm;
129*48e11a6eSGordon Ross ctx->mech.ulParameterLen = sizeof (ctx->param.gcm);
130*48e11a6eSGordon Ross }
131*48e11a6eSGordon Ross
132*48e11a6eSGordon Ross /*
133*48e11a6eSGordon Ross * Start the KCF encrypt session, load the key
134*48e11a6eSGordon Ross * If this returns zero, the caller should call
135*48e11a6eSGordon Ross * nsmb_enc_ctx_done to cleanup the context,
136*48e11a6eSGordon Ross * even if there are intervening errors.
137*48e11a6eSGordon Ross */
138*48e11a6eSGordon Ross int
nsmb_encrypt_init(smb_enc_ctx_t * ctxp,uint8_t * key,size_t keylen)139*48e11a6eSGordon Ross nsmb_encrypt_init(smb_enc_ctx_t *ctxp,
140*48e11a6eSGordon Ross uint8_t *key, size_t keylen)
141*48e11a6eSGordon Ross {
142*48e11a6eSGordon Ross CK_OBJECT_HANDLE hkey = 0;
143*48e11a6eSGordon Ross CK_MECHANISM *mech = &ctxp->mech;
144*48e11a6eSGordon Ross CK_RV rv;
145*48e11a6eSGordon Ross
146*48e11a6eSGordon Ross rv = SUNW_C_GetMechSession(mech->mechanism, &ctxp->ctx);
147*48e11a6eSGordon Ross if (rv != CKR_OK)
148*48e11a6eSGordon Ross return (-1);
149*48e11a6eSGordon Ross
150*48e11a6eSGordon Ross rv = SUNW_C_KeyToObject(ctxp->ctx, mech->mechanism,
151*48e11a6eSGordon Ross key, keylen, &hkey);
152*48e11a6eSGordon Ross if (rv != CKR_OK)
153*48e11a6eSGordon Ross return (-1);
154*48e11a6eSGordon Ross
155*48e11a6eSGordon Ross rv = C_EncryptInit(ctxp->ctx, mech, hkey);
156*48e11a6eSGordon Ross if (rv != CKR_OK) {
157*48e11a6eSGordon Ross cmn_err(CE_WARN, "C_EncryptInit failed: 0x%lx", rv);
158*48e11a6eSGordon Ross }
159*48e11a6eSGordon Ross (void) C_DestroyObject(ctxp->ctx, hkey);
160*48e11a6eSGordon Ross
161*48e11a6eSGordon Ross return (rv == CKR_OK ? 0 : -1);
162*48e11a6eSGordon Ross }
163*48e11a6eSGordon Ross
164*48e11a6eSGordon Ross /*
165*48e11a6eSGordon Ross * Start the KCF decrypt session, load the key
166*48e11a6eSGordon Ross * If this returns zero, the caller should call
167*48e11a6eSGordon Ross * nsmb_enc_ctx_done to cleanup the context,
168*48e11a6eSGordon Ross * even if there are intervening errors.
169*48e11a6eSGordon Ross */
170*48e11a6eSGordon Ross int
nsmb_decrypt_init(smb_enc_ctx_t * ctxp,uint8_t * key,size_t keylen)171*48e11a6eSGordon Ross nsmb_decrypt_init(smb_enc_ctx_t *ctxp,
172*48e11a6eSGordon Ross uint8_t *key, size_t keylen)
173*48e11a6eSGordon Ross {
174*48e11a6eSGordon Ross CK_OBJECT_HANDLE hkey = 0;
175*48e11a6eSGordon Ross CK_MECHANISM *mech = &ctxp->mech;
176*48e11a6eSGordon Ross CK_RV rv;
177*48e11a6eSGordon Ross
178*48e11a6eSGordon Ross rv = SUNW_C_GetMechSession(mech->mechanism, &ctxp->ctx);
179*48e11a6eSGordon Ross if (rv != CKR_OK)
180*48e11a6eSGordon Ross return (-1);
181*48e11a6eSGordon Ross
182*48e11a6eSGordon Ross rv = SUNW_C_KeyToObject(ctxp->ctx, mech->mechanism,
183*48e11a6eSGordon Ross key, keylen, &hkey);
184*48e11a6eSGordon Ross if (rv != CKR_OK)
185*48e11a6eSGordon Ross return (-1);
186*48e11a6eSGordon Ross
187*48e11a6eSGordon Ross rv = C_DecryptInit(ctxp->ctx, mech, hkey);
188*48e11a6eSGordon Ross if (rv != CKR_OK) {
189*48e11a6eSGordon Ross cmn_err(CE_WARN, "C_DecryptInit failed: 0x%lx", rv);
190*48e11a6eSGordon Ross }
191*48e11a6eSGordon Ross (void) C_DestroyObject(ctxp->ctx, hkey);
192*48e11a6eSGordon Ross
193*48e11a6eSGordon Ross return (rv == CKR_OK ? 0 : -1);
194*48e11a6eSGordon Ross }
195*48e11a6eSGordon Ross
196*48e11a6eSGordon Ross void
nsmb_enc_ctx_done(smb_enc_ctx_t * ctxp)197*48e11a6eSGordon Ross nsmb_enc_ctx_done(smb_enc_ctx_t *ctxp)
198*48e11a6eSGordon Ross {
199*48e11a6eSGordon Ross if (ctxp->ctx != 0) {
200*48e11a6eSGordon Ross (void) C_CloseSession(ctxp->ctx);
201*48e11a6eSGordon Ross ctxp->ctx = 0;
202*48e11a6eSGordon Ross }
203*48e11a6eSGordon Ross }
204*48e11a6eSGordon Ross
205*48e11a6eSGordon Ross /*
206*48e11a6eSGordon Ross * Encrypt a whole message with scatter/gather (MBLK)
207*48e11a6eSGordon Ross *
208*48e11a6eSGordon Ross * While the PKCS#11 implementation internally has the ability to
209*48e11a6eSGordon Ross * handle scatter/gather, it currently presents no interface for it.
210*48e11a6eSGordon Ross * As this library is used primarily for debugging, performance in
211*48e11a6eSGordon Ross * here is not a big concern, so we'll get around the limitation of
212*48e11a6eSGordon Ross * libpkcs11 by copying to/from a contiguous working buffer.
213*48e11a6eSGordon Ross */
214*48e11a6eSGordon Ross int
nsmb_encrypt_mblks(smb_enc_ctx_t * ctxp,mblk_t * mp,size_t clearlen)215*48e11a6eSGordon Ross nsmb_encrypt_mblks(smb_enc_ctx_t *ctxp, mblk_t *mp, size_t clearlen)
216*48e11a6eSGordon Ross {
217*48e11a6eSGordon Ross uint8_t *buf;
218*48e11a6eSGordon Ross size_t inlen, outlen;
219*48e11a6eSGordon Ross ulong_t tlen;
220*48e11a6eSGordon Ross int err;
221*48e11a6eSGordon Ross CK_RV rv;
222*48e11a6eSGordon Ross
223*48e11a6eSGordon Ross inlen = clearlen;
224*48e11a6eSGordon Ross outlen = clearlen + SMB2_SIG_SIZE;
225*48e11a6eSGordon Ross ASSERT(msgsize(mp) >= outlen);
226*48e11a6eSGordon Ross
227*48e11a6eSGordon Ross buf = malloc(outlen);
228*48e11a6eSGordon Ross if (buf == NULL)
229*48e11a6eSGordon Ross return (-1);
230*48e11a6eSGordon Ross
231*48e11a6eSGordon Ross /* Copy from mblk chain to buf */
232*48e11a6eSGordon Ross err = copy_mblks(buf, inlen, UIO_WRITE, mp);
233*48e11a6eSGordon Ross if (err != 0)
234*48e11a6eSGordon Ross return (-1);
235*48e11a6eSGordon Ross
236*48e11a6eSGordon Ross /* Encrypt in-place in our work buffer. */
237*48e11a6eSGordon Ross tlen = outlen;
238*48e11a6eSGordon Ross rv = C_Encrypt(ctxp->ctx, buf, inlen, buf, &tlen);
239*48e11a6eSGordon Ross if (rv != CKR_OK) {
240*48e11a6eSGordon Ross cmn_err(CE_WARN, "C_Encrypt failed: 0x%lx", rv);
241*48e11a6eSGordon Ross return (-1);
242*48e11a6eSGordon Ross }
243*48e11a6eSGordon Ross if (tlen != outlen) {
244*48e11a6eSGordon Ross cmn_err(CE_WARN, "nsmb_encrypt_mblks outlen %d vs %d",
245*48e11a6eSGordon Ross (int)tlen, (int)outlen);
246*48e11a6eSGordon Ross return (-1);
247*48e11a6eSGordon Ross }
248*48e11a6eSGordon Ross
249*48e11a6eSGordon Ross /* Copy from buf to mblk segs */
250*48e11a6eSGordon Ross err = copy_mblks(buf, outlen, UIO_READ, mp);
251*48e11a6eSGordon Ross if (err != 0)
252*48e11a6eSGordon Ross return (-1);
253*48e11a6eSGordon Ross
254*48e11a6eSGordon Ross return (0);
255*48e11a6eSGordon Ross }
256*48e11a6eSGordon Ross
257*48e11a6eSGordon Ross /*
258*48e11a6eSGordon Ross * Decrypt a whole message with scatter/gather (MBLK)
259*48e11a6eSGordon Ross */
260*48e11a6eSGordon Ross int
nsmb_decrypt_mblks(smb_enc_ctx_t * ctxp,mblk_t * mp,size_t cipherlen)261*48e11a6eSGordon Ross nsmb_decrypt_mblks(smb_enc_ctx_t *ctxp, mblk_t *mp, size_t cipherlen)
262*48e11a6eSGordon Ross {
263*48e11a6eSGordon Ross uint8_t *buf;
264*48e11a6eSGordon Ross size_t inlen, outlen;
265*48e11a6eSGordon Ross ulong_t tlen;
266*48e11a6eSGordon Ross int err;
267*48e11a6eSGordon Ross CK_RV rv;
268*48e11a6eSGordon Ross
269*48e11a6eSGordon Ross if (cipherlen <= SMB2_SIG_SIZE)
270*48e11a6eSGordon Ross return (-1);
271*48e11a6eSGordon Ross inlen = cipherlen;
272*48e11a6eSGordon Ross outlen = cipherlen - SMB2_SIG_SIZE;
273*48e11a6eSGordon Ross ASSERT(msgsize(mp) >= inlen);
274*48e11a6eSGordon Ross
275*48e11a6eSGordon Ross buf = malloc(inlen);
276*48e11a6eSGordon Ross if (buf == NULL)
277*48e11a6eSGordon Ross return (-1);
278*48e11a6eSGordon Ross
279*48e11a6eSGordon Ross /* Copy from mblk chain to buf */
280*48e11a6eSGordon Ross err = copy_mblks(buf, inlen, UIO_WRITE, mp);
281*48e11a6eSGordon Ross if (err != 0)
282*48e11a6eSGordon Ross return (-1);
283*48e11a6eSGordon Ross
284*48e11a6eSGordon Ross /* Decrypt in-place in our work buffer. */
285*48e11a6eSGordon Ross tlen = outlen;
286*48e11a6eSGordon Ross rv = C_Decrypt(ctxp->ctx, buf, inlen, buf, &tlen);
287*48e11a6eSGordon Ross if (rv != CKR_OK) {
288*48e11a6eSGordon Ross cmn_err(CE_WARN, "C_Decrypt failed: 0x%lx", rv);
289*48e11a6eSGordon Ross return (-1);
290*48e11a6eSGordon Ross }
291*48e11a6eSGordon Ross if (tlen != outlen) {
292*48e11a6eSGordon Ross cmn_err(CE_WARN, "nsmb_decrypt_mblks outlen %d vs %d",
293*48e11a6eSGordon Ross (int)tlen, (int)outlen);
294*48e11a6eSGordon Ross return (-1);
295*48e11a6eSGordon Ross }
296*48e11a6eSGordon Ross
297*48e11a6eSGordon Ross /* Copy from buf to mblk segs */
298*48e11a6eSGordon Ross err = copy_mblks(buf, outlen, UIO_READ, mp);
299*48e11a6eSGordon Ross if (err != 0)
300*48e11a6eSGordon Ross return (-1);
301*48e11a6eSGordon Ross
302*48e11a6eSGordon Ross return (0);
303*48e11a6eSGordon Ross }
304*48e11a6eSGordon Ross
305*48e11a6eSGordon Ross static int
copy_mblks(void * buf,size_t buflen,enum uio_rw rw,mblk_t * m)306*48e11a6eSGordon Ross copy_mblks(void *buf, size_t buflen, enum uio_rw rw, mblk_t *m)
307*48e11a6eSGordon Ross {
308*48e11a6eSGordon Ross uchar_t *p = buf;
309*48e11a6eSGordon Ross size_t rem = buflen;
310*48e11a6eSGordon Ross size_t len;
311*48e11a6eSGordon Ross
312*48e11a6eSGordon Ross while (rem > 0) {
313*48e11a6eSGordon Ross if (m == NULL)
314*48e11a6eSGordon Ross return (-1);
315*48e11a6eSGordon Ross ASSERT(m->b_datap->db_type == M_DATA);
316*48e11a6eSGordon Ross len = MBLKL(m);
317*48e11a6eSGordon Ross if (len > rem)
318*48e11a6eSGordon Ross len = rem;
319*48e11a6eSGordon Ross if (rw == UIO_READ) {
320*48e11a6eSGordon Ross /* buf to mblks */
321*48e11a6eSGordon Ross bcopy(p, m->b_rptr, len);
322*48e11a6eSGordon Ross } else {
323*48e11a6eSGordon Ross /* mblks to buf */
324*48e11a6eSGordon Ross bcopy(m->b_rptr, p, len);
325*48e11a6eSGordon Ross }
326*48e11a6eSGordon Ross m = m->b_cont;
327*48e11a6eSGordon Ross p += len;
328*48e11a6eSGordon Ross rem -= len;
329*48e11a6eSGordon Ross }
330*48e11a6eSGordon Ross return (0);
331*48e11a6eSGordon Ross }
332*48e11a6eSGordon Ross
333*48e11a6eSGordon Ross size_t
msgsize(mblk_t * mp)334*48e11a6eSGordon Ross msgsize(mblk_t *mp)
335*48e11a6eSGordon Ross {
336*48e11a6eSGordon Ross size_t n = 0;
337*48e11a6eSGordon Ross
338*48e11a6eSGordon Ross for (; mp != NULL; mp = mp->b_cont)
339*48e11a6eSGordon Ross n += MBLKL(mp);
340*48e11a6eSGordon Ross
341*48e11a6eSGordon Ross return (n);
342*48e11a6eSGordon Ross }
343