xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c (revision b02947bf393d39f68e6c7fa8ccb98688f7f9c407)
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 Nexenta Systems, 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 #define	SMB3_AES_CCM_NONCE_SIZE	11
29 #define	SMB3_AES_GCM_NONCE_SIZE	12
30 
31 /*
32  * Arbitrary value used to prevent nonce reuse via overflow. Currently
33  * 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
34  * 2^32 concurrent messages when we hit this number.
35  */
36 static uint64_t smb3_max_nonce = 0xffffffff00000000ULL;
37 
38 /*
39  * Nonce generation based on draft-mcgrew-iv-gen-01
40  * "Generation of Deterministic Initialization Vectors (IVs) and Nonces"
41  *
42  * Generate an 8-byte random salt and a 3-byte random 'fixed' value.
43  * then, nonce = (++counter ^ salt) || fixed
44  *
45  * This protects against nonce-reuse (8-byte counter), as well as known
46  * attacks on reusing nonces with different keys
47  */
48 
49 void
50 smb3_encrypt_init_nonce(smb_user_t *user)
51 {
52 	user->u_nonce_cnt = 0;
53 	(void) random_get_pseudo_bytes(user->u_nonce_fixed,
54 	    sizeof (user->u_nonce_fixed));
55 	(void) random_get_pseudo_bytes((uint8_t *)&user->u_salt,
56 	    sizeof (user->u_salt));
57 }
58 
59 int
60 smb3_encrypt_gen_nonce(smb_user_t *user, uint8_t *buf, size_t len)
61 {
62 	uint64_t cnt = atomic_inc_64_nv(&user->u_nonce_cnt);
63 
64 	/*
65 	 * Nonces must be unique per-key for the life of the key.
66 	 * Bail before we roll over to avoid breaking the crypto.
67 	 */
68 
69 	if (cnt > smb3_max_nonce)
70 		return (-1);
71 
72 	cnt ^= user->u_salt;
73 	bcopy((uint8_t *)&cnt, buf, sizeof (cnt));
74 
75 	ASSERT(len > sizeof (cnt));
76 	bcopy(user->u_nonce_fixed, buf + sizeof (cnt), len - sizeof (cnt));
77 	return (0);
78 }
79 
80 int
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
120 smb3_encrypt_begin(smb_request_t *sr, smb_token_t *token)
121 {
122 	smb_session_t *s = sr->session;
123 	smb_user_t *u = sr->uid_user;
124 	struct smb_key *enc_key = &u->u_enc_key;
125 	struct smb_key *dec_key = &u->u_dec_key;
126 	uint32_t derived_keylen, input_keylen;
127 
128 	/*
129 	 * In order to enforce encryption, all users need to
130 	 * have Session.EncryptData properly set, even anon/guest.
131 	 */
132 	u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
133 	enc_key->len = 0;
134 	dec_key->len = 0;
135 
136 	/*
137 	 * If we don't have a session key, we'll fail later when a
138 	 * request that requires (en/de)cryption can't be (en/de)crypted.
139 	 * Also don't bother initializing if we don't have a mechanism.
140 	 */
141 	if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
142 	    s->enc_mech == NULL)
143 		return;
144 
145 	/*
146 	 * Compute and store the encryption keys, which live in
147 	 * the user structure.
148 	 */
149 
150 	/*
151 	 * For SMB3, the encrypt/decrypt keys are derived from
152 	 * the session key using KDF in counter mode.
153 	 *
154 	 * AES256 Keys are derived from the 'FullSessionKey', which is the
155 	 * entirety of what we got in the token; AES128 Keys are derived from
156 	 * the 'SessionKey', which is the first 16 bytes of the key we got in
157 	 * the token.
158 	 */
159 	if (s->dialect >= SMB_VERS_3_11) {
160 		if (s->smb31_enc_cipherid == SMB3_CIPHER_AES256_GCM ||
161 		    s->smb31_enc_cipherid == SMB3_CIPHER_AES256_CCM) {
162 			derived_keylen = AES256_KEY_LENGTH;
163 			input_keylen = token->tkn_ssnkey.len;
164 		} else {
165 			derived_keylen = AES128_KEY_LENGTH;
166 			input_keylen = MIN(SMB2_SSN_KEYLEN,
167 			    token->tkn_ssnkey.len);
168 		}
169 
170 		if (smb3_kdf(enc_key->key, derived_keylen,
171 		    token->tkn_ssnkey.val, input_keylen,
172 		    (uint8_t *)"SMBS2CCipherKey", 16,
173 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
174 			return;
175 
176 		if (smb3_kdf(dec_key->key, derived_keylen,
177 		    token->tkn_ssnkey.val, input_keylen,
178 		    (uint8_t *)"SMBC2SCipherKey", 16,
179 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
180 			return;
181 
182 		enc_key->len = derived_keylen;
183 		dec_key->len = derived_keylen;
184 	} else {
185 		derived_keylen = AES128_KEY_LENGTH;
186 		input_keylen = MIN(SMB2_SSN_KEYLEN, token->tkn_ssnkey.len);
187 
188 		if (smb3_kdf(enc_key->key, derived_keylen,
189 		    token->tkn_ssnkey.val, input_keylen,
190 		    (uint8_t *)"SMB2AESCCM", 11,
191 		    (uint8_t *)"ServerOut", 10) != 0)
192 			return;
193 
194 		if (smb3_kdf(dec_key->key, derived_keylen,
195 		    token->tkn_ssnkey.val, input_keylen,
196 		    (uint8_t *)"SMB2AESCCM", 11,
197 		    (uint8_t *)"ServerIn ", 10) != 0)
198 			return;
199 
200 		enc_key->len = derived_keylen;
201 		dec_key->len = derived_keylen;
202 	}
203 
204 	smb3_encrypt_init_nonce(u);
205 }
206 
207 /*
208  * Decrypt the request in sr->command.
209  * This decrypts "in place", though due to CCM's design,
210  * it processes all input before doing any output.
211  */
212 int
213 smb3_decrypt_sr(smb_request_t *sr)
214 {
215 	struct mbuf_chain *mbc = &sr->command;
216 	smb_session_t *s = sr->session;
217 	smb_user_t *u = sr->tform_ssn;
218 	uint8_t tmp_hdr[SMB2_HDR_SIZE];
219 	smb3_enc_ctx_t ctx;
220 	struct smb_key *dec_key = &u->u_dec_key;
221 	struct mbuf *mbuf;
222 	int offset, resid, tlen, rc;
223 	smb3_crypto_param_t param;
224 	smb_crypto_mech_t mech;
225 	boolean_t gcm =
226 	    s->smb31_enc_cipherid == SMB3_CIPHER_AES256_GCM ||
227 	    s->smb31_enc_cipherid == SMB3_CIPHER_AES128_GCM;
228 	size_t nonce_size = (gcm ?
229 	    SMB3_AES_GCM_NONCE_SIZE :
230 	    SMB3_AES_CCM_NONCE_SIZE);
231 
232 	ASSERT(u != NULL);
233 
234 	if (s->enc_mech == NULL || dec_key->len == 0) {
235 		return (-1);
236 	}
237 
238 	tlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
239 	offset = mbc->chain_offset + SMB3_NONCE_OFFS;
240 	resid = mbc->max_bytes - offset;
241 
242 	if (resid < (sr->msgsize + tlen)) {
243 		cmn_err(CE_WARN, "too little data to decrypt");
244 		return (-1);
245 	}
246 
247 	if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0) {
248 		return (-1);
249 	}
250 
251 	offset += tlen;
252 	resid -= tlen;
253 
254 	/*
255 	 * The transform header, minus the PROTOCOL_ID and the
256 	 * SIGNATURE, is authenticated but not encrypted.
257 	 */
258 	if (gcm)
259 		smb3_crypto_init_gcm_param(&param, sr->nonce, nonce_size,
260 		    tmp_hdr, tlen);
261 	else
262 		smb3_crypto_init_ccm_param(&param, sr->nonce, nonce_size,
263 		    tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
264 
265 	/*
266 	 * Unlike signing, which uses one global mech struct,
267 	 * encryption requires modifying the mech to add a
268 	 * per-use param struct. Thus, we need to make a copy.
269 	 */
270 	mech = *(smb_crypto_mech_t *)s->enc_mech;
271 	rc = smb3_decrypt_init(&ctx, &mech, &param,
272 	    dec_key->key, dec_key->len);
273 	if (rc != 0) {
274 		return (rc);
275 	}
276 
277 	/*
278 	 * Digest the rest of the SMB packet, starting at the data
279 	 * just after the SMB header.
280 	 *
281 	 * Advance to the src mbuf where we start digesting.
282 	 */
283 	mbuf = mbc->chain;
284 	while (mbuf != NULL && (offset >= mbuf->m_len)) {
285 		offset -= mbuf->m_len;
286 		mbuf = mbuf->m_next;
287 	}
288 
289 	if (mbuf == NULL)
290 		return (-1);
291 
292 	/*
293 	 * Digest the remainder of this mbuf, limited to the
294 	 * residual count, and starting at the current offset.
295 	 */
296 	tlen = mbuf->m_len - offset;
297 	if (tlen > resid)
298 		tlen = resid;
299 
300 	rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data + offset, tlen);
301 	if (rc != 0) {
302 		return (rc);
303 	}
304 	resid -= tlen;
305 
306 	/*
307 	 * Digest any more mbufs in the chain.
308 	 */
309 	while (resid > 0) {
310 		mbuf = mbuf->m_next;
311 		if (mbuf == NULL) {
312 			smb3_encrypt_cancel(&ctx);
313 			return (-1);
314 		}
315 		tlen = mbuf->m_len;
316 		if (tlen > resid)
317 			tlen = resid;
318 		rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
319 		if (rc != 0) {
320 			return (rc);
321 		}
322 		resid -= tlen;
323 	}
324 
325 	/*
326 	 * AES_CCM processes the signature like normal data.
327 	 */
328 	rc = smb3_decrypt_update(&ctx, sr->smb2_sig, SMB2_SIG_SIZE);
329 
330 	if (rc != 0) {
331 		cmn_err(CE_WARN, "failed to process signature");
332 		return (rc);
333 	}
334 	/*
335 	 * smb3_decrypt_final will return an error
336 	 * if the signatures don't match.
337 	 */
338 	rc = smb3_decrypt_final(&ctx, sr->sr_request_buf, sr->sr_req_length);
339 
340 	/*
341 	 * We had to decode TFORM_HDR_SIZE bytes before we got here,
342 	 * and we just peeked the first TFORM_HDR_SIZE bytes at the
343 	 * beginning of this function, so this can't underflow.
344 	 */
345 	ASSERT(sr->command.max_bytes > SMB3_TFORM_HDR_SIZE);
346 	sr->command.max_bytes -= SMB3_TFORM_HDR_SIZE;
347 	return (rc);
348 }
349 
350 /*
351  * Encrypt the response in in_mbc, and output
352  * an encrypted response in out_mbc.
353  * The data in in_mbc is preserved.
354  */
355 int
356 smb3_encrypt_sr(smb_request_t *sr, struct mbuf_chain *in_mbc,
357     struct mbuf_chain *out_mbc)
358 {
359 	smb_session_t *s = sr->session;
360 	smb_user_t *u = sr->tform_ssn;
361 	uint8_t *buf = (uint8_t *)out_mbc->chain->m_data;
362 	size_t buflen = out_mbc->max_bytes;
363 	smb3_enc_ctx_t ctx;
364 	struct smb_key *enc_key = &u->u_enc_key;
365 	struct mbuf *mbuf;
366 	int resid, tlen, rc;
367 	smb3_crypto_param_t param;
368 	smb_crypto_mech_t mech;
369 	boolean_t gcm =
370 	    s->smb31_enc_cipherid == SMB3_CIPHER_AES256_GCM ||
371 	    s->smb31_enc_cipherid == SMB3_CIPHER_AES128_GCM;
372 	size_t nonce_size = (gcm ?
373 	    SMB3_AES_GCM_NONCE_SIZE :
374 	    SMB3_AES_CCM_NONCE_SIZE);
375 
376 	ASSERT(u != NULL);
377 
378 	if (s->enc_mech == NULL || enc_key->len == 0) {
379 		return (-1);
380 	}
381 
382 	rc = smb3_encrypt_gen_nonce(u, sr->nonce, nonce_size);
383 
384 	if (rc != 0) {
385 		cmn_err(CE_WARN, "ran out of nonces");
386 		return (-1);
387 	}
388 
389 	(void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
390 	    nonce_size, sr->nonce);
391 
392 	resid = in_mbc->max_bytes;
393 
394 	/*
395 	 * The transform header, minus the PROTOCOL_ID and the
396 	 * SIGNATURE, is authenticated but not encrypted.
397 	 */
398 	if (gcm)
399 		smb3_crypto_init_gcm_param(&param, sr->nonce, nonce_size,
400 		    buf + SMB3_NONCE_OFFS,
401 		    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS);
402 	else
403 		smb3_crypto_init_ccm_param(&param, sr->nonce, nonce_size,
404 		    buf + SMB3_NONCE_OFFS,
405 		    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS, resid);
406 
407 	/*
408 	 * Unlike signing, which uses one global mech struct,
409 	 * encryption requires modifying the mech to add a
410 	 * per-use param struct. Thus, we need to make a copy.
411 	 */
412 	mech = *(smb_crypto_mech_t *)s->enc_mech;
413 	rc = smb3_encrypt_init(&ctx, &mech, &param,
414 	    enc_key->key, enc_key->len, buf + SMB3_TFORM_HDR_SIZE,
415 	    buflen - SMB3_TFORM_HDR_SIZE);
416 	if (rc != 0) {
417 		return (rc);
418 	}
419 
420 	/*
421 	 * Unlike signing and decryption, we're processing the entirety of the
422 	 * message here, so we don't skip anything.
423 	 */
424 	mbuf = in_mbc->chain;
425 	while (resid > 0 && mbuf != NULL) {
426 		tlen = mbuf->m_len;
427 		if (tlen > resid)
428 			tlen = resid;
429 		rc = smb3_encrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
430 		if (rc != 0) {
431 			return (rc);
432 		}
433 		resid -= tlen;
434 		mbuf = mbuf->m_next;
435 	}
436 
437 	if (mbuf == NULL && resid > 0) {
438 		cmn_err(CE_WARN, "not enough data to encrypt");
439 		smb3_encrypt_cancel(&ctx);
440 		return (-1);
441 	}
442 
443 	rc = smb3_encrypt_final(&ctx, buf + SMB3_SIG_OFFS);
444 
445 	return (rc);
446 }
447 
448 void
449 smb3_encrypt_fini(smb_session_t *s)
450 {
451 	smb_crypto_mech_t *mech;
452 
453 	if ((mech = s->enc_mech) != NULL) {
454 		kmem_free(mech, sizeof (*mech));
455 		s->enc_mech = NULL;
456 	}
457 }
458