1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017-2021 Tintri by DDN, Inc. All rights reserved.
14 * Copyright 2022 RackTop Systems, Inc.
15 */
16
17 /*
18 * Routines for smb3 encryption.
19 */
20
21 #include <smbsrv/smb2_kproto.h>
22 #include <smbsrv/smb_kcrypt.h>
23 #include <sys/random.h>
24 #include <sys/cmn_err.h>
25
26 #define SMB3_NONCE_OFFS 20
27 #define SMB3_SIG_OFFS 4
28
29 /*
30 * Arbitrary value used to prevent nonce reuse via overflow. Currently
31 * 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
32 * 2^32 concurrent messages when we hit this number.
33 */
34 static uint64_t smb3_max_nonce = 0xffffffff00000000ULL;
35
36 /*
37 * Nonce generation based on draft-mcgrew-iv-gen-01
38 * "Generation of Deterministic Initialization Vectors (IVs) and Nonces"
39 *
40 * Generate an 8-byte random salt and a 3-byte random 'fixed' value.
41 * then, nonce = (++counter ^ salt) || fixed
42 *
43 * This protects against nonce-reuse (8-byte counter), as well as known
44 * attacks on reusing nonces with different keys
45 */
46
47 void
smb3_encrypt_init_nonce(smb_user_t * user)48 smb3_encrypt_init_nonce(smb_user_t *user)
49 {
50 user->u_nonce_cnt = 0;
51 (void) random_get_pseudo_bytes(user->u_nonce_fixed,
52 sizeof (user->u_nonce_fixed));
53 (void) random_get_pseudo_bytes((uint8_t *)&user->u_salt,
54 sizeof (user->u_salt));
55 }
56
57 static int
smb3_encrypt_gen_nonce(smb_user_t * user,uint8_t * buf,size_t len)58 smb3_encrypt_gen_nonce(smb_user_t *user, uint8_t *buf, size_t len)
59 {
60 uint64_t cnt;
61
62 /*
63 * Nonces must be unique per-key for the life of the key.
64 * Bail before we roll over to avoid breaking the crypto.
65 */
66 cnt = atomic_inc_64_nv(&user->u_nonce_cnt);
67 if (cnt > smb3_max_nonce)
68 return (-1);
69
70 cnt ^= user->u_salt;
71
72 bcopy((uint8_t *)&cnt, buf, sizeof (cnt));
73
74 ASSERT(len <= 16); // th_nonce
75 ASSERT(len > sizeof (cnt));
76 bcopy(user->u_nonce_fixed, buf + sizeof (cnt), len - sizeof (cnt));
77 return (0);
78 }
79
80 int
smb3_encrypt_init_mech(smb_session_t * s)81 smb3_encrypt_init_mech(smb_session_t *s)
82 {
83 smb_crypto_mech_t *mech;
84 int rc;
85
86 if (s->enc_mech != NULL)
87 return (0);
88
89 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
90
91 switch (s->smb31_enc_cipherid) {
92 case SMB3_CIPHER_AES256_GCM:
93 case SMB3_CIPHER_AES128_GCM:
94 rc = smb3_aes_gcm_getmech(mech);
95 break;
96 case SMB3_CIPHER_AES256_CCM:
97 case SMB3_CIPHER_AES128_CCM:
98 rc = smb3_aes_ccm_getmech(mech);
99 break;
100 default:
101 rc = -1;
102 break;
103 }
104
105 if (rc != 0) {
106 kmem_free(mech, sizeof (*mech));
107 return (rc);
108 }
109 s->enc_mech = mech;
110
111 return (0);
112 }
113
114 /*
115 * Initializes keys/state required for SMB3 Encryption.
116 * Note: If a failure occurs here, don't fail the request.
117 * Instead, return an error when we attempt to encrypt/decrypt.
118 */
119 void
smb3_encrypt_begin(smb_user_t * u,smb_token_t * token)120 smb3_encrypt_begin(smb_user_t *u, smb_token_t *token)
121 {
122 smb_session_t *s = u->u_session;
123 struct smb_key *enc_key = &u->u_enc_key;
124 struct smb_key *dec_key = &u->u_dec_key;
125 uint32_t derived_keylen, input_keylen;
126
127 /*
128 * In order to enforce encryption, all users need to
129 * have Session.EncryptData properly set, even anon/guest.
130 */
131 u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
132 enc_key->len = 0;
133 dec_key->len = 0;
134
135 /*
136 * If we don't have a session key, we'll fail later when a
137 * request that requires (en/de)cryption can't be (en/de)crypted.
138 * Also don't bother initializing if we don't have a mechanism.
139 */
140 if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
141 s->enc_mech == NULL)
142 return;
143
144 /*
145 * Compute and store the encryption keys, which live in
146 * the user structure.
147 */
148
149 /*
150 * For SMB3, the encrypt/decrypt keys are derived from
151 * the session key using KDF in counter mode.
152 *
153 * AES256 Keys are derived from the 'FullSessionKey', which is the
154 * entirety of what we got in the token; AES128 Keys are derived from
155 * the 'SessionKey', which is the first 16 bytes of the key we got in
156 * the token.
157 */
158 if (s->dialect >= SMB_VERS_3_11) {
159 if (s->smb31_enc_cipherid == SMB3_CIPHER_AES256_GCM ||
160 s->smb31_enc_cipherid == SMB3_CIPHER_AES256_CCM) {
161 derived_keylen = AES256_KEY_LENGTH;
162 input_keylen = token->tkn_ssnkey.len;
163 } else {
164 derived_keylen = AES128_KEY_LENGTH;
165 input_keylen = MIN(SMB2_SSN_KEYLEN,
166 token->tkn_ssnkey.len);
167 }
168
169 if (smb3_kdf(enc_key->key, derived_keylen,
170 token->tkn_ssnkey.val, input_keylen,
171 (uint8_t *)"SMBS2CCipherKey", 16,
172 u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
173 return;
174
175 if (smb3_kdf(dec_key->key, derived_keylen,
176 token->tkn_ssnkey.val, input_keylen,
177 (uint8_t *)"SMBC2SCipherKey", 16,
178 u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
179 return;
180
181 enc_key->len = derived_keylen;
182 dec_key->len = derived_keylen;
183 } else {
184 derived_keylen = AES128_KEY_LENGTH;
185 input_keylen = MIN(SMB2_SSN_KEYLEN, token->tkn_ssnkey.len);
186
187 if (smb3_kdf(enc_key->key, derived_keylen,
188 token->tkn_ssnkey.val, input_keylen,
189 (uint8_t *)"SMB2AESCCM", 11,
190 (uint8_t *)"ServerOut", 10) != 0)
191 return;
192
193 if (smb3_kdf(dec_key->key, derived_keylen,
194 token->tkn_ssnkey.val, input_keylen,
195 (uint8_t *)"SMB2AESCCM", 11,
196 (uint8_t *)"ServerIn ", 10) != 0)
197 return;
198
199 enc_key->len = derived_keylen;
200 dec_key->len = derived_keylen;
201 }
202
203 smb3_encrypt_init_nonce(u);
204
205 /*
206 * XXX todo: setup crypto context for enc_key, dec_key.
207 * See crypto_create_ctx_template(mech, key, tmpl,...)
208 *
209 * Will need a new indirect functions eg.
210 * smb3_encrypt_init_templ(s->enc_mech, enc_key);
211 * smb3_encrypt_init_templ(s->enc_mech, dec_key);
212 * where struct smb_key gains a new member:
213 * void *template;
214 *
215 * Already have s->enc_mech from smb3_encrypt_init_mech().
216 */
217 }
218
219 static int
smb3_decode_tform_header(smb_request_t * sr,struct mbuf_chain * mbc)220 smb3_decode_tform_header(smb_request_t *sr, struct mbuf_chain *mbc)
221 {
222 uint32_t protocolid;
223 uint16_t flags;
224 int rc;
225
226 rc = smb_mbc_decodef(
227 mbc, "l16c16cl..wq",
228 &protocolid, /* l */
229 sr->smb2_sig, /* 16c */
230 sr->th_nonce, /* 16c */
231 &sr->th_msglen, /* l */
232 /* reserved .. */
233 &flags, /* w */
234 &sr->th_ssnid); /* q */
235 if (rc)
236 return (rc);
237
238 /* This was checked in smb2sr_newrq() */
239 ASSERT3U(protocolid, ==, SMB3_ENCRYPTED_MAGIC);
240
241 if (flags != 1) {
242 #ifdef DEBUG
243 cmn_err(CE_NOTE, "flags field not 1: %x", flags);
244 #endif
245 return (-1);
246 }
247
248 return (rc);
249 }
250
251 static int
smb3_encode_tform_header(smb_request_t * sr,struct mbuf_chain * mbc)252 smb3_encode_tform_header(smb_request_t *sr, struct mbuf_chain *mbc)
253 {
254 int rc;
255
256 rc = smb_mbc_encodef(
257 mbc, "l16.16clwwq",
258 SMB3_ENCRYPTED_MAGIC, /* l */
259 /* signature(16) 16. (filled in later) */
260 sr->th_nonce, /* 16c */
261 sr->th_msglen, /* l */
262 0, /* reserved w */
263 1, /* flags w */
264 sr->th_ssnid); /* q */
265
266 return (rc);
267 }
268
269 /*
270 * Get an smb_vdb_t and initialize it.
271 * Free'd via smb_request_free
272 */
273 static smb_vdb_t *
smb3_get_vdb(smb_request_t * sr)274 smb3_get_vdb(smb_request_t *sr)
275 {
276 smb_vdb_t *vdb;
277
278 vdb = smb_srm_zalloc(sr, sizeof (*vdb));
279 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
280 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
281 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
282 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
283
284 return (vdb);
285 }
286
287 /*
288 * Decrypt the request in mbc_in into out_mbc which as been
289 * setup by the caller. The caller will replace sr->command
290 * with out_mbc if this succeeds, or will free which ever one
291 * ends up not being used as sr->command.
292 *
293 * The encrypted request in in_mbc is left unmodified here,
294 * and free'd by the caller when appropriate.
295 *
296 * Error return values here are just for visibility in dtrace.
297 * Anything non-zero results in a connection drop.
298 */
299 int
smb3_decrypt_sr(smb_request_t * sr,struct mbuf_chain * in_mbc,struct mbuf_chain * out_mbc)300 smb3_decrypt_sr(smb_request_t *sr,
301 struct mbuf_chain *in_mbc, // transform header + ciphertext
302 struct mbuf_chain *out_mbc) // cleartext
303 {
304 smb_enc_ctx_t ctx;
305 uint8_t th_raw[SMB3_TFORM_HDR_SIZE];
306 uint8_t *authdata;
307 size_t authlen;
308 size_t cipherlen;
309 smb_vdb_t *in_vdb = NULL;
310 smb_vdb_t *out_vdb = NULL;
311 smb_session_t *s = sr->session;
312 smb_user_t *u;
313 struct smb_key *dec_key;
314 int cnt, rc;
315 boolean_t gcm;
316 size_t nonce_size;
317 uint_t keylen;
318
319 if (s->enc_mech == NULL)
320 return (SET_ERROR(-1));
321
322 switch (s->smb31_enc_cipherid) {
323 default:
324 ASSERT(0);
325 /* fallthrough */
326 case SMB3_CIPHER_AES128_CCM: // 1
327 gcm = B_FALSE;
328 nonce_size = SMB3_AES_CCM_NONCE_SIZE;
329 keylen = AES128_KEY_LENGTH;
330 break;
331 case SMB3_CIPHER_AES128_GCM: // 2
332 gcm = B_TRUE;
333 nonce_size = SMB3_AES_GCM_NONCE_SIZE;
334 keylen = AES128_KEY_LENGTH;
335 break;
336 case SMB3_CIPHER_AES256_CCM: // 3
337 gcm = B_FALSE;
338 nonce_size = SMB3_AES_CCM_NONCE_SIZE;
339 keylen = AES256_KEY_LENGTH;
340 break;
341 case SMB3_CIPHER_AES256_GCM: // 4
342 gcm = B_TRUE;
343 nonce_size = SMB3_AES_GCM_NONCE_SIZE;
344 keylen = AES256_KEY_LENGTH;
345 break;
346 }
347
348 /*
349 * Get the transform header, in both raw form and decoded,
350 * then remove the transform header from the message.
351 * Note: the signature lands in sr->smb2_sig
352 */
353 if (smb_mbc_peek(in_mbc, 0, "#c",
354 SMB3_TFORM_HDR_SIZE, th_raw) != 0) {
355 return (SET_ERROR(-2));
356 }
357 rc = smb3_decode_tform_header(sr, in_mbc);
358 if (rc != 0) {
359 return (SET_ERROR(-3));
360 }
361 m_adjust(in_mbc->chain, SMB3_TFORM_HDR_SIZE);
362 ASSERT(in_mbc->max_bytes > SMB3_TFORM_HDR_SIZE);
363 in_mbc->max_bytes -= SMB3_TFORM_HDR_SIZE;
364 in_mbc->chain_offset = 0;
365
366 /*
367 * Bounds-check the stated length of the encapsulated message.
368 */
369 if (sr->th_msglen < SMB2_HDR_SIZE ||
370 sr->th_msglen > in_mbc->max_bytes) {
371 return (SET_ERROR(-4));
372 }
373 cipherlen = sr->th_msglen + SMB2_SIG_SIZE;
374
375 /*
376 * Lookup/validate the transform session ID so we'll
377 * have the key we'll need. Release for this happens
378 * in smb_request_free().
379 */
380 u = smb_session_lookup_ssnid(s, sr->th_ssnid);
381 if (u == NULL) {
382 return (SET_ERROR(-5));
383 }
384 sr->th_sid_user = u;
385 dec_key = &u->u_dec_key;
386 if (dec_key->len != keylen) {
387 return (SET_ERROR(-6));
388 }
389
390 /*
391 * Initialize crypto I/F: mech, params, key
392 *
393 * Unlike signing, which uses one global mech struct,
394 * encryption requires modifying the mech to add a
395 * per-use param struct. Thus, we need to make a copy.
396 */
397 bzero(&ctx, sizeof (ctx));
398 ctx.mech = *((smb_crypto_mech_t *)s->enc_mech);
399
400 /*
401 * The transform header, minus the PROTOCOL_ID and the
402 * SIGNATURE, is authenticated but not encrypted.
403 * (That's the "auth data" passed to init)
404 *
405 * Param init for CCM also needs the cipher length, which is
406 * the clear length + 16, but note that the last 16 bytes is
407 * the signature in the transform header.
408 */
409 authdata = th_raw + SMB3_NONCE_OFFS;
410 authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
411
412 if (gcm) {
413 smb3_crypto_init_gcm_param(&ctx,
414 sr->th_nonce, nonce_size,
415 authdata, authlen);
416 } else {
417 smb3_crypto_init_ccm_param(&ctx,
418 sr->th_nonce, nonce_size,
419 authdata, authlen, cipherlen);
420 }
421
422 rc = smb3_decrypt_init(&ctx,
423 dec_key->key, dec_key->len);
424 if (rc != 0)
425 return (SET_ERROR(-7));
426
427 /*
428 * Build a UIO vector for the ciphertext (in)
429 * a: remainder of the 1s segment after the transform header
430 * b: all subsequent segments of this message
431 * c: final 16 byte signature from the transform header
432 */
433 in_vdb = smb3_get_vdb(sr);
434 in_vdb->vdb_uio.uio_resid = sr->th_msglen;
435 rc = smb_mbuf_mkuio(in_mbc->chain, &in_vdb->vdb_uio);
436 if (rc != 0)
437 return (SET_ERROR(-8));
438
439 /* Add one more uio seg. for the signature. */
440 cnt = in_vdb->vdb_uio.uio_iovcnt;
441 if ((cnt + 1) > MAX_IOVEC)
442 return (SET_ERROR(-9));
443 in_vdb->vdb_uio.uio_iov[cnt].iov_base = (void *)sr->smb2_sig;
444 in_vdb->vdb_uio.uio_iov[cnt].iov_len = SMB2_SIG_SIZE;
445 in_vdb->vdb_uio.uio_iovcnt = cnt + 1;
446 in_vdb->vdb_uio.uio_resid += SMB2_SIG_SIZE;
447
448 /*
449 * Build a UIO vector for the cleartext (out)
450 */
451 out_vdb = smb3_get_vdb(sr);
452 out_vdb->vdb_uio.uio_resid = sr->th_msglen;
453 rc = smb_mbuf_mkuio(out_mbc->chain, &out_vdb->vdb_uio);
454 if (rc != 0)
455 return (SET_ERROR(-10));
456
457 /*
458 * Have in/out UIO descriptors. Decrypt!
459 */
460 rc = smb3_decrypt_uio(&ctx, &in_vdb->vdb_uio, &out_vdb->vdb_uio);
461 if (rc != 0) {
462 #ifdef DEBUG
463 cmn_err(CE_WARN, "smb3_decrypt_uio failed");
464 #endif
465 return (SET_ERROR(-11));
466 }
467
468 return (rc);
469 }
470
471 /*
472 * Encrypt the response in in_mbc into out_mbc which as been
473 * setup by the caller. The caller will send out_mbc if this
474 * returns success, and otherwise will free out_mbc.
475 *
476 * The cleartext response in in_mbc is left unmodified here,
477 * and free'd in smb_request_free.
478 *
479 * Error return values here are just for visibility in dtrace.
480 * Anything non-zero results in a connection drop.
481 */
482 int
smb3_encrypt_sr(smb_request_t * sr,struct mbuf_chain * in_mbc,struct mbuf_chain * out_mbc)483 smb3_encrypt_sr(smb_request_t *sr,
484 struct mbuf_chain *in_mbc, // cleartext
485 struct mbuf_chain *out_mbc) // transform header + ciphertext
486 {
487 smb_enc_ctx_t ctx;
488 uint8_t th_raw[SMB3_TFORM_HDR_SIZE];
489 uint8_t *authdata;
490 size_t authlen;
491 smb_vdb_t *in_vdb = NULL;
492 smb_vdb_t *out_vdb = NULL;
493 smb_session_t *s = sr->session;
494 smb_user_t *u = sr->th_sid_user;
495 struct smb_key *enc_key = &u->u_enc_key;
496 int cnt, rc;
497 boolean_t gcm;
498 size_t nonce_size;
499 uint_t keylen;
500
501 VERIFY(u != NULL); // and have sr->th_ssnid
502
503 switch (s->smb31_enc_cipherid) {
504 default:
505 ASSERT(0);
506 /* fallthrough */
507 case SMB3_CIPHER_AES128_CCM: // 1
508 gcm = B_FALSE;
509 nonce_size = SMB3_AES_CCM_NONCE_SIZE;
510 keylen = AES128_KEY_LENGTH;
511 break;
512 case SMB3_CIPHER_AES128_GCM: // 2
513 gcm = B_TRUE;
514 nonce_size = SMB3_AES_GCM_NONCE_SIZE;
515 keylen = AES128_KEY_LENGTH;
516 break;
517 case SMB3_CIPHER_AES256_CCM: // 3
518 gcm = B_FALSE;
519 nonce_size = SMB3_AES_CCM_NONCE_SIZE;
520 keylen = AES256_KEY_LENGTH;
521 break;
522 case SMB3_CIPHER_AES256_GCM: // 4
523 gcm = B_TRUE;
524 nonce_size = SMB3_AES_GCM_NONCE_SIZE;
525 keylen = AES256_KEY_LENGTH;
526 break;
527 }
528 if (s->enc_mech == NULL || enc_key->len != keylen) {
529 return (SET_ERROR(-1));
530 }
531
532 /*
533 * Need to fill in the transform header for everything
534 * after the signature, needed as the "auth" data.
535 * The signature is stuffed in later. So we need:
536 * the nonce, msgsize, flags, th_ssnid
537 */
538 rc = smb3_encrypt_gen_nonce(u, sr->th_nonce, nonce_size);
539 if (rc != 0) {
540 cmn_err(CE_WARN, "ran out of nonces");
541 return (SET_ERROR(-2));
542 }
543 if (smb3_encode_tform_header(sr, out_mbc) != 0) {
544 cmn_err(CE_WARN, "couldn't encode transform header");
545 return (SET_ERROR(-3));
546 }
547
548 /* Get the raw header to use as auth data */
549 if (smb_mbc_peek(out_mbc, 0, "#c",
550 SMB3_TFORM_HDR_SIZE, th_raw) != 0)
551 return (SET_ERROR(-4));
552
553 /*
554 * Initialize crypto I/F: mech, params, key
555 *
556 * Unlike signing, which uses one global mech struct,
557 * encryption requires modifying the mech to add a
558 * per-use param struct. Thus, we need to make a copy.
559 */
560 bzero(&ctx, sizeof (ctx));
561 ctx.mech = *((smb_crypto_mech_t *)s->enc_mech);
562
563 /*
564 * The transform header, minus the PROTOCOL_ID and the
565 * SIGNATURE, is authenticated but not encrypted.
566 * (That's the "auth data" passed to init)
567 *
568 * Param init for CCM also needs the cipher length, which is
569 * the clear length + 16, but note that the last 16 bytes is
570 * the signature in the transform header.
571 *
572 * Note: sr->th_msglen already set by caller
573 */
574 authdata = th_raw + SMB3_NONCE_OFFS;
575 authlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
576
577 if (gcm) {
578 smb3_crypto_init_gcm_param(&ctx,
579 sr->th_nonce, nonce_size,
580 authdata, authlen);
581 } else {
582 smb3_crypto_init_ccm_param(&ctx,
583 sr->th_nonce, nonce_size,
584 authdata, authlen, sr->th_msglen);
585 }
586
587 rc = smb3_encrypt_init(&ctx,
588 enc_key->key, enc_key->len);
589 if (rc != 0)
590 return (SET_ERROR(-5));
591
592 /*
593 * Build a UIO vector for the cleartext (in)
594 */
595 in_vdb = smb3_get_vdb(sr);
596 in_vdb->vdb_uio.uio_resid = sr->th_msglen;
597 rc = smb_mbuf_mkuio(in_mbc->chain, &in_vdb->vdb_uio);
598 if (rc != 0)
599 return (SET_ERROR(-6));
600
601 /*
602 * Build a UIO vector for the ciphertext (out)
603 * a: remainder of the 1s segment after the transform header
604 * b: all subsequent segments of this message
605 * c: final 16 byte signature that will go in the TH
606 *
607 * Caller puts transform header in its own mblk so we can
608 * just skip the first mlbk when building the uio.
609 */
610 out_vdb = smb3_get_vdb(sr);
611 out_vdb->vdb_uio.uio_resid = sr->th_msglen;
612 rc = smb_mbuf_mkuio(out_mbc->chain->m_next, &out_vdb->vdb_uio);
613 if (rc != 0)
614 return (SET_ERROR(-7));
615
616 /* Add one more uio seg. for the signature. */
617 cnt = out_vdb->vdb_uio.uio_iovcnt;
618 if ((cnt + 1) > MAX_IOVEC)
619 return (SET_ERROR(-8));
620 out_vdb->vdb_uio.uio_iov[cnt].iov_base = (void *)sr->smb2_sig;
621 out_vdb->vdb_uio.uio_iov[cnt].iov_len = SMB2_SIG_SIZE;
622 out_vdb->vdb_uio.uio_iovcnt = cnt + 1;
623 out_vdb->vdb_uio.uio_resid += SMB2_SIG_SIZE;
624
625 /*
626 * Have in/out UIO descriptors. Encrypt!
627 */
628 rc = smb3_encrypt_uio(&ctx, &in_vdb->vdb_uio, &out_vdb->vdb_uio);
629 if (rc != 0) {
630 #ifdef DEBUG
631 cmn_err(CE_WARN, "smb3_encrypt_uio failed");
632 #endif
633 return (SET_ERROR(-9));
634 }
635
636 /*
637 * Now patch the final signature into the transform header
638 */
639 (void) smb_mbc_poke(out_mbc, SMB3_SIG_OFFS, "#c",
640 SMB2_SIG_SIZE, sr->smb2_sig);
641
642 return (rc);
643 }
644
645 void
smb3_encrypt_ssn_fini(smb_session_t * s)646 smb3_encrypt_ssn_fini(smb_session_t *s)
647 {
648 smb_crypto_mech_t *mech;
649
650 if ((mech = s->enc_mech) != NULL) {
651 kmem_free(mech, sizeof (*mech));
652 s->enc_mech = NULL;
653 }
654 }
655