Print this page
12513 SMB 3.1.1 support for server

*** 9,18 **** --- 9,19 ---- * http://www.illumos.org/license/CDDL. */ /* * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2020 RackTop Systems, Inc. */ /* * Helper functions for SMB3 encryption using the * Kernel Cryptographic Framework (KCF)
*** 26,65 **** #include <smbsrv/smb_kcrypt.h> #include <smbsrv/smb2_kproto.h> #include <sys/cmn_err.h> /* ! * SMB3 encryption helpers: ! * (getmech, init, update, final) */ ! ! int ! smb3_encrypt_getmech(smb_crypto_mech_t *mech) { crypto_mech_type_t t; ! t = crypto_mech2id(SUN_CKM_AES_CCM); if (t == CRYPTO_MECH_INVALID) { ! cmn_err(CE_NOTE, "smb: no kcf mech: %s", SUN_CKM_AES_CCM); return (-1); } mech->cm_type = t; - return (0); } void ! smb3_crypto_init_param(smb3_crypto_param_t *param, uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize, size_t datasize) { ! param->ulMACSize = SMB2_SIG_SIZE; ! param->ulNonceSize = noncesize; ! param->nonce = nonce; ! param->ulDataSize = datasize; ! param->ulAuthDataSize = authsize; ! param->authData = auth; } /* * Start the KCF session, load the key */ --- 27,93 ---- #include <smbsrv/smb_kcrypt.h> #include <smbsrv/smb2_kproto.h> #include <sys/cmn_err.h> /* ! * Common function to see if a mech is available. */ ! static int ! find_mech(smb_crypto_mech_t *mech, crypto_mech_name_t name) { crypto_mech_type_t t; ! t = crypto_mech2id(name); if (t == CRYPTO_MECH_INVALID) { ! cmn_err(CE_NOTE, "smb: no kcf mech: %s", name); return (-1); } mech->cm_type = t; return (0); } + /* + * SMB3 encryption helpers: + * (getmech, init, update, final) + */ + + int + smb3_aes_ccm_getmech(smb_crypto_mech_t *mech) + { + return (find_mech(mech, SUN_CKM_AES_CCM)); + } + + int + smb3_aes_gcm_getmech(smb_crypto_mech_t *mech) + { + return (find_mech(mech, SUN_CKM_AES_GCM)); + } + void ! smb3_crypto_init_ccm_param(smb3_crypto_param_t *param, uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize, size_t datasize) { ! param->ccm.ulMACSize = SMB2_SIG_SIZE; ! param->ccm.ulNonceSize = noncesize; ! param->ccm.nonce = nonce; ! param->ccm.ulDataSize = datasize; ! param->ccm.ulAuthDataSize = authsize; ! param->ccm.authData = auth; ! } ! ! void ! smb3_crypto_init_gcm_param(smb3_crypto_param_t *param, ! uint8_t *nonce, size_t noncesize, uint8_t *auth, size_t authsize) ! { ! ASSERT3U(noncesize, ==, 12); ! param->gcm.pIv = nonce; ! param->gcm.ulIvLen = noncesize; /* should be 12 bytes */ ! /* tform hdr size - (protcolo id + signing) == 32 bytes */ ! param->gcm.ulTagBits = SMB2_SIG_SIZE << 3; /* convert bytes to bits */ ! param->gcm.pAAD = auth; /* auth data */ ! param->gcm.ulAADLen = authsize; /* auth data len */ } /* * Start the KCF session, load the key */
*** 197,207 **** --- 225,250 ---- if (rv != CRYPTO_SUCCESS) { cmn_err(CE_WARN, "crypto_encrypt_final failed: 0x%x", rv); return (-1); } + /* + * For some reason AES module processes ccm_encrypt_final and + * gcm_encrypt_final differently. + * For GCM it restores original offset (which is 0) and updates + * cd_length to size of residual data + mac len. + * For CCM it does nothing, what means offset is updated and cd_length + * is decreased by size of residual data + mac len. + */ + if (out.cd_offset == 0) { + /* GCM */ + outlen = out.cd_length - SMB2_SIG_SIZE; + } else { + /* CCM */ outlen = out.cd_offset - SMB2_SIG_SIZE; + } + if (outlen > 0) bcopy(buf, ctxp->output.cd_raw.iov_base + ctxp->output.cd_offset, outlen); bcopy(buf + outlen, digest16, SMB2_SIG_SIZE);