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 <me...@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 <me...@samba.org>
    Autobuild-Date: Wed Feb 29 04:54:48 CET 2012 on sn-devel-104

commit 39ae4737e0fbf8db348db76f7a534a55304918f0
Author: Stefan Metzmacher <me...@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 <me...@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 <me...@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 <me...@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 <abart...@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

Reply via email to