[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Tue Feb 28 20:55:05 MST 2012
The branch, master has been updated
via c9219fe libcli/smb/smbXcli: use smb2_key_deviration() to setup SMB 2.24 keys
via 39ae473 libcli/smb/smb2_signing: implement aes_cmac_128 based signing for SMB 2.24
via 7f5e569 libcli/smb/smb2_signing: add smb2_key_deviration()
via 7102eaf lib/crypto: add aes_cmac_128_test.c as local.crypto.aes_cmac_128 test
via 062d1a0 lib/crypto: add aes_cmac_128* (rfc 4493)
from de870e9 s3: Introduce "req" helper var in reply_lockingX_success
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit c9219fe5859957589570ff0deeaccd17125d347e
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Feb 27 09:33:46 2012 +0100
libcli/smb/smbXcli: use smb2_key_deviration() to setup SMB 2.24 keys
This uses the key diveration function from "NIST Special Publication 800-108"
in counter mode (section 5.1).
Thanks to Jeremy, Michael and Volker for the debugging!
metze
Autobuild-User: Stefan Metzmacher <metze at samba.org>
Autobuild-Date: Wed Feb 29 04:54:48 CET 2012 on sn-devel-104
commit 39ae4737e0fbf8db348db76f7a534a55304918f0
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Feb 27 09:32:33 2012 +0100
libcli/smb/smb2_signing: implement aes_cmac_128 based signing for SMB 2.24
metze
commit 7f5e56971f617fd71ec47a54866577d08dabd1d7
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Feb 22 13:13:47 2012 +0100
libcli/smb/smb2_signing: add smb2_key_deviration()
This implements a simplified version of "NIST Special Publication 800-108" section 5.1
using hmac-sha256.
Thanks to Jeremy, Michael and Volker for the debugging!
metze
commit 7102eafc266e82121b1a267991584885ebfa9a65
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Feb 29 01:39:31 2012 +0100
lib/crypto: add aes_cmac_128_test.c as local.crypto.aes_cmac_128 test
metze
commit 062d1a09c2ef5efcdb85c77d7d27109b1317b46c
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Feb 18 11:47:31 2012 +0100
lib/crypto: add aes_cmac_128* (rfc 4493)
Thanks to Jeremy, Michael and Volker for the debugging!
metze
-----------------------------------------------------------------------
Summary of changes:
lib/crypto/aes_cmac_128.c | 184 ++++++++++++++++++++
.../netlogon.h => lib/crypto/aes_cmac_128.h | 40 ++--
lib/crypto/aes_cmac_128_test.c | 92 ++++++++++
lib/crypto/crypto.h | 1 +
lib/crypto/wscript_build | 11 +-
libcli/smb/smb2_signing.c | 108 ++++++++++--
libcli/smb/smb2_signing.h | 5 +
libcli/smb/smbXcli_base.c | 43 +++++-
source3/Makefile.in | 3 +-
source4/torture/local/local.c | 2 +
10 files changed, 443 insertions(+), 46 deletions(-)
create mode 100644 lib/crypto/aes_cmac_128.c
copy libcli/netlogon/netlogon.h => lib/crypto/aes_cmac_128.h (50%)
create mode 100644 lib/crypto/aes_cmac_128_test.c
Changeset truncated at 500 lines:
diff --git a/lib/crypto/aes_cmac_128.c b/lib/crypto/aes_cmac_128.c
new file mode 100644
index 0000000..b630eea
--- /dev/null
+++ b/lib/crypto/aes_cmac_128.c
@@ -0,0 +1,184 @@
+/*
+ AES-CMAC-128 (rfc 4493)
+ Copyright (C) Stefan Metzmacher 2012
+ Copyright (C) Jeremy Allison 2012
+ Copyright (C) Michael Adam 2012
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "../lib/crypto/crypto.h"
+
+static const uint8_t const_Zero[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const uint8_t const_Rb[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
+};
+
+#define _MSB(x) (((x)[0] & 0x80)?1:0)
+
+static inline void aes_cmac_128_left_shift_1(const uint8_t in[AES_BLOCK_SIZE],
+ uint8_t out[AES_BLOCK_SIZE])
+{
+ uint8_t overflow = 0;
+ int8_t i;
+
+ for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
+ out[i] = in[i] << 1;
+
+ out[i] |= overflow;
+
+ overflow = _MSB(&in[i]);
+ }
+}
+
+static inline void aes_cmac_128_xor(const uint8_t in1[AES_BLOCK_SIZE],
+ const uint8_t in2[AES_BLOCK_SIZE],
+ uint8_t out[AES_BLOCK_SIZE])
+{
+ uint8_t i;
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
+ out[i] = in1[i] ^ in2[i];
+ }
+}
+
+void aes_cmac_128_init(struct aes_cmac_128_context *ctx,
+ const uint8_t K[AES_BLOCK_SIZE])
+{
+ uint8_t L[AES_BLOCK_SIZE];
+
+ ZERO_STRUCTP(ctx);
+
+ AES_set_encrypt_key(K, 128, &ctx->aes_key);
+
+ /* step 1 - generate subkeys k1 and k2 */
+
+ AES_encrypt(const_Zero, L, &ctx->aes_key);
+
+ if (_MSB(L) == 0) {
+ aes_cmac_128_left_shift_1(L, ctx->K1);
+ } else {
+ uint8_t tmp_block[AES_BLOCK_SIZE];
+
+ aes_cmac_128_left_shift_1(L, tmp_block);
+ aes_cmac_128_xor(tmp_block, const_Rb, ctx->K1);
+ ZERO_STRUCT(tmp_block);
+ }
+
+ if (_MSB(ctx->K1) == 0) {
+ aes_cmac_128_left_shift_1(ctx->K1, ctx->K2);
+ } else {
+ uint8_t tmp_block[AES_BLOCK_SIZE];
+
+ aes_cmac_128_left_shift_1(ctx->K1, tmp_block);
+ aes_cmac_128_xor(tmp_block, const_Rb, ctx->K2);
+ ZERO_STRUCT(tmp_block);
+ }
+
+ ZERO_STRUCT(L);
+}
+
+void aes_cmac_128_update(struct aes_cmac_128_context *ctx,
+ const uint8_t *_msg, size_t _msg_len)
+{
+ uint8_t tmp_block[AES_BLOCK_SIZE];
+ uint8_t Y[AES_BLOCK_SIZE];
+ const uint8_t *msg = _msg;
+ size_t msg_len = _msg_len;
+
+ /*
+ * copy the remembered last block
+ */
+ ZERO_STRUCT(tmp_block);
+ if (ctx->last_len) {
+ memcpy(tmp_block, ctx->last, ctx->last_len);
+ }
+
+ /*
+ * check if we expand the block
+ */
+ if (ctx->last_len < AES_BLOCK_SIZE) {
+ size_t len = MIN(AES_BLOCK_SIZE - ctx->last_len, msg_len);
+
+ memcpy(&tmp_block[ctx->last_len], msg, len);
+ memcpy(ctx->last, tmp_block, AES_BLOCK_SIZE);
+ msg += len;
+ msg_len -= len;
+ ctx->last_len += len;
+ }
+
+ if (msg_len == 0) {
+ /* if it is still the last block, we are done */
+ ZERO_STRUCT(tmp_block);
+ return;
+ }
+
+ /*
+ * It is not the last block anymore
+ */
+ ZERO_STRUCT(ctx->last);
+ ctx->last_len = 0;
+
+ /*
+ * now checksum everything but the last block
+ */
+ aes_cmac_128_xor(ctx->X, tmp_block, Y);
+ AES_encrypt(Y, ctx->X, &ctx->aes_key);
+
+ while (msg_len > AES_BLOCK_SIZE) {
+ memcpy(tmp_block, msg, AES_BLOCK_SIZE);
+ msg += AES_BLOCK_SIZE;
+ msg_len -= AES_BLOCK_SIZE;
+
+ aes_cmac_128_xor(ctx->X, tmp_block, Y);
+ AES_encrypt(Y, ctx->X, &ctx->aes_key);
+ }
+
+ /*
+ * copy the last block, it will be processed in
+ * aes_cmac_128_final().
+ */
+ memcpy(ctx->last, msg, msg_len);
+ ctx->last_len = msg_len;
+
+ ZERO_STRUCT(tmp_block);
+ ZERO_STRUCT(Y);
+}
+
+void aes_cmac_128_final(struct aes_cmac_128_context *ctx,
+ uint8_t T[AES_BLOCK_SIZE])
+{
+ uint8_t tmp_block[AES_BLOCK_SIZE];
+ uint8_t Y[AES_BLOCK_SIZE];
+
+ if (ctx->last_len < AES_BLOCK_SIZE) {
+ ctx->last[ctx->last_len] = 0x80;
+ aes_cmac_128_xor(ctx->last, ctx->K2, tmp_block);
+ } else {
+ aes_cmac_128_xor(ctx->last, ctx->K1, tmp_block);
+ }
+
+ aes_cmac_128_xor(tmp_block, ctx->X, Y);
+ AES_encrypt(Y, T, &ctx->aes_key);
+
+ ZERO_STRUCT(tmp_block);
+ ZERO_STRUCT(Y);
+ ZERO_STRUCTP(ctx);
+}
diff --git a/libcli/netlogon/netlogon.h b/lib/crypto/aes_cmac_128.h
similarity index 50%
copy from libcli/netlogon/netlogon.h
copy to lib/crypto/aes_cmac_128.h
index 0bf2a4c..28117a0 100644
--- a/libcli/netlogon/netlogon.h
+++ b/lib/crypto/aes_cmac_128.h
@@ -1,9 +1,6 @@
/*
- Unix SMB/CIFS implementation.
-
- CLDAP server structures
-
- Copyright (C) Andrew Bartlett <abartlet at samba.org> 2008
+ AES-CMAC-128 (rfc 4493)
+ Copyright (C) Stefan Metzmacher 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,23 +16,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __LIBCLI_NETLOGON_H__
-#define __LIBCLI_NETLOGON_H__
+#ifndef LIB_CRYPTO_AES_CMAC_128_H
+#define LIB_CRYPTO_AES_CMAC_128_H
-#include "librpc/gen_ndr/ndr_nbt.h"
+struct aes_cmac_128_context {
+ AES_KEY aes_key;
-#include "librpc/gen_ndr/ndr_misc.h"
-#include "librpc/gen_ndr/ndr_security.h"
+ uint8_t K1[AES_BLOCK_SIZE];
+ uint8_t K2[AES_BLOCK_SIZE];
-struct nbt_netlogon_response
-{
- enum {NETLOGON_GET_PDC, NETLOGON_SAMLOGON, NETLOGON_RESPONSE2} response_type;
- union {
- struct nbt_netlogon_response_from_pdc get_pdc;
- struct netlogon_samlogon_response samlogon;
- struct nbt_netlogon_response2 response2;
- } data;
+ uint8_t X[AES_BLOCK_SIZE];
+
+ uint8_t last[AES_BLOCK_SIZE];
+ size_t last_len;
};
-#include "../libcli/netlogon/netlogon_proto.h"
-#endif /* __CLDAP_SERVER_PROTO_H__ */
+void aes_cmac_128_init(struct aes_cmac_128_context *ctx,
+ const uint8_t K[AES_BLOCK_SIZE]);
+void aes_cmac_128_update(struct aes_cmac_128_context *ctx,
+ const uint8_t *_msg, size_t _msg_len);
+void aes_cmac_128_final(struct aes_cmac_128_context *ctx,
+ uint8_t T[AES_BLOCK_SIZE]);
+
+#endif /* LIB_CRYPTO_AES_CMAC_128_H */
diff --git a/lib/crypto/aes_cmac_128_test.c b/lib/crypto/aes_cmac_128_test.c
new file mode 100644
index 0000000..173087f
--- /dev/null
+++ b/lib/crypto/aes_cmac_128_test.c
@@ -0,0 +1,92 @@
+/*
+ AES-CMAC-128 tests
+ Copyright (C) Stefan Metzmacher 2012
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "replace.h"
+#include "../lib/util/samba_util.h"
+#include "../lib/crypto/crypto.h"
+
+struct torture_context;
+bool torture_local_crypto_aes_cmac_128(struct torture_context *torture);
+
+/*
+ This uses the test values from rfc 4493
+*/
+bool torture_local_crypto_aes_cmac_128(struct torture_context *torture)
+{
+ bool ret = true;
+ uint32_t i;
+ DATA_BLOB key;
+ struct {
+ DATA_BLOB data;
+ DATA_BLOB cmac;
+ } testarray[5];
+
+ TALLOC_CTX *tctx = talloc_new(torture);
+ if (!tctx) { return false; };
+
+ key = strhex_to_data_blob(tctx, "2b7e151628aed2a6abf7158809cf4f3c");
+
+ testarray[0].data = data_blob_null;
+ testarray[0].cmac = strhex_to_data_blob(tctx,
+ "bb1d6929e95937287fa37d129b756746");
+
+ testarray[1].data = strhex_to_data_blob(tctx,
+ "6bc1bee22e409f96e93d7e117393172a");
+ testarray[1].cmac = strhex_to_data_blob(tctx,
+ "070a16b46b4d4144f79bdd9dd04a287c");
+
+ testarray[2].data = strhex_to_data_blob(tctx,
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411");
+ testarray[2].cmac = strhex_to_data_blob(tctx,
+ "dfa66747de9ae63030ca32611497c827");
+
+ testarray[3].data = strhex_to_data_blob(tctx,
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710");
+ testarray[3].cmac = strhex_to_data_blob(tctx,
+ "51f0bebf7e3b9d92fc49741779363cfe");
+
+ ZERO_STRUCT(testarray[4]);
+
+ for (i=0; testarray[i].cmac.length != 0; i++) {
+ struct aes_cmac_128_context ctx;
+ uint8_t cmac[AES_BLOCK_SIZE];
+ int e;
+
+ aes_cmac_128_init(&ctx, key.data);
+ aes_cmac_128_update(&ctx,
+ testarray[i].data.data,
+ testarray[i].data.length);
+ aes_cmac_128_final(&ctx, cmac);
+
+ e = memcmp(testarray[i].cmac.data, cmac, sizeof(cmac));
+ if (e != 0) {
+ printf("aes_cmac_128 test[%u]: failed\n", i);
+ dump_data(0, key.data, key.length);
+ dump_data(0, testarray[i].data.data, testarray[i].data.length);
+ dump_data(0, testarray[i].cmac.data, testarray[i].cmac.length);
+ dump_data(0, cmac, sizeof(cmac));
+ ret = false;
+ }
+ }
+ talloc_free(tctx);
+ return ret;
+}
diff --git a/lib/crypto/crypto.h b/lib/crypto/crypto.h
index b5ea9c7..c0d85c8 100644
--- a/lib/crypto/crypto.h
+++ b/lib/crypto/crypto.h
@@ -25,4 +25,5 @@
#include "../lib/crypto/hmacsha256.h"
#include "../lib/crypto/arcfour.h"
#include "../lib/crypto/aes.h"
+#include "../lib/crypto/aes_cmac_128.h"
diff --git a/lib/crypto/wscript_build b/lib/crypto/wscript_build
index 6ad1cad..f502698 100644
--- a/lib/crypto/wscript_build
+++ b/lib/crypto/wscript_build
@@ -8,13 +8,14 @@ else:
extra_source += ' md5.c'
bld.SAMBA_SUBSYSTEM('LIBCRYPTO',
- source='crc32.c hmacmd5.c md4.c arcfour.c sha256.c hmacsha256.c aes.c rijndael-alg-fst.c' + extra_source,
- deps='talloc' + extra_deps
- )
-
+ source='''crc32.c hmacmd5.c md4.c arcfour.c sha256.c hmacsha256.c
+ aes.c rijndael-alg-fst.c aes_cmac_128.c
+ ''' + extra_source,
+ deps='talloc' + extra_deps
+ )
bld.SAMBA_SUBSYSTEM('TORTURE_LIBCRYPTO',
- source='md4test.c md5test.c hmacmd5test.c',
+ source='md4test.c md5test.c hmacmd5test.c aes_cmac_128_test.c',
autoproto='test_proto.h',
deps='LIBCRYPTO'
)
diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c
index 3017277..4204ed1 100644
--- a/libcli/smb/smb2_signing.c
+++ b/libcli/smb/smb2_signing.c
@@ -30,8 +30,7 @@ NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
{
uint8_t *hdr;
uint64_t session_id;
- struct HMACSHA256Context m;
- uint8_t res[SHA256_DIGEST_LENGTH];
+ uint8_t res[16];
int i;
if (count < 2) {
@@ -63,13 +62,33 @@ NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
- ZERO_STRUCT(m);
- hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
- for (i=0; i < count; i++) {
- hmac_sha256_update((const uint8_t *)vector[i].iov_base,
- vector[i].iov_len, &m);
+ if (protocol >= PROTOCOL_SMB2_24) {
+ struct aes_cmac_128_context ctx;
+ uint8_t key[AES_BLOCK_SIZE];
+
+ ZERO_STRUCT(key);
+ memcpy(key, signing_key.data, MIN(signing_key.length, 16));
+
+ aes_cmac_128_init(&ctx, key);
+ for (i=0; i < count; i++) {
+ aes_cmac_128_update(&ctx,
+ (const uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ aes_cmac_128_final(&ctx, res);
+ } else {
+ struct HMACSHA256Context m;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+
+ ZERO_STRUCT(m);
+ hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
+ for (i=0; i < count; i++) {
+ hmac_sha256_update((const uint8_t *)vector[i].iov_base,
+ vector[i].iov_len, &m);
+ }
+ hmac_sha256_final(digest, &m);
+ memcpy(res, digest, 16);
}
- hmac_sha256_final(res, &m);
DEBUG(5,("signed SMB2 message\n"));
memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
@@ -85,8 +104,7 @@ NTSTATUS smb2_signing_check_pdu(DATA_BLOB signing_key,
const uint8_t *hdr;
const uint8_t *sig;
uint64_t session_id;
- struct HMACSHA256Context m;
- uint8_t res[SHA256_DIGEST_LENGTH];
+ uint8_t res[16];
static const uint8_t zero_sig[16] = { 0, };
int i;
@@ -116,15 +134,37 @@ NTSTATUS smb2_signing_check_pdu(DATA_BLOB signing_key,
sig = hdr+SMB2_HDR_SIGNATURE;
- ZERO_STRUCT(m);
- hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
- hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m);
- hmac_sha256_update(zero_sig, 16, &m);
- for (i=1; i < count; i++) {
- hmac_sha256_update((const uint8_t *)vector[i].iov_base,
- vector[i].iov_len, &m);
+ if (protocol >= PROTOCOL_SMB2_24) {
+ struct aes_cmac_128_context ctx;
+ uint8_t key[AES_BLOCK_SIZE];
+
+ ZERO_STRUCT(key);
+ memcpy(key, signing_key.data, MIN(signing_key.length, 16));
+
+ aes_cmac_128_init(&ctx, key);
+ aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
+ aes_cmac_128_update(&ctx, zero_sig, 16);
+ for (i=1; i < count; i++) {
+ aes_cmac_128_update(&ctx,
+ (const uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ aes_cmac_128_final(&ctx, res);
+ } else {
+ struct HMACSHA256Context m;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+
+ ZERO_STRUCT(m);
+ hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
+ hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m);
+ hmac_sha256_update(zero_sig, 16, &m);
+ for (i=1; i < count; i++) {
+ hmac_sha256_update((const uint8_t *)vector[i].iov_base,
+ vector[i].iov_len, &m);
+ }
+ hmac_sha256_final(digest, &m);
+ memcpy(res, digest, 16);
}
- hmac_sha256_final(res, &m);
if (memcmp(res, sig, 16) != 0) {
DEBUG(0,("Bad SMB2 signature for message\n"));
@@ -135,3 +175,35 @@ NTSTATUS smb2_signing_check_pdu(DATA_BLOB signing_key,
return NT_STATUS_OK;
}
+
+void smb2_key_deviration(const uint8_t *KI, size_t KI_len,
+ const uint8_t *Label, size_t Label_len,
--
Samba Shared Repository
More information about the samba-cvs
mailing list