Print this page
12513 SMB 3.1.1 support for server

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb2_signing.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb2_signing.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2020 RackTop Systems, Inc.
  24   25   */
  25   26  /*
  26   27   * These routines provide the SMB MAC signing for the SMB2 server.
  27   28   * The routines calculate the signature of a SMB message in an mbuf chain.
  28   29   *
  29   30   * The following table describes the client server
  30   31   * signing registry relationship
  31   32   *
  32   33   *              | Required      | Enabled     | Disabled
  33   34   * -------------+---------------+------------ +--------------
↓ open down ↓ 77 lines elided ↑ open up ↑
 111  112      struct mbuf_chain *mbc,
 112  113      uint8_t *digest16)
 113  114  {
 114  115          int rv;
 115  116  
 116  117          rv = smb2_sign_calc_common(sr, mbc, digest16, &smb3_sign_ops);
 117  118  
 118  119          return (rv);
 119  120  }
 120  121  
 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  122  void
 132  123  smb2_sign_init_mech(smb_session_t *s)
 133  124  {
 134  125          smb_crypto_mech_t *mech;
 135  126          int (*get_mech)(smb_crypto_mech_t *);
 136  127          int (*sign_calc)(smb_request_t *, struct mbuf_chain *, uint8_t *);
 137  128          int rc;
 138  129  
 139  130          if (s->sign_mech != NULL)
 140  131                  return;
↓ open down ↓ 48 lines elided ↑ open up ↑
 189  180  
 190  181          /*
 191  182           * Compute and store the signing key, which lives in
 192  183           * the user structure.
 193  184           */
 194  185          if (s->dialect >= SMB_VERS_3_0) {
 195  186                  /*
 196  187                   * For SMB3, the signing key is a "KDF" hash of the
 197  188                   * session key.
 198  189                   */
 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;
      190 +                if (s->dialect >= SMB_VERS_3_11) {
      191 +                        if (smb3_kdf(sign_key->key,
      192 +                            token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      193 +                            (uint8_t *)"SMBSigningKey", 14,
      194 +                            s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH)
      195 +                            != 0)
      196 +                                return;
      197 +                } else {
      198 +                        if (smb3_kdf(sign_key->key,
      199 +                            token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      200 +                            (uint8_t *)"SMB2AESCMAC", 12,
      201 +                            (uint8_t *)"SmbSign", 8)
      202 +                            != 0)
      203 +                                return;
      204 +                }
 203  205                  sign_key->len = SMB3_KEYLEN;
 204  206          } else {
 205  207                  /*
 206  208                   * For SMB2, the signing key is just the first 16 bytes
 207  209                   * of the session key (truncated or padded with zeros).
 208  210                   * [MS-SMB2] 3.2.5.3.1
 209  211                   */
 210  212                  sign_key->len = SMB2_KEYLEN;
 211  213                  bcopy(token->tkn_ssnkey.val, sign_key->key,
 212  214                      MIN(token->tkn_ssnkey.len, sign_key->len));
↓ open down ↓ 209 lines elided ↑ open up ↑
 422  424           */
 423  425          if (s->sign_calc(sr, &tmp_mbc, reply_sig) != 0)
 424  426                  return;
 425  427  
 426  428          /*
 427  429           * Poke the signature into the response.
 428  430           */
 429  431          hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
 430  432          (void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
 431  433              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  434  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX