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_kcf.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb3_encrypt_kcf.c
↓ 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 2018 Nexenta Systems, Inc.  All rights reserved.
       14 + * Copyright 2020 RackTop Systems, Inc.
  14   15   */
  15   16  
  16   17  /*
  17   18   * Helper functions for SMB3 encryption using the
  18   19   * Kernel Cryptographic Framework (KCF)
  19   20   *
  20   21   * There are two implementations of these functions:
  21   22   * This one (for kernel) and another for user space:
  22   23   * See: lib/smbsrv/libfksmbsrv/common/fksmb_encrypt_pkcs.c
  23   24   */
  24   25  
  25   26  #include <sys/crypto/api.h>
  26   27  #include <smbsrv/smb_kcrypt.h>
  27   28  #include <smbsrv/smb2_kproto.h>
  28   29  #include <sys/cmn_err.h>
  29   30  
  30   31  /*
  31      - * SMB3 encryption helpers:
  32      - * (getmech, init, update, final)
       32 + * Common function to see if a mech is available.
  33   33   */
  34      -
  35      -int
  36      -smb3_encrypt_getmech(smb_crypto_mech_t *mech)
       34 +static int
       35 +find_mech(smb_crypto_mech_t *mech, crypto_mech_name_t name)
  37   36  {
  38   37          crypto_mech_type_t t;
  39   38  
  40      -        t = crypto_mech2id(SUN_CKM_AES_CCM);
       39 +        t = crypto_mech2id(name);
  41   40          if (t == CRYPTO_MECH_INVALID) {
  42      -                cmn_err(CE_NOTE, "smb: no kcf mech: %s", SUN_CKM_AES_CCM);
       41 +                cmn_err(CE_NOTE, "smb: no kcf mech: %s", name);
  43   42                  return (-1);
  44   43          }
  45   44          mech->cm_type = t;
  46      -
  47   45          return (0);
  48   46  }
  49   47  
       48 +/*
       49 + * SMB3 encryption helpers:
       50 + * (getmech, init, update, final)
       51 + */
       52 +
       53 +int
       54 +smb3_aes_ccm_getmech(smb_crypto_mech_t *mech)
       55 +{
       56 +        return (find_mech(mech, SUN_CKM_AES_CCM));
       57 +}
       58 +
       59 +int
       60 +smb3_aes_gcm_getmech(smb_crypto_mech_t *mech)
       61 +{
       62 +        return (find_mech(mech, SUN_CKM_AES_GCM));
       63 +}
       64 +
  50   65  void
  51      -smb3_crypto_init_param(smb3_crypto_param_t *param,
       66 +smb3_crypto_init_ccm_param(smb3_crypto_param_t *param,
  52   67      uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize,
  53   68      size_t datasize)
  54   69  {
  55      -        param->ulMACSize = SMB2_SIG_SIZE;
  56      -        param->ulNonceSize = noncesize;
  57      -        param->nonce = nonce;
  58      -        param->ulDataSize = datasize;
  59      -        param->ulAuthDataSize = authsize;
  60      -        param->authData = auth;
       70 +        param->ccm.ulMACSize = SMB2_SIG_SIZE;
       71 +        param->ccm.ulNonceSize = noncesize;
       72 +        param->ccm.nonce = nonce;
       73 +        param->ccm.ulDataSize = datasize;
       74 +        param->ccm.ulAuthDataSize = authsize;
       75 +        param->ccm.authData = auth;
       76 +}
       77 +
       78 +void
       79 +smb3_crypto_init_gcm_param(smb3_crypto_param_t *param,
       80 +    uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize)
       81 +{
       82 +        ASSERT3U(noncesize, ==, 12);
       83 +        param->gcm.pIv = nonce;
       84 +        param->gcm.ulIvLen = noncesize;         /* should be 12 bytes */
       85 +        /* tform hdr size - (protcolo id + signing) == 32 bytes */
       86 +        param->gcm.ulTagBits = SMB2_SIG_SIZE << 3; /* convert bytes to bits */
       87 +        param->gcm.pAAD = auth;                 /* auth data */
       88 +        param->gcm.ulAADLen = authsize;         /* auth data len */
  61   89  }
  62   90  
  63   91  /*
  64   92   * Start the KCF session, load the key
  65   93   */
  66   94  static int
  67   95  smb3_crypto_init(smb3_enc_ctx_t *ctxp, smb_crypto_mech_t *mech,
  68   96      uint8_t *key, size_t key_len, smb3_crypto_param_t *param,
  69   97      boolean_t is_encrypt)
  70   98  {
↓ open down ↓ 121 lines elided ↑ open up ↑
 192  220          out.cd_raw.iov_len = sizeof (buf);
 193  221          out.cd_raw.iov_base = (void *)buf;
 194  222  
 195  223          rv = crypto_encrypt_final(ctxp->ctx, &out, 0);
 196  224  
 197  225          if (rv != CRYPTO_SUCCESS) {
 198  226                  cmn_err(CE_WARN, "crypto_encrypt_final failed: 0x%x", rv);
 199  227                  return (-1);
 200  228          }
 201  229  
 202      -        outlen = out.cd_offset - SMB2_SIG_SIZE;
      230 +        /*
      231 +         * For some reason AES module processes ccm_encrypt_final and
      232 +         * gcm_encrypt_final differently.
      233 +         * For GCM it restores original offset (which is 0) and updates
      234 +         * cd_length to size of residual data + mac len.
      235 +         * For CCM it does nothing, what means offset is updated and cd_length
      236 +         * is decreased by size of residual data + mac len.
      237 +         */
      238 +        if (out.cd_offset == 0) {
      239 +                /* GCM */
      240 +                outlen = out.cd_length - SMB2_SIG_SIZE;
      241 +        } else {
      242 +                /* CCM */
      243 +                outlen = out.cd_offset - SMB2_SIG_SIZE;
      244 +        }
      245 +
 203  246          if (outlen > 0)
 204  247                  bcopy(buf, ctxp->output.cd_raw.iov_base +
 205  248                      ctxp->output.cd_offset, outlen);
 206  249          bcopy(buf + outlen, digest16, SMB2_SIG_SIZE);
 207  250  
 208  251          return (0);
 209  252  }
 210  253  
 211  254  int
 212  255  smb3_decrypt_final(smb3_enc_ctx_t *ctxp, uint8_t *buf, size_t buflen)
↓ open down ↓ 23 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX