diff options
-rw-r--r-- | source4/lib/crypto/config.mk | 2 | ||||
-rw-r--r-- | source4/lib/crypto/crypto.h | 2 | ||||
-rw-r--r-- | source4/lib/crypto/hmacsha256.c | 92 | ||||
-rw-r--r-- | source4/lib/crypto/hmacsha256.h | 38 | ||||
-rw-r--r-- | source4/libcli/smb2/signing.c | 21 |
5 files changed, 142 insertions, 13 deletions
diff --git a/source4/lib/crypto/config.mk b/source4/lib/crypto/config.mk index b9a7f7cb9e..fb1c1bf6ce 100644 --- a/source4/lib/crypto/config.mk +++ b/source4/lib/crypto/config.mk @@ -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] diff --git a/source4/lib/crypto/crypto.h b/source4/lib/crypto/crypto.h index 10e2258fa7..03a233ec98 100644 --- a/source4/lib/crypto/crypto.h +++ b/source4/lib/crypto/crypto.h @@ -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 index 0000000000..5503bdd59b --- /dev/null +++ b/source4/lib/crypto/hmacsha256.c @@ -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 index 0000000000..8960c636c1 --- /dev/null +++ b/source4/lib/crypto/hmacsha256.h @@ -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 */ diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index 01f7576134..16c0ff99c1 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -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); |