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 2019 Nexenta Systems, Inc. All rights reserved.
14*48e11a6eSGordon Ross * Copyright 2024 RackTop Systems, Inc.
15*48e11a6eSGordon Ross */
16*48e11a6eSGordon Ross
17*48e11a6eSGordon Ross /*
18*48e11a6eSGordon Ross * Support for SMB3 encryption (message privacy)
19*48e11a6eSGordon Ross */
20*48e11a6eSGordon Ross
21*48e11a6eSGordon Ross #include <sys/param.h>
22*48e11a6eSGordon Ross #include <sys/systm.h>
23*48e11a6eSGordon Ross #include <sys/conf.h>
24*48e11a6eSGordon Ross #include <sys/proc.h>
25*48e11a6eSGordon Ross #include <sys/fcntl.h>
26*48e11a6eSGordon Ross #include <sys/socket.h>
27*48e11a6eSGordon Ross #include <sys/kmem.h>
28*48e11a6eSGordon Ross #include <sys/errno.h>
29*48e11a6eSGordon Ross #include <sys/cmn_err.h>
30*48e11a6eSGordon Ross #include <sys/random.h>
31*48e11a6eSGordon Ross #include <sys/stream.h>
32*48e11a6eSGordon Ross #include <sys/strsun.h>
33*48e11a6eSGordon Ross #include <sys/sdt.h>
34*48e11a6eSGordon Ross
35*48e11a6eSGordon Ross #include <netsmb/smb_osdep.h>
36*48e11a6eSGordon Ross #include <netsmb/smb2.h>
37*48e11a6eSGordon Ross #include <netsmb/smb_conn.h>
38*48e11a6eSGordon Ross #include <netsmb/smb_subr.h>
39*48e11a6eSGordon Ross #include <netsmb/smb_dev.h>
40*48e11a6eSGordon Ross #include <netsmb/smb_rq.h>
41*48e11a6eSGordon Ross
42*48e11a6eSGordon Ross #include <netsmb/nsmb_kcrypt.h>
43*48e11a6eSGordon Ross
44*48e11a6eSGordon Ross #define SMB3_TFORM_HDR_SIZE 52
45*48e11a6eSGordon Ross #define SMB3_NONCE_OFFS 20
46*48e11a6eSGordon Ross #define SMB3_SIG_OFFS 4
47*48e11a6eSGordon Ross
48*48e11a6eSGordon Ross static const uint8_t SMB3_CRYPT_SIG[4] = { 0xFD, 'S', 'M', 'B' };
49*48e11a6eSGordon Ross
50*48e11a6eSGordon Ross /*
51*48e11a6eSGordon Ross * Initialize crypto mechanisms we'll need.
52*48e11a6eSGordon Ross * Called after negotiate.
53*48e11a6eSGordon Ross */
54*48e11a6eSGordon Ross void
nsmb_crypt_init_mech(struct smb_vc * vcp)55*48e11a6eSGordon Ross nsmb_crypt_init_mech(struct smb_vc *vcp)
56*48e11a6eSGordon Ross {
57*48e11a6eSGordon Ross smb_crypto_mech_t *mech;
58*48e11a6eSGordon Ross int rc;
59*48e11a6eSGordon Ross
60*48e11a6eSGordon Ross if (vcp->vc3_crypt_mech != NULL)
61*48e11a6eSGordon Ross return;
62*48e11a6eSGordon Ross
63*48e11a6eSGordon Ross mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
64*48e11a6eSGordon Ross
65*48e11a6eSGordon Ross /* Always CCM for now. */
66*48e11a6eSGordon Ross rc = nsmb_aes_ccm_getmech(mech);
67*48e11a6eSGordon Ross if (rc != 0) {
68*48e11a6eSGordon Ross kmem_free(mech, sizeof (*mech));
69*48e11a6eSGordon Ross cmn_err(CE_NOTE, "SMB3 found no AES mechanism"
70*48e11a6eSGordon Ross " (encryption disabled)");
71*48e11a6eSGordon Ross return;
72*48e11a6eSGordon Ross }
73*48e11a6eSGordon Ross vcp->vc3_crypt_mech = mech;
74*48e11a6eSGordon Ross }
75*48e11a6eSGordon Ross
76*48e11a6eSGordon Ross void
nsmb_crypt_free_mech(struct smb_vc * vcp)77*48e11a6eSGordon Ross nsmb_crypt_free_mech(struct smb_vc *vcp)
78*48e11a6eSGordon Ross {
79*48e11a6eSGordon Ross smb_crypto_mech_t *mech;
80*48e11a6eSGordon Ross
81*48e11a6eSGordon Ross if ((mech = vcp->vc3_crypt_mech) == NULL)
82*48e11a6eSGordon Ross return;
83*48e11a6eSGordon Ross
84*48e11a6eSGordon Ross kmem_free(mech, sizeof (*mech));
85*48e11a6eSGordon Ross }
86*48e11a6eSGordon Ross
87*48e11a6eSGordon Ross /*
88*48e11a6eSGordon Ross * Initialize keys for encryption
89*48e11a6eSGordon Ross * Called after session setup.
90*48e11a6eSGordon Ross */
91*48e11a6eSGordon Ross void
nsmb_crypt_init_keys(struct smb_vc * vcp)92*48e11a6eSGordon Ross nsmb_crypt_init_keys(struct smb_vc *vcp)
93*48e11a6eSGordon Ross {
94*48e11a6eSGordon Ross
95*48e11a6eSGordon Ross /*
96*48e11a6eSGordon Ross * If we don't have a session key, we'll fail later when a
97*48e11a6eSGordon Ross * request that requires (en/de)cryption can't be (en/de)crypted.
98*48e11a6eSGordon Ross * Also don't bother initializing if we don't have a mechanism.
99*48e11a6eSGordon Ross */
100*48e11a6eSGordon Ross if (vcp->vc3_crypt_mech == NULL ||
101*48e11a6eSGordon Ross vcp->vc_ssnkeylen <= 0)
102*48e11a6eSGordon Ross return;
103*48e11a6eSGordon Ross
104*48e11a6eSGordon Ross /*
105*48e11a6eSGordon Ross * For SMB3, the encrypt/decrypt keys are derived from
106*48e11a6eSGordon Ross * the session key using KDF in counter mode.
107*48e11a6eSGordon Ross */
108*48e11a6eSGordon Ross if (nsmb_kdf(vcp->vc3_encrypt_key, SMB3_KEYLEN,
109*48e11a6eSGordon Ross vcp->vc_ssnkey, vcp->vc_ssnkeylen,
110*48e11a6eSGordon Ross (uint8_t *)"SMB2AESCCM", 11,
111*48e11a6eSGordon Ross (uint8_t *)"ServerIn ", 10) != 0)
112*48e11a6eSGordon Ross return;
113*48e11a6eSGordon Ross
114*48e11a6eSGordon Ross if (nsmb_kdf(vcp->vc3_decrypt_key, SMB3_KEYLEN,
115*48e11a6eSGordon Ross vcp->vc_ssnkey, vcp->vc_ssnkeylen,
116*48e11a6eSGordon Ross (uint8_t *)"SMB2AESCCM", 11,
117*48e11a6eSGordon Ross (uint8_t *)"ServerOut", 10) != 0)
118*48e11a6eSGordon Ross return;
119*48e11a6eSGordon Ross
120*48e11a6eSGordon Ross vcp->vc3_encrypt_key_len = SMB3_KEYLEN;
121*48e11a6eSGordon Ross vcp->vc3_decrypt_key_len = SMB3_KEYLEN;
122*48e11a6eSGordon Ross
123*48e11a6eSGordon Ross (void) random_get_pseudo_bytes(
124*48e11a6eSGordon Ross (uint8_t *)&vcp->vc3_nonce_low,
125*48e11a6eSGordon Ross sizeof (vcp->vc3_nonce_low));
126*48e11a6eSGordon Ross (void) random_get_pseudo_bytes(
127*48e11a6eSGordon Ross (uint8_t *)&vcp->vc3_nonce_high,
128*48e11a6eSGordon Ross sizeof (vcp->vc3_nonce_high));
129*48e11a6eSGordon Ross }
130*48e11a6eSGordon Ross
131*48e11a6eSGordon Ross /*
132*48e11a6eSGordon Ross * Encrypt the message in *mpp, in place, prepending the
133*48e11a6eSGordon Ross * SMB3 transform header.
134*48e11a6eSGordon Ross *
135*48e11a6eSGordon Ross * Any non-zero return is an error (values not used).
136*48e11a6eSGordon Ross */
137*48e11a6eSGordon Ross int
smb3_msg_encrypt(struct smb_vc * vcp,mblk_t ** mpp)138*48e11a6eSGordon Ross smb3_msg_encrypt(struct smb_vc *vcp, mblk_t **mpp)
139*48e11a6eSGordon Ross {
140*48e11a6eSGordon Ross smb_enc_ctx_t ctx;
141*48e11a6eSGordon Ross mblk_t *body, *thdr, *lastm;
142*48e11a6eSGordon Ross struct mbchain mbp_store;
143*48e11a6eSGordon Ross struct mbchain *mbp = &mbp_store;
144*48e11a6eSGordon Ross uint32_t bodylen;
145*48e11a6eSGordon Ross uint8_t *authdata;
146*48e11a6eSGordon Ross size_t authlen;
147*48e11a6eSGordon Ross int rc;
148*48e11a6eSGordon Ross
149*48e11a6eSGordon Ross ASSERT(RW_WRITE_HELD(&vcp->iod_rqlock));
150*48e11a6eSGordon Ross
151*48e11a6eSGordon Ross if (vcp->vc3_crypt_mech == NULL ||
152*48e11a6eSGordon Ross vcp->vc3_encrypt_key_len != SMB3_KEYLEN) {
153*48e11a6eSGordon Ross return (ENOTSUP);
154*48e11a6eSGordon Ross }
155*48e11a6eSGordon Ross
156*48e11a6eSGordon Ross bzero(&ctx, sizeof (ctx));
157*48e11a6eSGordon Ross ctx.mech = *((smb_crypto_mech_t *)vcp->vc3_crypt_mech);
158*48e11a6eSGordon Ross
159*48e11a6eSGordon Ross body = *mpp;
160*48e11a6eSGordon Ross bodylen = msgdsize(body);
161*48e11a6eSGordon Ross
162*48e11a6eSGordon Ross /*
163*48e11a6eSGordon Ross * Get a new "nonce". Access to these counters is
164*48e11a6eSGordon Ross * serialized by iod_rqlock (assert above).
165*48e11a6eSGordon Ross */
166*48e11a6eSGordon Ross vcp->vc3_nonce_low++;
167*48e11a6eSGordon Ross if (vcp->vc3_nonce_low == 0) {
168*48e11a6eSGordon Ross vcp->vc3_nonce_low++;
169*48e11a6eSGordon Ross vcp->vc3_nonce_high++;
170*48e11a6eSGordon Ross }
171*48e11a6eSGordon Ross
172*48e11a6eSGordon Ross /*
173*48e11a6eSGordon Ross * Build the transform header, keeping pointers to the various
174*48e11a6eSGordon Ross * parts of it that we'll need to refer to later.
175*48e11a6eSGordon Ross */
176*48e11a6eSGordon Ross (void) mb_init(mbp);
177*48e11a6eSGordon Ross thdr = mbp->mb_top;
178*48e11a6eSGordon Ross ASSERT(MBLKTAIL(thdr) >= SMB3_TFORM_HDR_SIZE);
179*48e11a6eSGordon Ross mb_put_mem(mbp, SMB3_CRYPT_SIG, 4, MB_MSYSTEM);
180*48e11a6eSGordon Ross mb_put_mem(mbp, NULL, SMB2_SIG_SIZE, MB_MZERO); // signature (later)
181*48e11a6eSGordon Ross mb_put_uint64le(mbp, vcp->vc3_nonce_low);
182*48e11a6eSGordon Ross mb_put_uint64le(mbp, vcp->vc3_nonce_high);
183*48e11a6eSGordon Ross /* Zero last 5 bytes of nonce per. spec. */
184*48e11a6eSGordon Ross bzero(thdr->b_wptr - 5, 5);
185*48e11a6eSGordon Ross mb_put_uint32le(mbp, bodylen);
186*48e11a6eSGordon Ross mb_put_uint16le(mbp, 0); // reserved
187*48e11a6eSGordon Ross mb_put_uint16le(mbp, 1); // flags
188*48e11a6eSGordon Ross mb_put_uint64le(mbp, vcp->vc2_session_id);
189*48e11a6eSGordon Ross mbp->mb_top = NULL; // keeping thdr
190*48e11a6eSGordon Ross mb_done(mbp);
191*48e11a6eSGordon Ross
192*48e11a6eSGordon Ross /*
193*48e11a6eSGordon Ross * Need pointers to the part of the transfor header
194*48e11a6eSGordon Ross * after the signature (starting with the nonce).
195*48e11a6eSGordon Ross */
196*48e11a6eSGordon Ross authdata = thdr->b_rptr + SMB3_NONCE_OFFS;
197*48e11a6eSGordon Ross authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
198*48e11a6eSGordon Ross
199*48e11a6eSGordon Ross nsmb_crypto_init_ccm_param(&ctx,
200*48e11a6eSGordon Ross authdata, SMB2_SIG_SIZE,
201*48e11a6eSGordon Ross authdata, authlen, bodylen);
202*48e11a6eSGordon Ross
203*48e11a6eSGordon Ross rc = nsmb_encrypt_init(&ctx,
204*48e11a6eSGordon Ross vcp->vc3_encrypt_key, vcp->vc3_encrypt_key_len);
205*48e11a6eSGordon Ross if (rc != 0)
206*48e11a6eSGordon Ross goto errout;
207*48e11a6eSGordon Ross
208*48e11a6eSGordon Ross /*
209*48e11a6eSGordon Ross * Temporarily append the transform header onto the
210*48e11a6eSGordon Ross * body mblk chain with its r/w pointers set to cover
211*48e11a6eSGordon Ross * just the signature, needed for how encrypt works.
212*48e11a6eSGordon Ross * Could just use linkb() but we need to unlink the
213*48e11a6eSGordon Ross * block as well so just find the tail ourselves.
214*48e11a6eSGordon Ross */
215*48e11a6eSGordon Ross ASSERT(MBLKL(thdr) == SMB3_TFORM_HDR_SIZE);
216*48e11a6eSGordon Ross thdr->b_rptr += SMB3_SIG_OFFS;
217*48e11a6eSGordon Ross thdr->b_wptr = thdr->b_rptr + SMB2_SIG_SIZE;
218*48e11a6eSGordon Ross lastm = body;
219*48e11a6eSGordon Ross while (lastm->b_cont != NULL)
220*48e11a6eSGordon Ross lastm = lastm->b_cont;
221*48e11a6eSGordon Ross lastm->b_cont = thdr;
222*48e11a6eSGordon Ross
223*48e11a6eSGordon Ross /*
224*48e11a6eSGordon Ross * The mblk chain is ready. Encrypt!
225*48e11a6eSGordon Ross */
226*48e11a6eSGordon Ross rc = nsmb_encrypt_mblks(&ctx, body, bodylen);
227*48e11a6eSGordon Ross /* check rc below */
228*48e11a6eSGordon Ross
229*48e11a6eSGordon Ross /* Unlink thdr and restore r/w pointers. */
230*48e11a6eSGordon Ross lastm->b_cont = NULL;
231*48e11a6eSGordon Ross thdr->b_rptr -= SMB3_SIG_OFFS;
232*48e11a6eSGordon Ross thdr->b_wptr = thdr->b_rptr + SMB3_TFORM_HDR_SIZE;
233*48e11a6eSGordon Ross
234*48e11a6eSGordon Ross /* Now check rc from encrypt */
235*48e11a6eSGordon Ross if (rc != 0)
236*48e11a6eSGordon Ross goto errout;
237*48e11a6eSGordon Ross
238*48e11a6eSGordon Ross /*
239*48e11a6eSGordon Ross * Lastly, prepend the transform header.
240*48e11a6eSGordon Ross */
241*48e11a6eSGordon Ross thdr->b_cont = body;
242*48e11a6eSGordon Ross *mpp = thdr;
243*48e11a6eSGordon Ross nsmb_enc_ctx_done(&ctx);
244*48e11a6eSGordon Ross return (0);
245*48e11a6eSGordon Ross
246*48e11a6eSGordon Ross errout:
247*48e11a6eSGordon Ross freeb(thdr);
248*48e11a6eSGordon Ross nsmb_enc_ctx_done(&ctx);
249*48e11a6eSGordon Ross return (rc);
250*48e11a6eSGordon Ross }
251*48e11a6eSGordon Ross
252*48e11a6eSGordon Ross /*
253*48e11a6eSGordon Ross * Decrypt the message in *mpp, in place, removing the
254*48e11a6eSGordon Ross * SMB3 transform header.
255*48e11a6eSGordon Ross *
256*48e11a6eSGordon Ross * Any non-zero return is an error (values not used).
257*48e11a6eSGordon Ross */
258*48e11a6eSGordon Ross int
smb3_msg_decrypt(struct smb_vc * vcp,mblk_t ** mpp)259*48e11a6eSGordon Ross smb3_msg_decrypt(struct smb_vc *vcp, mblk_t **mpp)
260*48e11a6eSGordon Ross {
261*48e11a6eSGordon Ross smb_enc_ctx_t ctx;
262*48e11a6eSGordon Ross uint8_t th_sig[4];
263*48e11a6eSGordon Ross mblk_t *body, *thdr, *lastm;
264*48e11a6eSGordon Ross struct mdchain mdp_store;
265*48e11a6eSGordon Ross struct mdchain *mdp = &mdp_store;
266*48e11a6eSGordon Ross uint64_t th_ssnid;
267*48e11a6eSGordon Ross uint32_t bodylen, tlen;
268*48e11a6eSGordon Ross uint16_t th_flags;
269*48e11a6eSGordon Ross uint8_t *authdata;
270*48e11a6eSGordon Ross size_t authlen;
271*48e11a6eSGordon Ross int rc;
272*48e11a6eSGordon Ross
273*48e11a6eSGordon Ross if (vcp->vc3_crypt_mech == NULL ||
274*48e11a6eSGordon Ross vcp->vc3_encrypt_key_len != SMB3_KEYLEN) {
275*48e11a6eSGordon Ross return (ENOTSUP);
276*48e11a6eSGordon Ross }
277*48e11a6eSGordon Ross
278*48e11a6eSGordon Ross bzero(&ctx, sizeof (ctx));
279*48e11a6eSGordon Ross ctx.mech = *((smb_crypto_mech_t *)vcp->vc3_crypt_mech);
280*48e11a6eSGordon Ross
281*48e11a6eSGordon Ross /*
282*48e11a6eSGordon Ross * Split off the transform header
283*48e11a6eSGordon Ross * We need it contiguous.
284*48e11a6eSGordon Ross */
285*48e11a6eSGordon Ross thdr = *mpp;
286*48e11a6eSGordon Ross body = m_split(thdr, SMB3_TFORM_HDR_SIZE, 1);
287*48e11a6eSGordon Ross if (body == NULL)
288*48e11a6eSGordon Ross return (ENOSR);
289*48e11a6eSGordon Ross thdr = m_pullup(thdr, SMB3_TFORM_HDR_SIZE);
290*48e11a6eSGordon Ross if (thdr == NULL)
291*48e11a6eSGordon Ross return (ENOSR);
292*48e11a6eSGordon Ross
293*48e11a6eSGordon Ross /*
294*48e11a6eSGordon Ross * Decode the transform header
295*48e11a6eSGordon Ross */
296*48e11a6eSGordon Ross (void) md_initm(mdp, thdr);
297*48e11a6eSGordon Ross md_get_mem(mdp, th_sig, 4, MB_MSYSTEM);
298*48e11a6eSGordon Ross md_get_mem(mdp, NULL, SMB2_SIG_SIZE, MB_MZERO); // signature
299*48e11a6eSGordon Ross md_get_mem(mdp, NULL, SMB2_SIG_SIZE, MB_MZERO); // nonce
300*48e11a6eSGordon Ross md_get_uint32le(mdp, &bodylen);
301*48e11a6eSGordon Ross md_get_uint16le(mdp, NULL); // reserved
302*48e11a6eSGordon Ross md_get_uint16le(mdp, &th_flags);
303*48e11a6eSGordon Ross md_get_uint64le(mdp, &th_ssnid);
304*48e11a6eSGordon Ross mdp->md_top = NULL; // keeping thdr
305*48e11a6eSGordon Ross md_done(mdp);
306*48e11a6eSGordon Ross
307*48e11a6eSGordon Ross /*
308*48e11a6eSGordon Ross * Validate transform header fields
309*48e11a6eSGordon Ross */
310*48e11a6eSGordon Ross if (bcmp(th_sig, SMB3_CRYPT_SIG, 4) != 0) {
311*48e11a6eSGordon Ross rc = EPROTO;
312*48e11a6eSGordon Ross goto errout;
313*48e11a6eSGordon Ross }
314*48e11a6eSGordon Ross if (th_flags != 1 || th_ssnid != vcp->vc2_session_id) {
315*48e11a6eSGordon Ross rc = EINVAL;
316*48e11a6eSGordon Ross goto errout;
317*48e11a6eSGordon Ross }
318*48e11a6eSGordon Ross
319*48e11a6eSGordon Ross /*
320*48e11a6eSGordon Ross * Check actual body length (trim if necessary)
321*48e11a6eSGordon Ross */
322*48e11a6eSGordon Ross tlen = msgdsize(body);
323*48e11a6eSGordon Ross if (tlen < bodylen) {
324*48e11a6eSGordon Ross rc = EINVAL;
325*48e11a6eSGordon Ross goto errout;
326*48e11a6eSGordon Ross }
327*48e11a6eSGordon Ross if (tlen > bodylen) {
328*48e11a6eSGordon Ross /* trim from tail */
329*48e11a6eSGordon Ross ssize_t adj;
330*48e11a6eSGordon Ross
331*48e11a6eSGordon Ross adj = bodylen - tlen;
332*48e11a6eSGordon Ross ASSERT(adj < 0);
333*48e11a6eSGordon Ross (void) adjmsg(body, adj);
334*48e11a6eSGordon Ross }
335*48e11a6eSGordon Ross
336*48e11a6eSGordon Ross /*
337*48e11a6eSGordon Ross * Need pointers to the part of the transfor header
338*48e11a6eSGordon Ross * after the signature (starting with the nonce).
339*48e11a6eSGordon Ross * tlen is now length of ciphertext
340*48e11a6eSGordon Ross */
341*48e11a6eSGordon Ross authdata = thdr->b_rptr + SMB3_NONCE_OFFS;
342*48e11a6eSGordon Ross authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
343*48e11a6eSGordon Ross tlen = bodylen + SMB2_SIG_SIZE;
344*48e11a6eSGordon Ross
345*48e11a6eSGordon Ross nsmb_crypto_init_ccm_param(&ctx,
346*48e11a6eSGordon Ross authdata, SMB2_SIG_SIZE,
347*48e11a6eSGordon Ross authdata, authlen, tlen);
348*48e11a6eSGordon Ross
349*48e11a6eSGordon Ross rc = nsmb_decrypt_init(&ctx,
350*48e11a6eSGordon Ross vcp->vc3_decrypt_key, vcp->vc3_decrypt_key_len);
351*48e11a6eSGordon Ross if (rc != 0)
352*48e11a6eSGordon Ross goto errout;
353*48e11a6eSGordon Ross
354*48e11a6eSGordon Ross /*
355*48e11a6eSGordon Ross * Temporarily append the transform header onto the
356*48e11a6eSGordon Ross * body mblk chain with its r/w pointers set to cover
357*48e11a6eSGordon Ross * just the signature, needed for how decrypt works.
358*48e11a6eSGordon Ross * Could just use linkb() but we need to unlink the
359*48e11a6eSGordon Ross * block as well so just find the tail ourselves.
360*48e11a6eSGordon Ross */
361*48e11a6eSGordon Ross thdr->b_rptr += SMB3_SIG_OFFS;
362*48e11a6eSGordon Ross thdr->b_wptr = thdr->b_rptr + SMB2_SIG_SIZE;
363*48e11a6eSGordon Ross lastm = body;
364*48e11a6eSGordon Ross while (lastm->b_cont != NULL)
365*48e11a6eSGordon Ross lastm = lastm->b_cont;
366*48e11a6eSGordon Ross lastm->b_cont = thdr;
367*48e11a6eSGordon Ross
368*48e11a6eSGordon Ross /*
369*48e11a6eSGordon Ross * The mblk chain is ready. Decrypt!
370*48e11a6eSGordon Ross */
371*48e11a6eSGordon Ross rc = nsmb_decrypt_mblks(&ctx, body, tlen);
372*48e11a6eSGordon Ross /* check rc below */
373*48e11a6eSGordon Ross
374*48e11a6eSGordon Ross /* Unlink thdr and restore r/w pointers. */
375*48e11a6eSGordon Ross lastm->b_cont = NULL;
376*48e11a6eSGordon Ross thdr->b_rptr -= SMB3_SIG_OFFS;
377*48e11a6eSGordon Ross thdr->b_wptr = thdr->b_rptr + SMB3_TFORM_HDR_SIZE;
378*48e11a6eSGordon Ross
379*48e11a6eSGordon Ross /* Now check rc from decrypt */
380*48e11a6eSGordon Ross if (rc != 0)
381*48e11a6eSGordon Ross goto errout;
382*48e11a6eSGordon Ross
383*48e11a6eSGordon Ross /*
384*48e11a6eSGordon Ross * Lastly, discard the transform header
385*48e11a6eSGordon Ross * and return the body.
386*48e11a6eSGordon Ross */
387*48e11a6eSGordon Ross freeb(thdr);
388*48e11a6eSGordon Ross *mpp = body;
389*48e11a6eSGordon Ross nsmb_enc_ctx_done(&ctx);
390*48e11a6eSGordon Ross return (0);
391*48e11a6eSGordon Ross
392*48e11a6eSGordon Ross errout:
393*48e11a6eSGordon Ross freeb(thdr);
394*48e11a6eSGordon Ross nsmb_enc_ctx_done(&ctx);
395*48e11a6eSGordon Ross return (rc);
396*48e11a6eSGordon Ross }
397