wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
An implementation of the arcfour algorithm
|
||||
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
/* initialise the arcfour sbox with key */
|
||||
_PUBLIC_ void arcfour_init(struct arcfour_state *state, const DATA_BLOB *key)
|
||||
{
|
||||
int ind;
|
||||
uint8_t j = 0;
|
||||
for (ind = 0; ind < sizeof(state->sbox); ind++) {
|
||||
state->sbox[ind] = (uint8_t)ind;
|
||||
}
|
||||
|
||||
for (ind = 0; ind < sizeof(state->sbox); ind++) {
|
||||
uint8_t tc;
|
||||
|
||||
j += (state->sbox[ind] + key->data[ind%key->length]);
|
||||
|
||||
tc = state->sbox[ind];
|
||||
state->sbox[ind] = state->sbox[j];
|
||||
state->sbox[j] = tc;
|
||||
}
|
||||
state->index_i = 0;
|
||||
state->index_j = 0;
|
||||
}
|
||||
|
||||
/* crypt the data with arcfour */
|
||||
_PUBLIC_ void arcfour_crypt_sbox(struct arcfour_state *state, uint8_t *data, int len)
|
||||
{
|
||||
int ind;
|
||||
|
||||
for (ind = 0; ind < len; ind++) {
|
||||
uint8_t tc;
|
||||
uint8_t t;
|
||||
|
||||
state->index_i++;
|
||||
state->index_j += state->sbox[state->index_i];
|
||||
|
||||
tc = state->sbox[state->index_i];
|
||||
state->sbox[state->index_i] = state->sbox[state->index_j];
|
||||
state->sbox[state->index_j] = tc;
|
||||
|
||||
t = state->sbox[state->index_i] + state->sbox[state->index_j];
|
||||
data[ind] = data[ind] ^ state->sbox[t];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
arcfour encryption with a blob key
|
||||
*/
|
||||
_PUBLIC_ void arcfour_crypt_blob(uint8_t *data, int len, const DATA_BLOB *key)
|
||||
{
|
||||
struct arcfour_state state;
|
||||
arcfour_init(&state, key);
|
||||
arcfour_crypt_sbox(&state, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
a variant that assumes a 16 byte key. This should be removed
|
||||
when the last user is gone
|
||||
*/
|
||||
_PUBLIC_ void arcfour_crypt(uint8_t *data, const uint8_t keystr[16], int len)
|
||||
{
|
||||
DATA_BLOB key = data_blob(keystr, 16);
|
||||
|
||||
arcfour_crypt_blob(data, len, &key);
|
||||
|
||||
data_blob_free(&key);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*-
|
||||
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
|
||||
* code or tables extracted from it, as desired without restriction.
|
||||
*
|
||||
* First, the polynomial itself and its table of feedback terms. The
|
||||
* polynomial is
|
||||
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
|
||||
*
|
||||
* Note that we take it "backwards" and put the highest-order term in
|
||||
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
|
||||
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
|
||||
* the MSB being 1
|
||||
*
|
||||
* Note that the usual hardware shift register implementation, which
|
||||
* is what we're using (we're merely optimizing it by doing eight-bit
|
||||
* chunks at a time) shifts bits into the lowest-order term. In our
|
||||
* implementation, that means shifting towards the right. Why do we
|
||||
* do it this way? Because the calculated CRC must be transmitted in
|
||||
* order from highest-order term to lowest-order term. UARTs transmit
|
||||
* characters in order from LSB to MSB. By storing the CRC this way
|
||||
* we hand it to the UART in the order low-byte to high-byte; the UART
|
||||
* sends each low-bit to hight-bit; and the result is transmission bit
|
||||
* by bit from highest- to lowest-order term without requiring any bit
|
||||
* shuffling on our part. Reception works similarly
|
||||
*
|
||||
* The feedback terms table consists of 256, 32-bit entries. Notes
|
||||
*
|
||||
* The table can be generated at runtime if desired; code to do so
|
||||
* is shown later. It might not be obvious, but the feedback
|
||||
* terms simply represent the results of eight shift/xor opera
|
||||
* tions for all combinations of data and CRC register values
|
||||
*
|
||||
* The values must be right-shifted by eight bits by the "updcrc
|
||||
* logic; the shift must be unsigned (bring in zeroes). On some
|
||||
* hardware you could probably optimize the shift in assembler by
|
||||
* using byte-swap instructions
|
||||
* polynomial $edb88320
|
||||
*
|
||||
*
|
||||
* CRC32 code derived from work by Gary S. Brown.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
static const uint32_t crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t crc32_calc_buffer(const uint8_t *buf, size_t size)
|
||||
{
|
||||
const uint8_t *p;
|
||||
uint32_t crc;
|
||||
|
||||
p = buf;
|
||||
crc = ~0U;
|
||||
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
|
||||
return crc ^ ~0U;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uint32_t crc32_calc_buffer(const uint8_t *buf, size_t size);
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "lib/crypto/crc32.h"
|
||||
#include "lib/crypto/md4.h"
|
||||
#include "lib/crypto/md5.h"
|
||||
#include "lib/crypto/hmacmd5.h"
|
||||
#include "lib/crypto/sha1.h"
|
||||
#include "lib/crypto/hmacsha1.h"
|
||||
|
||||
struct arcfour_state {
|
||||
uint8_t sbox[256];
|
||||
uint8_t index_i;
|
||||
uint8_t index_j;
|
||||
};
|
||||
|
||||
void arcfour_init(struct arcfour_state *state, const DATA_BLOB *key);
|
||||
void arcfour_crypt_sbox(struct arcfour_state *state, uint8_t *data, int len);
|
||||
void arcfour_crypt_blob(uint8_t *data, int len, const DATA_BLOB *key);
|
||||
void arcfour_crypt(uint8_t *data, const uint8_t keystr[16], int len);
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
HMAC MD5 code for use in NTLMv2
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
|
||||
Copyright (C) Andrew Tridgell 1992-2000
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* taken direct from rfc2104 implementation and modified for suitable use
|
||||
* for ntlmv2.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
/***********************************************************************
|
||||
the rfc 2104 version of hmac_md5 initialisation.
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_md5_init_rfc2104(const uint8_t *key, int key_len, HMACMD5Context *ctx)
|
||||
{
|
||||
int i;
|
||||
uint8_t tk[16];
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64)
|
||||
{
|
||||
struct MD5Context tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
MD5Init(&ctx->ctx);
|
||||
MD5Update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
the microsoft version of hmac_md5 initialisation.
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_md5_init_limK_to_64(const uint8_t *key, int key_len,
|
||||
HMACMD5Context *ctx)
|
||||
{
|
||||
/* if key is longer than 64 bytes truncate it */
|
||||
if (key_len > 64)
|
||||
{
|
||||
key_len = 64;
|
||||
}
|
||||
|
||||
hmac_md5_init_rfc2104(key, key_len, ctx);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
update hmac_md5 "inner" buffer
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_md5_update(const uint8_t *text, int text_len, HMACMD5Context *ctx)
|
||||
{
|
||||
MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
finish off hmac_md5 "inner" buffer and generate outer one.
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_md5_final(uint8_t *digest, HMACMD5Context *ctx)
|
||||
{
|
||||
struct MD5Context ctx_o;
|
||||
|
||||
MD5Final(digest, &ctx->ctx);
|
||||
|
||||
MD5Init(&ctx_o);
|
||||
MD5Update(&ctx_o, ctx->k_opad, 64);
|
||||
MD5Update(&ctx_o, digest, 16);
|
||||
MD5Final(digest, &ctx_o);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
single function to calculate an HMAC MD5 digest from data.
|
||||
use the microsoft hmacmd5 init method because the key is 16 bytes.
|
||||
************************************************************/
|
||||
_PUBLIC_ void hmac_md5(const uint8_t key[16], const uint8_t *data, int data_len, uint8_t *digest)
|
||||
{
|
||||
HMACMD5Context ctx;
|
||||
hmac_md5_init_limK_to_64(key, 16, &ctx);
|
||||
if (data_len != 0)
|
||||
{
|
||||
hmac_md5_update(data, data_len, &ctx);
|
||||
}
|
||||
hmac_md5_final(digest, &ctx);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Interface header: HMAC MD5 code
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1996-1999
|
||||
Copyright (C) Andrew Tridgell 1992-1999
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _HMAC_MD5_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct MD5Context ctx;
|
||||
uint8_t k_ipad[65];
|
||||
uint8_t k_opad[65];
|
||||
|
||||
} HMACMD5Context;
|
||||
|
||||
void hmac_md5_init_limK_to_64(const uint8_t *key, int key_len,
|
||||
HMACMD5Context *ctx);
|
||||
void hmac_md5_update(const uint8_t *text, int text_len, HMACMD5Context *ctx);
|
||||
void hmac_md5_final(uint8_t *digest, HMACMD5Context *ctx);
|
||||
void hmac_md5(const uint8_t key[16], const uint8_t *data, int data_len, uint8_t *digest);
|
||||
void hmac_md5_init_rfc2104(const uint8_t *key, int key_len, HMACMD5Context *ctx);
|
||||
|
||||
#endif /* _HMAC_MD5_H */
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
HMAC MD5 tests
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
struct torture_context;
|
||||
|
||||
static DATA_BLOB data_blob_repeat_byte(uint8_t byte, size_t length)
|
||||
{
|
||||
DATA_BLOB b = data_blob(NULL, length);
|
||||
memset(b.data, byte, length);
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
This uses the test values from rfc 2104, 2202
|
||||
*/
|
||||
BOOL torture_local_crypto_hmacmd5(struct torture_context *torture)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint32_t i;
|
||||
struct {
|
||||
DATA_BLOB key;
|
||||
DATA_BLOB data;
|
||||
DATA_BLOB md5;
|
||||
} testarray[8];
|
||||
|
||||
testarray[0].key = data_blob_repeat_byte(0x0b, 16);
|
||||
testarray[0].data = data_blob_string_const("Hi There");
|
||||
testarray[0].md5 = strhex_to_data_blob("9294727a3638bb1c13f48ef8158bfc9d");
|
||||
|
||||
testarray[1].key = data_blob_string_const("Jefe");
|
||||
testarray[1].data = data_blob_string_const("what do ya want for nothing?");
|
||||
testarray[1].md5 = strhex_to_data_blob("750c783e6ab0b503eaa86e310a5db738");
|
||||
|
||||
testarray[2].key = data_blob_repeat_byte(0xaa, 16);
|
||||
testarray[2].data = data_blob_repeat_byte(0xdd, 50);
|
||||
testarray[2].md5 = strhex_to_data_blob("56be34521d144c88dbb8c733f0e8b3f6");
|
||||
|
||||
testarray[3].key = strhex_to_data_blob("0102030405060708090a0b0c0d0e0f10111213141516171819");
|
||||
testarray[3].data = data_blob_repeat_byte(0xcd, 50);
|
||||
testarray[3].md5 = strhex_to_data_blob("697eaf0aca3a3aea3a75164746ffaa79");
|
||||
|
||||
testarray[4].key = data_blob_repeat_byte(0x0c, 16);
|
||||
testarray[4].data = data_blob_string_const("Test With Truncation");
|
||||
testarray[4].md5 = strhex_to_data_blob("56461ef2342edc00f9bab995690efd4c");
|
||||
|
||||
testarray[5].key = data_blob_repeat_byte(0xaa, 80);
|
||||
testarray[5].data = data_blob_string_const("Test Using Larger Than Block-Size Key - Hash Key First");
|
||||
testarray[5].md5 = strhex_to_data_blob("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd");
|
||||
|
||||
testarray[6].key = data_blob_repeat_byte(0xaa, 80);
|
||||
testarray[6].data = data_blob_string_const("Test Using Larger Than Block-Size Key "
|
||||
"and Larger Than One Block-Size Data");
|
||||
testarray[6].md5 = strhex_to_data_blob("6f630fad67cda0ee1fb1f562db3aa53e");
|
||||
|
||||
testarray[7].key = data_blob(NULL, 0);
|
||||
|
||||
for (i=0; testarray[i].key.data; i++) {
|
||||
HMACMD5Context ctx;
|
||||
uint8_t md5[16];
|
||||
int e;
|
||||
|
||||
hmac_md5_init_rfc2104(testarray[i].key.data, testarray[i].key.length, &ctx);
|
||||
hmac_md5_update(testarray[i].data.data, testarray[i].data.length, &ctx);
|
||||
hmac_md5_final(md5, &ctx);
|
||||
|
||||
e = memcmp(testarray[i].md5.data,
|
||||
md5,
|
||||
MIN(testarray[i].md5.length, sizeof(md5)));
|
||||
if (e != 0) {
|
||||
printf("hmacmd5 test[%u]: failed\n", i);
|
||||
dump_data(0, testarray[i].key.data, testarray[i].key.length);
|
||||
dump_data(0, testarray[i].data.data, testarray[i].data.length);
|
||||
dump_data(0, testarray[i].md5.data, testarray[i].md5.length);
|
||||
dump_data(0, md5, sizeof(md5));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Interface header: HMAC SHA-1 code
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
taken direct from rfc2202 implementation and modified for suitable use
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
/***********************************************************************
|
||||
the rfc 2104/2202 version of hmac_sha1 initialisation.
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_sha1_init(const uint8_t *key, size_t key_len, struct HMACSHA1Context *ctx)
|
||||
{
|
||||
int i;
|
||||
uint8_t tk[SHA1HashSize];
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64)
|
||||
{
|
||||
struct SHA1Context tctx;
|
||||
|
||||
SHA1Init(&tctx);
|
||||
SHA1Update(&tctx, key, key_len);
|
||||
SHA1Final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = SHA1HashSize;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
SHA1Init(&ctx->ctx);
|
||||
SHA1Update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
update hmac_sha1 "inner" buffer
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_sha1_update(const uint8_t *data, size_t data_len, struct HMACSHA1Context *ctx)
|
||||
{
|
||||
SHA1Update(&ctx->ctx, data, data_len); /* then text of datagram */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
finish off hmac_sha1 "inner" buffer and generate outer one.
|
||||
***********************************************************************/
|
||||
_PUBLIC_ void hmac_sha1_final(uint8_t digest[SHA1HashSize], struct HMACSHA1Context *ctx)
|
||||
{
|
||||
struct SHA1Context ctx_o;
|
||||
|
||||
SHA1Final(digest, &ctx->ctx);
|
||||
|
||||
SHA1Init(&ctx_o);
|
||||
SHA1Update(&ctx_o, ctx->k_opad, 64);
|
||||
SHA1Update(&ctx_o, digest, SHA1HashSize);
|
||||
SHA1Final(digest, &ctx_o);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Interface header: HMAC SHA1 code
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _HMAC_SHA1_H
|
||||
|
||||
struct HMACSHA1Context {
|
||||
struct SHA1Context ctx;
|
||||
uint8_t k_ipad[65];
|
||||
uint8_t k_opad[65];
|
||||
|
||||
};
|
||||
|
||||
void hmac_sha1_init(const uint8_t *key, size_t key_len, struct HMACSHA1Context *ctx);
|
||||
void hmac_sha1_update(const uint8_t *data, size_t data_len, struct HMACSHA1Context *ctx);
|
||||
void hmac_sha1_final(uint8_t digest[20], struct HMACSHA1Context *ctx);
|
||||
|
||||
#endif /* _HMAC_SHA1_H */
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
HMAC SHA-1 tests
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
struct torture_context;
|
||||
|
||||
static DATA_BLOB data_blob_repeat_byte(uint8_t byte, size_t length)
|
||||
{
|
||||
DATA_BLOB b = data_blob(NULL, length);
|
||||
memset(b.data, byte, length);
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
This uses the test values from rfc2202
|
||||
*/
|
||||
BOOL torture_local_crypto_hmacsha1(struct torture_context *torture)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint32_t i;
|
||||
struct {
|
||||
DATA_BLOB key;
|
||||
DATA_BLOB data;
|
||||
DATA_BLOB sha1;
|
||||
} testarray[7];
|
||||
|
||||
testarray[0].key = data_blob_repeat_byte(0x0b, 20);
|
||||
testarray[0].data = data_blob_string_const("Hi There");
|
||||
testarray[0].sha1 = strhex_to_data_blob("b617318655057264e28bc0b6fb378c8ef146be00");
|
||||
|
||||
testarray[1].key = data_blob_string_const("Jefe");
|
||||
testarray[1].data = data_blob_string_const("what do ya want for nothing?");
|
||||
testarray[1].sha1 = strhex_to_data_blob("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79");
|
||||
|
||||
testarray[2].key = data_blob_repeat_byte(0xaa, 20);
|
||||
testarray[2].data = data_blob_repeat_byte(0xdd, 50);
|
||||
testarray[2].sha1 = strhex_to_data_blob("125d7342b9ac11cd91a39af48aa17b4f63f175d3");
|
||||
|
||||
testarray[3].key = strhex_to_data_blob("0102030405060708090a0b0c0d0e0f10111213141516171819");
|
||||
testarray[3].data = data_blob_repeat_byte(0xcd, 50);
|
||||
testarray[3].sha1 = strhex_to_data_blob("4c9007f4026250c6bc8414f9bf50c86c2d7235da");
|
||||
|
||||
testarray[4].key = data_blob_repeat_byte(0x0c, 20);
|
||||
testarray[4].data = data_blob_string_const("Test With Truncation");
|
||||
testarray[4].sha1 = strhex_to_data_blob("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04");
|
||||
/* sha1-96 = 0x4c1a03424b55e07fe7f27be1 */
|
||||
|
||||
testarray[5].key = data_blob_repeat_byte(0xaa, 80);
|
||||
testarray[5].data = data_blob_string_const("Test Using Larger Than Block-Size Key - Hash Key First");
|
||||
testarray[5].sha1 = strhex_to_data_blob("aa4ae5e15272d00e95705637ce8a3b55ed402112");
|
||||
|
||||
testarray[6].key = data_blob_repeat_byte(0xaa, 80);
|
||||
testarray[6].data = data_blob_string_const("Test Using Larger Than Block-Size Key "
|
||||
"and Larger Than One Block-Size Data");
|
||||
testarray[6].sha1 = strhex_to_data_blob("e8e99d0f45237d786d6bbaa7965c7808bbff1a91");
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(testarray); i++) {
|
||||
struct HMACSHA1Context ctx;
|
||||
uint8_t sha1[SHA1HashSize];
|
||||
int e;
|
||||
|
||||
hmac_sha1_init(testarray[i].key.data, testarray[i].key.length, &ctx);
|
||||
hmac_sha1_update(testarray[i].data.data, testarray[i].data.length, &ctx);
|
||||
hmac_sha1_final(sha1, &ctx);
|
||||
|
||||
e = memcmp(testarray[i].sha1.data,
|
||||
sha1,
|
||||
MIN(testarray[i].sha1.length, sizeof(sha1)));
|
||||
if (e != 0) {
|
||||
printf("hmacsha1 test[%u]: failed\n", i);
|
||||
dump_data(0, testarray[i].key.data, testarray[i].key.length);
|
||||
dump_data(0, testarray[i].data.data, testarray[i].data.length);
|
||||
dump_data(0, testarray[i].sha1.data, testarray[i].sha1.length);
|
||||
dump_data(0, sha1, sizeof(sha1));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
a implementation of MD4 designed for use in the SMB authentication protocol
|
||||
Copyright (C) Andrew Tridgell 1997-1998.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/* NOTE: This code makes no attempt to be fast!
|
||||
|
||||
It assumes that a int is at least 32 bits long
|
||||
*/
|
||||
|
||||
struct mdfour_state {
|
||||
uint32_t A, B, C, D;
|
||||
};
|
||||
|
||||
static uint32_t F(uint32_t X, uint32_t Y, uint32_t Z)
|
||||
{
|
||||
return (X&Y) | ((~X)&Z);
|
||||
}
|
||||
|
||||
static uint32_t G(uint32_t X, uint32_t Y, uint32_t Z)
|
||||
{
|
||||
return (X&Y) | (X&Z) | (Y&Z);
|
||||
}
|
||||
|
||||
static uint32_t H(uint32_t X, uint32_t Y, uint32_t Z)
|
||||
{
|
||||
return X^Y^Z;
|
||||
}
|
||||
|
||||
static uint32_t lshift(uint32_t x, int s)
|
||||
{
|
||||
x &= 0xFFFFFFFF;
|
||||
return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
|
||||
}
|
||||
|
||||
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
|
||||
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32_t)0x5A827999,s)
|
||||
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32_t)0x6ED9EBA1,s)
|
||||
|
||||
/* this applies md4 to 64 byte chunks */
|
||||
static void mdfour64(struct mdfour_state *s, uint32_t *M)
|
||||
{
|
||||
int j;
|
||||
uint32_t AA, BB, CC, DD;
|
||||
uint32_t X[16];
|
||||
|
||||
for (j=0;j<16;j++)
|
||||
X[j] = M[j];
|
||||
|
||||
AA = s->A; BB = s->B; CC = s->C; DD = s->D;
|
||||
|
||||
ROUND1(s->A,s->B,s->C,s->D, 0, 3); ROUND1(s->D,s->A,s->B,s->C, 1, 7);
|
||||
ROUND1(s->C,s->D,s->A,s->B, 2, 11); ROUND1(s->B,s->C,s->D,s->A, 3, 19);
|
||||
ROUND1(s->A,s->B,s->C,s->D, 4, 3); ROUND1(s->D,s->A,s->B,s->C, 5, 7);
|
||||
ROUND1(s->C,s->D,s->A,s->B, 6, 11); ROUND1(s->B,s->C,s->D,s->A, 7, 19);
|
||||
ROUND1(s->A,s->B,s->C,s->D, 8, 3); ROUND1(s->D,s->A,s->B,s->C, 9, 7);
|
||||
ROUND1(s->C,s->D,s->A,s->B, 10, 11); ROUND1(s->B,s->C,s->D,s->A, 11, 19);
|
||||
ROUND1(s->A,s->B,s->C,s->D, 12, 3); ROUND1(s->D,s->A,s->B,s->C, 13, 7);
|
||||
ROUND1(s->C,s->D,s->A,s->B, 14, 11); ROUND1(s->B,s->C,s->D,s->A, 15, 19);
|
||||
|
||||
ROUND2(s->A,s->B,s->C,s->D, 0, 3); ROUND2(s->D,s->A,s->B,s->C, 4, 5);
|
||||
ROUND2(s->C,s->D,s->A,s->B, 8, 9); ROUND2(s->B,s->C,s->D,s->A, 12, 13);
|
||||
ROUND2(s->A,s->B,s->C,s->D, 1, 3); ROUND2(s->D,s->A,s->B,s->C, 5, 5);
|
||||
ROUND2(s->C,s->D,s->A,s->B, 9, 9); ROUND2(s->B,s->C,s->D,s->A, 13, 13);
|
||||
ROUND2(s->A,s->B,s->C,s->D, 2, 3); ROUND2(s->D,s->A,s->B,s->C, 6, 5);
|
||||
ROUND2(s->C,s->D,s->A,s->B, 10, 9); ROUND2(s->B,s->C,s->D,s->A, 14, 13);
|
||||
ROUND2(s->A,s->B,s->C,s->D, 3, 3); ROUND2(s->D,s->A,s->B,s->C, 7, 5);
|
||||
ROUND2(s->C,s->D,s->A,s->B, 11, 9); ROUND2(s->B,s->C,s->D,s->A, 15, 13);
|
||||
|
||||
ROUND3(s->A,s->B,s->C,s->D, 0, 3); ROUND3(s->D,s->A,s->B,s->C, 8, 9);
|
||||
ROUND3(s->C,s->D,s->A,s->B, 4, 11); ROUND3(s->B,s->C,s->D,s->A, 12, 15);
|
||||
ROUND3(s->A,s->B,s->C,s->D, 2, 3); ROUND3(s->D,s->A,s->B,s->C, 10, 9);
|
||||
ROUND3(s->C,s->D,s->A,s->B, 6, 11); ROUND3(s->B,s->C,s->D,s->A, 14, 15);
|
||||
ROUND3(s->A,s->B,s->C,s->D, 1, 3); ROUND3(s->D,s->A,s->B,s->C, 9, 9);
|
||||
ROUND3(s->C,s->D,s->A,s->B, 5, 11); ROUND3(s->B,s->C,s->D,s->A, 13, 15);
|
||||
ROUND3(s->A,s->B,s->C,s->D, 3, 3); ROUND3(s->D,s->A,s->B,s->C, 11, 9);
|
||||
ROUND3(s->C,s->D,s->A,s->B, 7, 11); ROUND3(s->B,s->C,s->D,s->A, 15, 15);
|
||||
|
||||
s->A += AA;
|
||||
s->B += BB;
|
||||
s->C += CC;
|
||||
s->D += DD;
|
||||
|
||||
s->A &= 0xFFFFFFFF;
|
||||
s->B &= 0xFFFFFFFF;
|
||||
s->C &= 0xFFFFFFFF;
|
||||
s->D &= 0xFFFFFFFF;
|
||||
|
||||
for (j=0;j<16;j++)
|
||||
X[j] = 0;
|
||||
}
|
||||
|
||||
static void copy64(uint32_t *M, const uint8_t *in)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
|
||||
(in[i*4+1]<<8) | (in[i*4+0]<<0);
|
||||
}
|
||||
|
||||
static void copy4(uint8_t *out, uint32_t x)
|
||||
{
|
||||
out[0] = x&0xFF;
|
||||
out[1] = (x>>8)&0xFF;
|
||||
out[2] = (x>>16)&0xFF;
|
||||
out[3] = (x>>24)&0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* produce a md4 message digest from data of length n bytes
|
||||
*/
|
||||
_PUBLIC_ void mdfour(uint8_t *out, const uint8_t *in, int n)
|
||||
{
|
||||
uint8_t buf[128];
|
||||
uint32_t M[16];
|
||||
uint32_t b = n * 8;
|
||||
int i;
|
||||
struct mdfour_state state;
|
||||
|
||||
state.A = 0x67452301;
|
||||
state.B = 0xefcdab89;
|
||||
state.C = 0x98badcfe;
|
||||
state.D = 0x10325476;
|
||||
|
||||
while (n > 64) {
|
||||
copy64(M, in);
|
||||
mdfour64(&state, M);
|
||||
in += 64;
|
||||
n -= 64;
|
||||
}
|
||||
|
||||
for (i=0;i<128;i++)
|
||||
buf[i] = 0;
|
||||
memcpy(buf, in, n);
|
||||
buf[n] = 0x80;
|
||||
|
||||
if (n <= 55) {
|
||||
copy4(buf+56, b);
|
||||
copy64(M, buf);
|
||||
mdfour64(&state, M);
|
||||
} else {
|
||||
copy4(buf+120, b);
|
||||
copy64(M, buf);
|
||||
mdfour64(&state, M);
|
||||
copy64(M, buf+64);
|
||||
mdfour64(&state, M);
|
||||
}
|
||||
|
||||
for (i=0;i<128;i++)
|
||||
buf[i] = 0;
|
||||
copy64(M, buf);
|
||||
|
||||
copy4(out, state.A);
|
||||
copy4(out+4, state.B);
|
||||
copy4(out+8, state.C);
|
||||
copy4(out+12, state.D);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
void mdfour(uint8_t *out, const uint8_t *in, int n);
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
MD4 tests
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
struct torture_context;
|
||||
|
||||
/*
|
||||
This uses the test values from rfc1320
|
||||
*/
|
||||
BOOL torture_local_crypto_md4(struct torture_context *torture)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint32_t i;
|
||||
struct {
|
||||
const char *data;
|
||||
const char *md4;
|
||||
} testarray[] = {
|
||||
{
|
||||
.data = "",
|
||||
.md4 = "31d6cfe0d16ae931b73c59d7e0c089c0"
|
||||
},{
|
||||
.data = "a",
|
||||
.md4 = "bde52cb31de33e46245e05fbdbd6fb24"
|
||||
},{
|
||||
.data = "abc",
|
||||
.md4 = "a448017aaf21d8525fc10ae87aa6729d"
|
||||
},{
|
||||
.data = "message digest",
|
||||
.md4 = "d9130a8164549fe818874806e1c7014b"
|
||||
},{
|
||||
.data = "abcdefghijklmnopqrstuvwxyz",
|
||||
.md4 = "d79e1c308aa5bbcdeea8ed63df412da9"
|
||||
},{
|
||||
.data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
.md4 = "043f8582f241db351ce627e153e7f0e4"
|
||||
},{
|
||||
.data = "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
.md4 = "e33b4ddc9c38f2199c3e7b164fcc0536"
|
||||
}
|
||||
};
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(testarray); i++) {
|
||||
uint8_t md4[16];
|
||||
int e;
|
||||
DATA_BLOB data;
|
||||
DATA_BLOB md4blob;
|
||||
|
||||
data = data_blob_string_const(testarray[i].data);
|
||||
md4blob = strhex_to_data_blob(testarray[i].md4);
|
||||
|
||||
mdfour(md4, data.data, data.length);
|
||||
|
||||
e = memcmp(md4blob.data, md4, MIN(md4blob.length, sizeof(md4)));
|
||||
if (e != 0) {
|
||||
printf("md4 test[%u]: failed\n", i);
|
||||
dump_data(0, data.data, data.length);
|
||||
dump_data(0, md4blob.data, md4blob.length);
|
||||
dump_data(0, md4, sizeof(md4));
|
||||
ret = False;
|
||||
}
|
||||
talloc_free(md4blob.data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
/* This code slightly modified to fit into Samba by
|
||||
abartlet@samba.org Jun 2001 */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
|
||||
static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
|
||||
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(uint8_t *buf, uint_t longs)
|
||||
{
|
||||
uint32_t t;
|
||||
do {
|
||||
t = (uint32_t) ((uint_t) buf[3] << 8 | buf[2]) << 16 |
|
||||
((uint_t) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
_PUBLIC_ void _Samba_MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
_PUBLIC_ void _Samba_MD5Update(struct MD5Context *ctx, const uint8_t *buf, size_t len)
|
||||
{
|
||||
register uint32_t t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
uint8_t *p = (uint8_t *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memmove(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memmove(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memmove(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memmove(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
_PUBLIC_ void _Samba_MD5Final(uint8_t digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
uint_t count;
|
||||
uint8_t *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32_t *) ctx->in)[14] = ctx->bits[0];
|
||||
((uint32_t *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
byteReverse((uint8_t *) ctx->buf, 4);
|
||||
memmove(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
|
||||
{
|
||||
register uint32_t a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
#ifndef HEADER_MD5_H
|
||||
/* Try to avoid clashes with OpenSSL */
|
||||
#define HEADER_MD5_H
|
||||
#endif
|
||||
|
||||
struct MD5Context {
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
uint8_t in[64];
|
||||
};
|
||||
|
||||
/* Add this "namespace" prefix to work around an extraneous symbol in the libSystem.B
|
||||
library on MacOS 10.6 */
|
||||
#define MD5Init _Samba_MD5Init
|
||||
#define MD5Update _Samba_MD5Update
|
||||
#define MD5Final _Samba_MD5Final
|
||||
|
||||
void _Samba_MD5Init(struct MD5Context *context);
|
||||
void _Samba_MD5Update(struct MD5Context *context, const uint8_t *buf,
|
||||
size_t len);
|
||||
void _Samba_MD5Final(uint8_t digest[16], struct MD5Context *context);
|
||||
|
||||
#endif /* !MD5_H */
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
MD5 tests
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
struct torture_context;
|
||||
|
||||
/*
|
||||
This uses the test values from rfc1321
|
||||
*/
|
||||
BOOL torture_local_crypto_md5(struct torture_context *torture)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint32_t i;
|
||||
struct {
|
||||
const char *data;
|
||||
const char *md5;
|
||||
} testarray[] = {
|
||||
{
|
||||
.data = "",
|
||||
.md5 = "d41d8cd98f00b204e9800998ecf8427e"
|
||||
},{
|
||||
.data = "a",
|
||||
.md5 = "0cc175b9c0f1b6a831c399e269772661"
|
||||
},{
|
||||
.data = "abc",
|
||||
.md5 = "900150983cd24fb0d6963f7d28e17f72"
|
||||
},{
|
||||
.data = "message digest",
|
||||
.md5 = "f96b697d7cb7938d525a2f31aaf161d0"
|
||||
},{
|
||||
.data = "abcdefghijklmnopqrstuvwxyz",
|
||||
.md5 = "c3fcd3d76192e4007dfb496cca67e13b"
|
||||
},{
|
||||
.data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789",
|
||||
.md5 = "d174ab98d277d9f5a5611c2c9f419d9f"
|
||||
},{
|
||||
.data = "123456789012345678901234567890"
|
||||
"123456789012345678901234567890"
|
||||
"12345678901234567890",
|
||||
.md5 = "57edf4a22be3c955ac49da2e2107b67a"
|
||||
}
|
||||
};
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(testarray); i++) {
|
||||
struct MD5Context ctx;
|
||||
uint8_t md5[16];
|
||||
int e;
|
||||
|
||||
DATA_BLOB data;
|
||||
DATA_BLOB md5blob;
|
||||
|
||||
data = data_blob_string_const(testarray[i].data);
|
||||
md5blob = strhex_to_data_blob(testarray[i].md5);
|
||||
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, data.data, data.length);
|
||||
MD5Final(md5, &ctx);
|
||||
|
||||
e = memcmp(md5blob.data,
|
||||
md5,
|
||||
MIN(md5blob.length, sizeof(md5)));
|
||||
if (e != 0) {
|
||||
printf("md5 test[%u]: failed\n", i);
|
||||
dump_data(0, data.data, data.length);
|
||||
dump_data(0, md5blob.data, md5blob.length);
|
||||
dump_data(0, md5, sizeof(md5));
|
||||
ret = False;
|
||||
}
|
||||
talloc_free(md5blob.data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
This file contains the reference implementation of SHA-1
|
||||
from http://www.ietf.org/rfc/rfc3174.txt
|
||||
*/
|
||||
/*
|
||||
* sha1.c
|
||||
*
|
||||
* Description:
|
||||
* This file implements the Secure Hashing Algorithm 1 as
|
||||
* defined in FIPS PUB 180-1 published April 17, 1995.
|
||||
*
|
||||
* The SHA-1, produces a 160-bit message digest for a given
|
||||
* data stream. It should take about 2**n steps to find a
|
||||
* message with the same digest as a given message and
|
||||
* 2**(n/2) to find any two messages with the same digest,
|
||||
* when n is the digest size in bits. Therefore, this
|
||||
* algorithm can serve as a means of providing a
|
||||
* "fingerprint" for a message.
|
||||
*
|
||||
* Portability Issues:
|
||||
* SHA-1 is defined in terms of 32-bit "words". This code
|
||||
* uses <stdint.h> (included via "sha1.h" to define 32 and 8
|
||||
* bit unsigned integer types. If your C compiler does not
|
||||
* support 32 bit unsigned integers, this code is not
|
||||
* appropriate.
|
||||
*
|
||||
* Caveats:
|
||||
* SHA-1 is designed to work with messages less than 2^64 bits
|
||||
* long. Although SHA-1 allows a message digest to be generated
|
||||
* for messages of any number of bits less than 2^64, this
|
||||
* implementation only works with messages with a length that is
|
||||
* a multiple of the size of an 8-bit character.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
/*
|
||||
* Define the SHA1 circular left shift macro
|
||||
*/
|
||||
#define SHA1CircularShift(bits,word) \
|
||||
(((word) << (bits)) | ((word) >> (32-(bits))))
|
||||
|
||||
/* Local Function Prototyptes */
|
||||
static void SHA1PadMessage(struct SHA1Context *);
|
||||
static void SHA1ProcessMessageBlock(struct SHA1Context *);
|
||||
|
||||
/*
|
||||
* SHA1Init (SHA1Reset in the rfc)
|
||||
*
|
||||
* Description:
|
||||
* This function will initialize the SHA1Context in preparation
|
||||
* for computing a new SHA1 message digest.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to reset.
|
||||
*
|
||||
* Returns:
|
||||
* sha Error Code.
|
||||
*
|
||||
*/
|
||||
int SHA1Init(struct SHA1Context *context)
|
||||
{
|
||||
if (!context)
|
||||
{
|
||||
return shaNull;
|
||||
}
|
||||
|
||||
context->Length_Low = 0;
|
||||
context->Length_High = 0;
|
||||
context->Message_Block_Index = 0;
|
||||
|
||||
context->Intermediate_Hash[0] = 0x67452301;
|
||||
context->Intermediate_Hash[1] = 0xEFCDAB89;
|
||||
context->Intermediate_Hash[2] = 0x98BADCFE;
|
||||
context->Intermediate_Hash[3] = 0x10325476;
|
||||
context->Intermediate_Hash[4] = 0xC3D2E1F0;
|
||||
|
||||
context->Computed = 0;
|
||||
context->Corrupted = 0;
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1Final (SHA1Result in the rfc)
|
||||
*
|
||||
* Description:
|
||||
* This function will return the 160-bit message digest into the
|
||||
* Message_Digest array provided by the caller.
|
||||
* NOTE: The first octet of hash is stored in the 0th element,
|
||||
* the last octet of hash in the 19th element.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to use to calculate the SHA-1 hash.
|
||||
* Message_Digest: [out]
|
||||
* Where the digest is returned.
|
||||
*
|
||||
* Returns:
|
||||
* sha Error Code.
|
||||
*
|
||||
*/
|
||||
int SHA1Final(uint8_t Message_Digest[SHA1HashSize],
|
||||
struct SHA1Context *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!context || !Message_Digest)
|
||||
{
|
||||
return shaNull;
|
||||
}
|
||||
|
||||
if (context->Corrupted)
|
||||
{
|
||||
return context->Corrupted;
|
||||
}
|
||||
|
||||
if (!context->Computed)
|
||||
{
|
||||
SHA1PadMessage(context);
|
||||
for(i=0; i<64; ++i)
|
||||
{
|
||||
/* message may be sensitive, clear it out */
|
||||
context->Message_Block[i] = 0;
|
||||
}
|
||||
context->Length_Low = 0; /* and clear length */
|
||||
context->Length_High = 0;
|
||||
context->Computed = 1;
|
||||
}
|
||||
|
||||
for(i = 0; i < SHA1HashSize; ++i)
|
||||
{
|
||||
Message_Digest[i] = context->Intermediate_Hash[i>>2]
|
||||
>> 8 * ( 3 - ( i & 0x03 ) );
|
||||
}
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1Update (SHA1Input in the rfc)
|
||||
*
|
||||
* Description:
|
||||
* This function accepts an array of octets as the next portion
|
||||
* of the message.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The SHA context to update
|
||||
* message_array: [in]
|
||||
* An array of characters representing the next portion of
|
||||
* the message.
|
||||
* length: [in]
|
||||
* The length of the message in message_array
|
||||
*
|
||||
* Returns:
|
||||
* sha Error Code.
|
||||
*
|
||||
*/
|
||||
int SHA1Update(struct SHA1Context *context,
|
||||
const uint8_t *message_array,
|
||||
size_t length)
|
||||
{
|
||||
if (!length)
|
||||
{
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
if (!context || !message_array)
|
||||
{
|
||||
return shaNull;
|
||||
}
|
||||
|
||||
if (context->Computed)
|
||||
{
|
||||
context->Corrupted = shaStateError;
|
||||
return shaStateError;
|
||||
}
|
||||
|
||||
if (context->Corrupted)
|
||||
{
|
||||
return context->Corrupted;
|
||||
}
|
||||
while(length-- && !context->Corrupted)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] =
|
||||
(*message_array & 0xFF);
|
||||
|
||||
context->Length_Low += 8;
|
||||
if (context->Length_Low == 0)
|
||||
{
|
||||
context->Length_High++;
|
||||
if (context->Length_High == 0)
|
||||
{
|
||||
/* Message is too long */
|
||||
context->Corrupted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (context->Message_Block_Index == 64)
|
||||
{
|
||||
SHA1ProcessMessageBlock(context);
|
||||
}
|
||||
|
||||
message_array++;
|
||||
}
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1ProcessMessageBlock
|
||||
*
|
||||
* Description:
|
||||
* This function will process the next 512 bits of the message
|
||||
* stored in the Message_Block array.
|
||||
*
|
||||
* Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
* Many of the variable names in this code, especially the
|
||||
* single character names, were used because those were the
|
||||
* names used in the publication.
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void SHA1ProcessMessageBlock(struct SHA1Context *context)
|
||||
{
|
||||
const uint32_t K[] = { /* Constants defined in SHA-1 */
|
||||
0x5A827999,
|
||||
0x6ED9EBA1,
|
||||
0x8F1BBCDC,
|
||||
0xCA62C1D6
|
||||
};
|
||||
int t; /* Loop counter */
|
||||
uint32_t temp; /* Temporary word value */
|
||||
uint32_t W[80]; /* Word sequence */
|
||||
uint32_t A, B, C, D, E; /* Word buffers */
|
||||
|
||||
/*
|
||||
* Initialize the first 16 words in the array W
|
||||
*/
|
||||
for(t = 0; t < 16; t++)
|
||||
{
|
||||
W[t] = context->Message_Block[t * 4] << 24;
|
||||
W[t] |= context->Message_Block[t * 4 + 1] << 16;
|
||||
W[t] |= context->Message_Block[t * 4 + 2] << 8;
|
||||
W[t] |= context->Message_Block[t * 4 + 3];
|
||||
}
|
||||
|
||||
for(t = 16; t < 80; t++)
|
||||
{
|
||||
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
||||
}
|
||||
|
||||
A = context->Intermediate_Hash[0];
|
||||
B = context->Intermediate_Hash[1];
|
||||
C = context->Intermediate_Hash[2];
|
||||
D = context->Intermediate_Hash[3];
|
||||
E = context->Intermediate_Hash[4];
|
||||
|
||||
for(t = 0; t < 20; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) +
|
||||
((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 20; t < 40; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 40; t < 60; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) +
|
||||
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 60; t < 80; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
context->Intermediate_Hash[0] += A;
|
||||
context->Intermediate_Hash[1] += B;
|
||||
context->Intermediate_Hash[2] += C;
|
||||
context->Intermediate_Hash[3] += D;
|
||||
context->Intermediate_Hash[4] += E;
|
||||
|
||||
context->Message_Block_Index = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA1PadMessage
|
||||
*
|
||||
* Description:
|
||||
* According to the standard, the message must be padded to an even
|
||||
* 512 bits. The first padding bit must be a '1'. The last 64
|
||||
* bits represent the length of the original message. All bits in
|
||||
* between should be 0. This function will pad the message
|
||||
* according to those rules by filling the Message_Block array
|
||||
* accordingly. It will also call the ProcessMessageBlock function
|
||||
* provided appropriately. When it returns, it can be assumed that
|
||||
* the message digest has been computed.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to pad
|
||||
* ProcessMessageBlock: [in]
|
||||
* The appropriate SHA*ProcessMessageBlock function
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
*/
|
||||
|
||||
static void SHA1PadMessage(struct SHA1Context *context)
|
||||
{
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
* the initial padding bits and length. If so, we will pad the
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (context->Message_Block_Index > 55)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] = 0x80;
|
||||
while(context->Message_Block_Index < 64)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] = 0;
|
||||
}
|
||||
|
||||
SHA1ProcessMessageBlock(context);
|
||||
|
||||
while(context->Message_Block_Index < 56)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] = 0x80;
|
||||
while(context->Message_Block_Index < 56)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the message length as the last 8 octets
|
||||
*/
|
||||
context->Message_Block[56] = context->Length_High >> 24;
|
||||
context->Message_Block[57] = context->Length_High >> 16;
|
||||
context->Message_Block[58] = context->Length_High >> 8;
|
||||
context->Message_Block[59] = context->Length_High;
|
||||
context->Message_Block[60] = context->Length_Low >> 24;
|
||||
context->Message_Block[61] = context->Length_Low >> 16;
|
||||
context->Message_Block[62] = context->Length_Low >> 8;
|
||||
context->Message_Block[63] = context->Length_Low;
|
||||
|
||||
SHA1ProcessMessageBlock(context);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
This file contains the reference implementation of SHA-1
|
||||
from http://www.ietf.org/rfc/rfc3174.txt
|
||||
*/
|
||||
/*
|
||||
* sha1.h
|
||||
*
|
||||
* Description:
|
||||
* This is the header file for code which implements the Secure
|
||||
* Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
|
||||
* April 17, 1995.
|
||||
*
|
||||
* Many of the variable names in this code, especially the
|
||||
* single character names, were used because those were the names
|
||||
* used in the publication.
|
||||
*
|
||||
* Please read the file sha1.c for more information.
|
||||
*
|
||||
*/
|
||||
#ifndef _SHA1_H_
|
||||
#define _SHA1_H_
|
||||
|
||||
#ifndef _SHA_enum_
|
||||
#define _SHA_enum_
|
||||
enum
|
||||
{
|
||||
shaSuccess = 0,
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
shaStateError /* called Input after Result */
|
||||
};
|
||||
#endif
|
||||
#define SHA1HashSize 20
|
||||
|
||||
/*
|
||||
* This structure will hold context information for the SHA-1
|
||||
* hashing operation
|
||||
*/
|
||||
struct SHA1Context
|
||||
{
|
||||
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
|
||||
|
||||
uint32_t Length_Low; /* Message length in bits */
|
||||
uint32_t Length_High; /* Message length in bits */
|
||||
|
||||
/* Index into message block array */
|
||||
int16_t Message_Block_Index;
|
||||
uint8_t Message_Block[64]; /* 512-bit message blocks */
|
||||
|
||||
int Computed; /* Is the digest computed? */
|
||||
int Corrupted; /* Is the message digest corrupted? */
|
||||
};
|
||||
|
||||
/*
|
||||
* Function Prototypes
|
||||
*/
|
||||
|
||||
int SHA1Init(struct SHA1Context *);
|
||||
int SHA1Update(struct SHA1Context *, const uint8_t *data, size_t data_len);
|
||||
int SHA1Final(uint8_t Message_Digest[SHA1HashSize], struct SHA1Context *);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
This file contains the reference implementation of SHA-1
|
||||
from http://www.ietf.org/rfc/rfc3174.txt
|
||||
*/
|
||||
/*
|
||||
* sha1test.c
|
||||
*
|
||||
* Description:
|
||||
* This file will exercise the SHA-1 code performing the three
|
||||
* tests documented in FIPS PUB 180-1 plus one which calls
|
||||
* SHA1Input with an exact multiple of 512 bits, plus a few
|
||||
* error test checks.
|
||||
*
|
||||
* Portability Issues:
|
||||
* None.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "torture/ui.h"
|
||||
|
||||
#include "lib/crypto/crypto.h"
|
||||
|
||||
struct torture_context;
|
||||
|
||||
/*
|
||||
* Define patterns for testing
|
||||
*/
|
||||
#define TEST1 "abc"
|
||||
#define TEST2a "abcdbcdecdefdefgefghfghighijhi"
|
||||
#define TEST2b "jkijkljklmklmnlmnomnopnopq"
|
||||
#define TEST2 TEST2a TEST2b
|
||||
#define TEST3 "a"
|
||||
#define TEST4a "01234567012345670123456701234567"
|
||||
#define TEST4b "01234567012345670123456701234567"
|
||||
/* an exact multiple of 512 bits */
|
||||
#define TEST4 TEST4a TEST4b
|
||||
static const char *testarray[4] =
|
||||
{
|
||||
TEST1,
|
||||
TEST2,
|
||||
TEST3,
|
||||
TEST4
|
||||
};
|
||||
static int repeatcount[4] = { 1, 1, 1000000, 10 };
|
||||
static const char *resultarray[4] =
|
||||
{
|
||||
"A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D ",
|
||||
"84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1 ",
|
||||
"34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F ",
|
||||
"DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52 "
|
||||
};
|
||||
|
||||
|
||||
bool torture_local_crypto_sha1(struct torture_context *tctx)
|
||||
{
|
||||
struct SHA1Context sha;
|
||||
int i, j, err;
|
||||
uint8_t Message_Digest[20];
|
||||
BOOL ret = True;
|
||||
char tmp[60 + 10];
|
||||
|
||||
/*
|
||||
* Perform SHA-1 tests
|
||||
*/
|
||||
for(j = 0; j < 4; ++j)
|
||||
{
|
||||
ZERO_STRUCT(tmp);
|
||||
torture_comment(tctx, "Test %d: %d, '%s'\n",
|
||||
j+1,
|
||||
repeatcount[j],
|
||||
testarray[j]);
|
||||
|
||||
err = SHA1Init(&sha);
|
||||
torture_assert_int_equal(tctx, err, 0, "SHA1Init Error");
|
||||
|
||||
for(i = 0; i < repeatcount[j]; ++i)
|
||||
{
|
||||
err = SHA1Update(&sha,
|
||||
(const unsigned char *) testarray[j],
|
||||
strlen(testarray[j]));
|
||||
torture_assert_int_equal(tctx, err, 0, "SHA1Update Error");
|
||||
}
|
||||
|
||||
err = SHA1Final(Message_Digest, &sha);
|
||||
torture_assert_int_equal(tctx, err, 0,
|
||||
"SHA1Result Error, could not compute message digest.");
|
||||
torture_comment(tctx, "\t");
|
||||
for(i = 0; i < 20 ; ++i)
|
||||
{
|
||||
snprintf(tmp+(i*3), sizeof(tmp) - (i*3),"%02X ", Message_Digest[i]);
|
||||
torture_comment(tctx, "%02X ", Message_Digest[i]);
|
||||
}
|
||||
torture_comment(tctx, "\n");
|
||||
torture_comment(tctx, "Should match:\n\t%s\n", resultarray[j]);
|
||||
if (strcmp(resultarray[j], tmp) != 0) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test some error returns */
|
||||
err = SHA1Update(&sha,(const unsigned char *) testarray[1], 1);
|
||||
torture_assert_int_equal(tctx, err, shaStateError, "SHA1Update failed");
|
||||
err = SHA1Init(0);
|
||||
torture_assert_int_equal(tctx, err, shaNull, "SHA1Init failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user