Print this page
12513 SMB 3.1.1 support for server
@@ -19,10 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2018 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 RackTop Systems, Inc.
*/
/*
* These routines provide the SMB MAC signing for the SMB2 server.
* The routines calculate the signature of a SMB message in an mbuf chain.
*
@@ -116,20 +117,10 @@
rv = smb2_sign_calc_common(sr, mbc, digest16, &smb3_sign_ops);
return (rv);
}
-/*
- * Input to KDF for SigningKey.
- * See comment for smb3_do_kdf for content.
- */
-static uint8_t sign_kdf_input[29] = {
- 0, 0, 0, 1, 'S', 'M', 'B', '2',
- 'A', 'E', 'S', 'C', 'M', 'A', 'C', 0,
- 0, 'S', 'm', 'b', 'S', 'i', 'g', 'n',
- 0, 0, 0, 0, 0x80 };
-
void
smb2_sign_init_mech(smb_session_t *s)
{
smb_crypto_mech_t *mech;
int (*get_mech)(smb_crypto_mech_t *);
@@ -194,14 +185,25 @@
if (s->dialect >= SMB_VERS_3_0) {
/*
* For SMB3, the signing key is a "KDF" hash of the
* session key.
*/
- if (smb3_do_kdf(sign_key->key, sign_kdf_input,
- sizeof (sign_kdf_input), token->tkn_ssnkey.val,
- token->tkn_ssnkey.len) != 0)
+ if (s->dialect >= SMB_VERS_3_11) {
+ if (smb3_kdf(sign_key->key,
+ token->tkn_ssnkey.val, token->tkn_ssnkey.len,
+ (uint8_t *)"SMBSigningKey", 14,
+ s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH)
+ != 0)
return;
+ } else {
+ if (smb3_kdf(sign_key->key,
+ token->tkn_ssnkey.val, token->tkn_ssnkey.len,
+ (uint8_t *)"SMB2AESCMAC", 12,
+ (uint8_t *)"SmbSign", 8)
+ != 0)
+ return;
+ }
sign_key->len = SMB3_KEYLEN;
} else {
/*
* For SMB2, the signing key is just the first 16 bytes
* of the session key (truncated or padded with zeros).
@@ -428,65 +430,5 @@
*/
hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
(void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
SMB2_SIG_SIZE, reply_sig);
}
-
-/*
- * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2
- * and [NIST SP800-108]
- *
- * r = 32, L = 128, PRF = HMAC-SHA256, key = (session key)
- *
- * Note that these describe pre-3.1.1 inputs.
- *
- * Session.SigningKey for binding a session:
- * - Session.SessionKey as K1
- * - label = SMB2AESCMAC (size 12)
- * - context = SmbSign (size 8)
- * Channel.SigningKey for for all other requests
- * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1;
- * - otherwise, Session.SessionKey as K1
- * - label = SMB2AESCMAC (size 12)
- * - context = SmbSign (size 8)
- * Session.ApplicationKey for ... (not sure what yet)
- * - Session.SessionKey as K1
- * - label = SMB2APP (size 8)
- * - context = SmbRpc (size 7)
- * Session.EncryptionKey for encrypting server messages
- * - Session.SessionKey as K1
- * - label = "SMB2AESCCM" (size 11)
- * - context = "ServerOut" (size 10)
- * Session.DecryptionKey for decrypting client requests
- * - Session.SessionKey as K1
- * - label = "SMB2AESCCM" (size 11)
- * - context = "ServerIn " (size 10) (Note the space)
- */
-
-int
-smb3_do_kdf(void *outbuf, void *input, size_t input_len,
- uint8_t *key, uint32_t key_len)
-{
- uint8_t digest32[SHA256_DIGEST_LENGTH];
- smb_crypto_mech_t mech;
- smb_sign_ctx_t hctx = 0;
- int rc;
-
- bzero(&mech, sizeof (mech));
- if ((rc = smb2_hmac_getmech(&mech)) != 0)
- return (rc);
-
- /* Limit the SessionKey input to its maximum size (16 bytes) */
- rc = smb2_hmac_init(&hctx, &mech, key, MIN(key_len, SMB2_KEYLEN));
- if (rc != 0)
- return (rc);
-
- if ((rc = smb2_hmac_update(hctx, input, input_len)) != 0)
- return (rc);
-
- if ((rc = smb2_hmac_final(hctx, digest32)) != 0)
- return (rc);
-
- /* Output is first 16 bytes of digest. */
- bcopy(digest32, outbuf, SMB3_KEYLEN);
- return (0);
-}