[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