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
smb2_sign_init(smb_vc_t * vcp)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
smb3_do_kdf(void * outbuf,size_t outbuf_len,void * input,size_t input_len,uint8_t * key,uint32_t key_len)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
smb2_compute_MAC(struct smb_vc * vcp,mblk_t * mp,uchar_t * signature)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
smb2_rq_sign(struct smb_rq * rqp)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
smb2_rq_verify(struct smb_rq * rqp)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