Print this page
12513 SMB 3.1.1 support for server
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c
+++ new/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14 + * Copyright 2020 RackTop Systems, Inc.
14 15 */
15 16
16 17 /*
17 18 * Routines for smb3 encryption.
18 19 */
19 20
20 21 #include <smbsrv/smb2_kproto.h>
21 22 #include <smbsrv/smb_kcrypt.h>
22 23 #include <sys/random.h>
23 24 #include <sys/cmn_err.h>
24 25
25 26 #define SMB3_NONCE_OFFS 20
26 27 #define SMB3_SIG_OFFS 4
27 -#define SMB3_NONCE_SIZE 11 /* 12 for gcm later */
28 -
29 -/*
30 - * Inputs to KDF for EncryptionKey and DecryptionKey.
31 - * See comment for smb3_do_kdf for content.
32 - */
33 -static uint8_t encrypt_kdf_input[30] = {
34 - 0, 0, 0, 1, 'S', 'M', 'B', '2',
35 - 'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
36 - 'S', 'e', 'r', 'v', 'e', 'r', 'O',
37 - 'u', 't', 0, 0, 0, 0, 0x80 };
38 -
39 -static uint8_t decrypt_kdf_input[30] = {
40 - 0, 0, 0, 1, 'S', 'M', 'B', '2',
41 - 'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
42 - 'S', 'e', 'r', 'v', 'e', 'r', 'I',
43 - 'n', ' ', 0, 0, 0, 0, 0x80 };
28 +#define SMB3_AES128_CCM_NONCE_SIZE 11
29 +#define SMB3_AES128_GCM_NONCE_SIZE 12
44 30
45 31 /*
46 32 * Arbitrary value used to prevent nonce reuse via overflow. Currently
47 33 * 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
48 34 * 2^32 concurrent messages when we hit this number.
49 35 */
50 36 static uint64_t smb3_max_nonce = 0xffffffff00000000ULL;
51 37
52 38 /*
53 39 * Nonce generation based on draft-mcgrew-iv-gen-01
54 40 * "Generation of Deterministic Initialization Vectors (IVs) and Nonces"
55 41 *
56 42 * Generate an 8-byte random salt and a 3-byte random 'fixed' value.
57 43 * then, nonce = (++counter ^ salt) || fixed
58 44 *
59 45 * This protects against nonce-reuse (8-byte counter), as well as known
60 46 * attacks on reusing nonces with different keys
61 47 */
62 48
63 49 void
64 50 smb3_encrypt_init_nonce(smb_user_t *user)
65 51 {
66 52 user->u_nonce_cnt = 0;
67 53 (void) random_get_pseudo_bytes(user->u_nonce_fixed,
68 54 sizeof (user->u_nonce_fixed));
69 55 (void) random_get_pseudo_bytes((uint8_t *)&user->u_salt,
70 56 sizeof (user->u_salt));
71 57 }
72 58
73 59 int
74 60 smb3_encrypt_gen_nonce(smb_user_t *user, uint8_t *buf, size_t len)
75 61 {
76 62 uint64_t cnt = atomic_inc_64_nv(&user->u_nonce_cnt);
77 63
78 64 /*
79 65 * Nonces must be unique per-key for the life of the key.
80 66 * Bail before we roll over to avoid breaking the crypto.
81 67 */
82 68
83 69 if (cnt > smb3_max_nonce)
84 70 return (-1);
85 71
86 72 cnt ^= user->u_salt;
87 73 bcopy((uint8_t *)&cnt, buf, sizeof (cnt));
88 74
89 75 ASSERT(len > sizeof (cnt));
90 76 bcopy(user->u_nonce_fixed, buf + sizeof (cnt), len - sizeof (cnt));
91 77 return (0);
92 78 }
↓ open down ↓ |
39 lines elided |
↑ open up ↑ |
93 79
94 80 int
95 81 smb3_encrypt_init_mech(smb_session_t *s)
96 82 {
97 83 smb_crypto_mech_t *mech;
98 84 int rc;
99 85
100 86 if (s->enc_mech != NULL)
101 87 return (0);
102 88
89 + if (s->dialect < SMB_VERS_3_11)
90 + s->smb31_enc_cipherid = SMB3_CIPHER_AES128_CCM;
91 +
103 92 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
104 - rc = smb3_encrypt_getmech(mech);
93 +
94 + switch (s->smb31_enc_cipherid) {
95 + case SMB3_CIPHER_AES128_GCM:
96 + rc = smb3_aes_gcm_getmech(mech);
97 + break;
98 + case SMB3_CIPHER_AES128_CCM:
99 + rc = smb3_aes_ccm_getmech(mech);
100 + break;
101 + default:
102 + return (-1);
103 + }
104 +
105 105 if (rc != 0) {
106 106 kmem_free(mech, sizeof (*mech));
107 107 return (rc);
108 108 }
109 109 s->enc_mech = mech;
110 110
111 111 return (0);
112 112 }
113 113
114 114 /*
115 115 * Initializes keys/state required for SMB3 Encryption.
116 116 * Note: If a failure occurs here, don't fail the request.
117 117 * Instead, return an error when we attempt to encrypt/decrypt.
118 118 */
119 119 void
120 120 smb3_encrypt_begin(smb_request_t *sr, smb_token_t *token)
121 121 {
122 122 smb_session_t *s = sr->session;
123 123 smb_user_t *u = sr->uid_user;
124 124 struct smb_key *enc_key = &u->u_enc_key;
125 125 struct smb_key *dec_key = &u->u_dec_key;
126 126
127 127 /*
128 128 * In order to enforce encryption, all users need to
129 129 * have Session.EncryptData properly set, even anon/guest.
130 130 */
131 131 u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
132 132 enc_key->len = 0;
133 133 dec_key->len = 0;
134 134
135 135 /*
136 136 * If we don't have a session key, we'll fail later when a
137 137 * request that requires (en/de)cryption can't be (en/de)crypted.
138 138 * Also don't bother initializing if we don't have a mechanism.
139 139 */
140 140 if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
141 141 s->enc_mech == NULL)
142 142 return;
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
143 143
144 144 /*
145 145 * Compute and store the encryption keys, which live in
146 146 * the user structure.
147 147 */
148 148
149 149 /*
150 150 * For SMB3, the encrypt/decrypt keys are derived from
151 151 * the session key using KDF in counter mode.
152 152 */
153 - if (smb3_do_kdf(enc_key->key, encrypt_kdf_input,
154 - sizeof (encrypt_kdf_input), token->tkn_ssnkey.val,
155 - token->tkn_ssnkey.len) != 0)
156 - return;
157 -
158 - if (smb3_do_kdf(dec_key->key, decrypt_kdf_input,
159 - sizeof (decrypt_kdf_input), token->tkn_ssnkey.val,
160 - token->tkn_ssnkey.len) != 0)
161 - return;
153 + if (s->dialect >= SMB_VERS_3_11) {
154 + if (smb3_kdf(enc_key->key,
155 + token->tkn_ssnkey.val, token->tkn_ssnkey.len,
156 + (uint8_t *)"SMBS2CCipherKey", 16,
157 + s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
158 + return;
159 +
160 + if (smb3_kdf(dec_key->key,
161 + token->tkn_ssnkey.val, token->tkn_ssnkey.len,
162 + (uint8_t *)"SMBC2SCipherKey", 16,
163 + s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
164 + return;
165 + } else {
166 + if (smb3_kdf(enc_key->key,
167 + token->tkn_ssnkey.val, token->tkn_ssnkey.len,
168 + (uint8_t *)"SMB2AESCCM", 11,
169 + (uint8_t *)"ServerOut", 10) != 0)
170 + return;
171 +
172 + if (smb3_kdf(dec_key->key,
173 + token->tkn_ssnkey.val, token->tkn_ssnkey.len,
174 + (uint8_t *)"SMB2AESCCM", 11,
175 + (uint8_t *)"ServerIn ", 10) != 0)
176 + return;
177 + }
162 178
163 179 smb3_encrypt_init_nonce(u);
164 180
165 181 enc_key->len = SMB3_KEYLEN;
166 182 dec_key->len = SMB3_KEYLEN;
167 183 }
168 184
169 185 /*
170 186 * Decrypt the request in sr->command.
171 187 * This decrypts "in place", though due to CCM's design,
172 188 * it processes all input before doing any output.
173 189 */
174 190 int
175 191 smb3_decrypt_sr(smb_request_t *sr)
176 192 {
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
177 193 struct mbuf_chain *mbc = &sr->command;
178 194 smb_session_t *s = sr->session;
179 195 smb_user_t *u = sr->tform_ssn;
180 196 uint8_t tmp_hdr[SMB2_HDR_SIZE];
181 197 smb3_enc_ctx_t ctx;
182 198 struct smb_key *dec_key = &u->u_dec_key;
183 199 struct mbuf *mbuf;
184 200 int offset, resid, tlen, rc;
185 201 smb3_crypto_param_t param;
186 202 smb_crypto_mech_t mech;
203 + boolean_t gcm = sr->session->smb31_enc_cipherid ==
204 + SMB3_CIPHER_AES128_GCM;
205 + size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
206 + SMB3_AES128_CCM_NONCE_SIZE);
187 207
188 208 ASSERT(u != NULL);
189 209 if (s->enc_mech == NULL || dec_key->len != 16) {
190 210 return (-1);
191 211 }
192 212
193 213 tlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
194 214 offset = mbc->chain_offset + SMB3_NONCE_OFFS;
195 215 resid = mbc->max_bytes - offset;
196 216
197 217 if (resid < (sr->msgsize + tlen)) {
198 218 cmn_err(CE_WARN, "too little data to decrypt");
199 219 return (-1);
200 220 }
201 221
202 222 if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0) {
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
203 223 return (-1);
204 224 }
205 225
206 226 offset += tlen;
207 227 resid -= tlen;
208 228
209 229 /*
210 230 * The transform header, minus the PROTOCOL_ID and the
211 231 * SIGNATURE, is authenticated but not encrypted.
212 232 */
213 - smb3_crypto_init_param(¶m, sr->nonce, SMB3_NONCE_SIZE,
214 - tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
233 + if (gcm)
234 + smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
235 + tmp_hdr, tlen);
236 + else
237 + smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
238 + tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
215 239
216 240 /*
217 241 * Unlike signing, which uses one global mech struct,
218 242 * encryption requires modifying the mech to add a
219 243 * per-use param struct. Thus, we need to make a copy.
220 244 */
221 245 mech = *(smb_crypto_mech_t *)s->enc_mech;
222 246 rc = smb3_decrypt_init(&ctx, &mech, ¶m,
223 247 dec_key->key, dec_key->len);
224 248 if (rc != 0) {
225 249 return (rc);
226 250 }
227 251
228 252 /*
229 253 * Digest the rest of the SMB packet, starting at the data
230 254 * just after the SMB header.
231 255 *
232 256 * Advance to the src mbuf where we start digesting.
233 257 */
234 258 mbuf = mbc->chain;
235 259 while (mbuf != NULL && (offset >= mbuf->m_len)) {
236 260 offset -= mbuf->m_len;
237 261 mbuf = mbuf->m_next;
238 262 }
239 263
240 264 if (mbuf == NULL)
241 265 return (-1);
242 266
243 267 /*
244 268 * Digest the remainder of this mbuf, limited to the
245 269 * residual count, and starting at the current offset.
246 270 */
247 271 tlen = mbuf->m_len - offset;
248 272 if (tlen > resid)
249 273 tlen = resid;
250 274
251 275 rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data + offset, tlen);
252 276 if (rc != 0) {
253 277 return (rc);
254 278 }
255 279 resid -= tlen;
256 280
257 281 /*
258 282 * Digest any more mbufs in the chain.
259 283 */
260 284 while (resid > 0) {
261 285 mbuf = mbuf->m_next;
262 286 if (mbuf == NULL) {
263 287 smb3_encrypt_cancel(&ctx);
264 288 return (-1);
265 289 }
266 290 tlen = mbuf->m_len;
267 291 if (tlen > resid)
268 292 tlen = resid;
269 293 rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
270 294 if (rc != 0) {
271 295 return (rc);
272 296 }
273 297 resid -= tlen;
274 298 }
275 299
276 300 /*
277 301 * AES_CCM processes the signature like normal data.
278 302 */
279 303 rc = smb3_decrypt_update(&ctx, sr->smb2_sig, SMB2_SIG_SIZE);
280 304
281 305 if (rc != 0) {
282 306 cmn_err(CE_WARN, "failed to process signature");
283 307 return (rc);
284 308 }
285 309 /*
286 310 * smb3_decrypt_final will return an error
287 311 * if the signatures don't match.
288 312 */
289 313 rc = smb3_decrypt_final(&ctx, sr->sr_request_buf, sr->sr_req_length);
290 314
291 315 /*
292 316 * We had to decode TFORM_HDR_SIZE bytes before we got here,
293 317 * and we just peeked the first TFORM_HDR_SIZE bytes at the
294 318 * beginning of this function, so this can't underflow.
295 319 */
296 320 ASSERT(sr->command.max_bytes > SMB3_TFORM_HDR_SIZE);
297 321 sr->command.max_bytes -= SMB3_TFORM_HDR_SIZE;
298 322 return (rc);
299 323 }
300 324
301 325 /*
302 326 * Encrypt the response in in_mbc, and output
303 327 * an encrypted response in out_mbc.
304 328 * The data in in_mbc is preserved.
305 329 */
306 330 int
307 331 smb3_encrypt_sr(smb_request_t *sr, struct mbuf_chain *in_mbc,
308 332 struct mbuf_chain *out_mbc)
309 333 {
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
310 334 smb_session_t *s = sr->session;
311 335 smb_user_t *u = sr->tform_ssn;
312 336 uint8_t *buf = (uint8_t *)out_mbc->chain->m_data;
313 337 size_t buflen = out_mbc->max_bytes;
314 338 smb3_enc_ctx_t ctx;
315 339 struct smb_key *enc_key = &u->u_enc_key;
316 340 struct mbuf *mbuf;
317 341 int resid, tlen, rc;
318 342 smb3_crypto_param_t param;
319 343 smb_crypto_mech_t mech;
344 + boolean_t gcm = sr->session->smb31_enc_cipherid ==
345 + SMB3_CIPHER_AES128_GCM;
346 + size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
347 + SMB3_AES128_CCM_NONCE_SIZE);
320 348
321 349 ASSERT(u != NULL);
322 350 if (s->enc_mech == NULL || enc_key->len != 16) {
323 351 return (-1);
324 352 }
325 353
326 - rc = smb3_encrypt_gen_nonce(u, sr->nonce, SMB3_NONCE_SIZE);
354 + rc = smb3_encrypt_gen_nonce(u, sr->nonce, nonce_size);
327 355
328 356 if (rc != 0) {
329 357 cmn_err(CE_WARN, "ran out of nonces");
330 358 return (-1);
331 359 }
332 360
333 361 (void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
334 - SMB3_NONCE_SIZE, sr->nonce);
362 + nonce_size, sr->nonce);
335 363
336 364 resid = in_mbc->max_bytes;
337 365
338 366 /*
339 367 * The transform header, minus the PROTOCOL_ID and the
340 368 * SIGNATURE, is authenticated but not encrypted.
341 369 */
342 - smb3_crypto_init_param(¶m,
343 - sr->nonce, SMB3_NONCE_SIZE,
344 - buf + SMB3_NONCE_OFFS, SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS,
345 - resid);
370 + if (gcm)
371 + smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
372 + buf + SMB3_NONCE_OFFS,
373 + SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS);
374 + else
375 + smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
376 + buf + SMB3_NONCE_OFFS,
377 + SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS, resid);
346 378
347 379 /*
348 380 * Unlike signing, which uses one global mech struct,
349 381 * encryption requires modifying the mech to add a
350 382 * per-use param struct. Thus, we need to make a copy.
351 383 */
352 384 mech = *(smb_crypto_mech_t *)s->enc_mech;
353 385 rc = smb3_encrypt_init(&ctx, &mech, ¶m,
354 386 enc_key->key, enc_key->len, buf + SMB3_TFORM_HDR_SIZE,
355 387 buflen - SMB3_TFORM_HDR_SIZE);
356 388 if (rc != 0) {
357 389 return (rc);
358 390 }
359 391
360 392 /*
361 393 * Unlike signing and decryption, we're processing the entirety of the
362 394 * message here, so we don't skip anything.
363 395 */
364 396 mbuf = in_mbc->chain;
365 397 while (resid > 0 && mbuf != NULL) {
366 398 tlen = mbuf->m_len;
367 399 if (tlen > resid)
368 400 tlen = resid;
369 401 rc = smb3_encrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
370 402 if (rc != 0) {
371 403 return (rc);
372 404 }
373 405 resid -= tlen;
374 406 mbuf = mbuf->m_next;
375 407 }
376 408
377 409 if (mbuf == NULL && resid > 0) {
378 410 cmn_err(CE_WARN, "not enough data to encrypt");
379 411 smb3_encrypt_cancel(&ctx);
380 412 return (-1);
381 413 }
382 414
383 415 rc = smb3_encrypt_final(&ctx, buf + SMB3_SIG_OFFS);
384 416
385 417 return (rc);
386 418 }
387 419
388 420 void
389 421 smb3_encrypt_fini(smb_session_t *s)
390 422 {
391 423 smb_crypto_mech_t *mech;
392 424
393 425 if ((mech = s->enc_mech) != NULL) {
394 426 kmem_free(mech, sizeof (*mech));
395 427 s->enc_mech = NULL;
396 428 }
397 429 }
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX