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(&param, 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(&param, sr->nonce, nonce_size, ! tmp_hdr, tlen); ! else ! smb3_crypto_init_ccm_param(&param, 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(&param, ! 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(&param, sr->nonce, nonce_size, ! buf + SMB3_NONCE_OFFS, ! SMB3_TFORM_HDR_SIZE - SMB3_NONCE_OFFS); ! else ! smb3_crypto_init_ccm_param(&param, 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.