Print this page
    
12513 SMB 3.1.1 support for server
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb3_encrypt.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
       14 + * Copyright 2020 RackTop Systems, Inc.
  14   15   */
  15   16  
  16   17  /*
  17   18   * Routines for smb3 encryption.
  18   19   */
  19   20  
  20   21  #include <smbsrv/smb2_kproto.h>
  21   22  #include <smbsrv/smb_kcrypt.h>
  22   23  #include <sys/random.h>
  23   24  #include <sys/cmn_err.h>
  24   25  
  25   26  #define SMB3_NONCE_OFFS         20
  26   27  #define SMB3_SIG_OFFS           4
  27      -#define SMB3_NONCE_SIZE         11 /* 12 for gcm later */
  28      -
  29      -/*
  30      - * Inputs to KDF for EncryptionKey and DecryptionKey.
  31      - * See comment for smb3_do_kdf for content.
  32      - */
  33      -static uint8_t encrypt_kdf_input[30] = {
  34      -        0, 0, 0, 1, 'S', 'M', 'B', '2',
  35      -        'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
  36      -        'S', 'e', 'r', 'v', 'e', 'r', 'O',
  37      -        'u', 't', 0, 0, 0, 0, 0x80 };
  38      -
  39      -static uint8_t decrypt_kdf_input[30] = {
  40      -        0, 0, 0, 1, 'S', 'M', 'B', '2',
  41      -        'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
  42      -        'S', 'e', 'r', 'v', 'e', 'r', 'I',
  43      -        'n', ' ', 0, 0, 0, 0, 0x80 };
       28 +#define SMB3_AES128_CCM_NONCE_SIZE      11
       29 +#define SMB3_AES128_GCM_NONCE_SIZE      12
  44   30  
  45   31  /*
  46   32   * Arbitrary value used to prevent nonce reuse via overflow. Currently
  47   33   * 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
  48   34   * 2^32 concurrent messages when we hit this number.
  49   35   */
  50   36  static uint64_t smb3_max_nonce = 0xffffffff00000000ULL;
  51   37  
  52   38  /*
  53   39   * Nonce generation based on draft-mcgrew-iv-gen-01
  54   40   * "Generation of Deterministic Initialization Vectors (IVs) and Nonces"
  55   41   *
  56   42   * Generate an 8-byte random salt and a 3-byte random 'fixed' value.
  57   43   * then, nonce = (++counter ^ salt) || fixed
  58   44   *
  59   45   * This protects against nonce-reuse (8-byte counter), as well as known
  60   46   * attacks on reusing nonces with different keys
  61   47   */
  62   48  
  63   49  void
  64   50  smb3_encrypt_init_nonce(smb_user_t *user)
  65   51  {
  66   52          user->u_nonce_cnt = 0;
  67   53          (void) random_get_pseudo_bytes(user->u_nonce_fixed,
  68   54              sizeof (user->u_nonce_fixed));
  69   55          (void) random_get_pseudo_bytes((uint8_t *)&user->u_salt,
  70   56              sizeof (user->u_salt));
  71   57  }
  72   58  
  73   59  int
  74   60  smb3_encrypt_gen_nonce(smb_user_t *user, uint8_t *buf, size_t len)
  75   61  {
  76   62          uint64_t cnt = atomic_inc_64_nv(&user->u_nonce_cnt);
  77   63  
  78   64          /*
  79   65           * Nonces must be unique per-key for the life of the key.
  80   66           * Bail before we roll over to avoid breaking the crypto.
  81   67           */
  82   68  
  83   69          if (cnt > smb3_max_nonce)
  84   70                  return (-1);
  85   71  
  86   72          cnt ^= user->u_salt;
  87   73          bcopy((uint8_t *)&cnt, buf, sizeof (cnt));
  88   74  
  89   75          ASSERT(len > sizeof (cnt));
  90   76          bcopy(user->u_nonce_fixed, buf + sizeof (cnt), len - sizeof (cnt));
  91   77          return (0);
  92   78  }
  
    | 
      ↓ open down ↓ | 
    39 lines elided | 
    
      ↑ open up ↑ | 
  
  93   79  
  94   80  int
  95   81  smb3_encrypt_init_mech(smb_session_t *s)
  96   82  {
  97   83          smb_crypto_mech_t *mech;
  98   84          int rc;
  99   85  
 100   86          if (s->enc_mech != NULL)
 101   87                  return (0);
 102   88  
       89 +        if (s->dialect < SMB_VERS_3_11)
       90 +                s->smb31_enc_cipherid = SMB3_CIPHER_AES128_CCM;
       91 +
 103   92          mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
 104      -        rc = smb3_encrypt_getmech(mech);
       93 +
       94 +        switch (s->smb31_enc_cipherid) {
       95 +        case SMB3_CIPHER_AES128_GCM:
       96 +                rc = smb3_aes_gcm_getmech(mech);
       97 +                break;
       98 +        case SMB3_CIPHER_AES128_CCM:
       99 +                rc = smb3_aes_ccm_getmech(mech);
      100 +                break;
      101 +        default:
      102 +                return (-1);
      103 +        }
      104 +
 105  105          if (rc != 0) {
 106  106                  kmem_free(mech, sizeof (*mech));
 107  107                  return (rc);
 108  108          }
 109  109          s->enc_mech = mech;
 110  110  
 111  111          return (0);
 112  112  }
 113  113  
 114  114  /*
 115  115   * Initializes keys/state required for SMB3 Encryption.
 116  116   * Note: If a failure occurs here, don't fail the request.
 117  117   * Instead, return an error when we attempt to encrypt/decrypt.
 118  118   */
 119  119  void
 120  120  smb3_encrypt_begin(smb_request_t *sr, smb_token_t *token)
 121  121  {
 122  122          smb_session_t *s = sr->session;
 123  123          smb_user_t *u = sr->uid_user;
 124  124          struct smb_key *enc_key = &u->u_enc_key;
 125  125          struct smb_key *dec_key = &u->u_dec_key;
 126  126  
 127  127          /*
 128  128           * In order to enforce encryption, all users need to
 129  129           * have Session.EncryptData properly set, even anon/guest.
 130  130           */
 131  131          u->u_encrypt = s->s_server->sv_cfg.skc_encrypt;
 132  132          enc_key->len = 0;
 133  133          dec_key->len = 0;
 134  134  
 135  135          /*
 136  136           * If we don't have a session key, we'll fail later when a
 137  137           * request that requires (en/de)cryption can't be (en/de)crypted.
 138  138           * Also don't bother initializing if we don't have a mechanism.
 139  139           */
 140  140          if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
 141  141              s->enc_mech == NULL)
 142  142                  return;
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
 143  143  
 144  144          /*
 145  145           * Compute and store the encryption keys, which live in
 146  146           * the user structure.
 147  147           */
 148  148  
 149  149          /*
 150  150           * For SMB3, the encrypt/decrypt keys are derived from
 151  151           * the session key using KDF in counter mode.
 152  152           */
 153      -        if (smb3_do_kdf(enc_key->key, encrypt_kdf_input,
 154      -            sizeof (encrypt_kdf_input), token->tkn_ssnkey.val,
 155      -            token->tkn_ssnkey.len) != 0)
 156      -                return;
 157      -
 158      -        if (smb3_do_kdf(dec_key->key, decrypt_kdf_input,
 159      -            sizeof (decrypt_kdf_input), token->tkn_ssnkey.val,
 160      -            token->tkn_ssnkey.len) != 0)
 161      -                return;
      153 +        if (s->dialect >= SMB_VERS_3_11) {
      154 +                if (smb3_kdf(enc_key->key,
      155 +                    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      156 +                    (uint8_t *)"SMBS2CCipherKey", 16,
      157 +                    s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
      158 +                        return;
      159 +
      160 +                if (smb3_kdf(dec_key->key,
      161 +                    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      162 +                    (uint8_t *)"SMBC2SCipherKey", 16,
      163 +                    s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
      164 +                        return;
      165 +        } else {
      166 +                if (smb3_kdf(enc_key->key,
      167 +                    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      168 +                    (uint8_t *)"SMB2AESCCM", 11,
      169 +                    (uint8_t *)"ServerOut", 10) != 0)
      170 +                        return;
      171 +
      172 +                if (smb3_kdf(dec_key->key,
      173 +                    token->tkn_ssnkey.val, token->tkn_ssnkey.len,
      174 +                    (uint8_t *)"SMB2AESCCM", 11,
      175 +                    (uint8_t *)"ServerIn ", 10) != 0)
      176 +                        return;
      177 +        }
 162  178  
 163  179          smb3_encrypt_init_nonce(u);
 164  180  
 165  181          enc_key->len = SMB3_KEYLEN;
 166  182          dec_key->len = SMB3_KEYLEN;
 167  183  }
 168  184  
 169  185  /*
 170  186   * Decrypt the request in sr->command.
 171  187   * This decrypts "in place", though due to CCM's design,
 172  188   * it processes all input before doing any output.
 173  189   */
 174  190  int
 175  191  smb3_decrypt_sr(smb_request_t *sr)
 176  192  {
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 177  193          struct mbuf_chain *mbc = &sr->command;
 178  194          smb_session_t *s = sr->session;
 179  195          smb_user_t *u = sr->tform_ssn;
 180  196          uint8_t tmp_hdr[SMB2_HDR_SIZE];
 181  197          smb3_enc_ctx_t ctx;
 182  198          struct smb_key *dec_key = &u->u_dec_key;
 183  199          struct mbuf *mbuf;
 184  200          int offset, resid, tlen, rc;
 185  201          smb3_crypto_param_t param;
 186  202          smb_crypto_mech_t mech;
      203 +        boolean_t gcm = sr->session->smb31_enc_cipherid ==
      204 +            SMB3_CIPHER_AES128_GCM;
      205 +        size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
      206 +            SMB3_AES128_CCM_NONCE_SIZE);
 187  207  
 188  208          ASSERT(u != NULL);
 189  209          if (s->enc_mech == NULL || dec_key->len != 16) {
 190  210                  return (-1);
 191  211          }
 192  212  
 193  213          tlen = SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS;
 194  214          offset = mbc->chain_offset + SMB3_NONCE_OFFS;
 195  215          resid = mbc->max_bytes - offset;
 196  216  
 197  217          if (resid < (sr->msgsize + tlen)) {
 198  218                  cmn_err(CE_WARN, "too little data to decrypt");
 199  219                  return (-1);
 200  220          }
 201  221  
 202  222          if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0) {
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
 203  223                  return (-1);
 204  224          }
 205  225  
 206  226          offset += tlen;
 207  227          resid -= tlen;
 208  228  
 209  229          /*
 210  230           * The transform header, minus the PROTOCOL_ID and the
 211  231           * SIGNATURE, is authenticated but not encrypted.
 212  232           */
 213      -        smb3_crypto_init_param(¶m, sr->nonce, SMB3_NONCE_SIZE,
 214      -            tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
      233 +        if (gcm)
      234 +                smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
      235 +                    tmp_hdr, tlen);
      236 +        else
      237 +                smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
      238 +                    tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
 215  239  
 216  240          /*
 217  241           * Unlike signing, which uses one global mech struct,
 218  242           * encryption requires modifying the mech to add a
 219  243           * per-use param struct. Thus, we need to make a copy.
 220  244           */
 221  245          mech = *(smb_crypto_mech_t *)s->enc_mech;
 222  246          rc = smb3_decrypt_init(&ctx, &mech, ¶m,
 223  247              dec_key->key, dec_key->len);
 224  248          if (rc != 0) {
 225  249                  return (rc);
 226  250          }
 227  251  
 228  252          /*
 229  253           * Digest the rest of the SMB packet, starting at the data
 230  254           * just after the SMB header.
 231  255           *
 232  256           * Advance to the src mbuf where we start digesting.
 233  257           */
 234  258          mbuf = mbc->chain;
 235  259          while (mbuf != NULL && (offset >= mbuf->m_len)) {
 236  260                  offset -= mbuf->m_len;
 237  261                  mbuf = mbuf->m_next;
 238  262          }
 239  263  
 240  264          if (mbuf == NULL)
 241  265                  return (-1);
 242  266  
 243  267          /*
 244  268           * Digest the remainder of this mbuf, limited to the
 245  269           * residual count, and starting at the current offset.
 246  270           */
 247  271          tlen = mbuf->m_len - offset;
 248  272          if (tlen > resid)
 249  273                  tlen = resid;
 250  274  
 251  275          rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data + offset, tlen);
 252  276          if (rc != 0) {
 253  277                  return (rc);
 254  278          }
 255  279          resid -= tlen;
 256  280  
 257  281          /*
 258  282           * Digest any more mbufs in the chain.
 259  283           */
 260  284          while (resid > 0) {
 261  285                  mbuf = mbuf->m_next;
 262  286                  if (mbuf == NULL) {
 263  287                          smb3_encrypt_cancel(&ctx);
 264  288                          return (-1);
 265  289                  }
 266  290                  tlen = mbuf->m_len;
 267  291                  if (tlen > resid)
 268  292                          tlen = resid;
 269  293                  rc = smb3_decrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
 270  294                  if (rc != 0) {
 271  295                          return (rc);
 272  296                  }
 273  297                  resid -= tlen;
 274  298          }
 275  299  
 276  300          /*
 277  301           * AES_CCM processes the signature like normal data.
 278  302           */
 279  303          rc = smb3_decrypt_update(&ctx, sr->smb2_sig, SMB2_SIG_SIZE);
 280  304  
 281  305          if (rc != 0) {
 282  306                  cmn_err(CE_WARN, "failed to process signature");
 283  307                  return (rc);
 284  308          }
 285  309          /*
 286  310           * smb3_decrypt_final will return an error
 287  311           * if the signatures don't match.
 288  312           */
 289  313          rc = smb3_decrypt_final(&ctx, sr->sr_request_buf, sr->sr_req_length);
 290  314  
 291  315          /*
 292  316           * We had to decode TFORM_HDR_SIZE bytes before we got here,
 293  317           * and we just peeked the first TFORM_HDR_SIZE bytes at the
 294  318           * beginning of this function, so this can't underflow.
 295  319           */
 296  320          ASSERT(sr->command.max_bytes > SMB3_TFORM_HDR_SIZE);
 297  321          sr->command.max_bytes -= SMB3_TFORM_HDR_SIZE;
 298  322          return (rc);
 299  323  }
 300  324  
 301  325  /*
 302  326   * Encrypt the response in in_mbc, and output
 303  327   * an encrypted response in out_mbc.
 304  328   * The data in in_mbc is preserved.
 305  329   */
 306  330  int
 307  331  smb3_encrypt_sr(smb_request_t *sr, struct mbuf_chain *in_mbc,
 308  332      struct mbuf_chain *out_mbc)
 309  333  {
  
    | 
      ↓ open down ↓ | 
    85 lines elided | 
    
      ↑ open up ↑ | 
  
 310  334          smb_session_t *s = sr->session;
 311  335          smb_user_t *u = sr->tform_ssn;
 312  336          uint8_t *buf = (uint8_t *)out_mbc->chain->m_data;
 313  337          size_t buflen = out_mbc->max_bytes;
 314  338          smb3_enc_ctx_t ctx;
 315  339          struct smb_key *enc_key = &u->u_enc_key;
 316  340          struct mbuf *mbuf;
 317  341          int resid, tlen, rc;
 318  342          smb3_crypto_param_t param;
 319  343          smb_crypto_mech_t mech;
      344 +        boolean_t gcm = sr->session->smb31_enc_cipherid ==
      345 +            SMB3_CIPHER_AES128_GCM;
      346 +        size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
      347 +            SMB3_AES128_CCM_NONCE_SIZE);
 320  348  
 321  349          ASSERT(u != NULL);
 322  350          if (s->enc_mech == NULL || enc_key->len != 16) {
 323  351                  return (-1);
 324  352          }
 325  353  
 326      -        rc = smb3_encrypt_gen_nonce(u, sr->nonce, SMB3_NONCE_SIZE);
      354 +        rc = smb3_encrypt_gen_nonce(u, sr->nonce, nonce_size);
 327  355  
 328  356          if (rc != 0) {
 329  357                  cmn_err(CE_WARN, "ran out of nonces");
 330  358                  return (-1);
 331  359          }
 332  360  
 333  361          (void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
 334      -            SMB3_NONCE_SIZE, sr->nonce);
      362 +            nonce_size, sr->nonce);
 335  363  
 336  364          resid = in_mbc->max_bytes;
 337  365  
 338  366          /*
 339  367           * The transform header, minus the PROTOCOL_ID and the
 340  368           * SIGNATURE, is authenticated but not encrypted.
 341  369           */
 342      -        smb3_crypto_init_param(¶m,
 343      -            sr->nonce, SMB3_NONCE_SIZE,
 344      -            buf + SMB3_NONCE_OFFS, SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS,
 345      -            resid);
      370 +        if (gcm)
      371 +                smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
      372 +                    buf + SMB3_NONCE_OFFS,
      373 +                    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS);
      374 +        else
      375 +                smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
      376 +                    buf + SMB3_NONCE_OFFS,
      377 +                    SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS, resid);
 346  378  
 347  379          /*
 348  380           * Unlike signing, which uses one global mech struct,
 349  381           * encryption requires modifying the mech to add a
 350  382           * per-use param struct. Thus, we need to make a copy.
 351  383           */
 352  384          mech = *(smb_crypto_mech_t *)s->enc_mech;
 353  385          rc = smb3_encrypt_init(&ctx, &mech, ¶m,
 354  386              enc_key->key, enc_key->len, buf + SMB3_TFORM_HDR_SIZE,
 355  387              buflen - SMB3_TFORM_HDR_SIZE);
 356  388          if (rc != 0) {
 357  389                  return (rc);
 358  390          }
 359  391  
 360  392          /*
 361  393           * Unlike signing and decryption, we're processing the entirety of the
 362  394           * message here, so we don't skip anything.
 363  395           */
 364  396          mbuf = in_mbc->chain;
 365  397          while (resid > 0 && mbuf != NULL) {
 366  398                  tlen = mbuf->m_len;
 367  399                  if (tlen > resid)
 368  400                          tlen = resid;
 369  401                  rc = smb3_encrypt_update(&ctx, (uint8_t *)mbuf->m_data, tlen);
 370  402                  if (rc != 0) {
 371  403                          return (rc);
 372  404                  }
 373  405                  resid -= tlen;
 374  406                  mbuf = mbuf->m_next;
 375  407          }
 376  408  
 377  409          if (mbuf == NULL && resid > 0) {
 378  410                  cmn_err(CE_WARN, "not enough data to encrypt");
 379  411                  smb3_encrypt_cancel(&ctx);
 380  412                  return (-1);
 381  413          }
 382  414  
 383  415          rc = smb3_encrypt_final(&ctx, buf + SMB3_SIG_OFFS);
 384  416  
 385  417          return (rc);
 386  418  }
 387  419  
 388  420  void
 389  421  smb3_encrypt_fini(smb_session_t *s)
 390  422  {
 391  423          smb_crypto_mech_t *mech;
 392  424  
 393  425          if ((mech = s->enc_mech) != NULL) {
 394  426                  kmem_free(mech, sizeof (*mech));
 395  427                  s->enc_mech = NULL;
 396  428          }
 397  429  }
  
    | 
      ↓ open down ↓ | 
    42 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX