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