#include "smbXcli_base.h"
#include "librpc/ndr/libndr.h"
#include "libcli/smb/smb2_negotiate_context.h"
+#include "libcli/smb/smb2_signing.h"
#include "lib/crypto/sha512.h"
#include "lib/crypto/aes.h"
#include "lib/crypto/aes_ccm_128.h"
uint64_t session_id;
uint16_t session_flags;
DATA_BLOB application_key;
- DATA_BLOB signing_key;
+ struct smb2_signing_key *signing_key;
bool should_sign;
bool should_encrypt;
DATA_BLOB encryption_key;
struct smb2cli_session *smb2;
struct {
- DATA_BLOB signing_key;
+ struct smb2_signing_key *signing_key;
uint8_t preauth_sha512[64];
} smb2_channel;
session->smb2->require_signed_response;
if (cmd == SMB2_OP_SESSSETUP &&
- session->smb2_channel.signing_key.length == 0 &&
- session->smb2->signing_key.length != 0)
+ !smb2_signing_key_valid(session->smb2_channel.signing_key) &&
+ smb2_signing_key_valid(session->smb2->signing_key))
{
/*
* a session bind needs to be signed
}
if (cmd == SMB2_OP_SESSSETUP &&
- session->smb2_channel.signing_key.length == 0) {
+ !smb2_signing_key_valid(session->smb2_channel.signing_key)) {
state->smb2.should_encrypt = false;
}
if (additional_flags & SMB2_HDR_FLAG_SIGNED) {
- if (session->smb2_channel.signing_key.length == 0) {
+ if (!smb2_signing_key_valid(session->smb2_channel.signing_key)) {
tevent_req_nterror(req, NT_STATUS_NO_USER_SESSION_KEY);
return req;
}
uint16_t charge;
uint16_t credits;
uint64_t mid;
- const DATA_BLOB *signing_key = NULL;
+ const struct smb2_signing_key *signing_key = NULL;
if (!tevent_req_is_in_progress(reqs[i])) {
return NT_STATUS_INTERNAL_ERROR;
* already there.
*/
if (state->smb2.should_sign) {
- signing_key = &state->session->smb2_channel.signing_key;
+ signing_key = state->session->smb2_channel.signing_key;
}
/*
* If it is a channel binding, we already have the main
* signing key and try that one.
*/
- if (signing_key && signing_key->length == 0) {
- signing_key = &state->session->smb2->signing_key;
+ if (!smb2_signing_key_valid(signing_key)) {
+ signing_key = state->session->smb2->signing_key;
}
/*
* If we do not have any session key yet, we skip the
* signing of SMB2_OP_SESSSETUP requests.
*/
- if (signing_key && signing_key->length == 0) {
+ if (!smb2_signing_key_valid(signing_key)) {
signing_key = NULL;
}
}
if (signing_key != NULL) {
NTSTATUS status;
- status = smb2_signing_sign_pdu(*signing_key,
+ status = smb2_signing_sign_pdu(signing_key->blob,
state->session->conn->protocol,
&iov[hdr_iov], num_iov - hdr_iov);
if (!NT_STATUS_IS_OK(status)) {
uint16_t credits = SVAL(inhdr, SMB2_HDR_CREDIT);
uint32_t new_credits;
struct smbXcli_session *session = NULL;
- const DATA_BLOB *signing_key = NULL;
+ const struct smb2_signing_key *signing_key = NULL;
bool was_encrypted = false;
new_credits = conn->smb2.cur_credits;
}
last_session = session;
- signing_key = &session->smb2_channel.signing_key;
+ signing_key = session->smb2_channel.signing_key;
}
if (opcode == SMB2_OP_SESSSETUP) {
* we try the main signing key, if it is not
* the final response.
*/
- if (signing_key && signing_key->length == 0 &&
+ if (!smb2_signing_key_valid(signing_key) &&
!NT_STATUS_IS_OK(status)) {
- signing_key = &session->smb2->signing_key;
+ signing_key = session->smb2->signing_key;
}
- if (signing_key && signing_key->length == 0) {
+ if (!smb2_signing_key_valid(signing_key)) {
/*
* If we do not have a session key to
* verify the signature, we defer the
}
}
- if (signing_key == NULL && state->smb2.require_signed_response) {
- signing_key = &session->smb2_channel.signing_key;
+ if (!smb2_signing_key_valid(signing_key) &&
+ state->smb2.require_signed_response) {
+ signing_key = session->smb2_channel.signing_key;
}
if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
if (signing_key) {
NTSTATUS signing_status;
- signing_status = smb2_signing_check_pdu(*signing_key,
+ signing_status = smb2_signing_check_pdu(signing_key->blob,
state->conn->protocol,
&cur[1], 3);
if (!NT_STATUS_IS_OK(signing_status)) {
TALLOC_CTX *mem_ctx,
DATA_BLOB *key)
{
- DATA_BLOB *sig = NULL;
+ const struct smb2_signing_key *sig = NULL;
if (session->conn == NULL) {
return NT_STATUS_NO_USER_SESSION_KEY;
* to session.
*/
- if (session->smb2_channel.signing_key.length != 0) {
- sig = &session->smb2_channel.signing_key;
- } else if (session->smb2->signing_key.length != 0) {
- sig = &session->smb2->signing_key;
+ if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
+ sig = session->smb2_channel.signing_key;
+ } else if (smb2_signing_key_valid(session->smb2->signing_key)) {
+ sig = session->smb2->signing_key;
} else {
return NT_STATUS_NO_USER_SESSION_KEY;
}
- *key = data_blob_dup_talloc(mem_ctx, *sig);
+ *key = data_blob_dup_talloc(mem_ctx, sig->blob);
if (key->data == NULL) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_OK;
}
- if (session->smb2_channel.signing_key.length != 0) {
+ if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
return NT_STATUS_OK;
}
return NT_STATUS_OK;
}
- if (session->smb2->signing_key.length != 0) {
+ if (smb2_signing_key_valid(session->smb2->signing_key)) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
memcpy(session_key, _session_key.data,
MIN(_session_key.length, sizeof(session_key)));
- session->smb2->signing_key = data_blob_talloc(session,
- session_key,
- sizeof(session_key));
- if (session->smb2->signing_key.data == NULL) {
+ session->smb2->signing_key = talloc_zero(session,
+ struct smb2_signing_key);
+ if (session->smb2->signing_key == NULL) {
+ ZERO_STRUCT(session_key);
+ return NT_STATUS_NO_MEMORY;
+ }
+ /* TODO: setup destructor once we cache the hmac handle */
+
+ session->smb2->signing_key->blob =
+ data_blob_talloc(session->smb2->signing_key,
+ session_key,
+ sizeof(session_key));
+ if (!smb2_signing_key_valid(session->smb2->signing_key)) {
ZERO_STRUCT(session_key);
return NT_STATUS_NO_MEMORY;
}
smb2_key_derivation(session_key, sizeof(session_key),
d->label.data, d->label.length,
d->context.data, d->context.length,
- session->smb2->signing_key.data);
+ session->smb2->signing_key->blob.data);
}
- session->smb2->encryption_key = data_blob_dup_talloc(session,
- session->smb2->signing_key);
+ session->smb2->encryption_key =
+ data_blob_dup_talloc(session,
+ session->smb2->signing_key->blob);
if (session->smb2->encryption_key.data == NULL) {
ZERO_STRUCT(session_key);
return NT_STATUS_NO_MEMORY;
session->smb2->encryption_key.data);
}
- session->smb2->decryption_key = data_blob_dup_talloc(session,
- session->smb2->signing_key);
+ session->smb2->decryption_key =
+ data_blob_dup_talloc(session,
+ session->smb2->signing_key->blob);
if (session->smb2->decryption_key.data == NULL) {
ZERO_STRUCT(session_key);
return NT_STATUS_NO_MEMORY;
session->smb2->decryption_key.data);
}
- session->smb2->application_key = data_blob_dup_talloc(session,
- session->smb2->signing_key);
+ session->smb2->application_key =
+ data_blob_dup_talloc(session,
+ session->smb2->signing_key->blob);
if (session->smb2->application_key.data == NULL) {
ZERO_STRUCT(session_key);
return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCT(session_key);
- session->smb2_channel.signing_key = data_blob_dup_talloc(session,
- session->smb2->signing_key);
- if (session->smb2_channel.signing_key.data == NULL) {
+ session->smb2_channel.signing_key =
+ talloc_zero(session, struct smb2_signing_key);
+ if (session->smb2_channel.signing_key == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ /* TODO: setup destructor once we cache the hmac handle */
+
+ session->smb2_channel.signing_key->blob =
+ data_blob_dup_talloc(session->smb2_channel.signing_key,
+ session->smb2->signing_key->blob);
+ if (!smb2_signing_key_valid(session->smb2_channel.signing_key)) {
return NT_STATUS_NO_MEMORY;
}
}
if (check_signature) {
- status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
+ status = smb2_signing_check_pdu(session->smb2_channel.signing_key->blob,
session->conn->protocol,
recv_iov, 3);
if (!NT_STATUS_IS_OK(status)) {
{
struct smbXcli_session *session2;
- if (session1->smb2->signing_key.length == 0) {
+ if (!smb2_signing_key_valid(session1->smb2->signing_key)) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
return NT_STATUS_INVALID_PARAMETER_MIX;
}
- if (session->smb2_channel.signing_key.length != 0) {
+ if (smb2_signing_key_valid(session->smb2_channel.signing_key)) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
memcpy(channel_key, _channel_key.data,
MIN(_channel_key.length, sizeof(channel_key)));
- session->smb2_channel.signing_key = data_blob_talloc(session,
- channel_key,
- sizeof(channel_key));
- if (session->smb2_channel.signing_key.data == NULL) {
+ session->smb2_channel.signing_key->blob =
+ data_blob_talloc(session->smb2_channel.signing_key,
+ channel_key,
+ sizeof(channel_key));
+ if (!smb2_signing_key_valid(session->smb2_channel.signing_key)) {
ZERO_STRUCT(channel_key);
return NT_STATUS_NO_MEMORY;
}
smb2_key_derivation(channel_key, sizeof(channel_key),
d->label.data, d->label.length,
d->context.data, d->context.length,
- session->smb2_channel.signing_key.data);
+ session->smb2_channel.signing_key->blob.data);
}
ZERO_STRUCT(channel_key);
- status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
+ status = smb2_signing_check_pdu(session->smb2_channel.signing_key->blob,
session->conn->protocol,
recv_iov, 3);
if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_NOT_SUPPORTED;
}
- if (session->smb2->signing_key.data == NULL) {
+ if (!smb2_signing_key_valid(session->smb2->signing_key)) {
return NT_STATUS_NOT_SUPPORTED;
}
session->smb2->should_encrypt = true;