Print this page
12513 SMB 3.1.1 support for server
*** 9,18 ****
--- 9,19 ----
* http://www.illumos.org/license/CDDL.
*/
/*
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 RackTop Systems, Inc.
*/
/*
* Routines for smb3 encryption.
*/
*** 22,48 ****
#include <sys/random.h>
#include <sys/cmn_err.h>
#define SMB3_NONCE_OFFS 20
#define SMB3_SIG_OFFS 4
! #define SMB3_NONCE_SIZE 11 /* 12 for gcm later */
!
! /*
! * Inputs to KDF for EncryptionKey and DecryptionKey.
! * See comment for smb3_do_kdf for content.
! */
! static uint8_t encrypt_kdf_input[30] = {
! 0, 0, 0, 1, 'S', 'M', 'B', '2',
! 'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
! 'S', 'e', 'r', 'v', 'e', 'r', 'O',
! 'u', 't', 0, 0, 0, 0, 0x80 };
!
! static uint8_t decrypt_kdf_input[30] = {
! 0, 0, 0, 1, 'S', 'M', 'B', '2',
! 'A', 'E', 'S', 'C', 'C', 'M', 0, 0,
! 'S', 'e', 'r', 'v', 'e', 'r', 'I',
! 'n', ' ', 0, 0, 0, 0, 0x80 };
/*
* Arbitrary value used to prevent nonce reuse via overflow. Currently
* 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
* 2^32 concurrent messages when we hit this number.
--- 23,34 ----
#include <sys/random.h>
#include <sys/cmn_err.h>
#define SMB3_NONCE_OFFS 20
#define SMB3_SIG_OFFS 4
! #define SMB3_AES128_CCM_NONCE_SIZE 11
! #define SMB3_AES128_GCM_NONCE_SIZE 12
/*
* Arbitrary value used to prevent nonce reuse via overflow. Currently
* 2^64 - 2^32 - 1. Assumes we can't have (or are unlikely to have)
* 2^32 concurrent messages when we hit this number.
*** 98,109 ****
int rc;
if (s->enc_mech != NULL)
return (0);
mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
! rc = smb3_encrypt_getmech(mech);
if (rc != 0) {
kmem_free(mech, sizeof (*mech));
return (rc);
}
s->enc_mech = mech;
--- 84,109 ----
int rc;
if (s->enc_mech != NULL)
return (0);
+ if (s->dialect < SMB_VERS_3_11)
+ s->smb31_enc_cipherid = SMB3_CIPHER_AES128_CCM;
+
mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
!
! switch (s->smb31_enc_cipherid) {
! case SMB3_CIPHER_AES128_GCM:
! rc = smb3_aes_gcm_getmech(mech);
! break;
! case SMB3_CIPHER_AES128_CCM:
! rc = smb3_aes_ccm_getmech(mech);
! break;
! default:
! return (-1);
! }
!
if (rc != 0) {
kmem_free(mech, sizeof (*mech));
return (rc);
}
s->enc_mech = mech;
*** 148,166 ****
/*
* For SMB3, the encrypt/decrypt keys are derived from
* the session key using KDF in counter mode.
*/
! if (smb3_do_kdf(enc_key->key, encrypt_kdf_input,
! sizeof (encrypt_kdf_input), token->tkn_ssnkey.val,
! token->tkn_ssnkey.len) != 0)
return;
! if (smb3_do_kdf(dec_key->key, decrypt_kdf_input,
! sizeof (decrypt_kdf_input), token->tkn_ssnkey.val,
! token->tkn_ssnkey.len) != 0)
return;
smb3_encrypt_init_nonce(u);
enc_key->len = SMB3_KEYLEN;
dec_key->len = SMB3_KEYLEN;
--- 148,182 ----
/*
* For SMB3, the encrypt/decrypt keys are derived from
* the session key using KDF in counter mode.
*/
! if (s->dialect >= SMB_VERS_3_11) {
! if (smb3_kdf(enc_key->key,
! token->tkn_ssnkey.val, token->tkn_ssnkey.len,
! (uint8_t *)"SMBS2CCipherKey", 16,
! s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
! return;
!
! if (smb3_kdf(dec_key->key,
! token->tkn_ssnkey.val, token->tkn_ssnkey.len,
! (uint8_t *)"SMBC2SCipherKey", 16,
! s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH) != 0)
! return;
! } else {
! if (smb3_kdf(enc_key->key,
! token->tkn_ssnkey.val, token->tkn_ssnkey.len,
! (uint8_t *)"SMB2AESCCM", 11,
! (uint8_t *)"ServerOut", 10) != 0)
return;
! if (smb3_kdf(dec_key->key,
! token->tkn_ssnkey.val, token->tkn_ssnkey.len,
! (uint8_t *)"SMB2AESCCM", 11,
! (uint8_t *)"ServerIn ", 10) != 0)
return;
+ }
smb3_encrypt_init_nonce(u);
enc_key->len = SMB3_KEYLEN;
dec_key->len = SMB3_KEYLEN;
*** 182,191 ****
--- 198,211 ----
struct smb_key *dec_key = &u->u_dec_key;
struct mbuf *mbuf;
int offset, resid, tlen, rc;
smb3_crypto_param_t param;
smb_crypto_mech_t mech;
+ boolean_t gcm = sr->session->smb31_enc_cipherid ==
+ SMB3_CIPHER_AES128_GCM;
+ size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
+ SMB3_AES128_CCM_NONCE_SIZE);
ASSERT(u != NULL);
if (s->enc_mech == NULL || dec_key->len != 16) {
return (-1);
}
*** 208,218 ****
/*
* The transform header, minus the PROTOCOL_ID and the
* SIGNATURE, is authenticated but not encrypted.
*/
! smb3_crypto_init_param(¶m, sr->nonce, SMB3_NONCE_SIZE,
tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
/*
* Unlike signing, which uses one global mech struct,
* encryption requires modifying the mech to add a
--- 228,242 ----
/*
* The transform header, minus the PROTOCOL_ID and the
* SIGNATURE, is authenticated but not encrypted.
*/
! if (gcm)
! smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
! tmp_hdr, tlen);
! else
! smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
tmp_hdr, tlen, sr->msgsize + SMB2_SIG_SIZE);
/*
* Unlike signing, which uses one global mech struct,
* encryption requires modifying the mech to add a
*** 315,350 ****
struct smb_key *enc_key = &u->u_enc_key;
struct mbuf *mbuf;
int resid, tlen, rc;
smb3_crypto_param_t param;
smb_crypto_mech_t mech;
ASSERT(u != NULL);
if (s->enc_mech == NULL || enc_key->len != 16) {
return (-1);
}
! rc = smb3_encrypt_gen_nonce(u, sr->nonce, SMB3_NONCE_SIZE);
if (rc != 0) {
cmn_err(CE_WARN, "ran out of nonces");
return (-1);
}
(void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
! SMB3_NONCE_SIZE, sr->nonce);
resid = in_mbc->max_bytes;
/*
* The transform header, minus the PROTOCOL_ID and the
* SIGNATURE, is authenticated but not encrypted.
*/
! smb3_crypto_init_param(¶m,
! sr->nonce, SMB3_NONCE_SIZE,
! buf + SMB3_NONCE_OFFS, SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS,
! resid);
/*
* Unlike signing, which uses one global mech struct,
* encryption requires modifying the mech to add a
* per-use param struct. Thus, we need to make a copy.
--- 339,382 ----
struct smb_key *enc_key = &u->u_enc_key;
struct mbuf *mbuf;
int resid, tlen, rc;
smb3_crypto_param_t param;
smb_crypto_mech_t mech;
+ boolean_t gcm = sr->session->smb31_enc_cipherid ==
+ SMB3_CIPHER_AES128_GCM;
+ size_t nonce_size = (gcm ? SMB3_AES128_GCM_NONCE_SIZE :
+ SMB3_AES128_CCM_NONCE_SIZE);
ASSERT(u != NULL);
if (s->enc_mech == NULL || enc_key->len != 16) {
return (-1);
}
! rc = smb3_encrypt_gen_nonce(u, sr->nonce, nonce_size);
if (rc != 0) {
cmn_err(CE_WARN, "ran out of nonces");
return (-1);
}
(void) smb_mbc_poke(out_mbc, SMB3_NONCE_OFFS, "#c",
! nonce_size, sr->nonce);
resid = in_mbc->max_bytes;
/*
* The transform header, minus the PROTOCOL_ID and the
* SIGNATURE, is authenticated but not encrypted.
*/
! if (gcm)
! smb3_crypto_init_gcm_param(¶m, sr->nonce, nonce_size,
! buf + SMB3_NONCE_OFFS,
! SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS);
! else
! smb3_crypto_init_ccm_param(¶m, sr->nonce, nonce_size,
! buf + SMB3_NONCE_OFFS,
! SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS, resid);
/*
* Unlike signing, which uses one global mech struct,
* encryption requires modifying the mech to add a
* per-use param struct. Thus, we need to make a copy.