#include "system/time.h"
#include "../lib/crypto/crypto.h"
#include "libcli/auth/libcli_auth.h"
+#include "heimdal/lib/hcrypto/aes.h"
static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
const struct netr_Credential *in,
struct netr_Credential *out)
{
- des_crypt112(out->data, in->data, creds->session_key, 1);
+ if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+ AES_KEY key;
+ uint8_t aes_in[AES_BLOCK_SIZE];
+ uint8_t aes_out[AES_BLOCK_SIZE];
+
+ AES_set_encrypt_key(creds->session_key, 128, &key);
+
+ ZERO_STRUCT(aes_in);
+ memcpy(aes_in, in->data, 8);
+ AES_encrypt(aes_in, aes_out, &key);
+ memcpy(out->data, aes_out, 8);
+
+ ZERO_STRUCT(key);
+ ZERO_STRUCT(aes_in);
+ ZERO_STRUCT(aes_out);
+ } else {
+ des_crypt112(out->data, in->data, creds->session_key, 1);
+ }
}
/*
hmac_md5_final(creds->session_key, &ctx);
}
+/*
+ initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
+
+ this call is made after the netr_ServerReqChallenge call
+*/
+static void netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState *creds,
+ const struct netr_Credential *client_challenge,
+ const struct netr_Credential *server_challenge,
+ const struct samr_Password *machine_password)
+{
+ struct HMACSHA256Context ctx;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+
+ ZERO_STRUCT(creds->session_key);
+
+ hmac_sha256_init(machine_password->hash,
+ sizeof(machine_password->hash),
+ &ctx);
+ hmac_sha256_update(client_challenge->data, 8, &ctx);
+ hmac_sha256_update(server_challenge->data, 8, &ctx);
+ hmac_sha256_final(digest, &ctx);
+
+ memcpy(creds->session_key, digest, sizeof(creds->session_key));
+
+ ZERO_STRUCT(digest);
+ ZERO_STRUCT(ctx);
+}
+
static void netlogon_creds_first_step(struct netlogon_creds_CredentialState *creds,
const struct netr_Credential *client_challenge,
const struct netr_Credential *server_challenge)
dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
- if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
+ if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+ netlogon_creds_init_hmac_sha256(creds,
+ client_challenge,
+ server_challenge,
+ machine_password);
+ } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
netlogon_creds_init_128bit(creds, client_challenge, server_challenge, machine_password);
} else {
netlogon_creds_init_64bit(creds, client_challenge, server_challenge, machine_password);
{
struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
bool ok = false;
+ bool try_aes = true;
bool try_strong = true;
bool try_weak = true;
bool fallback = false;
return NULL;
}
+ if (!ok && try_aes) {
+ if (fallback) {
+ DEBUG(2,("credentials check fallback to aes key\n"));
+ }
+ creds->negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
+ netlogon_creds_init_hmac_sha256(creds,
+ client_challenge,
+ server_challenge,
+ machine_password);
+ netlogon_creds_first_step(creds, client_challenge, server_challenge);
+ ok = netlogon_creds_server_check_internal(creds, credentials_in);
+ if (!ok) {
+ creds->negotiate_flags &= ~NETLOGON_NEG_SUPPORTS_AES;
+ fallback = true;
+ }
+ }
+
if (!ok && try_strong) {
if (fallback) {
DEBUG(2,("credentials check fallback to strong key\n"));
}
+ creds->negotiate_flags &= ~NETLOGON_NEG_SUPPORTS_AES;
creds->negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
netlogon_creds_init_128bit(creds, client_challenge, server_challenge,
machine_password);
if (fallback) {
DEBUG(2,("credentials check fallback to weak key\n"));
}
+ creds->negotiate_flags &= ~NETLOGON_NEG_SUPPORTS_AES;
creds->negotiate_flags &= ~NETLOGON_NEG_STRONG_KEYS;
netlogon_creds_init_64bit(creds, client_challenge, server_challenge,
machine_password);