Print this page
12513 SMB 3.1.1 support for server
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.

  14  */
  15 
  16 /*
  17  * Helper functions for SMB3 encryption using the
  18  * Kernel Cryptographic Framework (KCF)
  19  *
  20  * There are two implementations of these functions:
  21  * This one (for kernel) and another for user space:
  22  * See: lib/smbsrv/libfksmbsrv/common/fksmb_encrypt_pkcs.c
  23  */
  24 
  25 #include <sys/crypto/api.h>
  26 #include <smbsrv/smb_kcrypt.h>
  27 #include <smbsrv/smb2_kproto.h>
  28 #include <sys/cmn_err.h>
  29 
  30 /*
  31  * SMB3 encryption helpers:
  32  * (getmech, init, update, final)
  33  */
  34 
  35 int
  36 smb3_encrypt_getmech(smb_crypto_mech_t *mech)
  37 {
  38         crypto_mech_type_t t;
  39 
  40         t = crypto_mech2id(SUN_CKM_AES_CCM);
  41         if (t == CRYPTO_MECH_INVALID) {
  42                 cmn_err(CE_NOTE, "smb: no kcf mech: %s", SUN_CKM_AES_CCM);
  43                 return (-1);
  44         }
  45         mech->cm_type = t;
  46 
  47         return (0);
  48 }
  49 

















  50 void
  51 smb3_crypto_init_param(smb3_crypto_param_t *param,
  52     uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize,
  53     size_t datasize)
  54 {
  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;













  61 }
  62 
  63 /*
  64  * Start the KCF session, load the key
  65  */
  66 static int
  67 smb3_crypto_init(smb3_enc_ctx_t *ctxp, smb_crypto_mech_t *mech,
  68     uint8_t *key, size_t key_len, smb3_crypto_param_t *param,
  69     boolean_t is_encrypt)
  70 {
  71         crypto_key_t ckey;
  72         int rv;
  73 
  74         bzero(&ckey, sizeof (ckey));
  75         ckey.ck_format = CRYPTO_KEY_RAW;
  76         ckey.ck_data = key;
  77         ckey.ck_length = key_len * 8; /* in bits */
  78 
  79         mech->cm_param = (caddr_t)param;
  80         mech->cm_param_len = sizeof (*param);


 182 smb3_encrypt_final(smb3_enc_ctx_t *ctxp, uint8_t *digest16)
 183 {
 184         crypto_data_t out;
 185         int rv;
 186         uint8_t buf[SMB2_SIG_SIZE + 16] = {0};
 187         size_t outlen;
 188 
 189         bzero(&out, sizeof (out));
 190         out.cd_format = CRYPTO_DATA_RAW;
 191         out.cd_length = sizeof (buf);
 192         out.cd_raw.iov_len = sizeof (buf);
 193         out.cd_raw.iov_base = (void *)buf;
 194 
 195         rv = crypto_encrypt_final(ctxp->ctx, &out, 0);
 196 
 197         if (rv != CRYPTO_SUCCESS) {
 198                 cmn_err(CE_WARN, "crypto_encrypt_final failed: 0x%x", rv);
 199                 return (-1);
 200         }
 201 













 202         outlen = out.cd_offset - SMB2_SIG_SIZE;


 203         if (outlen > 0)
 204                 bcopy(buf, ctxp->output.cd_raw.iov_base +
 205                     ctxp->output.cd_offset, outlen);
 206         bcopy(buf + outlen, digest16, SMB2_SIG_SIZE);
 207 
 208         return (0);
 209 }
 210 
 211 int
 212 smb3_decrypt_final(smb3_enc_ctx_t *ctxp, uint8_t *buf, size_t buflen)
 213 {
 214         crypto_data_t out;
 215         int rv;
 216 
 217         bzero(&out, sizeof (out));
 218         out.cd_format = CRYPTO_DATA_RAW;
 219         out.cd_length = buflen;
 220         out.cd_raw.iov_len = buflen;
 221         out.cd_raw.iov_base = (void *)buf;
 222 
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  14  * Copyright 2020 RackTop Systems, Inc.
  15  */
  16 
  17 /*
  18  * Helper functions for SMB3 encryption using the
  19  * Kernel Cryptographic Framework (KCF)
  20  *
  21  * There are two implementations of these functions:
  22  * This one (for kernel) and another for user space:
  23  * See: lib/smbsrv/libfksmbsrv/common/fksmb_encrypt_pkcs.c
  24  */
  25 
  26 #include <sys/crypto/api.h>
  27 #include <smbsrv/smb_kcrypt.h>
  28 #include <smbsrv/smb2_kproto.h>
  29 #include <sys/cmn_err.h>
  30 
  31 /*
  32  * Common function to see if a mech is available.

  33  */
  34 static int
  35 find_mech(smb_crypto_mech_t *mech, crypto_mech_name_t name)

  36 {
  37         crypto_mech_type_t t;
  38 
  39         t = crypto_mech2id(name);
  40         if (t == CRYPTO_MECH_INVALID) {
  41                 cmn_err(CE_NOTE, "smb: no kcf mech: %s", name);
  42                 return (-1);
  43         }
  44         mech->cm_type = t;

  45         return (0);
  46 }
  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 
  65 void
  66 smb3_crypto_init_ccm_param(smb3_crypto_param_t *param,
  67     uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize,
  68     size_t datasize)
  69 {
  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 */
  89 }
  90 
  91 /*
  92  * Start the KCF session, load the key
  93  */
  94 static int
  95 smb3_crypto_init(smb3_enc_ctx_t *ctxp, smb_crypto_mech_t *mech,
  96     uint8_t *key, size_t key_len, smb3_crypto_param_t *param,
  97     boolean_t is_encrypt)
  98 {
  99         crypto_key_t ckey;
 100         int rv;
 101 
 102         bzero(&ckey, sizeof (ckey));
 103         ckey.ck_format = CRYPTO_KEY_RAW;
 104         ckey.ck_data = key;
 105         ckey.ck_length = key_len * 8; /* in bits */
 106 
 107         mech->cm_param = (caddr_t)param;
 108         mech->cm_param_len = sizeof (*param);


 210 smb3_encrypt_final(smb3_enc_ctx_t *ctxp, uint8_t *digest16)
 211 {
 212         crypto_data_t out;
 213         int rv;
 214         uint8_t buf[SMB2_SIG_SIZE + 16] = {0};
 215         size_t outlen;
 216 
 217         bzero(&out, sizeof (out));
 218         out.cd_format = CRYPTO_DATA_RAW;
 219         out.cd_length = sizeof (buf);
 220         out.cd_raw.iov_len = sizeof (buf);
 221         out.cd_raw.iov_base = (void *)buf;
 222 
 223         rv = crypto_encrypt_final(ctxp->ctx, &out, 0);
 224 
 225         if (rv != CRYPTO_SUCCESS) {
 226                 cmn_err(CE_WARN, "crypto_encrypt_final failed: 0x%x", rv);
 227                 return (-1);
 228         }
 229 
 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 
 246         if (outlen > 0)
 247                 bcopy(buf, ctxp->output.cd_raw.iov_base +
 248                     ctxp->output.cd_offset, outlen);
 249         bcopy(buf + outlen, digest16, SMB2_SIG_SIZE);
 250 
 251         return (0);
 252 }
 253 
 254 int
 255 smb3_decrypt_final(smb3_enc_ctx_t *ctxp, uint8_t *buf, size_t buflen)
 256 {
 257         crypto_data_t out;
 258         int rv;
 259 
 260         bzero(&out, sizeof (out));
 261         out.cd_format = CRYPTO_DATA_RAW;
 262         out.cd_length = buflen;
 263         out.cd_raw.iov_len = buflen;
 264         out.cd_raw.iov_base = (void *)buf;
 265