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);
-}