mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
s3:smb2_server: In CCM and GCM mode we can't reuse nonces
Reuse of nonces with AES-CCM and AES-GCM leads to catastrophic failure, so make sure the server drops the connection if that ever happens. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11300 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Simo Sorce <simo@redhat.com> Signed-off-by: Stefan Metzmacher <metze@samba.org> Autobuild-User(master): Simo Sorce <idra@samba.org> Autobuild-Date(master): Fri May 29 22:38:50 CEST 2015 on sn-devel-104
This commit is contained in:
parent
477ecfbdaf
commit
461c69bd7c
@ -185,6 +185,8 @@ interface smbXsrv
|
||||
[ref] smbXsrv_session_global0 *global;
|
||||
NTSTATUS status;
|
||||
NTTIME idle_time;
|
||||
hyper nonce_high_random;
|
||||
hyper nonce_high_max;
|
||||
hyper nonce_high;
|
||||
hyper nonce_low;
|
||||
[ignore] gensec_security *gensec;
|
||||
|
@ -1458,6 +1458,41 @@ static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
|
||||
return key;
|
||||
}
|
||||
|
||||
static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
|
||||
uint64_t *new_nonce_high,
|
||||
uint64_t *new_nonce_low)
|
||||
{
|
||||
uint64_t nonce_high;
|
||||
uint64_t nonce_low;
|
||||
|
||||
session->nonce_low += 1;
|
||||
if (session->nonce_low == 0) {
|
||||
session->nonce_low += 1;
|
||||
session->nonce_high += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* CCM and GCM algorithms must never have their
|
||||
* nonce wrap, or the security of the whole
|
||||
* communication and the keys is destroyed.
|
||||
* We must drop the connection once we have
|
||||
* transfered too much data.
|
||||
*
|
||||
* NOTE: We assume nonces greater than 8 bytes.
|
||||
*/
|
||||
if (session->nonce_high >= session->nonce_high_max) {
|
||||
return NT_STATUS_ENCRYPTION_FAILED;
|
||||
}
|
||||
|
||||
nonce_high = session->nonce_high_random;
|
||||
nonce_high += session->nonce_high;
|
||||
nonce_low = session->nonce_low;
|
||||
|
||||
*new_nonce_high = nonce_high;
|
||||
*new_nonce_low = nonce_low;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
|
||||
struct tevent_timer *te,
|
||||
struct timeval current_time,
|
||||
@ -1524,15 +1559,13 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
|
||||
dyn = body + 8;
|
||||
|
||||
if (req->do_encryption) {
|
||||
struct smbXsrv_session *x = req->session;
|
||||
|
||||
nonce_high = x->nonce_high;
|
||||
nonce_low = x->nonce_low;
|
||||
|
||||
x->nonce_low += 1;
|
||||
if (x->nonce_low == 0) {
|
||||
x->nonce_low += 1;
|
||||
x->nonce_high += 1;
|
||||
status = smb2_get_new_nonce(req->session,
|
||||
&nonce_high,
|
||||
&nonce_low);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
smbd_server_connection_terminate(xconn,
|
||||
nt_errstr(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2374,17 +2407,14 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
|
||||
DATA_BLOB encryption_key = req->session->global->encryption_key;
|
||||
uint8_t *tf;
|
||||
uint64_t session_id = req->session->global->session_wire_id;
|
||||
struct smbXsrv_session *x = req->session;
|
||||
uint64_t nonce_high;
|
||||
uint64_t nonce_low;
|
||||
|
||||
nonce_high = x->nonce_high;
|
||||
nonce_low = x->nonce_low;
|
||||
|
||||
x->nonce_low += 1;
|
||||
if (x->nonce_low == 0) {
|
||||
x->nonce_low += 1;
|
||||
x->nonce_high += 1;
|
||||
status = smb2_get_new_nonce(req->session,
|
||||
&nonce_high,
|
||||
&nonce_low);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2829,13 +2859,11 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
|
||||
talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
|
||||
|
||||
if (do_encryption) {
|
||||
nonce_high = session->nonce_high;
|
||||
nonce_low = session->nonce_low;
|
||||
|
||||
session->nonce_low += 1;
|
||||
if (session->nonce_low == 0) {
|
||||
session->nonce_low += 1;
|
||||
session->nonce_high += 1;
|
||||
status = smb2_get_new_nonce(session,
|
||||
&nonce_high,
|
||||
&nonce_low);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "../libcli/security/security.h"
|
||||
#include "../lib/util/tevent_ntstatus.h"
|
||||
#include "lib/crypto/sha512.h"
|
||||
#include "lib/crypto/aes.h"
|
||||
#include "lib/crypto/aes_ccm_128.h"
|
||||
#include "lib/crypto/aes_gcm_128.h"
|
||||
|
||||
static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
@ -335,6 +338,7 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
|
||||
|
||||
if (xconn->protocol >= PROTOCOL_SMB2_24) {
|
||||
struct _derivation *d = &derivation.encryption;
|
||||
size_t nonce_size;
|
||||
|
||||
x->global->encryption_key = data_blob_talloc(x->global,
|
||||
session_key,
|
||||
@ -349,8 +353,31 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
|
||||
d->context.data, d->context.length,
|
||||
x->global->encryption_key.data);
|
||||
|
||||
generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
|
||||
x->nonce_low = 1;
|
||||
/*
|
||||
* CCM and GCM algorithms must never have their
|
||||
* nonce wrap, or the security of the whole
|
||||
* communication and the keys is destroyed.
|
||||
* We must drop the connection once we have
|
||||
* transfered too much data.
|
||||
*
|
||||
* NOTE: We assume nonces greater than 8 bytes.
|
||||
*/
|
||||
generate_random_buffer((uint8_t *)&x->nonce_high_random,
|
||||
sizeof(x->nonce_high_random));
|
||||
switch (xconn->smb2.server.cipher) {
|
||||
case SMB2_ENCRYPTION_AES128_CCM:
|
||||
nonce_size = AES_CCM_128_NONCE_SIZE;
|
||||
break;
|
||||
case SMB2_ENCRYPTION_AES128_GCM:
|
||||
nonce_size = AES_GCM_128_IV_SIZE;
|
||||
break;
|
||||
default:
|
||||
ZERO_STRUCT(session_key);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
|
||||
x->nonce_high = 0;
|
||||
x->nonce_low = 0;
|
||||
}
|
||||
|
||||
x->global->application_key = data_blob_dup_talloc(x->global,
|
||||
|
Loading…
Reference in New Issue
Block a user