SMB2 signing now works. The spec was wrong (and will be fixed in the
authorAndrew Tridgell <tridge@samba.org>
Tue, 3 Jun 2008 04:29:27 +0000 (14:29 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 3 Jun 2008 04:29:27 +0000 (14:29 +1000)
next version)
(This used to be commit 436cb17b869e2d6cc57936ccc5e81680fb992341)

source4/lib/crypto/config.mk
source4/lib/crypto/crypto.h
source4/lib/crypto/hmacsha256.c [new file with mode: 0644]
source4/lib/crypto/hmacsha256.h [new file with mode: 0644]
source4/libcli/smb2/signing.c

index b9a7f7cb9ec962809fc056a5ca6e9709714455fc..fb1c1bf6ce730a03f2ebbde22fa04c5c2a5728a6 100644 (file)
@@ -6,7 +6,7 @@
 
 LIBCRYPTO_OBJ_FILES = $(addprefix $(libcryptosrcdir)/, \
                                         crc32.o md5.o hmacmd5.o md4.o \
-                                        arcfour.o sha1.o hmacsha1.o)
+                                        arcfour.o sha1.o hmacsha1.o hmacsha256.o)
 
 
 [MODULE::TORTURE_LIBCRYPTO]
index 10e2258fa7d1371f82381d75b782dcf2f93678eb..03a233ec988c02672f7fa24dea77b26550052ec9 100644 (file)
@@ -23,6 +23,8 @@
 #include "lib/crypto/hmacmd5.h"
 #include "lib/crypto/sha1.h"
 #include "lib/crypto/hmacsha1.h"
+#include "heimdal/lib/hcrypto/sha.h"
+#include "lib/crypto/hmacsha256.h"
 
 struct arcfour_state {
        uint8_t sbox[256];
diff --git a/source4/lib/crypto/hmacsha256.c b/source4/lib/crypto/hmacsha256.c
new file mode 100644 (file)
index 0000000..5503bdd
--- /dev/null
@@ -0,0 +1,92 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Interface header:    HMAC SHA-256 code
+
+   Copyright (C) Andrew Tridgell 2008
+
+   based in hmacsha1.c which is:
+     Copyright (C) Stefan Metzmacher
+   
+   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/>.
+*/
+
+/*
+ taken direct from rfc2202 implementation and modified for suitable use
+ */
+
+#include "includes.h"
+#include "lib/crypto/crypto.h"
+#include "heimdal/lib/hcrypto/sha.h"
+
+/***********************************************************************
+ the rfc 2104/2202 version of hmac_sha256 initialisation.
+***********************************************************************/
+_PUBLIC_ void hmac_sha256_init(const uint8_t *key, size_t key_len, struct HMACSHA256Context *ctx)
+{
+        int i;
+       uint8_t tk[SHA256_DIGEST_LENGTH];
+
+        /* if key is longer than 64 bytes reset it to key=HASH(key) */
+        if (key_len > 64)
+       {
+                SHA256_CTX tctx;
+
+                SHA256_Init(&tctx);
+                SHA256_Update(&tctx, key, key_len);
+                SHA256_Final(tk, &tctx);
+
+                key = tk;
+                key_len = SHA256_DIGEST_LENGTH;
+        }
+
+        /* start out by storing key in pads */
+        ZERO_STRUCT(ctx->k_ipad);
+        ZERO_STRUCT(ctx->k_opad);
+        memcpy( ctx->k_ipad, key, key_len);
+        memcpy( ctx->k_opad, key, key_len);
+
+        /* XOR key with ipad and opad values */
+        for (i=0; i<64; i++)
+       {
+                ctx->k_ipad[i] ^= 0x36;
+                ctx->k_opad[i] ^= 0x5c;
+        }
+
+        SHA256_Init(&ctx->ctx);
+        SHA256_Update(&ctx->ctx, ctx->k_ipad, 64);  
+}
+
+/***********************************************************************
+ update hmac_sha256 "inner" buffer
+***********************************************************************/
+_PUBLIC_ void hmac_sha256_update(const uint8_t *data, size_t data_len, struct HMACSHA256Context *ctx)
+{
+        SHA256_Update(&ctx->ctx, data, data_len); /* then text of datagram */
+}
+
+/***********************************************************************
+ finish off hmac_sha256 "inner" buffer and generate outer one.
+***********************************************************************/
+_PUBLIC_ void hmac_sha256_final(uint8_t digest[SHA256_DIGEST_LENGTH], struct HMACSHA256Context *ctx)
+{
+        SHA256_CTX ctx_o;
+
+        SHA256_Final(digest, &ctx->ctx);
+
+        SHA256_Init(&ctx_o);
+        SHA256_Update(&ctx_o, ctx->k_opad, 64);
+        SHA256_Update(&ctx_o, digest, SHA256_DIGEST_LENGTH);
+        SHA256_Final(digest, &ctx_o);
+}
diff --git a/source4/lib/crypto/hmacsha256.h b/source4/lib/crypto/hmacsha256.h
new file mode 100644 (file)
index 0000000..8960c63
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Interface header:    HMAC SHA256 code
+
+   Copyright (C) Andrew Tridgell 2008
+
+   based on hmacsha1.h which is:
+
+    Copyright (C) Stefan Metzmacher 2006
+   
+   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/>.
+*/
+
+#ifndef _HMAC_SHA256_H
+
+struct HMACSHA256Context {
+        SHA256_CTX ctx;
+        uint8_t k_ipad[65];    
+        uint8_t k_opad[65];
+};
+
+void hmac_sha256_init(const uint8_t *key, size_t key_len, struct HMACSHA256Context *ctx);
+void hmac_sha256_update(const uint8_t *data, size_t data_len, struct HMACSHA256Context *ctx);
+void hmac_sha256_final(uint8_t digest[20], struct HMACSHA256Context *ctx);
+
+#endif /* _HMAC_SHA256_H */
index 01f7576134b67b64e16af31d2fe8fcf6b2f7b8ec..16c0ff99c1bab4a243d5fa541ce07038e16c557e 100644 (file)
@@ -23,7 +23,7 @@
 #include "libcli/raw/libcliraw.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
-#include "heimdal/lib/hcrypto/sha.h"
+#include "lib/crypto/crypto.h"
 
 /*
   NOTE: this code does not yet interoperate with the windows SMB2
@@ -54,7 +54,7 @@ NTSTATUS smb2_sign_message(struct smb2_request *req)
 {
        struct smb2_request_buffer *buf = &req->out;
        uint64_t session_id;
-       SHA256_CTX m;
+       struct HMACSHA256Context m;
        uint8_t res[32];
 
        if (!req->transport->signing.doing_signing ||
@@ -85,11 +85,9 @@ NTSTATUS smb2_sign_message(struct smb2_request *req)
        SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
 
        ZERO_STRUCT(m);
-       SHA256_Init(&m);
-       SHA256_Update(&m, req->transport->signing.session_key.data, 
-                     req->transport->signing.session_key.length);
-       SHA256_Update(&m, buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE);
-       SHA256_Final(res, &m);
+       hmac_sha256_init(req->transport->signing.session_key.data, 16, &m);
+       hmac_sha256_update(buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE, &m);
+       hmac_sha256_final(res, &m);
 
        DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
 
@@ -110,7 +108,7 @@ NTSTATUS smb2_check_signature(struct smb2_transport *transport,
                              uint8_t *buffer, uint_t length)
 {
        uint64_t session_id;
-       SHA256_CTX m;
+       struct HMACSHA256Context m;
        uint8_t res[SHA256_DIGEST_LENGTH];
        uint8_t sig[16];
 
@@ -147,10 +145,9 @@ NTSTATUS smb2_check_signature(struct smb2_transport *transport,
        memset(buffer + NBT_HDR_SIZE + SMB2_HDR_SIGNATURE, 0, 16);
 
        ZERO_STRUCT(m);
-       SHA256_Init(&m);
-       SHA256_Update(&m, transport->signing.session_key.data,    16);
-       SHA256_Update(&m, buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE);
-       SHA256_Final(res, &m);
+       hmac_sha256_init(transport->signing.session_key.data, 16, &m);
+       hmac_sha256_update(buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE, &m);
+       hmac_sha256_final(res, &m);
 
        memcpy(buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, sig, 16);