xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c (revision ab017dba278352f85f904f92ba32ab12cee76cb2)
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 2020 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_AES128_CCM_NONCE_SIZE	11
29 #define	SMB3_AES128_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_AES128_GCM:
93 		rc = smb3_aes_gcm_getmech(mech);
94 		break;
95 	case SMB3_CIPHER_AES128_CCM:
96 		rc = smb3_aes_ccm_getmech(mech);
97 		break;
98 	default:
99 		rc = -1;
100 		break;
101 	}
102 
103 	if (rc != 0) {
104 		kmem_free(mech, sizeof (*mech));
105 		return (rc);
106 	}
107 	s->enc_mech = mech;
108 
109 	return (0);
110 }
111 
112 /*
113  * Initializes keys/state required for SMB3 Encryption.
114  * Note: If a failure occurs here, don't fail the request.
115  * Instead, return an error when we attempt to encrypt/decrypt.
116  */
117 void
118 smb3_encrypt_begin(smb_request_t *sr, smb_token_t *token)
119 {
120 	smb_session_t *s = sr->session;
121 	smb_user_t *u = sr->uid_user;
122 	struct smb_key *enc_key = &u->u_enc_key;
123 	struct smb_key *dec_key = &u->u_dec_key;
124 
125 	/*
126 	 * In order to enforce encryption, all users need to
127 	 * have Session.EncryptData properly set, even anon/guest.
128 	 */
129 	u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
130 	enc_key->len = 0;
131 	dec_key->len = 0;
132 
133 	/*
134 	 * If we don't have a session key, we'll fail later when a
135 	 * request that requires (en/de)cryption can't be (en/de)crypted.
136 	 * Also don't bother initializing if we don't have a mechanism.
137 	 */
138 	if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
139 	    s->enc_mech == NULL)
140 		return;
141 
142 	/*
143 	 * Compute and store the encryption keys, which live in
144 	 * the user structure.
145 	 */
146 
147 	/*
148 	 * For SMB3, the encrypt/decrypt keys are derived from
149 	 * the session key using KDF in counter mode.
150 	 */
151 	if (s->dialect >= SMB_VERS_3_11) {
152 		if (smb3_kdf(enc_key->key,
153 		    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
154 		    (uint8_t *)"SMBS2CCipherKey", 16,
155 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
156 			return;
157 
158 		if (smb3_kdf(dec_key->key,
159 		    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
160 		    (uint8_t *)"SMBC2SCipherKey", 16,
161 		    u->u_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
162 			return;
163 	} else {
164 		if (smb3_kdf(enc_key->key,
165 		    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
166 		    (uint8_t *)"SMB2AESCCM", 11,
167 		    (uint8_t *)"ServerOut", 10) != 0)
168 			return;
169 
170 		if (smb3_kdf(dec_key->key,
171 		    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
172 		    (uint8_t *)"SMB2AESCCM", 11,
173 		    (uint8_t *)"ServerIn ", 10) != 0)
174 			return;
175 	}
176 
177 	smb3_encrypt_init_nonce(u);
178 
179 	enc_key->len = SMB3_KEYLEN;
180 	dec_key->len = SMB3_KEYLEN;
181 }
182 
183 /*
184  * Decrypt the request in sr->command.
185  * This decrypts "in place", though due to CCM's design,
186  * it processes all input before doing any output.
187  */
188 int
189 smb3_decrypt_sr(smb_request_t *sr)
190 {
191 	struct mbuf_chain *mbc = &sr->command;
192 	smb_session_t *s = sr->session;
193 	smb_user_t *u = sr->tform_ssn;
194 	uint8_t tmp_hdr[SMB2_HDR_SIZE];
195 	smb3_enc_ctx_t ctx;
196 	struct smb_key *dec_key = &u->u_dec_key;
197 	struct mbuf *mbuf;
198 	int offset, resid, tlen, rc;
199 	smb3_crypto_param_t param;
200 	smb_crypto_mech_t mech;
201 	boolean_t gcm = sr->session->smb31_enc_cipherid ==
202 	    SMB3_CIPHER_AES128_GCM;
203 	size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
204 	    SMB3_AES128_CCM_NONCE_SIZE);
205 
206 	ASSERT(u != NULL);
207 	if (s->enc_mech == NULL || dec_key->len != 16) {
208 		return (-1);
209 	}
210 
211 	tlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
212 	offset = mbc->chain_offset + SMB3_NONCE_OFFS;
213 	resid = mbc->max_bytes - offset;
214 
215 	if (resid < (sr->msgsize + tlen)) {
216 		cmn_err(CE_WARN, "too little data to decrypt");
217 		return (-1);
218 	}
219 
220 	if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0) {
221 		return (-1);
222 	}
223 
224 	offset += tlen;
225 	resid -= tlen;
226 
227 	/*
228 	 * The transform header, minus the PROTOCOL_ID and the
229 	 * SIGNATURE, is authenticated but not encrypted.
230 	 */
231 	if (gcm)
232 		smb3_crypto_init_gcm_param(&param, sr->nonce, nonce_size,
233 		    tmp_hdr, tlen);
234 	else
235 		smb3_crypto_init_ccm_param(&param, sr->nonce, nonce_size,
236 		    tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
237 
238 	/*
239 	 * Unlike signing, which uses one global mech struct,
240 	 * encryption requires modifying the mech to add a
241 	 * per-use param struct. Thus, we need to make a copy.
242 	 */
243 	mech = *(smb_crypto_mech_t *)s->enc_mech;
244 	rc = smb3_decrypt_init(&ctx, &mech, &param,
245 	    dec_key->key, dec_key->len);
246 	if (rc != 0) {
247 		return (rc);
248 	}
249 
250 	/*
251 	 * Digest the rest of the SMB packet, starting at the data
252 	 * just after the SMB header.
253 	 *
254 	 * Advance to the src mbuf where we start digesting.
255 	 */
256 	mbuf = mbc->chain;
257 	while (mbuf != NULL && (offset >= mbuf->m_len)) {
258 		offset -= mbuf->m_len;
259 		mbuf = mbuf->m_next;
260 	}
261 
262 	if (mbuf == NULL)
263 		return (-1);
264 
265 	/*
266 	 * Digest the remainder of this mbuf, limited to the
267 	 * residual count, and starting at the current offset.
268 	 */
269 	tlen = mbuf->m_len - offset;
270 	if (tlen > resid)
271 		tlen = resid;
272 
273 	rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data + offset, tlen);
274 	if (rc != 0) {
275 		return (rc);
276 	}
277 	resid -= tlen;
278 
279 	/*
280 	 * Digest any more mbufs in the chain.
281 	 */
282 	while (resid > 0) {
283 		mbuf = mbuf->m_next;
284 		if (mbuf == NULL) {
285 			smb3_encrypt_cancel(&ctx);
286 			return (-1);
287 		}
288 		tlen = mbuf->m_len;
289 		if (tlen > resid)
290 			tlen = resid;
291 		rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
292 		if (rc != 0) {
293 			return (rc);
294 		}
295 		resid -= tlen;
296 	}
297 
298 	/*
299 	 * AES_CCM processes the signature like normal data.
300 	 */
301 	rc = smb3_decrypt_update(&ctx, sr->smb2_sig, SMB2_SIG_SIZE);
302 
303 	if (rc != 0) {
304 		cmn_err(CE_WARN, "failed to process signature");
305 		return (rc);
306 	}
307 	/*
308 	 * smb3_decrypt_final will return an error
309 	 * if the signatures don't match.
310 	 */
311 	rc = smb3_decrypt_final(&ctx, sr->sr_request_buf, sr->sr_req_length);
312 
313 	/*
314 	 * We had to decode TFORM_HDR_SIZE bytes before we got here,
315 	 * and we just peeked the first TFORM_HDR_SIZE bytes at the
316 	 * beginning of this function, so this can't underflow.
317 	 */
318 	ASSERT(sr->command.max_bytes > SMB3_TFORM_HDR_SIZE);
319 	sr->command.max_bytes -= SMB3_TFORM_HDR_SIZE;
320 	return (rc);
321 }
322 
323 /*
324  * Encrypt the response in in_mbc, and output
325  * an encrypted response in out_mbc.
326  * The data in in_mbc is preserved.
327  */
328 int
329 smb3_encrypt_sr(smb_request_t *sr, struct mbuf_chain *in_mbc,
330     struct mbuf_chain *out_mbc)
331 {
332 	smb_session_t *s = sr->session;
333 	smb_user_t *u = sr->tform_ssn;
334 	uint8_t *buf = (uint8_t *)out_mbc->chain->m_data;
335 	size_t buflen = out_mbc->max_bytes;
336 	smb3_enc_ctx_t ctx;
337 	struct smb_key *enc_key = &u->u_enc_key;
338 	struct mbuf *mbuf;
339 	int resid, tlen, rc;
340 	smb3_crypto_param_t param;
341 	smb_crypto_mech_t mech;
342 	boolean_t gcm = sr->session->smb31_enc_cipherid ==
343 	    SMB3_CIPHER_AES128_GCM;
344 	size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
345 	    SMB3_AES128_CCM_NONCE_SIZE);
346 
347 	ASSERT(u != NULL);
348 	if (s->enc_mech == NULL || enc_key->len != 16) {
349 		return (-1);
350 	}
351 
352 	rc = smb3_encrypt_gen_nonce(u, sr->nonce, nonce_size);
353 
354 	if (rc != 0) {
355 		cmn_err(CE_WARN, "ran out of nonces");
356 		return (-1);
357 	}
358 
359 	(void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
360 	    nonce_size, sr->nonce);
361 
362 	resid = in_mbc->max_bytes;
363 
364 	/*
365 	 * The transform header, minus the PROTOCOL_ID and the
366 	 * SIGNATURE, is authenticated but not encrypted.
367 	 */
368 	if (gcm)
369 		smb3_crypto_init_gcm_param(&param, sr->nonce, nonce_size,
370 		    buf + SMB3_NONCE_OFFS,
371 		    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS);
372 	else
373 		smb3_crypto_init_ccm_param(&param, sr->nonce, nonce_size,
374 		    buf + SMB3_NONCE_OFFS,
375 		    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS, resid);
376 
377 	/*
378 	 * Unlike signing, which uses one global mech struct,
379 	 * encryption requires modifying the mech to add a
380 	 * per-use param struct. Thus, we need to make a copy.
381 	 */
382 	mech = *(smb_crypto_mech_t *)s->enc_mech;
383 	rc = smb3_encrypt_init(&ctx, &mech, &param,
384 	    enc_key->key, enc_key->len, buf + SMB3_TFORM_HDR_SIZE,
385 	    buflen - SMB3_TFORM_HDR_SIZE);
386 	if (rc != 0) {
387 		return (rc);
388 	}
389 
390 	/*
391 	 * Unlike signing and decryption, we're processing the entirety of the
392 	 * message here, so we don't skip anything.
393 	 */
394 	mbuf = in_mbc->chain;
395 	while (resid > 0 && mbuf != NULL) {
396 		tlen = mbuf->m_len;
397 		if (tlen > resid)
398 			tlen = resid;
399 		rc = smb3_encrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
400 		if (rc != 0) {
401 			return (rc);
402 		}
403 		resid -= tlen;
404 		mbuf = mbuf->m_next;
405 	}
406 
407 	if (mbuf == NULL && resid > 0) {
408 		cmn_err(CE_WARN, "not enough data to encrypt");
409 		smb3_encrypt_cancel(&ctx);
410 		return (-1);
411 	}
412 
413 	rc = smb3_encrypt_final(&ctx, buf + SMB3_SIG_OFFS);
414 
415 	return (rc);
416 }
417 
418 void
419 smb3_encrypt_fini(smb_session_t *s)
420 {
421 	smb_crypto_mech_t *mech;
422 
423 	if ((mech = s->enc_mech) != NULL) {
424 		kmem_free(mech, sizeof (*mech));
425 		s->enc_mech = NULL;
426 	}
427 }
428