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 }