xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c (revision 8a2b682e57a046b828f37bcde1776f131ef4629f)
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 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
25  */
26 
27 /*
28  * Support for SMB2 "signing" (message integrity)
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/conf.h>
34 #include <sys/proc.h>
35 #include <sys/fcntl.h>
36 #include <sys/socket.h>
37 #include <sys/md4.h>
38 #include <sys/md5.h>
39 #include <sys/des.h>
40 #include <sys/kmem.h>
41 #include <sys/cmn_err.h>
42 #include <sys/stream.h>
43 #include <sys/strsun.h>
44 #include <sys/sdt.h>
45 
46 #include <netsmb/smb_osdep.h>
47 #include <netsmb/smb2.h>
48 #include <netsmb/smb_conn.h>
49 #include <netsmb/smb_subr.h>
50 #include <netsmb/smb_dev.h>
51 #include <netsmb/smb_rq.h>
52 #include <netsmb/smb_signing.h>
53 
54 #define	SMB2_SIG_OFF	48
55 #define	SMB2_SIG_LEN	16
56 
57 typedef struct smb_mac_ops {
58 	int (*mac_init)(smb_sign_ctx_t *, smb_sign_mech_t *,
59 			uint8_t *, size_t);
60 	int (*mac_update)(smb_sign_ctx_t, uint8_t *, size_t);
61 	int (*mac_final)(smb_sign_ctx_t, uint8_t *);
62 } smb_mac_ops_t;
63 
64 static smb_mac_ops_t
65 smb2_sign_ops = {
66 	smb2_hmac_init,
67 	smb2_hmac_update,
68 	smb2_hmac_final
69 };
70 
71 static struct smb_mac_ops
72 smb3_sign_ops = {
73 	smb3_cmac_init,
74 	smb3_cmac_update,
75 	smb3_cmac_final
76 };
77 
78 /*
79  * Input to KDF for SigningKey.
80  * See comment for smb3_do_kdf for content.
81  */
82 static uint8_t sign_kdf_input[29] = {
83 	0, 0, 0, 1, 'S', 'M', 'B', '2',
84 	'A', 'E', 'S', 'C', 'M', 'A', 'C', 0,
85 	0, 'S', 'm', 'b', 'S', 'i', 'g', 'n',
86 	0, 0, 0, 0, 0x80 };
87 
88 int smb3_do_kdf(void *outbuf, size_t outbuf_len,
89     void *input, size_t input_len,
90     uint8_t *key, uint32_t key_len);
91 
92 /*
93  * smb2_sign_init
94  *
95  * Get the mechanism info and initilize SMB2 or SMB3 signing.
96  */
97 int
98 smb2_sign_init(smb_vc_t *vcp)
99 {
100 	uint_t copysize;
101 	int rc;
102 
103 	ASSERT(vcp->vc_ssnkey != NULL);
104 	ASSERT(vcp->vc_mackey == NULL);
105 
106 	if (SMB_DIALECT(vcp) < SMB2_DIALECT_0300)
107 		rc = smb2_hmac_getmech(&vcp->vc_signmech);
108 	else
109 		rc = smb3_cmac_getmech(&vcp->vc_signmech);
110 	if (rc != 0)
111 		return (EAUTH);
112 
113 	/*
114 	 * Convert the session key to the MAC key.
115 	 *
116 	 * For SMB2, the signing key is just the first 16 bytes
117 	 * of the session key (truncated or padded with zeros).
118 	 * For SMB3, the signing key is a "KDF" hash of the
119 	 * session key.   [MS-SMB2] 3.2.5.3.1
120 	 */
121 	vcp->vc_mackeylen = SMB2_SIG_LEN;
122 	vcp->vc_mackey = kmem_zalloc(vcp->vc_mackeylen, KM_SLEEP);
123 	if (SMB_DIALECT(vcp) < SMB2_DIALECT_0300) {
124 		copysize = vcp->vc_ssnkeylen;
125 		if (copysize > vcp->vc_mackeylen)
126 			copysize = vcp->vc_mackeylen;
127 		bcopy(vcp->vc_ssnkey, vcp->vc_mackey, copysize);
128 
129 		vcp->vc_sign_ops = &smb2_sign_ops;
130 	} else {
131 		rc = smb3_do_kdf(vcp->vc_mackey, vcp->vc_mackeylen,
132 		    sign_kdf_input, sizeof (sign_kdf_input),
133 		    vcp->vc_ssnkey, vcp->vc_ssnkeylen);
134 		if (rc != 0)
135 			return (EAUTH);
136 		vcp->vc_sign_ops = &smb3_sign_ops;
137 	}
138 
139 	return (0);
140 }
141 
142 /*
143  * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2
144  * and [NIST SP800-108]
145  *
146  * r = 32, L = 128, PRF = HMAC-SHA256, key = (session key)
147  *
148  * Note that these describe pre-3.1.1 inputs.
149  *
150  * Session.SigningKey for binding a session:
151  * - Session.SessionKey as K1
152  * - label = SMB2AESCMAC (size 12)
153  * - context = SmbSign (size 8)
154  * Channel.SigningKey for for all other requests
155  * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1;
156  * - otherwise, Session.SessionKey as K1
157  * - label = SMB2AESCMAC (size 12)
158  * - context = SmbSign (size 8)
159  * Session.ApplicationKey for ... (not sure what yet)
160  * - Session.SessionKey as K1
161  * - label = SMB2APP (size 8)
162  * - context = SmbRpc (size 7)
163  * Session.EncryptionKey for encrypting server messages
164  * - Session.SessionKey as K1
165  * - label = "SMB2AESCCM" (size 11)
166  * - context = "ServerOut" (size 10)
167  * Session.DecryptionKey for decrypting client requests
168  * - Session.SessionKey as K1
169  * - label = "SMB2AESCCM" (size 11)
170  * - context = "ServerIn " (size 10) (Note the space)
171  */
172 int
173 smb3_do_kdf(void *outbuf, size_t outbuf_len,
174     void *input, size_t input_len,
175     uint8_t *key, uint32_t key_len)
176 {
177 	uint8_t digest32[SHA256_DIGEST_LENGTH];
178 	smb_sign_mech_t mech;
179 	smb_sign_ctx_t hctx = 0;
180 	int rc;
181 
182 	bzero(&mech, sizeof (mech));
183 	if ((rc = smb2_hmac_getmech(&mech)) != 0)
184 		return (rc);
185 
186 	/* Limit the SessionKey input to its maximum size (16 bytes) */
187 	if (key_len > SMB2_SIG_SIZE)
188 		key_len = SMB2_SIG_SIZE;
189 	rc = smb2_hmac_init(&hctx, &mech, key, key_len);
190 	if (rc != 0)
191 		return (rc);
192 
193 	if ((rc = smb2_hmac_update(hctx, input, input_len)) != 0)
194 		return (rc);
195 
196 	if ((rc = smb2_hmac_final(hctx, digest32)) != 0)
197 		return (rc);
198 
199 	/* Output is first 16 bytes of digest. */
200 	bcopy(digest32, outbuf, outbuf_len);
201 	return (0);
202 }
203 
204 /*
205  * Compute MAC signature of packet data, using the stored MAC key.
206  *
207  * The signature is in the last 16 bytes of the SMB2 header.
208  * The signature algorighm is to compute HMAC SHA256 over the
209  * entire command, with the signature field set to zeros.
210  *
211  * See similar code for the server side:
212  * uts/common/fs/smbsrv/smb2_signing.c : smb2_sign_calc
213  */
214 static int
215 smb2_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uchar_t *signature)
216 {
217 	uint8_t tmp_hdr[SMB2_HDR_SIZE];
218 	smb_sign_ctx_t ctx = 0;
219 	smb_mac_ops_t *ops;
220 	mblk_t *m = mp;
221 	int size;
222 	int rc;
223 
224 	if (vcp->vc_mackey == NULL)
225 		return (-1);
226 	if ((ops = vcp->vc_sign_ops) == NULL)
227 		return (-1);
228 
229 	rc = ops->mac_init(&ctx, &vcp->vc_signmech,
230 	    vcp->vc_mackey, vcp->vc_mackeylen);
231 	if (rc != 0)
232 		return (rc);
233 
234 	/* Our caller should ensure mp has a contiguous header */
235 	ASSERT(m != NULL);
236 	ASSERT(MBLKL(m) >= SMB2_HDRLEN);
237 
238 	/*
239 	 * Copy of the SMB2 header, zero out the signature, and digest.
240 	 */
241 	size = SMB2_HDRLEN;
242 	bcopy(m->b_rptr, tmp_hdr, size);
243 	bzero(tmp_hdr + SMB2_SIG_OFF, SMB2_SIG_LEN);
244 	rc = ops->mac_update(ctx, tmp_hdr, size);
245 	if (rc != 0)
246 		return (rc);
247 
248 	/*
249 	 * Digest the rest of the SMB2 header packet, starting at
250 	 * the data just after the SMB2 header.
251 	 */
252 	size = MBLKL(m) - SMB2_HDRLEN;
253 	rc = ops->mac_update(ctx, m->b_rptr + SMB2_HDRLEN, size);
254 	if (rc != 0)
255 		return (rc);
256 	m = m->b_cont;
257 
258 	/* Digest rest of the SMB2 message. */
259 	while (m != NULL) {
260 		size = MBLKL(m);
261 		if (size > 0) {
262 			rc = ops->mac_update(ctx, m->b_rptr, size);
263 			if (rc != 0)
264 				return (rc);
265 		}
266 		m = m->b_cont;
267 	}
268 	rc = ops->mac_final(ctx, signature);
269 
270 	return (rc);
271 }
272 
273 /*
274  * Sign a request with HMAC-MD5.
275  */
276 void
277 smb2_rq_sign(struct smb_rq *rqp)
278 {
279 	struct smb_vc *vcp = rqp->sr_vc;
280 	mblk_t *mp = rqp->sr_rq.mb_top;
281 	uint8_t *sigloc;
282 	int rc;
283 
284 	/*
285 	 * smb_rq_new() ensures this,
286 	 * but just in case..
287 	 */
288 	ASSERT(MBLKL(mp) >= SMB2_HDRLEN);
289 	sigloc = mp->b_rptr + SMB2_SIG_OFF;
290 
291 	if (vcp->vc_mackey == NULL)
292 		return;
293 
294 	/*
295 	 * This will compute the MAC and store it
296 	 * directly into the message at sigloc.
297 	 */
298 	rc = smb2_compute_MAC(vcp, mp, sigloc);
299 	if (rc != 0) {
300 		SMBSDEBUG("Crypto error %d", rc);
301 		bzero(sigloc, SMB2_SIG_LEN);
302 	}
303 }
304 
305 /*
306  * Verify reply signature.
307  */
308 int
309 smb2_rq_verify(struct smb_rq *rqp)
310 {
311 	struct smb_vc *vcp = rqp->sr_vc;
312 	mblk_t *mp = rqp->sr_rp.md_top;
313 	uint8_t sigbuf[SMB2_SIG_LEN];
314 	uint8_t *sigloc;
315 	int rc;
316 
317 	/*
318 	 * Note vc_mackey and vc_mackeylen gets filled in by
319 	 * smb_usr_iod_work as the connection comes in.
320 	 */
321 	if (vcp->vc_mackey == NULL) {
322 		SMBSDEBUG("no mac key\n");
323 		return (0);
324 	}
325 
326 	/*
327 	 * Let caller deal with empty reply or short messages by
328 	 * returning zero.  Caller will fail later, in parsing.
329 	 */
330 	if (mp == NULL) {
331 		SMBSDEBUG("empty reply\n");
332 		return (0);
333 	}
334 
335 	/* smb2_iod_process ensures this */
336 	ASSERT(MBLKL(mp) >= SMB2_HDRLEN);
337 	sigloc = mp->b_rptr + SMB2_SIG_OFF;
338 
339 	/*
340 	 * Compute the expected signature in sigbuf.
341 	 */
342 	rc = smb2_compute_MAC(vcp, mp, sigbuf);
343 	if (rc != 0) {
344 		SMBSDEBUG("Crypto error %d", rc);
345 		/*
346 		 * If we can't compute a MAC, then there's
347 		 * no point trying other seqno values.
348 		 */
349 		return (EBADRPC);
350 	}
351 
352 	/*
353 	 * Compare the computed signature with the
354 	 * one found in the message (at sigloc)
355 	 */
356 	if (bcmp(sigbuf, sigloc, SMB2_SIG_LEN) == 0)
357 		return (0);
358 
359 	SMBERROR("BAD signature, Server=%s MID=0x%llx\n",
360 	    vcp->vc_srvname, (long long)rqp->sr2_messageid);
361 
362 	return (EBADRPC);
363 }
364