xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb2_signing.c (revision f52943a93040563107b95bccb9db87d9971ef47d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
24  */
25 /*
26  * These routines provide the SMB MAC signing for the SMB2 server.
27  * The routines calculate the signature of a SMB message in an mbuf chain.
28  *
29  * The following table describes the client server
30  * signing registry relationship
31  *
32  *		| Required	| Enabled     | Disabled
33  * -------------+---------------+------------ +--------------
34  * Required	| Signed	| Signed      | Fail
35  * -------------+---------------+-------------+-----------------
36  * Enabled	| Signed	| Signed      | Not Signed
37  * -------------+---------------+-------------+----------------
38  * Disabled	| Fail		| Not Signed  | Not Signed
39  */
40 
41 #include <sys/uio.h>
42 #include <smbsrv/smb2_kproto.h>
43 #include <smbsrv/smb_kcrypt.h>
44 #include <sys/isa_defs.h>
45 #include <sys/byteorder.h>
46 #include <sys/cmn_err.h>
47 
48 #define	SMB2_SIG_OFFS	48
49 #define	SMB2_SIG_SIZE	16
50 
51 typedef struct mac_ops {
52 	int (*mac_init)(smb_sign_ctx_t *, smb_crypto_mech_t *,
53 			uint8_t *, size_t);
54 	int (*mac_update)(smb_sign_ctx_t, uint8_t *, size_t);
55 	int (*mac_final)(smb_sign_ctx_t, uint8_t *);
56 } mac_ops_t;
57 
58 static int smb2_sign_calc_common(smb_request_t *, struct mbuf_chain *,
59     uint8_t *, mac_ops_t *);
60 
61 /*
62  * SMB2 wrapper functions
63  */
64 
65 static mac_ops_t
66 smb2_sign_ops = {
67 	smb2_hmac_init,
68 	smb2_hmac_update,
69 	smb2_hmac_final
70 };
71 
72 static int
73 smb2_sign_calc(smb_request_t *sr,
74     struct mbuf_chain *mbc,
75     uint8_t *digest16)
76 {
77 	int rv;
78 
79 	rv = smb2_sign_calc_common(sr, mbc, digest16, &smb2_sign_ops);
80 
81 	return (rv);
82 }
83 
84 /*
85  * Called during session destroy.
86  */
87 static void
88 smb2_sign_fini(smb_session_t *s)
89 {
90 	smb_crypto_mech_t *mech;
91 
92 	if ((mech = s->sign_mech) != NULL) {
93 		kmem_free(mech, sizeof (*mech));
94 		s->sign_mech = NULL;
95 	}
96 }
97 
98 /*
99  * SMB3 wrapper functions
100  */
101 
102 static struct mac_ops
103 smb3_sign_ops = {
104 	smb3_cmac_init,
105 	smb3_cmac_update,
106 	smb3_cmac_final
107 };
108 
109 static int
110 smb3_sign_calc(smb_request_t *sr,
111     struct mbuf_chain *mbc,
112     uint8_t *digest16)
113 {
114 	int rv;
115 
116 	rv = smb2_sign_calc_common(sr, mbc, digest16, &smb3_sign_ops);
117 
118 	return (rv);
119 }
120 
121 /*
122  * Input to KDF for SigningKey.
123  * See comment for smb3_do_kdf for content.
124  */
125 static uint8_t sign_kdf_input[29] = {
126 	0, 0, 0, 1, 'S', 'M', 'B', '2',
127 	'A', 'E', 'S', 'C', 'M', 'A', 'C', 0,
128 	0, 'S', 'm', 'b', 'S', 'i', 'g', 'n',
129 	0, 0, 0, 0, 0x80 };
130 
131 void
132 smb2_sign_init_mech(smb_session_t *s)
133 {
134 	smb_crypto_mech_t *mech;
135 	int (*get_mech)(smb_crypto_mech_t *);
136 	int (*sign_calc)(smb_request_t *, struct mbuf_chain *, uint8_t *);
137 	int rc;
138 
139 	if (s->sign_mech != NULL)
140 		return;
141 
142 	if (s->dialect >= SMB_VERS_3_0) {
143 		get_mech = smb3_cmac_getmech;
144 		sign_calc = smb3_sign_calc;
145 	} else {
146 		get_mech = smb2_hmac_getmech;
147 		sign_calc = smb2_sign_calc;
148 	}
149 
150 	mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
151 	rc = get_mech(mech);
152 	if (rc != 0) {
153 		kmem_free(mech, sizeof (*mech));
154 		return;
155 	}
156 	s->sign_mech = mech;
157 	s->sign_calc = sign_calc;
158 	s->sign_fini = smb2_sign_fini;
159 }
160 
161 /*
162  * smb2_sign_begin
163  * Handles both SMB2 & SMB3
164  *
165  * Get the mechanism info.
166  * Intializes MAC key based on the user session key and store it in
167  * the signing structure.  This begins signing on this session.
168  */
169 void
170 smb2_sign_begin(smb_request_t *sr, smb_token_t *token)
171 {
172 	smb_session_t *s = sr->session;
173 	smb_user_t *u = sr->uid_user;
174 	struct smb_key *sign_key = &u->u_sign_key;
175 
176 	sign_key->len = 0;
177 
178 	/*
179 	 * We should normally have a session key here because
180 	 * our caller filters out Anonymous and Guest logons.
181 	 * However, buggy clients could get us here without a
182 	 * session key, in which case we'll fail later when a
183 	 * request that requires signing can't be checked.
184 	 * Also, don't bother initializing if we don't have a mechanism.
185 	 */
186 	if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
187 	    s->sign_mech == NULL)
188 		return;
189 
190 	/*
191 	 * Compute and store the signing key, which lives in
192 	 * the user structure.
193 	 */
194 	if (s->dialect >= SMB_VERS_3_0) {
195 		/*
196 		 * For SMB3, the signing key is a "KDF" hash of the
197 		 * session key.
198 		 */
199 		if (smb3_do_kdf(sign_key->key, sign_kdf_input,
200 		    sizeof (sign_kdf_input), token->tkn_ssnkey.val,
201 		    token->tkn_ssnkey.len) != 0)
202 			return;
203 		sign_key->len = SMB3_KEYLEN;
204 	} else {
205 		/*
206 		 * For SMB2, the signing key is just the first 16 bytes
207 		 * of the session key (truncated or padded with zeros).
208 		 * [MS-SMB2] 3.2.5.3.1
209 		 */
210 		sign_key->len = SMB2_KEYLEN;
211 		bcopy(token->tkn_ssnkey.val, sign_key->key,
212 		    MIN(token->tkn_ssnkey.len, sign_key->len));
213 	}
214 
215 	mutex_enter(&u->u_mutex);
216 	if ((s->srv_secmode & SMB2_NEGOTIATE_SIGNING_ENABLED) != 0)
217 		u->u_sign_flags |= SMB_SIGNING_ENABLED;
218 	if ((s->srv_secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED) != 0 ||
219 	    (s->cli_secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED) != 0)
220 		u->u_sign_flags |=
221 		    SMB_SIGNING_ENABLED | SMB_SIGNING_CHECK;
222 	mutex_exit(&u->u_mutex);
223 
224 	/*
225 	 * If we just turned on signing, the current request
226 	 * (an SMB2 session setup) will have come in without
227 	 * SMB2_FLAGS_SIGNED (and not signed) but the response
228 	 * is is supposed to be signed. [MS-SMB2] 3.3.5.5
229 	 */
230 	if (u->u_sign_flags & SMB_SIGNING_ENABLED)
231 		sr->smb2_hdr_flags |= SMB2_FLAGS_SIGNED;
232 }
233 
234 /*
235  * smb2_sign_calc_common
236  *
237  * Calculates MAC signature for the given buffer and returns
238  * it in the mac_sign parameter.
239  *
240  * The signature algorithm is to compute HMAC SHA256 or AES_CMAC
241  * over the entire command, with the signature field set to zeros.
242  *
243  * Return 0 if  success else -1
244  */
245 
246 static int
247 smb2_sign_calc_common(smb_request_t *sr, struct mbuf_chain *mbc,
248     uint8_t *digest, mac_ops_t *ops)
249 {
250 	uint8_t tmp_hdr[SMB2_HDR_SIZE];
251 	smb_sign_ctx_t ctx = 0;
252 	smb_session_t *s = sr->session;
253 	smb_user_t *u = sr->uid_user;
254 	struct smb_key *sign_key = &u->u_sign_key;
255 	struct mbuf *mbuf;
256 	int offset, resid, tlen, rc;
257 
258 	if (s->sign_mech == NULL || sign_key->len == 0)
259 		return (-1);
260 
261 	/* smb2_hmac_init or smb3_cmac_init */
262 	rc = ops->mac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
263 	if (rc != 0)
264 		return (rc);
265 
266 	/*
267 	 * Work with a copy of the SMB2 header so we can
268 	 * clear the signature field without modifying
269 	 * the original message.
270 	 */
271 	tlen = SMB2_HDR_SIZE;
272 	offset = mbc->chain_offset;
273 	resid = mbc->max_bytes - offset;
274 	if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
275 		return (-1);
276 	bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
277 	/* smb2_hmac_update or smb3_cmac_update */
278 	if ((rc = ops->mac_update(ctx, tmp_hdr, tlen)) != 0)
279 		return (rc);
280 	offset += tlen;
281 	resid -= tlen;
282 
283 	/*
284 	 * Digest the rest of the SMB packet, starting at the data
285 	 * just after the SMB header.
286 	 *
287 	 * Advance to the src mbuf where we start digesting.
288 	 */
289 	mbuf = mbc->chain;
290 	while (mbuf != NULL && (offset >= mbuf->m_len)) {
291 		offset -= mbuf->m_len;
292 		mbuf = mbuf->m_next;
293 	}
294 
295 	if (mbuf == NULL)
296 		return (-1);
297 
298 	/*
299 	 * Digest the remainder of this mbuf, limited to the
300 	 * residual count, and starting at the current offset.
301 	 * (typically SMB2_HDR_SIZE)
302 	 */
303 	tlen = mbuf->m_len - offset;
304 	if (tlen > resid)
305 		tlen = resid;
306 	/* smb2_hmac_update or smb3_cmac_update */
307 	rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
308 	if (rc != 0)
309 		return (rc);
310 	resid -= tlen;
311 
312 	/*
313 	 * Digest any more mbufs in the chain.
314 	 */
315 	while (resid > 0) {
316 		mbuf = mbuf->m_next;
317 		if (mbuf == NULL)
318 			return (-1);
319 		tlen = mbuf->m_len;
320 		if (tlen > resid)
321 			tlen = resid;
322 		rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
323 		if (rc != 0)
324 			return (rc);
325 		resid -= tlen;
326 	}
327 
328 	/*
329 	 * smb2_hmac_final or smb3_cmac_final
330 	 * Note: digest is _always_ SMB2_SIG_SIZE,
331 	 * even if the mech uses a longer one.
332 	 *
333 	 * smb2_hmac_update or smb3_cmac_update
334 	 */
335 	if ((rc = ops->mac_final(ctx, digest)) != 0)
336 		return (rc);
337 
338 	return (0);
339 }
340 
341 /*
342  * smb2_sign_check_request
343  *
344  * Calculates MAC signature for the request mbuf chain
345  * using the next expected sequence number and compares
346  * it to the given signature.
347  *
348  * Note it does not check the signature for secondary transactions
349  * as their sequence number is the same as the original request.
350  *
351  * Return 0 if the signature verifies, otherwise, returns -1;
352  *
353  */
354 int
355 smb2_sign_check_request(smb_request_t *sr)
356 {
357 	uint8_t req_sig[SMB2_SIG_SIZE];
358 	uint8_t vfy_sig[SMB2_SIG_SIZE];
359 	struct mbuf_chain *mbc = &sr->smb_data;
360 	smb_session_t *s = sr->session;
361 	smb_user_t *u = sr->uid_user;
362 	int sig_off;
363 
364 	/*
365 	 * Don't check commands with a zero session ID.
366 	 * [MS-SMB2] 3.3.4.1.1
367 	 */
368 	if (sr->smb2_ssnid == 0 || u == NULL)
369 		return (0);
370 
371 	/* In case _sign_begin failed. */
372 	if (s->sign_calc == NULL)
373 		return (-1);
374 
375 	/* Get the request signature. */
376 	sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
377 	if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
378 		return (-1);
379 
380 	/*
381 	 * Compute the correct signature and compare.
382 	 * smb2_sign_calc() or smb3_sign_calc()
383 	 */
384 	if (s->sign_calc(sr, mbc, vfy_sig) != 0)
385 		return (-1);
386 	if (memcmp(vfy_sig, req_sig, SMB2_SIG_SIZE) != 0) {
387 		cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
388 		return (-1);
389 	}
390 
391 	return (0);
392 }
393 
394 /*
395  * smb2_sign_reply
396  *
397  * Calculates MAC signature for the given mbuf chain,
398  * and write it to the signature field in the mbuf.
399  *
400  */
401 void
402 smb2_sign_reply(smb_request_t *sr)
403 {
404 	uint8_t reply_sig[SMB2_SIG_SIZE];
405 	struct mbuf_chain tmp_mbc;
406 	smb_session_t *s = sr->session;
407 	smb_user_t *u = sr->uid_user;
408 	int hdr_off, msg_len;
409 
410 	if (u == NULL)
411 		return;
412 	if (s->sign_calc == NULL)
413 		return;
414 
415 	msg_len = sr->reply.chain_offset - sr->smb2_reply_hdr;
416 	(void) MBC_SHADOW_CHAIN(&tmp_mbc, &sr->reply,
417 	    sr->smb2_reply_hdr, msg_len);
418 
419 	/*
420 	 * Calculate the MAC signature for this reply.
421 	 * smb2_sign_calc() or smb3_sign_calc()
422 	 */
423 	if (s->sign_calc(sr, &tmp_mbc, reply_sig) != 0)
424 		return;
425 
426 	/*
427 	 * Poke the signature into the response.
428 	 */
429 	hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
430 	(void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
431 	    SMB2_SIG_SIZE, reply_sig);
432 }
433 
434 /*
435  * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2
436  * and [NIST SP800-108]
437  *
438  * r = 32, L = 128, PRF = HMAC-SHA256, key = (session key)
439  *
440  * Note that these describe pre-3.1.1 inputs.
441  *
442  * Session.SigningKey for binding a session:
443  * - Session.SessionKey as K1
444  * - label = SMB2AESCMAC (size 12)
445  * - context = SmbSign (size 8)
446  * Channel.SigningKey for for all other requests
447  * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1;
448  * - otherwise, Session.SessionKey as K1
449  * - label = SMB2AESCMAC (size 12)
450  * - context = SmbSign (size 8)
451  * Session.ApplicationKey for ... (not sure what yet)
452  * - Session.SessionKey as K1
453  * - label = SMB2APP (size 8)
454  * - context = SmbRpc (size 7)
455  * Session.EncryptionKey for encrypting server messages
456  * - Session.SessionKey as K1
457  * - label = "SMB2AESCCM" (size 11)
458  * - context = "ServerOut" (size 10)
459  * Session.DecryptionKey for decrypting client requests
460  * - Session.SessionKey as K1
461  * - label = "SMB2AESCCM" (size 11)
462  * - context = "ServerIn " (size 10) (Note the space)
463  */
464 
465 int
466 smb3_do_kdf(void *outbuf, void *input, size_t input_len,
467     uint8_t *key, uint32_t key_len)
468 {
469 	uint8_t digest32[SHA256_DIGEST_LENGTH];
470 	smb_crypto_mech_t mech;
471 	smb_sign_ctx_t hctx = 0;
472 	int rc;
473 
474 	bzero(&mech, sizeof (mech));
475 	if ((rc = smb2_hmac_getmech(&mech)) != 0)
476 		return (rc);
477 
478 	/* Limit the SessionKey input to its maximum size (16 bytes) */
479 	rc = smb2_hmac_init(&hctx, &mech, key, MIN(key_len, SMB2_KEYLEN));
480 	if (rc != 0)
481 		return (rc);
482 
483 	if ((rc = smb2_hmac_update(hctx, input, input_len)) != 0)
484 		return (rc);
485 
486 	if ((rc = smb2_hmac_final(hctx, digest32)) != 0)
487 		return (rc);
488 
489 	/* Output is first 16 bytes of digest. */
490 	bcopy(digest32, outbuf, SMB3_KEYLEN);
491 	return (0);
492 }
493