348 lines
9.8 KiB
C
348 lines
9.8 KiB
C
/*
|
|
* The IKE Scanner (ike-scan) is Copyright (C) 2003-2007 Roy Hills,
|
|
* NTA Monitor Ltd.
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* In addition, as a special exception, the copyright holders give
|
|
* permission to link the code of portions of this program with the
|
|
* OpenSSL library, and distribute linked combinations including the two.
|
|
*
|
|
* You must obey the GNU General Public License in all respects
|
|
* for all of the code used other than OpenSSL. If you modify
|
|
* file(s) with this exception, you may extend this exception to your
|
|
* version of the file(s), but you are not obligated to do so. If you
|
|
* do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*
|
|
* If this license is unacceptable to you, I may be willing to negotiate
|
|
* alternative licenses (contact ike-scan@nta-monitor.com).
|
|
*
|
|
* You are encouraged to send comments, improvements or suggestions to
|
|
* me at ike-scan@nta-monitor.com.
|
|
*
|
|
* $Id: hash_functions.h 9884 2007-01-14 19:05:39Z rsh $
|
|
*
|
|
* hash_functions.h -- Header file for hash functions
|
|
*
|
|
* Author: Roy Hills
|
|
* Date: 23 December 2006
|
|
*/
|
|
|
|
#ifndef IKE_SCAN_HASH_H
|
|
#define IKE_SCAN_HASH_H 1
|
|
|
|
#ifndef HAVE_OPENSSL
|
|
/*
|
|
* MD5 -- Calculate MD5 hash of specified data
|
|
*
|
|
* Inputs:
|
|
*
|
|
* d The data to hash
|
|
* n The length of the data
|
|
* md The resulting MD5 hash
|
|
*
|
|
* Returns:
|
|
*
|
|
* The MD5 hash.
|
|
*
|
|
* This function is a wrapper for the MD5 routines in md5.c. If ike-scan
|
|
* was compiled with OpenSSL, then the OpenSSL MD5 routines are used
|
|
* instead, and this wrapper is not used.
|
|
*/
|
|
static inline unsigned char *
|
|
MD5(const unsigned char *d, size_t n, unsigned char *md) {
|
|
md5_state_t context;
|
|
static unsigned char m[16];
|
|
|
|
if (md == NULL) /* Use static storage if no buffer specified */
|
|
md=m;
|
|
|
|
md5_init(&context);
|
|
md5_append(&context, d, n);
|
|
md5_finish(&context, md);
|
|
|
|
return md;
|
|
}
|
|
#endif
|
|
|
|
#ifndef HAVE_OPENSSL
|
|
/*
|
|
* SHA1 -- Calculate SHA1 hash of specified data
|
|
*
|
|
* Inputs:
|
|
*
|
|
* d The data to hash
|
|
* n The length of the data
|
|
* md The resulting SHA1 hash
|
|
*
|
|
* Returns:
|
|
*
|
|
* The SHA1 hash.
|
|
*
|
|
* This function is a wrapper for the SHA1 routines in sha1.c. If ike-scan
|
|
* was compiled with OpenSSL, then the OpenSSL SHA1 routines are used
|
|
* instead, and this wrapper is not used.
|
|
*/
|
|
static inline unsigned char *
|
|
SHA1(const unsigned char *d, size_t n, unsigned char *md) {
|
|
SHA1_CTX context;
|
|
static unsigned char m[20];
|
|
|
|
if (md == NULL) /* Use static storage if no buffer specified */
|
|
md=m;
|
|
|
|
SHA1Init(&context);
|
|
/*
|
|
* SHA1Update's prototype doesn't use "const", so we use a cast to prevent
|
|
* a warning. It would really be better to fix sha1.[ch] so that they use
|
|
* const, and I may do that some day.
|
|
*/
|
|
SHA1Update(&context, (unsigned char *)d, n);
|
|
SHA1Final(md, &context);
|
|
|
|
return md;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* hmac_md5 -- Calculate HMAC-MD5 keyed hash
|
|
*
|
|
* Inputs:
|
|
*
|
|
* text The data to hash
|
|
* text_len Length of the data in bytes
|
|
* key The key
|
|
* key_len Length of the key in bytes
|
|
* digest The resulting HMAC-MD5 digest
|
|
*
|
|
* Returns:
|
|
*
|
|
* The HMAC-MD5 hash.
|
|
*
|
|
* This function is based on the code from the RFC 2104 appendix.
|
|
*
|
|
* We use #ifdef to select either the OpenSSL MD5 functions or the
|
|
* built-in MD5 functions depending on whether HAVE_OPENSSL is defined.
|
|
* This is faster that calling OpenSSL "HMAC" directly.
|
|
*/
|
|
static inline unsigned char *
|
|
hmac_md5(const unsigned char *text, size_t text_len, const unsigned char *key,
|
|
size_t key_len, unsigned char *md) {
|
|
static unsigned char m[16];
|
|
#ifdef HAVE_OPENSSL
|
|
MD5_CTX context;
|
|
#else
|
|
md5_state_t context;
|
|
#endif
|
|
unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
|
|
unsigned char k_opad[65]; /* outer padding - key XORd with opad */
|
|
unsigned char tk[16];
|
|
int i;
|
|
|
|
if (md == NULL) /* Use static storage if no buffer specified */
|
|
md=m;
|
|
|
|
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
|
if (key_len > 64) {
|
|
#ifdef HAVE_OPENSSL
|
|
MD5_CTX tctx;
|
|
|
|
MD5_Init(&tctx);
|
|
MD5_Update(&tctx, key, key_len);
|
|
MD5_Final(tk, &tctx);
|
|
#else
|
|
md5_state_t tctx;
|
|
|
|
md5_init(&tctx);
|
|
md5_append(&tctx, key, key_len);
|
|
md5_finish(&tctx, tk);
|
|
#endif
|
|
|
|
key = tk;
|
|
key_len = 16;
|
|
}
|
|
/*
|
|
* the HMAC_MD5 transform looks like:
|
|
*
|
|
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
|
*
|
|
* where K is an n byte key
|
|
* ipad is the byte 0x36 repeated 64 times
|
|
* opad is the byte 0x5c repeated 64 times
|
|
* and text is the data being protected
|
|
*/
|
|
|
|
/* start out by storing key in pads */
|
|
memset(k_ipad, '\0', sizeof k_ipad);
|
|
memset(k_opad, '\0', sizeof k_opad);
|
|
memcpy(k_ipad, key, key_len);
|
|
memcpy(k_opad, key, key_len);
|
|
|
|
/* XOR key with ipad and opad values */
|
|
for (i=0; i<64; i++) {
|
|
k_ipad[i] ^= 0x36;
|
|
k_opad[i] ^= 0x5c;
|
|
}
|
|
#ifdef HAVE_OPENSSL
|
|
/*
|
|
* perform inner MD5
|
|
*/
|
|
MD5_Init(&context); /* init context for 1st pass */
|
|
MD5_Update(&context, k_ipad, 64); /* start with inner pad */
|
|
MD5_Update(&context, text, text_len); /* then text of datagram */
|
|
MD5_Final(md, &context); /* finish up 1st pass */
|
|
/*
|
|
* perform outer MD5
|
|
*/
|
|
MD5_Init(&context); /* init context for 2nd pass */
|
|
MD5_Update(&context, k_opad, 64); /* start with outer pad */
|
|
MD5_Update(&context, md, 16); /* then results of 1st hash */
|
|
MD5_Final(md, &context); /* finish up 2nd pass */
|
|
#else
|
|
/*
|
|
* perform inner MD5
|
|
*/
|
|
md5_init(&context); /* init context for 1st pass */
|
|
md5_append(&context, k_ipad, 64); /* start with inner pad */
|
|
md5_append(&context, text, text_len); /* then text of datagram */
|
|
md5_finish(&context, md); /* finish up 1st pass */
|
|
/*
|
|
* perform outer MD5
|
|
*/
|
|
md5_init(&context); /* init context for 2nd pass */
|
|
md5_append(&context, k_opad, 64); /* start with outer pad */
|
|
md5_append(&context, md, 16); /* then results of 1st hash */
|
|
md5_finish(&context, md); /* finish up 2nd pass */
|
|
#endif
|
|
|
|
return md;
|
|
}
|
|
|
|
/*
|
|
* hmac_sha1 -- Calculate HMAC-SHA1 keyed hash
|
|
*
|
|
* Inputs:
|
|
*
|
|
* text The data to hash
|
|
* text_len Length of the data in bytes
|
|
* key The key
|
|
* key_len Length of the key in bytes
|
|
* digest The resulting HMAC-SHA1 digest
|
|
*
|
|
* Returns:
|
|
*
|
|
* The HMAC-SHA1 hash.
|
|
*
|
|
* This function is based on the code from the RFC 2104 appendix.
|
|
*
|
|
* We use #ifdef to select either the OpenSSL SHA1 functions or the
|
|
* built-in SHA1 functions depending on whether HAVE_OPENSSL is defined.
|
|
* This is faster that calling OpenSSL "HMAC" directly.
|
|
*/
|
|
static inline unsigned char *
|
|
hmac_sha1(const unsigned char *text, size_t text_len, const unsigned char *key,
|
|
size_t key_len, unsigned char *md) {
|
|
static unsigned char m[20];
|
|
#ifdef HAVE_OPENSSL
|
|
SHA_CTX context;
|
|
#else
|
|
SHA1_CTX context;
|
|
#endif
|
|
unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
|
|
unsigned char k_opad[65]; /* outer padding - key XORd with opad */
|
|
unsigned char tk[20];
|
|
int i;
|
|
|
|
if (md == NULL) /* Use static storage if no buffer specified */
|
|
md=m;
|
|
|
|
/* if key is longer than 64 bytes reset it to key=SHA1(key) */
|
|
if (key_len > 64) {
|
|
#ifdef HAVE_OPENSSL
|
|
SHA_CTX tctx;
|
|
|
|
SHA1_Init(&tctx);
|
|
SHA1_Update(&tctx, key, key_len);
|
|
SHA1_Final(tk, &tctx);
|
|
#else
|
|
SHA1_CTX tctx;
|
|
|
|
SHA1Init(&tctx);
|
|
SHA1Update(&tctx, (unsigned char *)key, key_len);
|
|
SHA1Final(tk, &tctx);
|
|
#endif
|
|
|
|
key = tk;
|
|
key_len = 20;
|
|
}
|
|
/*
|
|
* the HMAC_SHA1 transform looks like:
|
|
*
|
|
* SHA1(K XOR opad, SHA1(K XOR ipad, text))
|
|
*
|
|
* where K is an n byte key
|
|
* ipad is the byte 0x36 repeated 64 times
|
|
* opad is the byte 0x5c repeated 64 times
|
|
* and text is the data being protected
|
|
*/
|
|
|
|
/* start out by storing key in pads */
|
|
memset(k_ipad, '\0', sizeof k_ipad);
|
|
memset(k_opad, '\0', sizeof k_opad);
|
|
memcpy(k_ipad, key, key_len);
|
|
memcpy(k_opad, key, key_len);
|
|
|
|
/* XOR key with ipad and opad values */
|
|
for (i=0; i<64; i++) {
|
|
k_ipad[i] ^= 0x36;
|
|
k_opad[i] ^= 0x5c;
|
|
}
|
|
#ifdef HAVE_OPENSSL
|
|
/*
|
|
* perform inner SHA1
|
|
*/
|
|
SHA1_Init(&context); /* init context for 1st pass */
|
|
SHA1_Update(&context, k_ipad, 64); /* start with inner pad */
|
|
SHA1_Update(&context, text, text_len); /* then text of datagram */
|
|
SHA1_Final(md, &context); /* finish up 1st pass */
|
|
/*
|
|
* perform outer SHA1
|
|
*/
|
|
SHA1_Init(&context); /* init context for 2nd pass */
|
|
SHA1_Update(&context, k_opad, 64); /* start with outer pad */
|
|
SHA1_Update(&context, md, 20); /* then results of 1st hash */
|
|
SHA1_Final(md, &context); /* finish up 2nd pass */
|
|
#else
|
|
/*
|
|
* perform inner SHA1
|
|
*/
|
|
SHA1Init(&context); /* init context for 1st pass */
|
|
SHA1Update(&context, k_ipad, 64); /* start with inner pad */
|
|
SHA1Update(&context, (unsigned char *)text, text_len); /* then text of datagram */
|
|
SHA1Final(md, &context); /* finish up 1st pass */
|
|
/*
|
|
* perform outer SHA1
|
|
*/
|
|
SHA1Init(&context); /* init context for 2nd pass */
|
|
SHA1Update(&context, k_opad, 64); /* start with outer pad */
|
|
SHA1Update(&context, md, 20); /* then results of 1st hash */
|
|
SHA1Final(md, &context); /* finish up 2nd pass */
|
|
#endif
|
|
|
|
return md;
|
|
}
|
|
|
|
#endif /* IKE_SCAN_HASH_H */
|