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 2015 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/smb_kproto.h>
43 #include <smbsrv/smb_signing.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 /*
52 * Called during session destroy.
53 */
54 static void
55 smb2_sign_fini(smb_session_t *s)
56 {
57 smb_sign_mech_t *mech;
58
59 if ((mech = s->sign_mech) != NULL) {
60 kmem_free(mech, sizeof (*mech));
61 s->sign_mech = NULL;
62 }
63 }
64
65 /*
66 * smb2_sign_begin
67 *
68 * Get the mechanism info.
69 * Intializes MAC key based on the user session key and store it in
70 * the signing structure. This begins signing on this session.
71 */
72 int
73 smb2_sign_begin(smb_request_t *sr, smb_token_t *token)
74 {
75 smb_session_t *s = sr->session;
76 smb_user_t *u = sr->uid_user;
77 struct smb_key *sign_key = &u->u_sign_key;
78 smb_sign_mech_t *mech;
79 int rc;
80
81 /*
82 * We should normally have a session key here because
83 * our caller filters out Anonymous and Guest logons.
84 * However, buggy clients could get us here without a
85 * session key, in which case we'll fail later when a
86 * request that requires signing can't be checked.
87 */
88 if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
89 return (0);
90
91 /*
92 * Session-level initialization (once per session)
93 * Get mech handle, sign_fini function.
94 */
95 smb_rwx_rwenter(&s->s_lock, RW_WRITER);
96 if (s->sign_mech == NULL) {
97 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
98 rc = smb2_hmac_getmech(mech);
99 if (rc != 0) {
100 kmem_free(mech, sizeof (*mech));
101 smb_rwx_rwexit(&s->s_lock);
102 return (rc);
103 }
104 s->sign_mech = mech;
105 s->sign_fini = smb2_sign_fini;
106 }
107 smb_rwx_rwexit(&s->s_lock);
108
109 /*
110 * Compute and store the signing key, which lives in
111 * the user structure.
112 */
113 sign_key->len = SMB2_SIG_SIZE;
114
115 /*
116 * For SMB2, the signing key is just the first 16 bytes
117 * of the session key (truncated or padded with zeros).
118 * [MS-SMB2] 3.2.5.3.1
119 */
120 bcopy(token->tkn_ssnkey.val, sign_key->key,
121 MIN(token->tkn_ssnkey.len, sign_key->len));
122
123 mutex_enter(&u->u_mutex);
124 if (s->secmode & SMB2_NEGOTIATE_SIGNING_ENABLED)
125 u->u_sign_flags |= SMB_SIGNING_ENABLED;
126 if (s->secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
127 u->u_sign_flags |=
128 SMB_SIGNING_ENABLED | SMB_SIGNING_CHECK;
129 mutex_exit(&u->u_mutex);
130
131 /*
132 * If we just turned on signing, the current request
133 * (an SMB2 session setup) will have come in without
134 * SMB2_FLAGS_SIGNED (and not signed) but the response
135 * is is supposed to be signed. [MS-SMB2] 3.3.5.5
136 */
137 if (u->u_sign_flags & SMB_SIGNING_ENABLED)
138 sr->smb2_hdr_flags |= SMB2_FLAGS_SIGNED;
139
140 return (0);
141 }
142
143 /*
144 * smb2_sign_calc
145 *
146 * Calculates MAC signature for the given buffer and returns
147 * it in the mac_sign parameter.
148 *
149 * The signature is in the last 16 bytes of the SMB2 header.
150 * The signature algorighm is to compute HMAC SHA256 over the
151 * entire command, with the signature field set to zeros.
152 *
153 * Return 0 if success else -1
154 */
155 static int
156 smb2_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
157 uint8_t *digest)
158 {
159 uint8_t tmp_hdr[SMB2_HDR_SIZE];
160 smb_sign_ctx_t ctx = 0;
161 smb_session_t *s = sr->session;
162 smb_user_t *u = sr->uid_user;
163 struct smb_key *sign_key = &u->u_sign_key;
164 struct mbuf *mbuf;
165 int offset, resid, tlen, rc;
166
167 if (s->sign_mech == NULL || sign_key->len == 0)
168 return (-1);
169
170 rc = smb2_hmac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
171 if (rc != 0)
172 return (rc);
173
174 /*
175 * Work with a copy of the SMB2 header so we can
176 * clear the signature field without modifying
177 * the original message.
178 */
179 tlen = SMB2_HDR_SIZE;
180 offset = mbc->chain_offset;
181 resid = mbc->max_bytes - offset;
182 if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
183 return (-1);
184 bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
185 if ((rc = smb2_hmac_update(ctx, tmp_hdr, tlen)) != 0)
186 return (rc);
187 offset += tlen;
188 resid -= tlen;
189
190 /*
191 * Digest the rest of the SMB packet, starting at the data
192 * just after the SMB header.
193 *
194 * Advance to the src mbuf where we start digesting.
195 */
196 mbuf = mbc->chain;
197 while (mbuf != NULL && (offset >= mbuf->m_len)) {
198 offset -= mbuf->m_len;
199 mbuf = mbuf->m_next;
200 }
201
202 if (mbuf == NULL)
203 return (-1);
204
205 /*
206 * Digest the remainder of this mbuf, limited to the
207 * residual count, and starting at the current offset.
208 * (typically SMB2_HDR_SIZE)
209 */
210 tlen = mbuf->m_len - offset;
211 if (tlen > resid)
212 tlen = resid;
213 rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
214 if (rc != 0)
215 return (rc);
216 resid -= tlen;
217
218 /*
219 * Digest any more mbufs in the chain.
220 */
221 while (resid > 0) {
222 mbuf = mbuf->m_next;
223 if (mbuf == NULL)
224 return (-1);
225 tlen = mbuf->m_len;
226 if (tlen > resid)
227 tlen = resid;
228 rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
229 if (rc != 0)
230 return (rc);
231 resid -= tlen;
232 }
233
234 /*
235 * Note: digest is _always_ SMB2_SIG_SIZE,
236 * even if the mech uses a longer one.
237 */
238 if ((rc = smb2_hmac_final(ctx, digest)) != 0)
239 return (rc);
240
241 return (0);
242 }
243
244 /*
245 * smb2_sign_check_request
246 *
247 * Calculates MAC signature for the request mbuf chain
248 * using the next expected sequence number and compares
249 * it to the given signature.
250 *
251 * Note it does not check the signature for secondary transactions
252 * as their sequence number is the same as the original request.
253 *
254 * Return 0 if the signature verifies, otherwise, returns -1;
255 *
256 */
257 int
258 smb2_sign_check_request(smb_request_t *sr)
259 {
260 uint8_t req_sig[SMB2_SIG_SIZE];
261 uint8_t vfy_sig[SMB2_SIG_SIZE];
262 struct mbuf_chain *mbc = &sr->smb_data;
263 smb_user_t *u = sr->uid_user;
264 int sig_off;
265
266 /*
267 * Don't check commands with a zero session ID.
268 * [MS-SMB2] 3.3.4.1.1
269 */
270 if (sr->smb_uid == 0 || u == NULL)
271 return (0);
272
273 /* Get the request signature. */
274 sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
275 if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
276 return (-1);
277
278 /*
279 * Compute the correct signature and compare.
280 */
281 if (smb2_sign_calc(sr, mbc, vfy_sig) != 0)
282 return (-1);
283 if (memcmp(vfy_sig, req_sig, SMB2_SIG_SIZE) != 0) {
284 cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
285 return (-1);
286 }
287
288 return (0);
289 }
290
291 /*
292 * smb2_sign_reply
293 *
294 * Calculates MAC signature for the given mbuf chain,
295 * and write it to the signature field in the mbuf.
296 *
297 */
298 void
299 smb2_sign_reply(smb_request_t *sr)
300 {
301 uint8_t reply_sig[SMB2_SIG_SIZE];
302 struct mbuf_chain tmp_mbc;
303 smb_user_t *u = sr->uid_user;
304 int hdr_off, msg_len;
305
306 if (u == NULL)
307 return;
308
309 msg_len = sr->reply.chain_offset - sr->smb2_reply_hdr;
310 (void) MBC_SHADOW_CHAIN(&tmp_mbc, &sr->reply,
311 sr->smb2_reply_hdr, msg_len);
312
313 /*
314 * Calculate the MAC signature for this reply.
315 */
316 if (smb2_sign_calc(sr, &tmp_mbc, reply_sig) != 0)
317 return;
318
319 /*
320 * Poke the signature into the response.
321 */
322 hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
323 (void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
324 SMB2_SIG_SIZE, reply_sig);
325 }
|
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 }
|