< draft-eastlake-sha2b-03.txt   draft-eastlake-sha2b-04.txt >
Network Working Group Donald Eastlake 3rd Network Working Group Donald Eastlake 3rd
INTERNET-DRAFT Stellar Switches INTERNET-DRAFT Stellar Switches
Obsoletes: 4634 Tony Hansen Obsoletes: 4634 Tony Hansen
Updates: 3174 AT&T Labs Updates: 3174 AT&T Labs
Intended Status: Informational Intended Status: Informational
Expires: January 29, 2011 July 30, 2010 Expires: March 21, 2011 September 22, 2010
US Secure Hash Algorithms US Secure Hash Algorithms
(SHA and SHA based HMAC and HKDF) (SHA and SHA based HMAC and HKDF)
<draft-eastlake-sha2b-03.txt> <draft-eastlake-sha2b-04.txt>
Abstract Abstract
This document is an update of RFC 4634 to fix errata and to add code This document replaces RFC 4634, fixing errata and adding code for an
for an HMAC-based extract-and-expand key derivation function. HMAC-based extract-and-expand key derivation function.
The United States of America has adopted a suite of secure hash The United States of America has adopted a suite of secure hash
algorithms (SHAs), including four beyond SHA-1, as part of a Federal algorithms (SHAs), including four beyond SHA-1, as part of a Federal
Information Processing Standard (FIPS), specifically SHA-224, Information Processing Standard (FIPS), specifically SHA-224,
SHA-256, SHA-384, and SHA-512. The purpose of this document is to SHA-256, SHA-384, and SHA-512. This document makes open source code
make open source code performing the SHA hash functions conveniently performing the SHA hash functions conveniently available to the
available to the Internet community. The sample code supports input Internet community. The sample code supports input strings of
strings of arbitrary bit length. Much of the text herein was adapted arbitrary bit length. Much of the text herein was adapted by the
by the authors from FIPS 180-2. authors from FIPS 180-2.
As with RFC 4634, code to perform SHA based HMACs is included and, As with RFC 4634, code to perform SHA based HMACs is included and,
new in this version, code for HKDF (RFC 5869) is included. new in this version, code for HKDF (RFC 5869) is included.
Status of This Memo Status of This Memo
This Internet-Draft is submitted to IETF in full conformance with the This Internet-Draft is submitted to IETF in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
Distribution of this document is unlimited. Comments should be sent Distribution of this document is unlimited. Comments should be sent
skipping to change at page 2, line 39 skipping to change at page 2, line 39
7.2 HKDF..................................................17 7.2 HKDF..................................................17
8. C Code for SHAs, HMAC, and HKDF........................18 8. C Code for SHAs, HMAC, and HKDF........................18
8.1 The Header Files......................................21 8.1 The Header Files......................................21
8.1.1 The .h file.........................................21 8.1.1 The .h file.........................................21
8.1.2 sha-private.h.......................................29 8.1.2 sha-private.h.......................................29
8.2 The SHA Code..........................................29 8.2 The SHA Code..........................................29
8.2.1 sha1.c..............................................29 8.2.1 sha1.c..............................................29
8.2.2 sha224-256.c........................................38 8.2.2 sha224-256.c........................................38
8.2.3 sha384-512.c........................................50 8.2.3 sha384-512.c........................................50
8.2.4 usha.c..............................................71 8.2.4 usha.c..............................................70
8.3 The HMAC Code.........................................77 8.3 The HMAC Code.........................................76
8.4 The HKDF Code.........................................82 8.4 The HKDF Code.........................................81
8.5 The Test Driver.......................................89 8.5 The Test Driver.......................................88
9. IANA Considerations...................................120
10. Security Considerations..............................120
11. Acknowledgements.....................................120
12. References...........................................121 9. IANA Considerations...................................119
12.1 Normative References................................121 10. Security Considerations..............................119
12.2 Informative References..............................121 11. Acknowledgements.....................................119
12. References...........................................120
12.1 Normative References................................120
12.2 Informative References..............................120
Appendix: Changes from RFC 4634..........................123 Appendix: Changes from RFC 4634..........................121
Appendix Z: Edit History.................................124 Appendix Z: Edit History.................................122
Z.1 Changes from -00 to -01..............................124 Z.1 Changes from -00 to -01..............................122
Z.2 Changes from -01 to -02..............................124 Z.2 Changes from -01 to -02..............................122
Z.3 Changes from -02 to -03..............................124 Z.3 Changes from -02 to -03..............................122
Z.4 Changes from -03 to -04..............................122
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
1. Overview of Contents 1. Overview of Contents
This document obsoletes [RFC4634]; and the changes from that RFC are This document obsoletes [RFC4634]; and the changes from that RFC are
summarized in the Appendix. summarized in the Appendix.
This document includes specifications for the United States of This document includes specifications for the United States of
America (USA) Federal Information Processing Standard (FIPS) Secure America (USA) Federal Information Processing Standard (FIPS) Secure
skipping to change at page 22, line 39 skipping to change at page 22, line 39
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef _SHA_H_ #ifndef _SHA_H_
#define _SHA_H_ #define _SHA_H_
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithms * This file implements the Secure Hash Algorithms
* as defined in the National Institute of Standards * as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2 * Publication (FIPS PUB) 180-3 published in October 2008
* published on August 1, 2002, and the FIPS PUB 180-2 Change * and formerly defined in its predecessors, FIPS PUB 180-1
* Notice published on February 28, 2004. * and FIP PUB 180-2.
* *
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-3/fips180-3_final.pdf
* *
* The five hashes are defined in these sizes: * The five hashes are defined in these sizes:
* SHA-1 20 byte / 160 bit * SHA-1 20 byte / 160 bit
* SHA-224 28 byte / 224 bit * SHA-224 28 byte / 224 bit
* SHA-256 32 byte / 256 bit * SHA-256 32 byte / 256 bit
* SHA-384 48 byte / 384 bit * SHA-384 48 byte / 384 bit
* SHA-512 64 byte / 512 bit * SHA-512 64 byte / 512 bit
* *
* Compilation Note: * Compilation Note:
skipping to change at page 24, line 26 skipping to change at page 24, line 26
SHA1, SHA224, SHA256, SHA384, SHA512 SHA1, SHA224, SHA256, SHA384, SHA512
} SHAversion; } SHAversion;
/* /*
* This structure will hold context information for the SHA-1 * This structure will hold context information for the SHA-1
* hashing operation. * hashing operation.
*/ */
typedef struct SHA1Context { typedef struct SHA1Context {
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */ uint32_t Length_High; /* Message length in bits */
uint32_t Length_Low; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */ /* 512-bit message blocks */
uint8_t Message_Block[SHA1_Message_Block_Size]; uint8_t Message_Block[SHA1_Message_Block_Size];
int Computed; /* Is the digest computed? */ int Computed; /* Is the hash computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Cumulative corruption code */
} SHA1Context; } SHA1Context;
/* /*
* This structure will hold context information for the SHA-256 * This structure will hold context information for the SHA-256
* hashing operation. * hashing operation.
*/ */
typedef struct SHA256Context { typedef struct SHA256Context {
uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */ uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */ uint32_t Length_High; /* Message length in bits */
uint32_t Length_Low; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */ /* 512-bit message blocks */
uint8_t Message_Block[SHA256_Message_Block_Size]; uint8_t Message_Block[SHA256_Message_Block_Size];
int Computed; /* Is the digest computed? */ int Computed; /* Is the hash computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Cumulative corruption code */
} SHA256Context; } SHA256Context;
/* /*
* This structure will hold context information for the SHA-512 * This structure will hold context information for the SHA-512
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* hashing operation. * hashing operation.
*/ */
typedef struct SHA512Context { typedef struct SHA512Context {
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */ uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */
uint32_t Length[4]; /* Message length in bits */ uint32_t Length[4]; /* Message length in bits */
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */ uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
uint64_t Length_Low, Length_High; /* Message length in bits */ uint64_t Length_High, Length_Low; /* Message length in bits */
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
/* 1024-bit message blocks */ /* 1024-bit message blocks */
uint8_t Message_Block[SHA512_Message_Block_Size]; uint8_t Message_Block[SHA512_Message_Block_Size];
int Computed; /* Is the digest computed?*/ int Computed; /* Is the hash computed?*/
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Cumulative corruption code */
} SHA512Context; } SHA512Context;
/* /*
* This structure will hold context information for the SHA-224 * This structure will hold context information for the SHA-224
* hashing operation. It uses the SHA-256 structure for computation. * hashing operation. It uses the SHA-256 structure for computation.
*/ */
typedef struct SHA256Context SHA224Context; typedef struct SHA256Context SHA224Context;
/* /*
* This structure will hold context information for the SHA-384 * This structure will hold context information for the SHA-384
skipping to change at page 26, line 12 skipping to change at page 26, line 12
typedef struct HMACContext { typedef struct HMACContext {
int whichSha; /* which SHA is being used */ int whichSha; /* which SHA is being used */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int hashSize; /* hash size of SHA being used */ int hashSize; /* hash size of SHA being used */
int blockSize; /* block size of SHA being used */ int blockSize; /* block size of SHA being used */
USHAContext shaContext; /* SHA context */ USHAContext shaContext; /* SHA context */
unsigned char k_opad[USHA_Max_Message_Block_Size]; unsigned char k_opad[USHA_Max_Message_Block_Size];
/* outer padding - key XORd with opad */ /* outer padding - key XORd with opad */
int Computed; /* Is the digest computed? */ int Computed; /* Is the MAC computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Cumulative corruption code */
} HMACContext; } HMACContext;
/* /*
* This structure will hold context information for the HKDF * This structure will hold context information for the HKDF
* Extract-and-Expand Key Derivation functions. * Extract-and-Expand Key Derivation functions.
*/ */
typedef struct HKDFContext { typedef struct HKDFContext {
int whichSha; /* which SHA is being used */ int whichSha; /* which SHA is being used */
HMACContext hmacContext; HMACContext hmacContext;
int hashSize; /* hash size of SHA being used */ int hashSize; /* hash size of SHA being used */
unsigned char prk[USHAMaxHashSize]; unsigned char prk[USHAMaxHashSize];
/* Pseudo Random Key - output of hkdfInput */ /* Pseudo Random Key - output of hkdfInput */
int Computed; /* Is the digest computed? */ int Computed; /* Is the key material computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Cumulative corruption code */
} HKDFContext; } HKDFContext;
/* /*
* Function Prototypes * Function Prototypes
*/ */
/* SHA-1 */ /* SHA-1 */
extern int SHA1Reset(SHA1Context *); extern int SHA1Reset(SHA1Context *);
extern int SHA1Input(SHA1Context *, const uint8_t *bytes, extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
skipping to change at page 26, line 54 skipping to change at page 27, line 4
extern int SHA224Reset(SHA224Context *); extern int SHA224Reset(SHA224Context *);
extern int SHA224Input(SHA224Context *, const uint8_t *bytes, extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
extern int SHA224FinalBits(SHA224Context *, uint8_t bits, extern int SHA224FinalBits(SHA224Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA224Result(SHA224Context *, extern int SHA224Result(SHA224Context *,
uint8_t Message_Digest[SHA224HashSize]); uint8_t Message_Digest[SHA224HashSize]);
/* SHA-256 */ /* SHA-256 */
extern int SHA256Reset(SHA256Context *); extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
extern int SHA256FinalBits(SHA256Context *, uint8_t bits, extern int SHA256FinalBits(SHA256Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA256Result(SHA256Context *, extern int SHA256Result(SHA256Context *,
uint8_t Message_Digest[SHA256HashSize]); uint8_t Message_Digest[SHA256HashSize]);
/* SHA-384 */ /* SHA-384 */
extern int SHA384Reset(SHA384Context *); extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t *bytes, extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
skipping to change at page 27, line 55 skipping to change at page 28, line 5
* for all SHAs. * for all SHAs.
* This interface allows a fixed-length text input to be used. * This interface allows a fixed-length text input to be used.
*/ */
extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */ extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
const unsigned char *text, /* pointer to data stream */ const unsigned char *text, /* pointer to data stream */
int text_len, /* length of data stream */ int text_len, /* length of data stream */
const unsigned char *key, /* pointer to authentication key */ const unsigned char *key, /* pointer to authentication key */
int key_len, /* length of authentication key */ int key_len, /* length of authentication key */
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */ uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
/*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/*
* HMAC Keyed-Hashing for Message Authentication, RFC 2104, * HMAC Keyed-Hashing for Message Authentication, RFC 2104,
* for all SHAs. * for all SHAs.
* This interface allows any length of text input to be used. * This interface allows any length of text input to be used.
*/ */
extern int hmacReset(HMACContext *context, enum SHAversion whichSha, extern int hmacReset(HMACContext *context, enum SHAversion whichSha,
const unsigned char *key, int key_len); const unsigned char *key, int key_len);
extern int hmacInput(HMACContext *context, const unsigned char *text, extern int hmacInput(HMACContext *context, const unsigned char *text,
int text_len); int text_len);
extern int hmacFinalBits(HMACContext *context, uint8_t bits, extern int hmacFinalBits(HMACContext *context, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
skipping to change at page 29, line 13 skipping to change at page 29, line 13
#endif /* _SHA_H_ */ #endif /* _SHA_H_ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8.1.2 sha-private.h 8.1.2 sha-private.h
/************************ sha-private.h ************************/ /************************ sha-private.h ************************/
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
#ifndef _SHA_PRIVATE__H #ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H #define _SHA_PRIVATE__H
/* /*
* These definitions are defined in FIPS-180-2, section 4.1. * These definitions are defined in FIPS 180-3, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1, * Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2 and 4.1.3. * 4.1.2 and 4.1.3.
* *
* The definitions used in FIPS-180-2 are as follows: * The definitions used in FIPS 180-3 are as follows:
*/ */
#ifndef USE_MODIFIED_MACROS #ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* USE_MODIFIED_MACROS */ #else /* USE_MODIFIED_MACROS */
/* /*
* The following definitions are equivalent and potentially faster. * The following definitions are equivalent and potentially faster.
*/ */
skipping to change at page 30, line 13 skipping to change at page 30, line 13
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithm SHA-1 * This file implements the Secure Hash Algorithm SHA-1
* as defined in the National Institute of Standards * as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2 * Publication (FIPS PUB) 180-3 published in October 2008
* published on August 1, 2002, and the FIPS PUB 180-2 Change * and formerly defined in its predecessors, FIPS PUB 180-1
* Notice published on February 28, 2004. * and FIP PUB 180-2.
* *
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-3/fips180-3_final.pdf
* *
* The SHA-1 algorithm produces a 160-bit message digest for a * The SHA-1 algorithm produces a 160-bit message digest for a
* given data stream. It should take about 2**n steps to find a * given data stream. It should take about 2**n steps to find a
* message with the same digest as a given message and * message with the same digest as a given message and
* 2**(n/2) to find any two messages with the same digest, * 2**(n/2) to find any two messages with the same digest,
* when n is the digest size in bits. Therefore, this * when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a * algorithm can serve as a means of providing a
* "fingerprint" for a message. * "fingerprint" for a message.
* *
* Portability Issues: * Portability Issues:
skipping to change at page 31, line 15 skipping to change at page 31, line 15
* Add "length" to the length. * Add "length" to the length.
* Set Corrupted when overflow has occurred. * Set Corrupted when overflow has occurred.
*/ */
static uint32_t addTemp; static uint32_t addTemp;
#define SHA1AddLength(context, length) \ #define SHA1AddLength(context, length) \
(addTemp = (context)->Length_Low, \ (addTemp = (context)->Length_Low, \
(context)->Corrupted = \ (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \ (((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong \ (++(context)->Length_High == 0) ? shaInputTooLong \
: shaSuccess ) : (context)->Corrupted )
/* Local Function Prototypes */ /* Local Function Prototypes */
static void SHA1ProcessMessageBlock(SHA1Context *context);
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte); static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte);
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte); static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte);
static void SHA1ProcessMessageBlock(SHA1Context *context);
/* /*
* SHA1Reset * SHA1Reset
* *
* Description: * Description:
* This function will initialize the SHA1Context in preparation * This function will initialize the SHA1Context in preparation
* for computing a new SHA1 message digest. * for computing a new SHA1 message digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA1Reset(SHA1Context *context) int SHA1Reset(SHA1Context *context)
{ {
if (!context) if (!context) return shaNull;
return shaNull;
context->Length_Low = 0; context->Length_High = context->Length_Low = 0;
context->Length_High = 0; context->Message_Block_Index = 0;
context->Message_Block_Index = 0;
/* Initial Hash Values: FIPS-180-2 section 5.3.1 */ /* Initial Hash Values: FIPS 180-3 section 5.3.1 */
context->Intermediate_Hash[0] = 0x67452301; context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89; context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE; context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476; context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0; context->Intermediate_Hash[4] = 0xC3D2E1F0;
context->Computed = 0; context->Computed = 0;
context->Corrupted = 0; context->Corrupted = shaSuccess;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return shaSuccess; return shaSuccess;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* SHA1Input * SHA1Input
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA1Input(SHA1Context *context, int SHA1Input(SHA1Context *context,
const uint8_t *message_array, unsigned length) const uint8_t *message_array, unsigned length)
{ {
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (!message_array) return shaNull;
if (!context || !message_array)
return shaNull;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
while (length-- && !context->Corrupted) { while (length--) {
context->Message_Block[context->Message_Block_Index++] = context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF); *message_array;
if ((SHA1AddLength(context, 8) == shaSuccess) && if ((SHA1AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA1_Message_Block_Size)) (context->Message_Block_Index == SHA1_Message_Block_Size))
SHA1ProcessMessageBlock(context); SHA1ProcessMessageBlock(context);
message_array++; message_array++;
} }
return context->Corrupted; return context->Corrupted;
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* SHA1FinalBits * SHA1FinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA1FinalBits(SHA1Context *context, uint8_t message_bits, int SHA1FinalBits(SHA1Context *context, uint8_t message_bits,
unsigned int length) unsigned int length)
{ {
uint8_t masks[8] = { static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
}; };
uint8_t markbit[8] = { static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
}; };
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (!context)
return shaNull;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
if (length >= 8) return context->Corrupted = shaBadParam;
if ((length >= 8) || (length == 0))
return context->Corrupted = shaBadParam;
if (context->Corrupted)
return context->Corrupted;
SHA1AddLength(context, length); SHA1AddLength(context, length);
SHA1Finalize(context, SHA1Finalize(context,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
(uint8_t) ((message_bits & masks[length]) | markbit[length])); (uint8_t) ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted; return context->Corrupted;
} }
/* /*
* SHA1Result * SHA1Result
* *
* Description: * Description:
* This function will return the 160-bit message digest * This function will return the 160-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 19. * the last octet of hash in the element with index 19.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA-1 hash. * The context to use to calculate the SHA-1 hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA1Result(SHA1Context *context, int SHA1Result(SHA1Context *context,
uint8_t Message_Digest[SHA1HashSize]) uint8_t Message_Digest[SHA1HashSize])
{ {
int i; int i;
if (!context || !Message_Digest) if (!context) return shaNull;
return shaNull; if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed) if (!context->Computed)
SHA1Finalize(context, 0x80); SHA1Finalize(context, 0x80);
for (i = 0; i < SHA1HashSize; ++i) for (i = 0; i < SHA1HashSize; ++i)
Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2] Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2]
>> 8 * ( 3 - ( i & 0x03 ) )); >> (8 * ( 3 - ( i & 0x03 ) )));
return shaSuccess; return shaSuccess;
} }
/* /*
* SHA1Finalize
*
* Description:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*
*/
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
{
int i;
SHA1PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */
for (i = 0; i < SHA1_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 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 helper function will pad
* the message according to those rules by filling the Message_Block
* array accordingly. When it returns, it can be assumed that the
* message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
{
/*
* 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 >= (SHA1_Message_Block_Size - 8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA1_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low);
SHA1ProcessMessageBlock(context);
}
/*
* SHA1ProcessMessageBlock * SHA1ProcessMessageBlock
* *
* Description: * Description:
* This helper function will process the next 512 bits of the * This helper function will process the next 512 bits of the
* message stored in the Message_Block array. * message stored in the Message_Block array.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* *
* Returns: * Returns:
* Nothing. * Nothing.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Comments: * Comments:
* Many of the variable names in this code, especially the * Many of the variable names in this code, especially the
* single character names, were used because those were the * single character names, were used because those were the
* names used in the publication. * names used in the Secure Hash Standard.
*/ */
static void SHA1ProcessMessageBlock(SHA1Context *context) static void SHA1ProcessMessageBlock(SHA1Context *context)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ {
/* Constants defined in FIPS-180-2, section 4.2.1 */ /* Constants defined in FIPS 180-3, section 4.2.1 */
const uint32_t K[4] = { const uint32_t K[4] = {
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
}; };
int t; /* Loop counter */ int t; /* Loop counter */
uint32_t temp; /* Temporary word value */ uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */ uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */ uint32_t A, B, C, D, E; /* Word buffers */
/* /*
* Initialize the first 16 words in the array W * Initialize the first 16 words in the array W
skipping to change at page 38, line 4 skipping to change at page 35, line 50
B = A; B = A;
A = temp; A = temp;
} }
for (t = 20; t < 40; t++) { for (t = 20; t < 40; t++) {
temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1]; temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
E = D; E = D;
D = C; D = C;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
A = temp; A = temp;
} }
for (t = 40; t < 60; t++) { for (t = 40; t < 60; t++) {
temp = SHA1_ROTL(5,A) + SHA_Maj(B, C, D) + E + W[t] + K[2]; temp = SHA1_ROTL(5,A) + SHA_Maj(B, C, D) + E + W[t] + K[2];
E = D; E = D;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
D = C; D = C;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
A = temp; A = temp;
} }
for (t = 60; t < 80; t++) { for (t = 60; t < 80; t++) {
temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[3]; temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[3];
E = D; E = D;
D = C; D = C;
skipping to change at page 38, line 37 skipping to change at page 36, line 31
context->Intermediate_Hash[0] += A; context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B; context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C; context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D; context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E; context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
} }
/*
* SHA1Finalize
*
* Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*
*/
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
{
int i;
SHA1PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */
for (i = 0; i < SHA1_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Length_High = 0; /* and clear length */
context->Length_Low = 0;
context->Computed = 1;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 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 helper function will pad
* the message according to those rules by filling the Message_Block
* array accordingly. When it returns, it can be assumed that the
* message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
{
/*
* 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 >= (SHA1_Message_Block_Size - 8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA1_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low);
SHA1ProcessMessageBlock(context);
}
8.2.2 sha224-256.c 8.2.2 sha224-256.c
/************************* sha224-256.c ************************/ /************************* sha224-256.c ************************/
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithms SHA-224 and * This file implements the Secure Hash Algorithms SHA-224 and
* SHA-256 as defined in the National Institute of Standards * SHA-256 as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-2 published on August 1, 2002, and * Publication (FIPS PUB) 180-3 published in October 2008
* the FIPS PUB 180-2 Change Notice published on February 28, 2004. * and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2.
* *
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-3/fips180-3_final.pdf
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* fips180-2/fips180-2withchangenotice.pdf
* *
* The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
* message digests for a given data stream. It should take about * message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given * 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 * message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this * digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a * algorithm can serve as a means of providing a
* "fingerprint" for a message. * "fingerprint" for a message.
* *
* Portability Issues: * Portability Issues:
* SHA-224 and SHA-256 are defined in terms of 32-bit "words". * SHA-224 and SHA-256 are defined in terms of 32-bit "words".
* This code uses <stdint.h> (included via "sha.h") to define 32 * This code uses <stdint.h> (included via "sha.h") to define 32
* and 8 bit unsigned integer types. If your C compiler does not * and 8 bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not * support 32 bit unsigned integers, this code is not
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* appropriate. * appropriate.
* *
* Caveats: * Caveats:
* SHA-224 and SHA-256 are designed to work with messages less * SHA-224 and SHA-256 are designed to work with messages less
* than 2^64 bits long. This implementation uses SHA224/256Input() * than 2^64 bits long. This implementation uses SHA224/256Input()
* to hash the bits that are a multiple of the size of an 8-bit * to hash the bits that are a multiple of the size of an 8-bit
* octet, and then optionally uses SHA224/256FinalBits() * octet, and then optionally uses SHA224/256FinalBits()
* to hash the final few bits of the input. * to hash the final few bits of the input.
*/ */
skipping to change at page 40, line 4 skipping to change at page 39, line 42
#define SHA256_sigma0(word) \ #define SHA256_sigma0(word) \
(SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word)) (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
#define SHA256_sigma1(word) \ #define SHA256_sigma1(word) \
(SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word)) (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
/* /*
* Add "length" to the length. * Add "length" to the length.
* Set Corrupted when overflow has occurred. * Set Corrupted when overflow has occurred.
*/ */
static uint32_t addTemp; static uint32_t addTemp;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define SHA224_256AddLength(context, length) \ #define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \ (addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \ (((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong : \ (++(context)->Length_High == 0) ? shaInputTooLong : \
shaSuccess ) (context)->Corrupted )
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
static void SHA224_256ProcessMessageBlock(SHA256Context *context);
static void SHA224_256Finalize(SHA256Context *context, static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA224_256PadMessage(SHA256Context *context, static void SHA224_256PadMessage(SHA256Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA224_256ProcessMessageBlock(SHA256Context *context);
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
static int SHA224_256ResultN(SHA256Context *context, static int SHA224_256ResultN(SHA256Context *context,
uint8_t Message_Digest[ ], int HashSize); uint8_t Message_Digest[ ], int HashSize);
/* Initial Hash Values: FIPS-180-2 Change Notice 1 */ INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
static uint32_t SHA224_H0[SHA256HashSize/4] = { static uint32_t SHA224_H0[SHA256HashSize/4] = {
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
}; };
/* Initial Hash Values: FIPS-180-2 section 5.3.2 */ /* Initial Hash Values: FIPS 180-3 section 5.3.3 */
static uint32_t SHA256_H0[SHA256HashSize/4] = { static uint32_t SHA256_H0[SHA256HashSize/4] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
}; };
/* /*
* SHA224Reset * SHA224Reset
* *
* Description: * Description:
* This function will initialize the SHA224Context in preparation * This function will initialize the SHA224Context in preparation
skipping to change at page 41, line 4 skipping to change at page 40, line 41
* sha Error Code. * sha Error Code.
*/ */
int SHA224Reset(SHA224Context *context) int SHA224Reset(SHA224Context *context)
{ {
return SHA224_256Reset(context, SHA224_H0); return SHA224_256Reset(context, SHA224_H0);
} }
/* /*
* SHA224Input * SHA224Input
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
int SHA224Input(SHA224Context *context, const uint8_t *message_array, int SHA224Input(SHA224Context *context, const uint8_t *message_array,
unsigned int length) unsigned int length)
{ {
return SHA256Input(context, message_array, length); return SHA256Input(context, message_array, length);
} }
/* /*
* SHA224FinalBits * SHA224FinalBits
* *
skipping to change at page 42, line 4 skipping to change at page 41, line 41
* sha Error Code. * sha Error Code.
*/ */
int SHA224FinalBits(SHA224Context *context, int SHA224FinalBits(SHA224Context *context,
uint8_t message_bits, unsigned int length) uint8_t message_bits, unsigned int length)
{ {
return SHA256FinalBits(context, message_bits, length); return SHA256FinalBits(context, message_bits, length);
} }
/* /*
* SHA224Result * SHA224Result
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Description: * Description:
* This function will return the 224-bit message digest * This function will return the 224-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 27. * the last octet of hash in the element with index 27.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
int SHA224Result(SHA224Context *context, int SHA224Result(SHA224Context *context,
uint8_t Message_Digest[SHA224HashSize]) uint8_t Message_Digest[SHA224HashSize])
{ {
return SHA224_256ResultN(context, Message_Digest, SHA224HashSize); return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
} }
/* /*
* SHA256Reset * SHA256Reset
* *
skipping to change at page 43, line 4 skipping to change at page 42, line 41
} }
/* /*
* SHA256Input * SHA256Input
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA256Input(SHA256Context *context, const uint8_t *message_array, int SHA256Input(SHA256Context *context, const uint8_t *message_array,
unsigned int length) unsigned int length)
{ {
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (!context || !message_array)
return shaNull;
if (context->Computed) INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return context->Corrupted = shaStateError;
if (context->Corrupted) if (!message_array) return shaNull;
return context->Corrupted; if (context->Computed) return context->Corrupted = shaStateError;
if (context->Corrupted) return context->Corrupted;
while (length-- && !context->Corrupted) { while (length--) {
context->Message_Block[context->Message_Block_Index++] = context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF); *message_array;
if ((SHA224_256AddLength(context, 8) == shaSuccess) && if ((SHA224_256AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA256_Message_Block_Size)) (context->Message_Block_Index == SHA256_Message_Block_Size))
SHA224_256ProcessMessageBlock(context); SHA224_256ProcessMessageBlock(context);
message_array++; message_array++;
} }
return context->Corrupted; return context->Corrupted;
skipping to change at page 44, line 4 skipping to change at page 43, line 35
/* /*
* SHA256FinalBits * SHA256FinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA256FinalBits(SHA256Context *context, int SHA256FinalBits(SHA256Context *context,
uint8_t message_bits, unsigned int length) uint8_t message_bits, unsigned int length)
{ {
uint8_t masks[8] = { static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
}; };
uint8_t markbit[8] = { static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
}; };
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (!context) if (context->Computed) return context->Corrupted = shaStateError;
return shaNull; if (length >= 8) return context->Corrupted = shaBadParam;
if (context->Computed)
return context->Corrupted = shaStateError;
if ((length >= 8) || (length == 0))
return context->Corrupted = shaBadParam;
if (context->Corrupted)
return context->Corrupted;
SHA224_256AddLength(context, length); SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t) SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length])); ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted; return context->Corrupted;
} }
/* /*
* SHA256Result * SHA256Result
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Description: * Description:
* This function will return the 256-bit message digest * This function will return the 256-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 31. * the last octet of hash in the element with index 31.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA256Result(SHA256Context *context, int SHA256Result(SHA256Context *context,
uint8_t Message_Digest[SHA256HashSize]) uint8_t Message_Digest[SHA256HashSize])
{ {
return SHA224_256ResultN(context, Message_Digest, SHA256HashSize); return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
} }
/* /*
* SHA224_256Finalize * SHA224_256Reset
* *
* Description: * Description:
* This helper function finishes off the digest calculations. * This helper function will initialize the SHA256Context in
* preparation for computing a new SHA-224 or SHA-256 message digest.
* *
* Parameters: * Parameters:
* context: [in/out]
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*/
static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte)
{
int i;
SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_Low = 0; /* and clear length */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Length_High = 0;
context->Computed = 1;
}
/*
* SHA224_256PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 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 helper function will pad
* the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
* Parameters:
* context: [in/out] * context: [in/out]
* The context to pad * The context to reset.
* Pad_Byte: [in] * H0[ ]: [in]
* The last byte to add to the digest before the 0-padding * The initial hash value array to use.
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* Nothing. * sha Error Code.
*/ */
static void SHA224_256PadMessage(SHA256Context *context, static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
uint8_t Pad_Byte)
{ {
/* if (!context) return shaNull;
* 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 >= (SHA256_Message_Block_Size-8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
context->Message_Block[context->Message_Block_Index++] = 0;
/* context->Length_High = context->Length_Low = 0;
* Store the message length as the last 8 octets context->Message_Block_Index = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF context->Intermediate_Hash[0] = H0[0];
context->Intermediate_Hash[1] = H0[1];
context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7];
*/ context->Computed = 0;
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24); context->Corrupted = shaSuccess;
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context); return shaSuccess;
} }
/* /*
* SHA224_256ProcessMessageBlock * SHA224_256ProcessMessageBlock
* *
* Description: * Description:
* This helper function will process the next 512 bits of the * This helper function will process the next 512 bits of the
* message stored in the Message_Block array. * message stored in the Message_Block array.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* *
* Returns: * Returns:
* Nothing. * Nothing.
* *
* Comments: * Comments:
* Many of the variable names in this code, especially the * Many of the variable names in this code, especially the
* single character names, were used because those were the * single character names, were used because those were the
* names used in the publication. * names used in the Secure Hash Standard.
*/ */
static void SHA224_256ProcessMessageBlock(SHA256Context *context) static void SHA224_256ProcessMessageBlock(SHA256Context *context)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ {
/* Constants defined in FIPS-180-2, section 4.2.2 */ /* Constants defined in FIPS 180-3, section 4.2.2 */
static const uint32_t K[64] = { static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
}; };
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int t, t4; /* Loop counter */ int t, t4; /* Loop counter */
uint32_t temp1, temp2; /* Temporary word value */ uint32_t temp1, temp2; /* Temporary word value */
uint32_t W[64]; /* Word sequence */ uint32_t W[64]; /* Word sequence */
uint32_t A, B, C, D, E, F, G, H; /* Word buffers */ uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
/* /*
* Initialize the first 16 words in the array W * Initialize the first 16 words in the array W
*/ */
for (t = t4 = 0; t < 16; t++, t4 += 4) for (t = t4 = 0; t < 16; t++, t4 += 4)
W[t] = (((uint32_t)context->Message_Block[t4]) << 24) | W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
skipping to change at page 48, line 40 skipping to change at page 47, line 4
F = context->Intermediate_Hash[5]; F = context->Intermediate_Hash[5];
G = context->Intermediate_Hash[6]; G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7]; H = context->Intermediate_Hash[7];
for (t = 0; t < 64; t++) { for (t = 0; t < 64; t++) {
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C); temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C);
H = G; H = G;
G = F; G = F;
F = E; F = E;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
E = D + temp1; E = D + temp1;
D = C; D = C;
C = B; C = B;
B = A; B = A;
A = temp1 + temp2; A = temp1 + temp2;
} }
context->Intermediate_Hash[0] += A; context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B; context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C; context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D; context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E; context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F; context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G; context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H; context->Intermediate_Hash[7] += H;
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
* SHA224_256Reset * SHA224_256Finalize
* *
* Description: * Description:
* This helper function will initialize the SHA256Context in * This helper function finishes off the digest calculations.
* preparation for computing a new SHA-224 or SHA-256 message digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The SHA context to update
* H0 * Pad_Byte: [in]
* The initial hash value to use. * The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0) static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte)
{ {
if (!context) int i;
return shaNull; SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_High = 0; /* and clear length */
context->Length_Low = 0;
context->Computed = 1;
}
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Length_Low = 0; /*
context->Length_High = 0; * SHA224_256PadMessage
context->Message_Block_Index = 0; *
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 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 helper function will pad
* the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void SHA224_256PadMessage(SHA256Context *context,
uint8_t Pad_Byte)
{
/*
* 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 >= (SHA256_Message_Block_Size-8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
context->Intermediate_Hash[0] = H0[0]; while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
context->Intermediate_Hash[1] = H0[1]; context->Message_Block[context->Message_Block_Index++] = 0;
context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7];
context->Computed = 0; /*
context->Corrupted = 0; * Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
return shaSuccess; INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context);
} }
/* /*
* SHA224_256ResultN * SHA224_256ResultN
* *
* Description: * Description:
* This helper function will return the 224-bit or 256-bit message * This helper function will return the 224-bit or 256-bit message
* digest into the Message_Digest array provided by the caller. * digest into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* the last octet of hash in the element with index 27/31. * the last octet of hash in the element with index 27/31.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* HashSize: [in] * HashSize: [in]
* The size of the hash, either 28 or 32. * The size of the hash, either 28 or 32.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
static int SHA224_256ResultN(SHA256Context *context, static int SHA224_256ResultN(SHA256Context *context,
uint8_t Message_Digest[ ], int HashSize) uint8_t Message_Digest[ ], int HashSize)
{ {
int i; int i;
if (!context || !Message_Digest) if (!context) return shaNull;
return shaNull; if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed) if (!context->Computed)
SHA224_256Finalize(context, 0x80); SHA224_256Finalize(context, 0x80);
for (i = 0; i < HashSize; ++i) for (i = 0; i < HashSize; ++i)
Message_Digest[i] = (uint8_t) Message_Digest[i] = (uint8_t)
(context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) )); (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
return shaSuccess; return shaSuccess;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8.2.3 sha384-512.c 8.2.3 sha384-512.c
/************************* sha384-512.c ************************/ /************************* sha384-512.c ************************/
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithms SHA-384 and * This file implements the Secure Hash Algorithms SHA-384 and
* SHA-512 as defined in the National Institute of Standards * SHA-512 as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-2 published on August 1, 2002, and * Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF * and FIP PUB 180-2.
* the FIPS PUB 180-2 Change Notice published on February 28, 2004.
* *
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-3/fips180-3_final.pdf
* *
* The SHA-384 and SHA-512 algorithms produce 384-bit and 512-bit * The SHA-384 and SHA-512 algorithms produce 384-bit and 512-bit
* message digests for a given data stream. It should take about * message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given * 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 * message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this * digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a * algorithm can serve as a means of providing a
* "fingerprint" for a message. * "fingerprint" for a message.
* *
* Portability Issues: * Portability Issues:
skipping to change at page 51, line 40 skipping to change at page 50, line 54
* Caveats: * Caveats:
* SHA-384 and SHA-512 are designed to work with messages less * SHA-384 and SHA-512 are designed to work with messages less
* than 2^128 bits long. This implementation uses SHA384/512Input() * than 2^128 bits long. This implementation uses SHA384/512Input()
* to hash the bits that are a multiple of the size of an 8-bit * to hash the bits that are a multiple of the size of an 8-bit
* octet, and then optionally uses SHA384/256FinalBits() * octet, and then optionally uses SHA384/256FinalBits()
* to hash the final few bits of the input. * to hash the final few bits of the input.
* *
*/ */
#include "sha.h" #include "sha.h"
#include "sha-private.h"
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Define 64-bit arithmetic in terms of 32-bit arithmetic. * Define 64-bit arithmetic in terms of 32-bit arithmetic.
* Each 64-bit number is represented in a 2-word array. * Each 64-bit number is represented in a 2-word array.
* All macros are defined such that the result is the last parameter. * All macros are defined such that the result is the last parameter.
*/ */
/* /*
* Define shift, rotate left and rotate right functions * Define shift, rotate left and rotate right functions
*/ */
#define SHA512_SHR(bits, word, ret) ( \ #define SHA512_SHR(bits, word, ret) ( \
/* (((uint64_t)((word))) >> (bits)) */ \ /* (((uint64_t)((word))) >> (bits)) */ \
(ret)[0] = (((bits) < 32) && ((bits) >= 0)) ? \ (ret)[0] = (((bits) < 32) && ((bits) >= 0)) ? \
((word)[0] >> (bits)) : 0, \ ((word)[0] >> (bits)) : 0, \
(ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) : \ (ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) : \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
((bits) == 32) ? (word)[0] : \ ((bits) == 32) ? (word)[0] : \
((bits) >= 0) ? \ ((bits) >= 0) ? \
(((word)[0] << (32 - (bits))) | \ (((word)[0] << (32 - (bits))) | \
((word)[1] >> (bits))) : 0 ) ((word)[1] >> (bits))) : 0 )
#define SHA512_SHL(bits, word, ret) ( \ #define SHA512_SHL(bits, word, ret) ( \
/* (((uint64_t)(word)) << (bits)) */ \ /* (((uint64_t)(word)) << (bits)) */ \
(ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \ (ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \
((bits) == 32) ? (word)[1] : \ ((bits) == 32) ? (word)[1] : \
((bits) >= 0) ? \ ((bits) >= 0) ? \
skipping to change at page 52, line 44 skipping to change at page 52, line 5
(ret)[0] = (word1)[0] ^ (word2)[0], \ (ret)[0] = (word1)[0] ^ (word2)[0], \
(ret)[1] = (word1)[1] ^ (word2)[1] ) (ret)[1] = (word1)[1] ^ (word2)[1] )
/* /*
* Define 64-bit AND * Define 64-bit AND
*/ */
#define SHA512_AND(word1, word2, ret) ( \ #define SHA512_AND(word1, word2, ret) ( \
(ret)[0] = (word1)[0] & (word2)[0], \ (ret)[0] = (word1)[0] & (word2)[0], \
(ret)[1] = (word1)[1] & (word2)[1] ) (ret)[1] = (word1)[1] & (word2)[1] )
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Define 64-bit TILDA * Define 64-bit TILDA
*/ */
#define SHA512_TILDA(word, ret) \ #define SHA512_TILDA(word, ret) \
( (ret)[0] = ~(word)[0], (ret)[1] = ~(word)[1] ) ( (ret)[0] = ~(word)[0], (ret)[1] = ~(word)[1] )
/* /*
* Define 64-bit ADD * Define 64-bit ADD
*/ */
#define SHA512_ADD(word1, word2, ret) ( \ #define SHA512_ADD(word1, word2, ret) ( \
(ret)[1] = (word1)[1], (ret)[1] += (word2)[1], \ (ret)[1] = (word1)[1], (ret)[1] += (word2)[1], \
(ret)[0] = (word1)[0] + (word2)[0] + ((ret)[1] < (word1)[1]) ) (ret)[0] = (word1)[0] + (word2)[0] + ((ret)[1] < (word1)[1]) )
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Add the 4word value in word2 to word1. * Add the 4word value in word2 to word1.
*/ */
static uint32_t ADDTO4_temp, ADDTO4_temp2; static uint32_t ADDTO4_temp, ADDTO4_temp2;
#define SHA512_ADDTO4(word1, word2) ( \ #define SHA512_ADDTO4(word1, word2) ( \
ADDTO4_temp = (word1)[3], \ ADDTO4_temp = (word1)[3], \
(word1)[3] += (word2)[3], \ (word1)[3] += (word2)[3], \
ADDTO4_temp2 = (word1)[2], \ ADDTO4_temp2 = (word1)[2], \
(word1)[2] += (word2)[2] + ((word1)[3] < ADDTO4_temp), \ (word1)[2] += (word2)[2] + ((word1)[3] < ADDTO4_temp), \
ADDTO4_temp = (word1)[1], \ ADDTO4_temp = (word1)[1], \
skipping to change at page 53, line 40 skipping to change at page 52, line 53
* SHA rotate ((word >> bits) | (word << (64-bits))) * SHA rotate ((word >> bits) | (word << (64-bits)))
*/ */
static uint32_t ROTR_temp1[2], ROTR_temp2[2]; static uint32_t ROTR_temp1[2], ROTR_temp2[2];
#define SHA512_ROTR(bits, word, ret) ( \ #define SHA512_ROTR(bits, word, ret) ( \
SHA512_SHR((bits), (word), ROTR_temp1), \ SHA512_SHR((bits), (word), ROTR_temp1), \
SHA512_SHL(64-(bits), (word), ROTR_temp2), \ SHA512_SHL(64-(bits), (word), ROTR_temp2), \
SHA512_OR(ROTR_temp1, ROTR_temp2, (ret)) ) SHA512_OR(ROTR_temp1, ROTR_temp2, (ret)) )
/* /*
* Define the SHA SIGMA and sigma macros * Define the SHA SIGMA and sigma macros
*
* SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word) * SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)
*/ */
static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2], static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2],
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SIGMA0_temp3[2], SIGMA0_temp4[2]; SIGMA0_temp3[2], SIGMA0_temp4[2];
#define SHA512_SIGMA0(word, ret) ( \ #define SHA512_SIGMA0(word, ret) ( \
SHA512_ROTR(28, (word), SIGMA0_temp1), \ SHA512_ROTR(28, (word), SIGMA0_temp1), \
SHA512_ROTR(34, (word), SIGMA0_temp2), \ SHA512_ROTR(34, (word), SIGMA0_temp2), \
SHA512_ROTR(39, (word), SIGMA0_temp3), \ SHA512_ROTR(39, (word), SIGMA0_temp3), \
SHA512_XOR(SIGMA0_temp2, SIGMA0_temp3, SIGMA0_temp4), \ SHA512_XOR(SIGMA0_temp2, SIGMA0_temp3, SIGMA0_temp4), \
SHA512_XOR(SIGMA0_temp1, SIGMA0_temp4, (ret)) ) SHA512_XOR(SIGMA0_temp1, SIGMA0_temp4, (ret)) )
/* /*
* SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word) * SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word)
*/ */
static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2], static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2],
SIGMA1_temp3[2], SIGMA1_temp4[2]; SIGMA1_temp3[2], SIGMA1_temp4[2];
#define SHA512_SIGMA1(word, ret) ( \ #define SHA512_SIGMA1(word, ret) ( \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SHA512_ROTR(14, (word), SIGMA1_temp1), \ SHA512_ROTR(14, (word), SIGMA1_temp1), \
SHA512_ROTR(18, (word), SIGMA1_temp2), \ SHA512_ROTR(18, (word), SIGMA1_temp2), \
SHA512_ROTR(41, (word), SIGMA1_temp3), \ SHA512_ROTR(41, (word), SIGMA1_temp3), \
SHA512_XOR(SIGMA1_temp2, SIGMA1_temp3, SIGMA1_temp4), \ SHA512_XOR(SIGMA1_temp2, SIGMA1_temp3, SIGMA1_temp4), \
SHA512_XOR(SIGMA1_temp1, SIGMA1_temp4, (ret)) ) SHA512_XOR(SIGMA1_temp1, SIGMA1_temp4, (ret)) )
/* /*
* (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word)) * (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
*/ */
static uint32_t sigma0_temp1[2], sigma0_temp2[2], static uint32_t sigma0_temp1[2], sigma0_temp2[2],
skipping to change at page 54, line 36 skipping to change at page 53, line 50
*/ */
static uint32_t sigma1_temp1[2], sigma1_temp2[2], static uint32_t sigma1_temp1[2], sigma1_temp2[2],
sigma1_temp3[2], sigma1_temp4[2]; sigma1_temp3[2], sigma1_temp4[2];
#define SHA512_sigma1(word, ret) ( \ #define SHA512_sigma1(word, ret) ( \
SHA512_ROTR(19, (word), sigma1_temp1), \ SHA512_ROTR(19, (word), sigma1_temp1), \
SHA512_ROTR(61, (word), sigma1_temp2), \ SHA512_ROTR(61, (word), sigma1_temp2), \
SHA512_SHR( 6, (word), sigma1_temp3), \ SHA512_SHR( 6, (word), sigma1_temp3), \
SHA512_XOR(sigma1_temp2, sigma1_temp3, sigma1_temp4), \ SHA512_XOR(sigma1_temp2, sigma1_temp3, sigma1_temp4), \
SHA512_XOR(sigma1_temp1, sigma1_temp4, (ret)) ) SHA512_XOR(sigma1_temp1, sigma1_temp4, (ret)) )
#undef SHA_Ch
#undef SHA_Maj
#ifndef USE_MODIFIED_MACROS #ifndef USE_MODIFIED_MACROS
/* /*
* These definitions are the ones used in FIPS-180-2, section 4.1.3 * These definitions are the ones used in FIPS 180-3, section 4.1.3
* Ch(x,y,z) ((x & y) ^ (~x & z)) * Ch(x,y,z) ((x & y) ^ (~x & z))
*/ */
static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2]; static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define SHA_Ch(x, y, z, ret) ( \ #define SHA_Ch(x, y, z, ret) ( \
SHA512_AND(x, y, Ch_temp1), \ SHA512_AND(x, y, Ch_temp1), \
SHA512_TILDA(x, Ch_temp2), \ SHA512_TILDA(x, Ch_temp2), \
SHA512_AND(Ch_temp2, z, Ch_temp3), \ SHA512_AND(Ch_temp2, z, Ch_temp3), \
SHA512_XOR(Ch_temp1, Ch_temp3, (ret)) ) SHA512_XOR(Ch_temp1, Ch_temp3, (ret)) )
/* /*
* Maj(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z))) * Maj(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
*/ */
static uint32_t Maj_temp1[2], Maj_temp2[2], static uint32_t Maj_temp1[2], Maj_temp2[2],
Maj_temp3[2], Maj_temp4[2]; Maj_temp3[2], Maj_temp4[2];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define SHA_Maj(x, y, z, ret) ( \ #define SHA_Maj(x, y, z, ret) ( \
SHA512_AND(x, y, Maj_temp1), \ SHA512_AND(x, y, Maj_temp1), \
SHA512_AND(x, z, Maj_temp2), \ SHA512_AND(x, z, Maj_temp2), \
SHA512_AND(y, z, Maj_temp3), \ SHA512_AND(y, z, Maj_temp3), \
SHA512_XOR(Maj_temp2, Maj_temp3, Maj_temp4), \ SHA512_XOR(Maj_temp2, Maj_temp3, Maj_temp4), \
SHA512_XOR(Maj_temp1, Maj_temp4, (ret)) ) SHA512_XOR(Maj_temp1, Maj_temp4, (ret)) )
#else /* !USE_MODIFIED_MACROS */ #else /* !USE_MODIFIED_MACROS */
/* /*
* These definitions are potentially faster equivalents for the ones * These definitions are potentially faster equivalents for the ones
* used in FIPS-180-2, section 4.1.3. * used in FIPS 180-3, section 4.1.3.
* ((x & y) ^ (~x & z)) becomes * ((x & y) ^ (~x & z)) becomes
* ((x & (y ^ z)) ^ z) * ((x & (y ^ z)) ^ z)
*/ */
#define SHA_Ch(x, y, z, ret) ( \ #define SHA_Ch(x, y, z, ret) ( \
(ret)[0] = (((x)[0] & ((y)[0] ^ (z)[0])) ^ (z)[0]), \ (ret)[0] = (((x)[0] & ((y)[0] ^ (z)[0])) ^ (z)[0]), \
(ret)[1] = (((x)[1] & ((y)[1] ^ (z)[1])) ^ (z)[1]) ) (ret)[1] = (((x)[1] & ((y)[1] ^ (z)[1])) ^ (z)[1]) )
/* /*
* ((x & y) ^ (x & z) ^ (y & z)) becomes * ((x & y) ^ (x & z) ^ (y & z)) becomes
* ((x & (y | z)) | (y & z)) * ((x & (y | z)) | (y & z))
skipping to change at page 55, line 43 skipping to change at page 54, line 53
/* /*
* Add "length" to the length. * Add "length" to the length.
* Set Corrupted when overflow has occurred. * Set Corrupted when overflow has occurred.
*/ */
static uint32_t addTemp[4] = { 0, 0, 0, 0 }; static uint32_t addTemp[4] = { 0, 0, 0, 0 };
#define SHA384_512AddLength(context, length) ( \ #define SHA384_512AddLength(context, length) ( \
addTemp[3] = (length), SHA512_ADDTO4((context)->Length, addTemp), \ addTemp[3] = (length), SHA512_ADDTO4((context)->Length, addTemp), \
(context)->Corrupted = (((context)->Length[3] < (length)) && \ (context)->Corrupted = (((context)->Length[3] < (length)) && \
((context)->Length[2] == 0) && ((context)->Length[1] == 0) && \ ((context)->Length[2] == 0) && ((context)->Length[1] == 0) && \
((context)->Length[0] == 0)) ? shaInputTooLong : shaSuccess ) ((context)->Length[0] == 0)) ? shaInputTooLong : \
(context)->Corrupted )
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA384_512Reset(SHA512Context *context,
uint32_t H0[SHA512HashSize/4]);
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static void SHA384_512Finalize(SHA512Context *context, static void SHA384_512Finalize(SHA512Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA384_512PadMessage(SHA512Context *context, static void SHA384_512PadMessage(SHA512Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static int SHA384_512Reset(SHA512Context *context,
uint32_t H0[SHA512HashSize/4]);
static int SHA384_512ResultN( SHA512Context *context, static int SHA384_512ResultN( SHA512Context *context,
uint8_t Message_Digest[ ], int HashSize); uint8_t Message_Digest[ ], int HashSize);
/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */ /* Initial Hash Values: FIPS 180-3 sections 5.3.4 and 5.3.5 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
static uint32_t SHA384_H0[SHA512HashSize/4] = { static uint32_t SHA384_H0[SHA512HashSize/4] = {
0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A, 0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A,
0x3070DD17, 0x152FECD8, 0xF70E5939, 0x67332667, 0xFFC00B31, 0x3070DD17, 0x152FECD8, 0xF70E5939, 0x67332667, 0xFFC00B31,
0x8EB44A87, 0x68581511, 0xDB0C2E0D, 0x64F98FA7, 0x47B5481D, 0x8EB44A87, 0x68581511, 0xDB0C2E0D, 0x64F98FA7, 0x47B5481D,
0xBEFA4FA4 0xBEFA4FA4
}; };
static uint32_t SHA512_H0[SHA512HashSize/4] = { static uint32_t SHA512_H0[SHA512HashSize/4] = {
0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B, 0x3C6EF372, 0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B, 0x3C6EF372,
0xFE94F82B, 0xA54FF53A, 0x5F1D36F1, 0x510E527F, 0xADE682D1, 0xFE94F82B, 0xA54FF53A, 0x5F1D36F1, 0x510E527F, 0xADE682D1,
0x9B05688C, 0x2B3E6C1F, 0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19, 0x9B05688C, 0x2B3E6C1F, 0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19,
0x137E2179 0x137E2179
}; };
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
#include "sha-private.h"
/* Define the SHA shift, rotate left and rotate right macro */ /* Define the SHA shift, rotate left and rotate right macro */
#define SHA512_SHR(bits,word) (((uint64_t)(word)) >> (bits)) #define SHA512_SHR(bits,word) (((uint64_t)(word)) >> (bits))
#define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \ #define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \
(((uint64_t)(word)) << (64-(bits)))) (((uint64_t)(word)) << (64-(bits))))
/* Define the SHA SIGMA and sigma macros */ /*
* Define the SHA SIGMA and sigma macros
*
* SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)
*/
#define SHA512_SIGMA0(word) \ #define SHA512_SIGMA0(word) \
(SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)) (SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word))
#define SHA512_SIGMA1(word) \ #define SHA512_SIGMA1(word) \
(SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word)) (SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word))
#define SHA512_sigma0(word) \ #define SHA512_sigma0(word) \
(SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word)) (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
#define SHA512_sigma1(word) \ #define SHA512_sigma1(word) \
(SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word)) (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word))
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Add "length" to the length. * Add "length" to the length.
* Set Corrupted when overflow has occurred. * Set Corrupted when overflow has occurred.
*/ */
static uint64_t addTemp; static uint64_t addTemp;
#define SHA384_512AddLength(context, length) \ #define SHA384_512AddLength(context, length) \
(addTemp = context->Length_Low, context->Corrupted = \ (addTemp = context->Length_Low, context->Corrupted = \
((context->Length_Low += length) < addTemp) && \ ((context->Length_Low += length) < addTemp) && \
(++context->Length_High == 0) ? 1 : 0) (++context->Length_High == 0) ? shaInputTooLong : \
(context)->Corrupted)
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA384_512Reset(SHA512Context *context,
uint64_t H0[SHA512HashSize/8]);
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static void SHA384_512Finalize(SHA512Context *context, static void SHA384_512Finalize(SHA512Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA384_512PadMessage(SHA512Context *context, static void SHA384_512PadMessage(SHA512Context *context,
uint8_t Pad_Byte); uint8_t Pad_Byte);
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static int SHA384_512Reset(SHA512Context *context,
uint64_t H0[SHA512HashSize/8]);
static int SHA384_512ResultN(SHA512Context *context, static int SHA384_512ResultN(SHA512Context *context,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t Message_Digest[ ], int HashSize); uint8_t Message_Digest[ ], int HashSize);
/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */ /* Initial Hash Values: FIPS 180-3 sections 5.3.4 and 5.3.5 */
static uint64_t SHA384_H0[ ] = { static uint64_t SHA384_H0[ ] = {
0xCBBB9D5DC1059ED8ll, 0x629A292A367CD507ll, 0x9159015A3070DD17ll, 0xCBBB9D5DC1059ED8ll, 0x629A292A367CD507ll, 0x9159015A3070DD17ll,
0x152FECD8F70E5939ll, 0x67332667FFC00B31ll, 0x8EB44A8768581511ll, 0x152FECD8F70E5939ll, 0x67332667FFC00B31ll, 0x8EB44A8768581511ll,
0xDB0C2E0D64F98FA7ll, 0x47B5481DBEFA4FA4ll 0xDB0C2E0D64F98FA7ll, 0x47B5481DBEFA4FA4ll
}; };
static uint64_t SHA512_H0[ ] = { static uint64_t SHA512_H0[ ] = {
0x6A09E667F3BCC908ll, 0xBB67AE8584CAA73Bll, 0x3C6EF372FE94F82Bll, 0x6A09E667F3BCC908ll, 0xBB67AE8584CAA73Bll, 0x3C6EF372FE94F82Bll,
0xA54FF53A5F1D36F1ll, 0x510E527FADE682D1ll, 0x9B05688C2B3E6C1Fll, 0xA54FF53A5F1D36F1ll, 0x510E527FADE682D1ll, 0x9B05688C2B3E6C1Fll,
0x1F83D9ABFB41BD6Bll, 0x5BE0CD19137E2179ll 0x1F83D9ABFB41BD6Bll, 0x5BE0CD19137E2179ll
}; };
skipping to change at page 57, line 37 skipping to change at page 57, line 4
* for computing a new SHA384 message digest. * for computing a new SHA384 message digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int SHA384Reset(SHA384Context *context) int SHA384Reset(SHA384Context *context)
{ {
return SHA384_512Reset(context, SHA384_H0); return SHA384_512Reset(context, SHA384_H0);
} }
/* /*
* SHA384Input * SHA384Input
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA384Input(SHA384Context *context, int SHA384Input(SHA384Context *context,
const uint8_t *message_array, unsigned int length) const uint8_t *message_array, unsigned int length)
{ {
return SHA512Input(context, message_array, length); return SHA512Input(context, message_array, length);
skipping to change at page 58, line 38 skipping to change at page 58, line 4
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
int SHA384FinalBits(SHA384Context *context, int SHA384FinalBits(SHA384Context *context,
uint8_t message_bits, unsigned int length) uint8_t message_bits, unsigned int length)
{ {
return SHA512FinalBits(context, message_bits, length); return SHA512FinalBits(context, message_bits, length);
} }
/* /*
* SHA384Result * SHA384Result
* *
* Description: * Description:
* This function will return the 384-bit message digest * This function will return the 384-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 47. * the last octet of hash in the element with index 47.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA384Result(SHA384Context *context, int SHA384Result(SHA384Context *context,
uint8_t Message_Digest[SHA384HashSize]) uint8_t Message_Digest[SHA384HashSize])
{ {
return SHA384_512ResultN(context, Message_Digest, SHA384HashSize); return SHA384_512ResultN(context, Message_Digest, SHA384HashSize);
skipping to change at page 59, line 38 skipping to change at page 59, line 4
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA512Reset(SHA512Context *context) int SHA512Reset(SHA512Context *context)
{ {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return SHA384_512Reset(context, SHA512_H0); return SHA384_512Reset(context, SHA512_H0);
} }
/* /*
* SHA512Input * SHA512Input
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
* The length of the message in message_array * The length of the message in message_array
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA512Input(SHA512Context *context, int SHA512Input(SHA512Context *context,
const uint8_t *message_array, const uint8_t *message_array,
unsigned int length) unsigned int length)
{ {
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (!message_array) return shaNull;
if (!context || !message_array) if (context->Computed) return context->Corrupted = shaStateError;
return shaNull; if (context->Corrupted) return context->Corrupted;
if (context->Computed)
return context->Corrupted = shaStateError;
if (context->Corrupted)
return context->Corrupted;
while (length-- && !context->Corrupted) { while (length--) {
context->Message_Block[context->Message_Block_Index++] = context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF); *message_array;
if ((SHA384_512AddLength(context, 8) == shaSuccess) && if ((SHA384_512AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA512_Message_Block_Size)) (context->Message_Block_Index == SHA512_Message_Block_Size))
SHA384_512ProcessMessageBlock(context); SHA384_512ProcessMessageBlock(context);
message_array++; message_array++;
} }
return context->Corrupted; return context->Corrupted;
} }
/* /*
* SHA512FinalBits * SHA512FinalBits
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA512FinalBits(SHA512Context *context, int SHA512FinalBits(SHA512Context *context,
uint8_t message_bits, unsigned int length) uint8_t message_bits, unsigned int length)
{ {
uint8_t masks[8] = { static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
}; };
uint8_t markbit[8] = { static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
}; };
if (!length) if (!context) return shaNull;
return shaSuccess; if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (!context) if (context->Computed) return context->Corrupted = shaStateError;
return shaNull; if (length >= 8) return context->Corrupted = shaBadParam;
if (context->Computed)
return context->Corrupted = shaStateError;
if ((length >= 8) || (length == 0))
return context->Corrupted = shaBadParam;
if (context->Corrupted)
return context->Corrupted;
SHA384_512AddLength(context, length); SHA384_512AddLength(context, length);
SHA384_512Finalize(context, (uint8_t) SHA384_512Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length])); ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted; return context->Corrupted;
} }
/* /*
* SHA384_512Finalize * SHA512Result
* *
* Description: * Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*
*/
static void SHA384_512Finalize(SHA512Context *context,
uint8_t Pad_Byte)
{
int_least16_t i;
SHA384_512PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */
for (i = 0; i < SHA512_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
#ifdef USE_32BIT_ONLY /* and clear length */
context->Length[0] = context->Length[1] = 0;
context->Length[2] = context->Length[3] = 0;
#else /* !USE_32BIT_ONLY */
context->Length_Low = 0;
context->Length_High = 0;
#endif /* USE_32BIT_ONLY */
context->Computed = 1;
}
/*
* SHA512Result
*
* Description:
* This function will return the 512-bit message digest * This function will return the 512-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 63. * the last octet of hash in the element with index 63.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int SHA512Result(SHA512Context *context, int SHA512Result(SHA512Context *context,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t Message_Digest[SHA512HashSize]) uint8_t Message_Digest[SHA512HashSize])
{ {
return SHA384_512ResultN(context, Message_Digest, SHA512HashSize); return SHA384_512ResultN(context, Message_Digest, SHA512HashSize);
} }
/* /*
* SHA384_512PadMessage * SHA384_512Reset
* *
* Description: * Description:
* According to the standard, the message must be padded to the next * This helper function will initialize the SHA512Context in
* even multiple of 1024 bits. The first padding bit must be a '1'. * preparation for computing a new SHA384 or SHA512 message
* The last 128 bits represent the length of the original message. * digest.
* All bits in between should be 0. This helper function will
* pad the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to pad * The context to reset.
* Pad_Byte: [in] * H0[ ]: [in]
* The last byte to add to the digest before the 0-padding * The initial hash value array to use.
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* Nothing. * sha Error Code.
* *
*/ */
static void SHA384_512PadMessage(SHA512Context *context, #ifdef USE_32BIT_ONLY
uint8_t Pad_Byte) static int SHA384_512Reset(SHA512Context *context,
uint32_t H0[SHA512HashSize/4])
#else /* !USE_32BIT_ONLY */
static int SHA384_512Reset(SHA512Context *context,
uint64_t H0[SHA512HashSize/8])
#endif /* USE_32BIT_ONLY */
{ {
/* int i;
* Check to see if the current message block is too small to hold if (!context) return shaNull;
* 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 >= (SHA512_Message_Block_Size-16)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA512_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA384_512ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA512_Message_Block_Size-16))
context->Message_Block[context->Message_Block_Index++] = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* context->Message_Block_Index = 0;
* Store the message length as the last 16 octets
*/
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
context->Message_Block[112] = (uint8_t)(context->Length[0] >> 24); context->Length[0] = context->Length[1] =
context->Message_Block[113] = (uint8_t)(context->Length[0] >> 16); context->Length[2] = context->Length[3] = 0;
context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8);
context->Message_Block[115] = (uint8_t)(context->Length[0]);
context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24);
context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16);
context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8);
context->Message_Block[119] = (uint8_t)(context->Length[1]);
context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24); for (i = 0; i < SHA512HashSize/4; i++)
context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16); context->Intermediate_Hash[i] = H0[i];
context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8);
context->Message_Block[123] = (uint8_t)(context->Length[2]);
context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24);
context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16);
context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8);
context->Message_Block[127] = (uint8_t)(context->Length[3]);
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
context->Message_Block[112] = (uint8_t)(context->Length_High >> 56); context->Length_High = context->Length_Low = 0;
context->Message_Block[113] = (uint8_t)(context->Length_High >> 48);
context->Message_Block[114] = (uint8_t)(context->Length_High >> 40);
context->Message_Block[115] = (uint8_t)(context->Length_High >> 32);
context->Message_Block[116] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[117] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[118] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[119] = (uint8_t)(context->Length_High);
context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56); for (i = 0; i < SHA512HashSize/8; i++)
context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48); context->Intermediate_Hash[i] = H0[i];
context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40);
context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32);
context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[127] = (uint8_t)(context->Length_Low);
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
SHA384_512ProcessMessageBlock(context); context->Computed = 0;
context->Corrupted = shaSuccess;
return shaSuccess;
} }
/* /*
* SHA384_512ProcessMessageBlock * SHA384_512ProcessMessageBlock
* *
* Description: * Description:
* This helper function will process the next 1024 bits of the * This helper function will process the next 1024 bits of the
* message stored in the Message_Block array. * message stored in the Message_Block array.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* *
* Returns: * Returns:
* Nothing. * Nothing.
* *
* Comments: * Comments:
* Many of the variable names in this code, especially the * Many of the variable names in this code, especially the
* single character names, were used because those were the * single character names, were used because those were the
* names used in the publication. * names used in the Secure Hash Standard.
* *
* *
*/ */
static void SHA384_512ProcessMessageBlock(SHA512Context *context) static void SHA384_512ProcessMessageBlock(SHA512Context *context)
{ {
/* Constants defined in FIPS-180-2, section 4.2.3 */
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
/* Constants defined in FIPS 180-3, section 4.2.3 */
static const uint32_t K[80*2] = { static const uint32_t K[80*2] = {
0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, 0xB5C0FBCF, 0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, 0xB5C0FBCF,
0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, 0x3956C25B, 0xF348B538, 0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, 0x3956C25B, 0xF348B538,
0x59F111F1, 0xB605D019, 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5, 0x59F111F1, 0xB605D019, 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
0xDA6D8118, 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE, 0xDA6D8118, 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE,
0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, 0x72BE5D74, 0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, 0x72BE5D74,
0xF27B896F, 0x80DEB1FE, 0x3B1696B1, 0x9BDC06A7, 0x25C71235, 0xF27B896F, 0x80DEB1FE, 0x3B1696B1, 0x9BDC06A7, 0x25C71235,
0xC19BF174, 0xCF692694, 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786, 0xC19BF174, 0xCF692694, 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786,
0x384F25E3, 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65, 0x384F25E3, 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65,
0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, 0x5CB0A9DC, 0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, 0x5CB0A9DC,
0xBD41FBD4, 0x76F988DA, 0x831153B5, 0x983E5152, 0xEE66DFAB, 0xBD41FBD4, 0x76F988DA, 0x831153B5, 0x983E5152, 0xEE66DFAB,
0xA831C66D, 0x2DB43210, 0xB00327C8, 0x98FB213F, 0xBF597FC7, 0xA831C66D, 0x2DB43210, 0xB00327C8, 0x98FB213F, 0xBF597FC7,
0xBEEF0EE4, 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725, 0xBEEF0EE4, 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725,
0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, 0x27B70A85, 0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, 0x27B70A85,
skipping to change at page 66, line 4 skipping to change at page 63, line 34
0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, 0x391C0CB3, 0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, 0x391C0CB3,
0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, 0x5B9CCA4F, 0x7763E373, 0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, 0x5B9CCA4F, 0x7763E373,
0x682E6FF3, 0xD6B2B8A3, 0x748F82EE, 0x5DEFB2FC, 0x78A5636F, 0x682E6FF3, 0xD6B2B8A3, 0x748F82EE, 0x5DEFB2FC, 0x78A5636F,
0x43172F60, 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC, 0x43172F60, 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC,
0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, 0xBEF9A3F7, 0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, 0xBEF9A3F7,
0xB2C67915, 0xC67178F2, 0xE372532B, 0xCA273ECE, 0xEA26619C, 0xB2C67915, 0xC67178F2, 0xE372532B, 0xCA273ECE, 0xEA26619C,
0xD186B8C7, 0x21C0C207, 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F, 0xD186B8C7, 0x21C0C207, 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F,
0xEE6ED178, 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6, 0xEE6ED178, 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6,
0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, 0x28DB77F5, 0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, 0x28DB77F5,
0x23047D84, 0x32CAAB7B, 0x40C72493, 0x3C9EBE0A, 0x15C9BEBC, 0x23047D84, 0x32CAAB7B, 0x40C72493, 0x3C9EBE0A, 0x15C9BEBC,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
0x431D67C4, 0x9C100D4C, 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C, 0x431D67C4, 0x9C100D4C, 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C,
0xFC657E2A, 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817 0xFC657E2A, 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817
}; };
int t, t2, t8; /* Loop counter */ int t, t2, t8; /* Loop counter */
uint32_t temp1[2], temp2[2], /* Temporary word values */ uint32_t temp1[2], temp2[2], /* Temporary word values */
temp3[2], temp4[2], temp5[2]; temp3[2], temp4[2], temp5[2];
uint32_t W[2*80]; /* Word sequence */ uint32_t W[2*80]; /* Word sequence */
uint32_t A[2], B[2], C[2], D[2], /* Word buffers */ uint32_t A[2], B[2], C[2], D[2], /* Word buffers */
E[2], F[2], G[2], H[2]; E[2], F[2], G[2], H[2];
skipping to change at page 66, line 30 skipping to change at page 64, line 4
((((uint32_t)context->Message_Block[t8 + 1])) << 16) | ((((uint32_t)context->Message_Block[t8 + 1])) << 16) |
((((uint32_t)context->Message_Block[t8 + 2])) << 8) | ((((uint32_t)context->Message_Block[t8 + 2])) << 8) |
((((uint32_t)context->Message_Block[t8 + 3]))); ((((uint32_t)context->Message_Block[t8 + 3])));
W[t2++] = ((((uint32_t)context->Message_Block[t8 + 4])) << 24) | W[t2++] = ((((uint32_t)context->Message_Block[t8 + 4])) << 24) |
((((uint32_t)context->Message_Block[t8 + 5])) << 16) | ((((uint32_t)context->Message_Block[t8 + 5])) << 16) |
((((uint32_t)context->Message_Block[t8 + 6])) << 8) | ((((uint32_t)context->Message_Block[t8 + 6])) << 8) |
((((uint32_t)context->Message_Block[t8 + 7]))); ((((uint32_t)context->Message_Block[t8 + 7])));
} }
for (t = 16; t < 80; t++, t2 += 2) { for (t = 16; t < 80; t++, t2 += 2) {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* W[t] = SHA512_sigma1(W[t-2]) + W[t-7] + /* W[t] = SHA512_sigma1(W[t-2]) + W[t-7] +
SHA512_sigma0(W[t-15]) + W[t-16]; */ SHA512_sigma0(W[t-15]) + W[t-16]; */
uint32_t *Wt2 = &W[t2-2*2]; uint32_t *Wt2 = &W[t2-2*2];
uint32_t *Wt7 = &W[t2-7*2]; uint32_t *Wt7 = &W[t2-7*2];
uint32_t *Wt15 = &W[t2-15*2]; uint32_t *Wt15 = &W[t2-15*2];
uint32_t *Wt16 = &W[t2-16*2]; uint32_t *Wt16 = &W[t2-16*2];
SHA512_sigma1(Wt2, temp1); SHA512_sigma1(Wt2, temp1);
SHA512_ADD(temp1, Wt7, temp2); SHA512_ADD(temp1, Wt7, temp2);
SHA512_sigma0(Wt15, temp1); SHA512_sigma0(Wt15, temp1);
SHA512_ADD(temp1, Wt16, temp3); SHA512_ADD(temp1, Wt16, temp3);
skipping to change at page 67, line 4 skipping to change at page 64, line 34
C[0] = context->Intermediate_Hash[4]; C[0] = context->Intermediate_Hash[4];
C[1] = context->Intermediate_Hash[5]; C[1] = context->Intermediate_Hash[5];
D[0] = context->Intermediate_Hash[6]; D[0] = context->Intermediate_Hash[6];
D[1] = context->Intermediate_Hash[7]; D[1] = context->Intermediate_Hash[7];
E[0] = context->Intermediate_Hash[8]; E[0] = context->Intermediate_Hash[8];
E[1] = context->Intermediate_Hash[9]; E[1] = context->Intermediate_Hash[9];
F[0] = context->Intermediate_Hash[10]; F[0] = context->Intermediate_Hash[10];
F[1] = context->Intermediate_Hash[11]; F[1] = context->Intermediate_Hash[11];
G[0] = context->Intermediate_Hash[12]; G[0] = context->Intermediate_Hash[12];
G[1] = context->Intermediate_Hash[13]; G[1] = context->Intermediate_Hash[13];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
H[0] = context->Intermediate_Hash[14]; H[0] = context->Intermediate_Hash[14];
H[1] = context->Intermediate_Hash[15]; H[1] = context->Intermediate_Hash[15];
for (t = t2 = 0; t < 80; t++, t2 += 2) { for (t = t2 = 0; t < 80; t++, t2 += 2) {
/* /*
* temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; * temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
*/ */
SHA512_SIGMA1(E,temp1); SHA512_SIGMA1(E,temp1);
SHA512_ADD(H, temp1, temp2); SHA512_ADD(H, temp1, temp2);
SHA_Ch(E,F,G,temp3); SHA_Ch(E,F,G,temp3);
skipping to change at page 67, line 30 skipping to change at page 65, line 4
/* /*
* temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C); * temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C);
*/ */
SHA512_SIGMA0(A,temp3); SHA512_SIGMA0(A,temp3);
SHA_Maj(A,B,C,temp4); SHA_Maj(A,B,C,temp4);
SHA512_ADD(temp3, temp4, temp2); SHA512_ADD(temp3, temp4, temp2);
H[0] = G[0]; H[1] = G[1]; H[0] = G[0]; H[1] = G[1];
G[0] = F[0]; G[1] = F[1]; G[0] = F[0]; G[1] = F[1];
F[0] = E[0]; F[1] = E[1]; F[0] = E[0]; F[1] = E[1];
SHA512_ADD(D, temp1, E); SHA512_ADD(D, temp1, E);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
D[0] = C[0]; D[1] = C[1]; D[0] = C[0]; D[1] = C[1];
C[0] = B[0]; C[1] = B[1]; C[0] = B[0]; C[1] = B[1];
B[0] = A[0]; B[1] = A[1]; B[0] = A[0]; B[1] = A[1];
SHA512_ADD(temp1, temp2, A); SHA512_ADD(temp1, temp2, A);
} }
SHA512_ADDTO2(&context->Intermediate_Hash[0], A); SHA512_ADDTO2(&context->Intermediate_Hash[0], A);
SHA512_ADDTO2(&context->Intermediate_Hash[2], B); SHA512_ADDTO2(&context->Intermediate_Hash[2], B);
SHA512_ADDTO2(&context->Intermediate_Hash[4], C); SHA512_ADDTO2(&context->Intermediate_Hash[4], C);
SHA512_ADDTO2(&context->Intermediate_Hash[6], D); SHA512_ADDTO2(&context->Intermediate_Hash[6], D);
SHA512_ADDTO2(&context->Intermediate_Hash[8], E); SHA512_ADDTO2(&context->Intermediate_Hash[8], E);
SHA512_ADDTO2(&context->Intermediate_Hash[10], F); SHA512_ADDTO2(&context->Intermediate_Hash[10], F);
SHA512_ADDTO2(&context->Intermediate_Hash[12], G); SHA512_ADDTO2(&context->Intermediate_Hash[12], G);
SHA512_ADDTO2(&context->Intermediate_Hash[14], H); SHA512_ADDTO2(&context->Intermediate_Hash[14], H);
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
/* Constants defined in FIPS 180-3, section 4.2.3 */
static const uint64_t K[80] = { static const uint64_t K[80] = {
0x428A2F98D728AE22ll, 0x7137449123EF65CDll, 0xB5C0FBCFEC4D3B2Fll, 0x428A2F98D728AE22ll, 0x7137449123EF65CDll, 0xB5C0FBCFEC4D3B2Fll,
0xE9B5DBA58189DBBCll, 0x3956C25BF348B538ll, 0x59F111F1B605D019ll, 0xE9B5DBA58189DBBCll, 0x3956C25BF348B538ll, 0x59F111F1B605D019ll,
0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll, 0xD807AA98A3030242ll, 0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll, 0xD807AA98A3030242ll,
0x12835B0145706FBEll, 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll, 0x12835B0145706FBEll, 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll,
0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll, 0x9BDC06A725C71235ll, 0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll, 0x9BDC06A725C71235ll,
0xC19BF174CF692694ll, 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll, 0xC19BF174CF692694ll, 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll,
0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll, 0x2DE92C6F592B0275ll, 0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll, 0x2DE92C6F592B0275ll,
0x4A7484AA6EA6E483ll, 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll, 0x4A7484AA6EA6E483ll, 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll,
0x983E5152EE66DFABll, 0xA831C66D2DB43210ll, 0xB00327C898FB213Fll, 0x983E5152EE66DFABll, 0xA831C66D2DB43210ll, 0xB00327C898FB213Fll,
0xBF597FC7BEEF0EE4ll, 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll, 0xBF597FC7BEEF0EE4ll, 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
0x06CA6351E003826Fll, 0x142929670A0E6E70ll, 0x27B70A8546D22FFCll, 0x06CA6351E003826Fll, 0x142929670A0E6E70ll, 0x27B70A8546D22FFCll,
0x2E1B21385C26C926ll, 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll, 0x2E1B21385C26C926ll, 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll,
0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll, 0x81C2C92E47EDAEE6ll, 0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll, 0x81C2C92E47EDAEE6ll,
0x92722C851482353Bll, 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll, 0x92722C851482353Bll, 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll,
0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll, 0xD192E819D6EF5218ll, 0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll, 0xD192E819D6EF5218ll,
0xD69906245565A910ll, 0xF40E35855771202All, 0x106AA07032BBD1B8ll, 0xD69906245565A910ll, 0xF40E35855771202All, 0x106AA07032BBD1B8ll,
0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll, 0x2748774CDF8EEB99ll, 0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll, 0x2748774CDF8EEB99ll,
0x34B0BCB5E19B48A8ll, 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll, 0x34B0BCB5E19B48A8ll, 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll,
0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll, 0x748F82EE5DEFB2FCll, 0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll, 0x748F82EE5DEFB2FCll,
0x78A5636F43172F60ll, 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll, 0x78A5636F43172F60ll, 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll,
skipping to change at page 68, line 30 skipping to change at page 66, line 5
0x0A637DC5A2C898A6ll, 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll, 0x0A637DC5A2C898A6ll, 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll,
0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll, 0x3C9EBE0A15C9BEBCll, 0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll, 0x3C9EBE0A15C9BEBCll,
0x431D67C49C100D4Cll, 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All, 0x431D67C49C100D4Cll, 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All,
0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll 0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll
}; };
int t, t8; /* Loop counter */ int t, t8; /* Loop counter */
uint64_t temp1, temp2; /* Temporary word value */ uint64_t temp1, temp2; /* Temporary word value */
uint64_t W[80]; /* Word sequence */ uint64_t W[80]; /* Word sequence */
uint64_t A, B, C, D, E, F, G, H; /* Word buffers */ uint64_t A, B, C, D, E, F, G, H; /* Word buffers */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Initialize the first 16 words in the array W * Initialize the first 16 words in the array W
*/ */
for (t = t8 = 0; t < 16; t++, t8 += 8) for (t = t8 = 0; t < 16; t++, t8 += 8)
W[t] = ((uint64_t)(context->Message_Block[t8 ]) << 56) | W[t] = ((uint64_t)(context->Message_Block[t8 ]) << 56) |
((uint64_t)(context->Message_Block[t8 + 1]) << 48) | ((uint64_t)(context->Message_Block[t8 + 1]) << 48) |
((uint64_t)(context->Message_Block[t8 + 2]) << 40) | ((uint64_t)(context->Message_Block[t8 + 2]) << 40) |
((uint64_t)(context->Message_Block[t8 + 3]) << 32) | ((uint64_t)(context->Message_Block[t8 + 3]) << 32) |
((uint64_t)(context->Message_Block[t8 + 4]) << 24) | ((uint64_t)(context->Message_Block[t8 + 4]) << 24) |
((uint64_t)(context->Message_Block[t8 + 5]) << 16) | ((uint64_t)(context->Message_Block[t8 + 5]) << 16) |
skipping to change at page 69, line 4 skipping to change at page 66, line 34
A = context->Intermediate_Hash[0]; A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1]; B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2]; C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3]; D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4]; E = context->Intermediate_Hash[4];
F = context->Intermediate_Hash[5]; F = context->Intermediate_Hash[5];
G = context->Intermediate_Hash[6]; G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7]; H = context->Intermediate_Hash[7];
for (t = 0; t < 80; t++) { for (t = 0; t < 80; t++) {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t]; temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C); temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C);
H = G; H = G;
G = F; G = F;
F = E; F = E;
E = D + temp1; E = D + temp1;
D = C; D = C;
C = B; C = B;
B = A; B = A;
A = temp1 + temp2; A = temp1 + temp2;
skipping to change at page 69, line 30 skipping to change at page 67, line 4
context->Intermediate_Hash[1] += B; context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C; context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D; context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E; context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F; context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G; context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H; context->Intermediate_Hash[7] += H;
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
* SHA384_512Reset * SHA384_512Finalize
* *
* Description: * Description:
* This helper function will initialize the SHA512Context in * This helper function finishes off the digest calculations.
* preparation for computing a new SHA384 or SHA512 message
* digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The SHA context to update
* H0 * Pad_Byte: [in]
* The initial hash value to use. * The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
#ifdef USE_32BIT_ONLY static void SHA384_512Finalize(SHA512Context *context,
static int SHA384_512Reset(SHA512Context *context, uint8_t Pad_Byte)
uint32_t H0[SHA512HashSize/4]) {
int_least16_t i;
SHA384_512PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */
for (i = 0; i < SHA512_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
#ifdef USE_32BIT_ONLY /* and clear length */
context->Length[0] = context->Length[1] = 0;
context->Length[2] = context->Length[3] = 0;
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
static int SHA384_512Reset(SHA512Context *context, context->Length_High = context->Length_Low = 0;
uint64_t H0[SHA512HashSize/8])
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
context->Computed = 1;
}
/*
* SHA384_512PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 1024 bits. The first padding bit must be a '1'.
* The last 128 bits represent the length of the original message.
* All bits in between should be 0. This helper function will
* pad the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*
*/
static void SHA384_512PadMessage(SHA512Context *context,
uint8_t Pad_Byte)
{ {
int i; /*
if (!context) * Check to see if the current message block is too small to hold
return shaNull; * 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 >= (SHA512_Message_Block_Size-16)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA512_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
context->Message_Block_Index = 0; SHA384_512ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA512_Message_Block_Size-16))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 16 octets
*/
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
context->Length[0] = context->Length[1] = context->Message_Block[112] = (uint8_t)(context->Length[0] >> 24);
context->Length[2] = context->Length[3] = 0; context->Message_Block[113] = (uint8_t)(context->Length[0] >> 16);
context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8);
context->Message_Block[115] = (uint8_t)(context->Length[0]);
context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24);
context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16);
context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8);
context->Message_Block[119] = (uint8_t)(context->Length[1]);
for (i = 0; i < SHA512HashSize/4; i++) context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24);
context->Intermediate_Hash[i] = H0[i]; context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16);
context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block[123] = (uint8_t)(context->Length[2]);
context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24);
context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16);
context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8);
context->Message_Block[127] = (uint8_t)(context->Length[3]);
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
context->Length_High = context->Length_Low = 0; context->Message_Block[112] = (uint8_t)(context->Length_High >> 56);
context->Message_Block[113] = (uint8_t)(context->Length_High >> 48);
context->Message_Block[114] = (uint8_t)(context->Length_High >> 40);
context->Message_Block[115] = (uint8_t)(context->Length_High >> 32);
context->Message_Block[116] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[117] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[118] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[119] = (uint8_t)(context->Length_High);
for (i = 0; i < SHA512HashSize/8; i++) context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56);
context->Intermediate_Hash[i] = H0[i]; context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48);
context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40);
context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32);
context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[127] = (uint8_t)(context->Length_Low);
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
context->Computed = 0; SHA384_512ProcessMessageBlock(context);
context->Corrupted = 0;
return shaSuccess;
} }
/* /*
* SHA384_512ResultN * SHA384_512ResultN
* *
* Description: * Description:
* This helper function will return the 384-bit or 512-bit message * This helper function will return the 384-bit or 512-bit message
* digest into the Message_Digest array provided by the caller. * digest into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 47/63. * the last octet of hash in the element with index 47/63.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the SHA hash. * The context to use to calculate the SHA hash.
* Message_Digest: [out] * Message_Digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* HashSize: [in] * HashSize: [in]
* The size of the hash, either 48 or 64. * The size of the hash, either 48 or 64.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
static int SHA384_512ResultN(SHA512Context *context,
uint8_t Message_Digest[ ], int HashSize)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
static int SHA384_512ResultN(SHA512Context *context,
uint8_t Message_Digest[ ], int HashSize)
{ {
int i; int i;
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
int i2; int i2;
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
if (!context || !Message_Digest) if (!context) return shaNull;
return shaNull; if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed) if (!context->Computed)
SHA384_512Finalize(context, 0x80); SHA384_512Finalize(context, 0x80);
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
for (i = i2 = 0; i < HashSize; ) { for (i = i2 = 0; i < HashSize; ) {
Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24); Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24);
Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16); Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16);
Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8); Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8);
Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]); Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]);
skipping to change at page 72, line 28 skipping to change at page 71, line 28
* The context to reset. * The context to reset.
* whichSha: [in] * whichSha: [in]
* Selects which SHA reset to call * Selects which SHA reset to call
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int USHAReset(USHAContext *context, enum SHAversion whichSha) int USHAReset(USHAContext *context, enum SHAversion whichSha)
{ {
if (context) { if (!context) return shaNull;
context->whichSha = whichSha; context->whichSha = whichSha;
switch (whichSha) { switch (whichSha) {
case SHA1: return SHA1Reset((SHA1Context*)&context->ctx); case SHA1: return SHA1Reset((SHA1Context*)&context->ctx);
case SHA224: return SHA224Reset((SHA224Context*)&context->ctx); case SHA224: return SHA224Reset((SHA224Context*)&context->ctx);
case SHA256: return SHA256Reset((SHA256Context*)&context->ctx); case SHA256: return SHA256Reset((SHA256Context*)&context->ctx);
case SHA384: return SHA384Reset((SHA384Context*)&context->ctx); case SHA384: return SHA384Reset((SHA384Context*)&context->ctx);
case SHA512: return SHA512Reset((SHA512Context*)&context->ctx); case SHA512: return SHA512Reset((SHA512Context*)&context->ctx);
default: return shaBadParam; default: return shaBadParam;
}
} else {
return shaNull;
} }
} }
/* /*
* USHAInput * USHAInput
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* sha Error Code. * sha Error Code.
* *
*/ */
int USHAInput(USHAContext *context, int USHAInput(USHAContext *context,
const uint8_t *bytes, unsigned int bytecount) const uint8_t *bytes, unsigned int bytecount)
{ {
if (context) { if (!context) return shaNull;
switch (context->whichSha) { switch (context->whichSha) {
case SHA1: case SHA1:
return SHA1Input((SHA1Context*)&context->ctx, bytes, return SHA1Input((SHA1Context*)&context->ctx, bytes,
bytecount); bytecount);
case SHA224: case SHA224:
return SHA224Input((SHA224Context*)&context->ctx, bytes, return SHA224Input((SHA224Context*)&context->ctx, bytes,
bytecount); bytecount);
case SHA256: case SHA256:
return SHA256Input((SHA256Context*)&context->ctx, bytes, return SHA256Input((SHA256Context*)&context->ctx, bytes,
bytecount); bytecount);
case SHA384: case SHA384:
return SHA384Input((SHA384Context*)&context->ctx, bytes, return SHA384Input((SHA384Context*)&context->ctx, bytes,
bytecount); bytecount);
case SHA512: case SHA512:
return SHA512Input((SHA512Context*)&context->ctx, bytes, return SHA512Input((SHA512Context*)&context->ctx, bytes,
bytecount); bytecount);
default: return shaBadParam; default: return shaBadParam;
}
} else {
return shaNull;
} }
} }
/* /*
* USHAFinalBits * USHAFinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* sha Error Code. * sha Error Code.
*/ */
int USHAFinalBits(USHAContext *context, int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count) uint8_t bits, unsigned int bit_count)
{ {
if (context) { if (!context) return shaNull;
switch (context->whichSha) {
case SHA1: INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return SHA1FinalBits((SHA1Context*)&context->ctx, bits,
bit_count); switch (context->whichSha) {
case SHA224: case SHA1:
return SHA224FinalBits((SHA224Context*)&context->ctx, bits, return SHA1FinalBits((SHA1Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA256: case SHA224:
return SHA256FinalBits((SHA256Context*)&context->ctx, bits, return SHA224FinalBits((SHA224Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA384: case SHA256:
return SHA384FinalBits((SHA384Context*)&context->ctx, bits, return SHA256FinalBits((SHA256Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA512: case SHA384:
return SHA512FinalBits((SHA512Context*)&context->ctx, bits, return SHA384FinalBits((SHA384Context*)&context->ctx, bits,
bit_count); bit_count);
default: return shaBadParam; case SHA512:
} return SHA512FinalBits((SHA512Context*)&context->ctx, bits,
} else { bit_count);
return shaNull; default: return shaBadParam;
} }
} }
/* /*
* USHAResult * USHAResult
* *
* Description: * Description:
* This function will return the message digest of the appropriate * This function will return the message digest of the appropriate
* bit size, as returned by USHAHashSizeBits(whichSHA) for the * bit size, as returned by USHAHashSizeBits(whichSHA) for the
* 'whichSHA' value used in the preceeding call to USHAReset, * 'whichSHA' value used in the preceeding call to USHAReset,
skipping to change at page 75, line 4 skipping to change at page 73, line 48
* The context to use to calculate the SHA-1 hash. * The context to use to calculate the SHA-1 hash.
* Message_Digest: [out] * Message_Digest: [out]
* Where the digest is returned. * Where the digest is returned.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int USHAResult(USHAContext *context, int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize]) uint8_t Message_Digest[USHAMaxHashSize])
{
if (!context) return shaNull;
switch (context->whichSha) {
case SHA1:
return SHA1Result((SHA1Context*)&context->ctx, Message_Digest);
case SHA224:
return SHA224Result((SHA224Context*)&context->ctx,
Message_Digest);
case SHA256:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ return SHA256Result((SHA256Context*)&context->ctx,
if (context) { Message_Digest);
switch (context->whichSha) { case SHA384:
case SHA1: return SHA384Result((SHA384Context*)&context->ctx,
return SHA1Result((SHA1Context*)&context->ctx, Message_Digest); Message_Digest);
case SHA224: case SHA512:
return SHA224Result((SHA224Context*)&context->ctx, return SHA512Result((SHA512Context*)&context->ctx,
Message_Digest); Message_Digest);
case SHA256: default: return shaBadParam;
return SHA256Result((SHA256Context*)&context->ctx,
Message_Digest);
case SHA384:
return SHA384Result((SHA384Context*)&context->ctx,
Message_Digest);
case SHA512:
return SHA512Result((SHA512Context*)&context->ctx,
Message_Digest);
default: return shaBadParam;
}
} else {
return shaNull;
} }
} }
/* /*
* USHABlockSize * USHABlockSize
* *
* Description: * Description:
* This function will return the blocksize for the given SHA * This function will return the blocksize for the given SHA
* algorithm. * algorithm.
* *
skipping to change at page 76, line 4 skipping to change at page 74, line 45
{ {
switch (whichSha) { switch (whichSha) {
case SHA1: return SHA1_Message_Block_Size; case SHA1: return SHA1_Message_Block_Size;
case SHA224: return SHA224_Message_Block_Size; case SHA224: return SHA224_Message_Block_Size;
case SHA256: return SHA256_Message_Block_Size; case SHA256: return SHA256_Message_Block_Size;
case SHA384: return SHA384_Message_Block_Size; case SHA384: return SHA384_Message_Block_Size;
default: default:
case SHA512: return SHA512_Message_Block_Size; case SHA512: return SHA512_Message_Block_Size;
} }
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* USHAHashSize * USHAHashSize
* *
* Description: * Description:
* This function will return the hashsize for the given SHA * This function will return the hashsize for the given SHA
* algorithm. * algorithm.
* *
* Parameters: * Parameters:
* whichSha: * whichSha:
* which SHA algorithm to query * which SHA algorithm to query
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Returns: * Returns:
* hash size * hash size
* *
*/ */
int USHAHashSize(enum SHAversion whichSha) int USHAHashSize(enum SHAversion whichSha)
{ {
switch (whichSha) { switch (whichSha) {
case SHA1: return SHA1HashSize; case SHA1: return SHA1HashSize;
case SHA224: return SHA224HashSize; case SHA224: return SHA224HashSize;
case SHA256: return SHA256HashSize; case SHA256: return SHA256HashSize;
skipping to change at page 77, line 4 skipping to change at page 75, line 46
* *
*/ */
int USHAHashSizeBits(enum SHAversion whichSha) int USHAHashSizeBits(enum SHAversion whichSha)
{ {
switch (whichSha) { switch (whichSha) {
case SHA1: return SHA1HashSizeBits; case SHA1: return SHA1HashSizeBits;
case SHA224: return SHA224HashSizeBits; case SHA224: return SHA224HashSizeBits;
case SHA256: return SHA256HashSizeBits; case SHA256: return SHA256HashSizeBits;
case SHA384: return SHA384HashSizeBits; case SHA384: return SHA384HashSizeBits;
default: default:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case SHA512: return SHA512HashSizeBits; case SHA512: return SHA512HashSizeBits;
} }
} }
/* /*
* USHAHashName * USHAHashName
* *
* Description: * Description:
* This function will return the name of the given SHA algorithm * This function will return the name of the given SHA algorithm
* as a string. * as a string.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters: * Parameters:
* whichSha: * whichSha:
* which SHA algorithm to query * which SHA algorithm to query
* *
* Returns: * Returns:
* character string with the name in it * character string with the name in it
* *
*/ */
const char *USHAHashName(enum SHAversion whichSha) const char *USHAHashName(enum SHAversion whichSha)
{ {
skipping to change at page 78, line 4 skipping to change at page 76, line 43
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the HMAC algorithm (Keyed-Hashing for * This file implements the HMAC algorithm (Keyed-Hashing for
* Message Authentication, [RFC 2104]), expressed in terms of * Message Authentication, [RFC 2104]), expressed in terms of
* the various SHA algorithms. * the various SHA algorithms.
*/ */
#include "sha.h" #include "sha.h"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* hmac * hmac
* *
* Description: * Description:
* This function will compute an HMAC message digest. * This function will compute an HMAC message digest.
* *
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* key: [in] * message_array[ ]: [in]
* The secret shared key.
* key_len: [in]
* The length of the secret shared key.
* message_array: [in]
* An array of octets representing the message. * An array of octets representing the message.
* Note: in RFC 2109, this parameter is known
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Note: in RFC 2104, this parameter is known
* as 'text'. * as 'text'.
* length: [in] * length: [in]
* The length of the message in message_array. * The length of the message in message_array.
* digest: [out] * key[ ]: [in]
* Where the digest is returned. * The secret shared key.
* key_len: [in]
* The length of the secret shared key.
* digest[ ]: [out]
* Where the digest is to be returned.
* NOTE: The length of the digest is determined by * NOTE: The length of the digest is determined by
* the value of whichSha. * the value of whichSha.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmac(SHAversion whichSha, int hmac(SHAversion whichSha,
const unsigned char *message_array, int length, const unsigned char *message_array, int length,
const unsigned char *key, int key_len, const unsigned char *key, int key_len,
skipping to change at page 79, line 4 skipping to change at page 77, line 46
* hmacReset * hmacReset
* *
* Description: * Description:
* This function will initialize the hmacContext in preparation * This function will initialize the hmacContext in preparation
* for computing a new HMAC message digest. * for computing a new HMAC message digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* whichSha: [in] * whichSha: [in]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* key: [in] * key[ ]: [in]
* The secret shared key. * The secret shared key.
* key_len: [in] * key_len: [in]
* The length of the secret shared key. * The length of the secret shared key.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacReset(HMACContext *context, enum SHAversion whichSha, int hmacReset(HMACContext *context, enum SHAversion whichSha,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
const unsigned char *key, int key_len) const unsigned char *key, int key_len)
{ {
int i, blocksize, hashsize, ret; int i, blocksize, hashsize, ret;
/* inner padding - key XORd with ipad */ /* inner padding - key XORd with ipad */
unsigned char k_ipad[USHA_Max_Message_Block_Size]; unsigned char k_ipad[USHA_Max_Message_Block_Size];
/* temporary buffer when keylen > blocksize */ /* temporary buffer when keylen > blocksize */
unsigned char tempkey[USHAMaxHashSize]; unsigned char tempkey[USHAMaxHashSize];
skipping to change at page 80, line 4 skipping to change at page 78, line 45
key = tempkey; key = tempkey;
key_len = hashsize; key_len = hashsize;
} }
/* /*
* The HMAC transform looks like: * The HMAC transform looks like:
* *
* SHA(K XOR opad, SHA(K XOR ipad, text)) * SHA(K XOR opad, SHA(K XOR ipad, text))
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* where K is an n byte key, 0-padded to a total of blocksize bytes, * where K is an n byte key, 0-padded to a total of blocksize bytes,
* ipad is the byte 0x36 repeated blocksize times, * ipad is the byte 0x36 repeated blocksize times,
* opad is the byte 0x5c repeated blocksize times, * opad is the byte 0x5c repeated blocksize times,
* and text is the data being protected. * and text is the data being protected.
*/ */
/* store key into the pads, XOR'd with ipad and opad values */ /* store key into the pads, XOR'd with ipad and opad values */
for (i = 0; i < key_len; i++) { for (i = 0; i < key_len; i++) {
k_ipad[i] = key[i] ^ 0x36; k_ipad[i] = key[i] ^ 0x36;
context->k_opad[i] = key[i] ^ 0x5c; context->k_opad[i] = key[i] ^ 0x5c;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* remaining pad bytes are '\0' XOR'd with ipad and opad values */ /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
for ( ; i < blocksize; i++) { for ( ; i < blocksize; i++) {
k_ipad[i] = 0x36; k_ipad[i] = 0x36;
context->k_opad[i] = 0x5c; context->k_opad[i] = 0x5c;
} }
/* perform inner hash */ /* perform inner hash */
/* init context for 1st pass */ /* init context for 1st pass */
ret = USHAReset(&context->shaContext, whichSha) || ret = USHAReset(&context->shaContext, whichSha) ||
/* and start with inner pad */ /* and start with inner pad */
skipping to change at page 80, line 42 skipping to change at page 79, line 31
/* /*
* hmacInput * hmacInput
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. It may be called multiple times. * of the message. It may be called multiple times.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HMAC context to update * The HMAC context to update
* message_array: [in] * text[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * text_len: [in]
* The length of the message in message_array * The length of the message in text
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacInput(HMACContext *context, const unsigned char *text, int hmacInput(HMACContext *context, const unsigned char *text,
int text_len) int text_len)
{ {
if (!context) return shaNull; if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
/* then text of datagram */ /* then text of datagram */
return context->Corrupted = return context->Corrupted =
USHAInput(&context->shaContext, text, text_len); USHAInput(&context->shaContext, text, text_len);
} }
/* /*
* hmacFinalBits * hmacFinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HMAC context to update * The HMAC context to update
* message_bits: [in] * message_bits: [in]
* The final bits of the message, in the upper portion of the * The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the * byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.) * three bits ###.)
* length: [in] * length: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
skipping to change at page 81, line 53 skipping to change at page 80, line 42
/* /*
* hmacResult * hmacResult
* *
* Description: * Description:
* This function will return the N-byte message digest into the * This function will return the N-byte message digest into the
* Message_Digest array provided by the caller. * Message_Digest array provided by the caller.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the HMAC hash. * The context to use to calculate the HMAC hash.
* digest: [out] * digest[ ]: [out]
* Where the digest is returned. * Where the digest is returned.
* NOTE 2: The length of the hash is determined by the value of * NOTE 2: The length of the hash is determined by the value of
* whichSha that was passed to hmacReset(). * whichSha that was passed to hmacReset().
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacResult(HMACContext *context, uint8_t *digest) int hmacResult(HMACContext *context, uint8_t *digest)
{ {
int ret; int ret;
if (!context) return shaNull; if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* finish up 1st pass */ /* finish up 1st pass */
/* (Use digest here as a temporary buffer.) */ /* (Use digest here as a temporary buffer.) */
ret = ret =
USHAResult(&context->shaContext, digest) || USHAResult(&context->shaContext, digest) ||
/* perform outer SHA */ /* perform outer SHA */
/* init context for 2nd pass */ /* init context for 2nd pass */
USHAReset(&context->shaContext, context->whichSha) || USHAReset(&context->shaContext, context->whichSha) ||
/* start with outer pad */ /* start with outer pad */
skipping to change at page 83, line 4 skipping to change at page 81, line 43
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the HKDF algorithm (HMAC-based * This file implements the HKDF algorithm (HMAC-based
* Extract-and-Expand Key Derivation Function, RFC 5869), * Extract-and-Expand Key Derivation Function, RFC 5869),
* expressed in terms of the various SHA algorithms. * expressed in terms of the various SHA algorithms.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
#include "sha.h" #include "sha.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/* /*
* hkdf * hkdf
* *
* Description: * Description:
* This function will compute an HKDF message digest. * This function will generate keying material using HKDF.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt: [in] * salt[ ]: [in]
* The optional salt value (a non-secret random value); * The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally * if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros. * to a string of HashLen(whichSha) zeros.
* salt_len: [in] * salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.) * The length of the salt value. (Ignored if salt == NULL.)
* ikm: [in] * ikm[ ]: [in]
* Input keying material. * Input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of the input keying material. * The length of the input keying material.
* info: [in] * info[ ]: [in]
* The optional context and application specific information. * The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored. * If info == NULL or a zero-length string, it is ignored.
* info_len: [in] * info_len: [in]
* The length of the optional context and application specific * The length of the optional context and application specific
* information. (Ignored if info == NULL.) * information. (Ignored if info == NULL.)
* okm: [out] * okm[ ]: [out]
* Where the HKDF is to be stored. * Where the HKDF is to be stored.
* okm_len: [in] * okm_len: [in]
* The length of the buffer to hold okm. * The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha) * okm_len must be <= 255 * USHABlockSize(whichSha)
* *
* Notes: * Notes:
* Calls hkdfExtract() and hkdfExpand(). * Calls hkdfExtract() and hkdfExpand().
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdf(SHAversion whichSha, int hkdf(SHAversion whichSha,
const unsigned char *salt, int salt_len, const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len, const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len) uint8_t okm[ ], int okm_len)
{ {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t prk[USHAMaxHashSize]; uint8_t prk[USHAMaxHashSize];
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) || return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
info_len, okm, okm_len); info_len, okm, okm_len);
} }
/* /*
* hkdfExtract * hkdfExtract
* *
* Description: * Description:
* This function will perform HKDF extraction. * This function will perform HKDF extraction.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt: [in] * salt[ ]: [in]
* The optional salt value (a non-secret random value); * The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally * if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros. * to a string of HashLen(whichSha) zeros.
* salt_len: [in] * salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.) * The length of the salt value. (Ignored if salt == NULL.)
* ikm: [in] * ikm[ ]: [in]
* Input keying material. * Input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of the input keying material. * The length of the input keying material.
* prk: [out] * prk[ ]: [out]
* Where the HKDF extraction is to be stored. * Array where the HKDF extraction is to be stored.
* Must be larger than USHAHashSize(whichSha); * Must be larger than USHAHashSize(whichSha);
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfExtract(SHAversion whichSha, int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len, const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len, const unsigned char *ikm, int ikm_len,
uint8_t prk[USHAMaxHashSize]) uint8_t prk[USHAMaxHashSize])
skipping to change at page 85, line 4 skipping to change at page 83, line 45
salt = nullSalt; salt = nullSalt;
salt_len = USHAHashSize(whichSha); salt_len = USHAHashSize(whichSha);
memset(nullSalt, '\0', salt_len); memset(nullSalt, '\0', salt_len);
} else if (salt_len < 0) { } else if (salt_len < 0) {
return shaBadParam; return shaBadParam;
} }
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk); return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* hkdfExpand * hkdfExpand
* *
* Description: * Description:
* This function will perform HKDF expansion. * This function will perform HKDF expansion.
* *
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* info: [in] * prk[ ]: [in]
* The pseudorandom key to be expanded; either obtained
* directly from a cryptographically strong, uniformly
* distributed pseudorandom number generator, or as the
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* output from hkdfExtract().
* prk_len: [in]
* The length of the pseudorandom key in prk;
* should at least be equal to USHAHashSize(whichSHA).
* info[ ]: [in]
* The optional context and application specific information. * The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored. * If info == NULL or a zero-length string, it is ignored.
* info_len: [in] * info_len: [in]
* The length of the optional context and application specific * The length of the optional context and application specific
* information. (Ignored if info == NULL.) * information. (Ignored if info == NULL.)
* okm: [out] * okm[ ]: [out]
* Where the HKDF is to be stored. * Where the HKDF is to be stored.
* okm_len: [in] * okm_len: [in]
* The length of the buffer to hold okm. * The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha) * okm_len must be <= 255 * USHABlockSize(whichSha)
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len, int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len,
skipping to change at page 85, line 43 skipping to change at page 84, line 40
{ {
int hash_len, N; int hash_len, N;
unsigned char T[USHAMaxHashSize]; unsigned char T[USHAMaxHashSize];
int Tlen, where, i; int Tlen, where, i;
if (info == 0) { if (info == 0) {
info = (const unsigned char *)""; info = (const unsigned char *)"";
info_len = 0; info_len = 0;
} else if (info_len < 0) { } else if (info_len < 0) {
return shaBadParam; return shaBadParam;
} else if (prk_len < 0) {
return shaBadParam;
} else if (!okm) {
return shaBadParam;
} }
if (okm_len <= 0) return shaBadParam;
if (!okm) return shaBadParam;
hash_len = USHAHashSize(whichSha); hash_len = USHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam; if (prk_len < hash_len) return shaBadParam;
N = okm_len / hash_len; N = okm_len / hash_len;
if ((okm_len % hash_len) != 0) N++; if ((okm_len % hash_len) != 0) N++;
if (N > 255) return shaBadParam; if (N > 255) return shaBadParam;
Tlen = 0; Tlen = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
where = 0; where = 0;
for (i = 1; i <= N; i++) { for (i = 1; i <= N; i++) {
HMACContext context; HMACContext context;
unsigned char c = i; unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, hash_len) || int ret = hmacReset(&context, whichSha, prk, prk_len) ||
hmacInput(&context, T, Tlen) || hmacInput(&context, T, Tlen) ||
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
hmacInput(&context, info, info_len) || hmacInput(&context, info, info_len) ||
hmacInput(&context, &c, 1) || hmacInput(&context, &c, 1) ||
hmacResult(&context, T); hmacResult(&context, T);
if (ret != shaSuccess) return ret; if (ret != shaSuccess) return ret;
memcpy(okm + where, T, memcpy(okm + where, T,
(i != N) ? hash_len : (okm_len - where)); (i != N) ? hash_len : (okm_len - where));
where += hash_len; where += hash_len;
Tlen = hash_len; Tlen = hash_len;
} }
return shaSuccess; return shaSuccess;
} }
/* /*
* hkdfReset * hkdfReset
* *
* Description: * Description:
* This function will initialize the hkdfContext in preparation * This function will initialize the hkdfContext in preparation
* for computing a new HKDF message digest. It is used for * for key derivation using the modular HKDF interface for
* arbitrary length inputs. * arbitrary length inputs.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt: [in] * salt[ ]: [in]
* The optional salt value (a non-secret random value); * The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally * if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros. * to a string of HashLen(whichSha) zeros.
* salt_len: [in] * salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.) * The length of the salt value. (Ignored if salt == NULL.)
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfReset(HKDFContext *context, enum SHAversion whichSha, int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len) const unsigned char *salt, int salt_len)
{ {
unsigned char nullSalt[USHAMaxHashSize]; unsigned char nullSalt[USHAMaxHashSize];
if (!context) return shaNull; if (!context) return shaNull;
context->whichSha = whichSha; context->whichSha = whichSha;
context->hashSize = USHAHashSize(whichSha); context->hashSize = USHAHashSize(whichSha);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (salt == 0) { if (salt == 0) {
salt = nullSalt; salt = nullSalt;
salt_len = context->hashSize; salt_len = context->hashSize;
memset(nullSalt, '\0', salt_len); memset(nullSalt, '\0', salt_len);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return hmacReset(&context->hmacContext, whichSha, salt, salt_len); return hmacReset(&context->hmacContext, whichSha, salt, salt_len);
} }
/* /*
* hkdfInput * hkdfInput
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the input keying material. It may be called multiple times. * of the input keying material. It may be called multiple times.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HKDF context to update. * The HKDF context to update.
* ikm: [in] * ikm[ ]: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the input keying material. * the input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of ikm. * The length of ikm.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfInput(HKDFContext *context, const unsigned char *ikm, int hkdfInput(HKDFContext *context, const unsigned char *ikm,
skipping to change at page 88, line 4 skipping to change at page 86, line 51
* *
* Description: * Description:
* This function will add in any final bits of the * This function will add in any final bits of the
* input keying material. * input keying material.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HKDF context to update * The HKDF context to update
* ikm_bits: [in] * ikm_bits: [in]
* The final bits of the input keying material, in the upper * The final bits of the input keying material, in the upper
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* portion of the byte. (Use 0b###00000 instead of 0b00000### * portion of the byte. (Use 0b###00000 instead of 0b00000###
* to input the three bits ###.) * to input the three bits ###.)
* ikm_bit_count: [in] * ikm_bit_count: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* sha Error Code. * sha Error Code.
*/ */
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count) unsigned int ikm_bit_count)
{ {
if (!context) return shaNull; if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
return hmacFinalBits(&context->hmacContext, ikm_bits, ikm_bit_count); return hmacFinalBits(&context->hmacContext, ikm_bits, ikm_bit_count);
} }
skipping to change at page 88, line 34 skipping to change at page 87, line 28
/* /*
* hkdfResult * hkdfResult
* *
* Description: * Description:
* This function will finish the HKDF extraction and perform the * This function will finish the HKDF extraction and perform the
* final HKDF expansion. * final HKDF expansion.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HKDF context to use to calculate the HKDF hash. * The HKDF context to use to calculate the HKDF hash.
* prk: [out] * prk[ ]: [out]
* An optional location to store the HKDF extraction. * An optional location to store the HKDF extraction.
* Either NULL, or pointer to a buffer that must be * Either NULL, or pointer to a buffer that must be
* larger than USHAHashSize(whichSha); * larger than USHAHashSize(whichSha);
* info: [in] * info[ ]: [in]
* The optional context and application specific information. * The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored. * If info == NULL or a zero-length string, it is ignored.
* info_len: [in] * info_len: [in]
* The length of the optional context and application specific * The length of the optional context and application specific
* information. (Ignored if info == NULL.) * information. (Ignored if info == NULL.)
* okm: [out] * okm[ ]: [out]
* Where the HKDF is to be stored. * Where the HKDF is to be stored.
* okm_len: [in] * okm_len: [in]
* The length of the buffer to hold okm. * The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha) * okm_len must be <= 255 * USHABlockSize(whichSha)
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfResult(HKDFContext *context, int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize], uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t okm[ ], int okm_len) uint8_t okm[ ], int okm_len)
{ {
uint8_t prkbuf[USHAMaxHashSize]; uint8_t prkbuf[USHAMaxHashSize];
int ret; int ret;
if (!context) return shaNull; if (!context) return shaNull;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
if (!okm) return context->Corrupted = shaBadParam; if (!okm) return context->Corrupted = shaBadParam;
if (!prk) prk = prkbuf; if (!prk) prk = prkbuf;
ret = hmacResult(&context->hmacContext, prk) || ret = hmacResult(&context->hmacContext, prk) ||
hkdfExpand(context->whichSha, prk, context->hashSize, info, hkdfExpand(context->whichSha, prk, context->hashSize, info,
info_len, okm, okm_len); info_len, okm, okm_len);
context->Computed = 1; context->Computed = 1;
return context->Corrupted = ret; return context->Corrupted = ret;
skipping to change at page 89, line 43 skipping to change at page 88, line 37
/************************** shatest.c **************************/ /************************** shatest.c **************************/
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file will exercise the SHA code performing * This file will exercise the SHA code performing
* the three tests documented in FIPS PUB 180-2 * the three tests documented in FIPS PUB 180-3
* (http://csrc.nist.gov/publications/fips/ * (http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf) * fips180-2/fips180-2withchangenotice.pdf)
* one that calls SHAInput with an exact multiple of 512 bits * one that calls SHAInput with an exact multiple of 512 bits
* the seven tests documented for each algorithm in * the seven tests documented for each algorithm in
* "The Secure Hash Algorithm Validation System (SHAVS)" * "The Secure Hash Algorithm Validation System (SHAVS)"
* (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf), * (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf),
* three of which are bit-level tests * three of which are bit-level tests
* *
* These tests have subsequently been moved to pages linked from
* http://csrc.nist.gov/groups/ST/toolkit/examples.html
*
* This file will exercise the HMAC SHA1 code performing * This file will exercise the HMAC SHA1 code performing
* the seven tests documented in RFCs [RFC 2202] and [RFC 4231]. * the seven tests documented in RFCs [RFC 2202] and [RFC 4231].
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* This file will exercise the HKDF code performing * This file will exercise the HKDF code performing
* the seven tests documented in RFC 4869. * the seven tests documented in RFC 4869.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* To run the tests and just see PASSED/FAILED, use the -p option. * To run the tests and just see PASSED/FAILED, use the -p option.
* *
* Other options exercise: * Other options exercise:
* hashing an arbitrary string * hashing an arbitrary string
* hashing a file's contents * hashing a file's contents
* a few error test checks * a few error test checks
* printing the results in raw format * printing the results in raw format
* *
* Portability Issues: * Portability Issues:
* None. * None.
skipping to change at page 91, line 4 skipping to change at page 89, line 54
/* an exact multiple of 512 bits */ /* an exact multiple of 512 bits */
#define TEST4 TEST4a TEST4b /* times 10 */ #define TEST4 TEST4a TEST4b /* times 10 */
#define TEST7_1 \ #define TEST7_1 \
"\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8" "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8"
#define TEST8_1 \ #define TEST8_1 \
"\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46" "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46"
#define TEST9_1 \ #define TEST9_1 \
"\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \ "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \
"\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \ "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \ "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \
"\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \ "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \
"\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a" "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define TEST10_1 \ #define TEST10_1 \
"\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \ "\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \
"\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \ "\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \
"\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \ "\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \
"\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \ "\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \
"\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \ "\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \
"\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \ "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \
"\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \ "\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \
"\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \ "\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \
"\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \ "\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \
skipping to change at page 92, line 4 skipping to change at page 90, line 54
"\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52" "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52"
#define TEST9_256 \ #define TEST9_256 \
"\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \ "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \
"\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \ "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \
"\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \ "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \
"\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \ "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \
"\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3" "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3"
#define TEST10_256 \ #define TEST10_256 \
"\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \ "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \
"\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \ "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \ "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \
"\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \ "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \
"\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \ "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \ "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \
"\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \ "\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \
"\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \ "\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \
"\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \ "\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \
"\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \ "\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \
"\x3d\x54\xd6" "\x3d\x54\xd6"
#define TEST7_384 \ #define TEST7_384 \
"\x8b\xc5\x00\xc7\x7c\xee\xd9\x87\x9d\xa9\x89\x10\x7c\xe0\xaa" "\x8b\xc5\x00\xc7\x7c\xee\xd9\x87\x9d\xa9\x89\x10\x7c\xe0\xaa"
#define TEST8_384 \ #define TEST8_384 \
"\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1\x0a\x7f\x4e\x08\x59\x17\x39" "\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1\x0a\x7f\x4e\x08\x59\x17\x39"
skipping to change at page 93, line 4 skipping to change at page 91, line 54
"\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70" "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70"
#define TEST8_512 \ #define TEST8_512 \
"\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0" "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0"
#define TEST9_512 \ #define TEST9_512 \
"\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \ "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \
"\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \ "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \
"\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \ "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \
"\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \ "\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \
"\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \ "\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \
"\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \ "\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \ "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \
"\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \ "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \
"\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06" "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define TEST10_512 \ #define TEST10_512 \
"\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \ "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \
"\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \ "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \
"\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \ "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \
"\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \ "\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \
"\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \ "\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \
"\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \ "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \
"\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \ "\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \
"\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \ "\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \
"\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \ "\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \
skipping to change at page 94, line 4 skipping to change at page 92, line 54
#define HMACTESTCOUNT 7 #define HMACTESTCOUNT 7
#define HKDFTESTCOUNT 7 #define HKDFTESTCOUNT 7
#define PRINTNONE 0 #define PRINTNONE 0
#define PRINTTEXT 1 #define PRINTTEXT 1
#define PRINTRAW 2 #define PRINTRAW 2
#define PRINTHEX 3 #define PRINTHEX 3
#define PRINTBASE64 4 #define PRINTBASE64 4
#define PRINTPASSFAIL 1 #define PRINTPASSFAIL 1
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define PRINTFAIL 2 #define PRINTFAIL 2
#define length(x) (sizeof(x)-1) #define length(x) (sizeof(x)-1)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Test arrays for hashes. */ /* Test arrays for hashes. */
struct hash { struct hash {
const char *name; const char *name;
SHAversion whichSha; SHAversion whichSha;
int hashsize; int hashsize;
struct { struct {
const char *testarray; const char *testarray;
int length; int length;
long repeatcount; long repeatcount;
skipping to change at page 95, line 4 skipping to change at page 93, line 52
/* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0, /* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0,
"CB0082C8F197D260991BA6A460E76E202BAD27B3" } "CB0082C8F197D260991BA6A460E76E202BAD27B3" }
}, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4", }, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4",
"A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC", "A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC",
"DB1F9050BB863DFEF4CE37186044E2EEB17EE013", "DB1F9050BB863DFEF4CE37186044E2EEB17EE013",
"127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B" "127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B"
} }, } },
{ "SHA224", SHA224, SHA224HashSize, { "SHA224", SHA224, SHA224HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" }, "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" },
/* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0,
"75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" }, "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"20794655980C91D8BBB4C1EA97618A4BF03F42581948B2EE4EE7AD67" }, "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2EE4EE7AD67" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0, /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
"567F69F168CD7844E65259CE658FE7AADFA25216E68ECA0EB7AB8262" }, "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA0EB7AB8262" },
/* 5 */ { "", 0, 0, 0x68, 5, /* 5 */ { "", 0, 0, 0x68, 5,
"E3B048552C3C387BCAB37F6EB06BB79B96A4AEE5FF27F51531A9551C" }, "E3B048552C3C387BCAB37F6EB06BB79B96A4AEE5FF27F51531A9551C" },
/* 6 */ { "\x07", 1, 1, 0, 0, /* 6 */ { "\x07", 1, 1, 0, 0,
"00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450BEE2AA8C2A" }, "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450BEE2AA8C2A" },
/* 7 */ { TEST7_224, length(TEST7_224), 1, 0xA0, 3, /* 7 */ { TEST7_224, length(TEST7_224), 1, 0xA0, 3,
"1B01DB6CB4A9E43DED1516BEB3DB0B87B6D1EA43187462C608137150" }, "1B01DB6CB4A9E43DED1516BEB3DB0B87B6D1EA43187462C608137150" },
/* 8 */ { TEST8_224, length(TEST8_224), 1, 0, 0, /* 8 */ { TEST8_224, length(TEST8_224), 1, 0, 0,
skipping to change at page 96, line 4 skipping to change at page 94, line 53
"9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" }, "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" },
/* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA" /* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA"
"9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" }, "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" },
/* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646" /* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646"
"8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" }, "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" },
/* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D" /* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D"
"F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" }, "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" },
}, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44" }, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44"
"EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399" "EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399"
"5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7" "5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408" "25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408"
"E31536B70FF906EC51B00447CA97D7DD97C12411F4" "E31536B70FF906EC51B00447CA97D7DD97C12411F4"
} }, } },
{ "SHA384", SHA384, SHA384HashSize, { "SHA384", SHA384, SHA384HashSize,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163" "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163"
"1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7" }, "1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7" },
/* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
"09330C33F71147E83D192FC782CD1B4753111B173B3B05D2" "09330C33F71147E83D192FC782CD1B4753111B173B3B05D2"
"2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039" }, "2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
"9D0E1809716474CB086E834E310A4A1CED149E9C00F24852" "9D0E1809716474CB086E834E310A4A1CED149E9C00F24852"
"7972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985" }, "7972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985" },
skipping to change at page 97, line 4 skipping to change at page 95, line 53
"638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2" "638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2"
"5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7" "5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7"
} }, } },
{ "SHA512", SHA512, SHA512HashSize, { "SHA512", SHA512, SHA512HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2"
"0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD"
"454D4423643CE80E2A9AC94FA54CA49F" }, "454D4423643CE80E2A9AC94FA54CA49F" },
/* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1"
"7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A"
"C7D329EEB6DD26545E96E55B874BE909" }, "C7D329EEB6DD26545E96E55B874BE909" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428" "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428"
"5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B" "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B"
"EB009C5C2C49AA2E4EADB217AD8CC09B" }, "EB009C5C2C49AA2E4EADB217AD8CC09B" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0, /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
"89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024" "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024"
"DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51" "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51"
"0813A39CD5A84C4ACAA64D3F3FB7BAE9" }, "0813A39CD5A84C4ACAA64D3F3FB7BAE9" },
/* 5 */ { "", 0, 0, 0xB0, 5, /* 5 */ { "", 0, 0, 0xB0, 5,
"D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0" "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0"
"720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2" "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2"
skipping to change at page 98, line 4 skipping to change at page 96, line 53
"92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B" "92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B"
"6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D" "6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D"
"19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877" "19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877"
"6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F" "6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F"
} }
} }
}; };
/* Test arrays for HMAC. */ /* Test arrays for HMAC. */
struct hmachash { struct hmachash {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
const char *keyarray[5]; const char *keyarray[5];
int keylength[5]; int keylength[5];
const char *dataarray[5]; const char *dataarray[5];
int datalength[5]; int datalength[5];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
const char *resultarray[5]; const char *resultarray[5];
int resultlength[5]; int resultlength[5];
} hmachashes[HMACTESTCOUNT] = { } hmachashes[HMACTESTCOUNT] = {
{ /* 1 */ { { /* 1 */ {
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b"
}, { 20 }, { }, { 20 }, {
"\x48\x69\x20\x54\x68\x65\x72\x65" /* "Hi There" */ "\x48\x69\x20\x54\x68\x65\x72\x65" /* "Hi There" */
}, { 8 }, { }, { 8 }, {
/* HMAC-SHA-1 */ /* HMAC-SHA-1 */
skipping to change at page 99, line 4 skipping to change at page 97, line 53
"A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44", "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC" "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC"
"3843", "3843",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322" "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322"
"445E8E2240CA5E69E2C78B3239ECFAB21649", "445E8E2240CA5E69E2C78B3239ECFAB21649",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25" "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25"
"05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A" "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"38BCE737" "38BCE737"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
}, },
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ /* 3 */ { /* 3 */
{ {
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa"
}, { 20 }, { }, { 20 }, {
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd"
}, { 50 }, { }, { 50 }, {
skipping to change at page 100, line 4 skipping to change at page 98, line 53
/* HMAC-SHA-1 */ /* HMAC-SHA-1 */
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA", "4C9007F4026250C6BC8414F9BF50C86C2D7235DA",
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A", "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729" "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729"
"665B", "665B",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57" "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57"
"3B4E6801DD23C4A7D679CCF8A386C674CFFB", "3B4E6801DD23C4A7D679CCF8A386C674CFFB",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E" "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E"
"E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB" "E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB"
"10A298DD" "10A298DD"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
}, },
{ /* 5 */ { { /* 5 */ {
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c"
}, { 20 }, { }, { 20 }, {
"Test With Truncation" "Test With Truncation"
}, { 20 }, { }, { 20 }, {
/* HMAC-SHA-1 */ /* HMAC-SHA-1 */
skipping to change at page 101, line 4 skipping to change at page 99, line 53
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E", "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3" "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3"
"7F54", "7F54",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A" "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A"
"C4C60C2EF6AB4030FE8296248DF163F44952", "C4C60C2EF6AB4030FE8296248DF163F44952",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8" "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98" "F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98"
"5D786598" "5D786598"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}, },
{ /* 7 */ { { /* 7 */ {
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
skipping to change at page 102, line 4 skipping to change at page 100, line 53
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E" "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E"
"99C5A678CC31E799176D3860E6110C46523E", "99C5A678CC31E799176D3860E6110C46523E",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD" "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD"
"C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440" "C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440"
"FA8C6A58" "FA8C6A58"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}; };
/* Test arrays for HKDF. */ /* Test arrays for HKDF. */
struct hkdfhash { struct hkdfhash {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SHAversion whichSha; SHAversion whichSha;
int ikmlength; int ikmlength;
const char *ikmarray; const char *ikmarray;
int saltlength; int saltlength;
const char *saltarray; const char *saltarray;
int infolength; int infolength;
const char *infoarray; const char *infoarray;
int prklength; int prklength;
const char *prkarray; const char *prkarray;
int okmlength; int okmlength;
skipping to change at page 103, line 4 skipping to change at page 101, line 52
"\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
80, "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd" 80, "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd"
"\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb" "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb"
"\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9"
"\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
"\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5" "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5"
"\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
32, "06A6B88C5853361A06104C9CEB35B45C" 32, "06A6B88C5853361A06104C9CEB35B45C"
"EF760014904671014A193F40C15FC244", "EF760014904671014A193F40C15FC244",
82, "B11E398DC80327A1C8E7F78C596A4934" 82, "B11E398DC80327A1C8E7F78C596A4934"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"4F012EDA2D4EFAD8A050CC4C19AFA97C" "4F012EDA2D4EFAD8A050CC4C19AFA97C"
"59045A99CAC7827271CB41C65E590E09" "59045A99CAC7827271CB41C65E590E09"
"DA3275600C2F09B8367793A9ACA3DB71" "DA3275600C2F09B8367793A9ACA3DB71"
"CC30C58179EC3E87C14C01D5C1F3434F" "CC30C58179EC3E87C14C01D5C1F3434F"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"1D87" "1D87"
}, },
{ /* RFC 5869 A.3. Test Case 3 */ { /* RFC 5869 A.3. Test Case 3 */
SHA256, SHA256,
22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
0, "", 0, "",
0, "", 0, "",
32, "19EF24A32C717B167F33A91D6F648BDF" 32, "19EF24A32C717B167F33A91D6F648BDF"
"96596776AFDB6377AC434C1C293CCB04", "96596776AFDB6377AC434C1C293CCB04",
skipping to change at page 104, line 4 skipping to change at page 102, line 53
"\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5" "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5"
"\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", "\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF",
80, "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD" 80, "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD"
"\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB" "\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB"
"\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9" "\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9"
"\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7" "\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7"
"\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5" "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5"
"\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", "\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF",
20, "8ADAE09A2A307059478D309B26C4115A224CFAF6", 20, "8ADAE09A2A307059478D309B26C4115A224CFAF6",
82, "0BD770A74D1160F7C9F12CD5912A06EB" 82, "0BD770A74D1160F7C9F12CD5912A06EB"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"FF6ADCAE899D92191FE4305673BA2FFE" "FF6ADCAE899D92191FE4305673BA2FFE"
"8FA3F1A4E5AD79F3F334B3B202B2173C" "8FA3F1A4E5AD79F3F334B3B202B2173C"
"486EA37CE3D397ED034C7F9DFEB15C5E" "486EA37CE3D397ED034C7F9DFEB15C5E"
"927336D0441F4C4300E2CFF0D0900B52" "927336D0441F4C4300E2CFF0D0900B52"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"D3B4" "D3B4"
}, },
{ /* RFC 5869 A.6. Test Case 6 */ { /* RFC 5869 A.6. Test Case 6 */
SHA1, SHA1,
22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 22, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
0, "", 0, "",
0, "", 0, "",
20, "DA8C8A73C7FA77288EC6F5E7C297786AA0D32D01", 20, "DA8C8A73C7FA77288EC6F5E7C297786AA0D32D01",
42, "0AC1AF7002B3D761D1E55298DA9D0506" 42, "0AC1AF7002B3D761D1E55298DA9D0506"
skipping to change at page 105, line 4 skipping to change at page 103, line 53
return 0; return 0;
if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0; if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0;
} }
return 1; return 1;
} }
/* /*
* Print the string, converting non-printable characters to "." * Print the string, converting non-printable characters to "."
*/ */
void printstr(const char *str, int len) void printstr(const char *str, int len)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ {
for ( ; len-- > 0; str++) for ( ; len-- > 0; str++)
putchar(isprint((unsigned char)*str) ? *str : '.'); putchar(isprint((unsigned char)*str) ? *str : '.');
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Print the string, converting all characters to hex "## ". * Print the string, converting all characters to hex "## ".
*/ */
void printxstr(const char *str, int len) void printxstr(const char *str, int len)
{ {
char *sep = ""; char *sep = "";
for ( ; len-- > 0; str++) { for ( ; len-- > 0; str++) {
printf("%s%c%c", sep, hexdigits[(*str >> 4) & 0xF], printf("%s%c%c", sep, hexdigits[(*str >> 4) & 0xF],
hexdigits[*str & 0xF]); hexdigits[*str & 0xF]);
skipping to change at page 106, line 4 skipping to change at page 104, line 51
"\t%s [-m | -d] [-l loopcount] [-t test#] [-e]\n" "\t%s [-m | -d] [-l loopcount] [-t test#] [-e]\n"
"\t\t[-r randomseed] [-R randomloop-count] " "\t\t[-r randomseed] [-R randomloop-count] "
"[-p] [-P|-X]\n" "[-p] [-P|-X]\n"
"-h\thash to test: " "-h\thash to test: "
"0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n" "0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n"
"-m\tperform hmac standard tests\n" "-m\tperform hmac standard tests\n"
"-k\tkey for hmac test\n" "-k\tkey for hmac test\n"
"-d\tperform hkdf standard tests\n" "-d\tperform hkdf standard tests\n"
"-t\ttest case to run, 1-10\n" "-t\ttest case to run, 1-10\n"
"-l\thow many times to run the test\n" "-l\thow many times to run the test\n"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"-e\ttest error returns\n" "-e\ttest error returns\n"
"-p\tdo not print results\n" "-p\tdo not print results\n"
"-P\tdo not print PASSED/FAILED\n" "-P\tdo not print PASSED/FAILED\n"
"-X\tprint FAILED, but not PASSED\n" "-X\tprint FAILED, but not PASSED\n"
"-r\tseed for random test\n" "-r\tseed for random test\n"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"-R\thow many times to run random test\n" "-R\thow many times to run random test\n"
"-s\tstring to hash\n" "-s\tstring to hash\n"
"-S\texpected result of hashed string, in hex\n" "-S\texpected result of hashed string, in hex\n"
"-w\toutput hash in raw format\n" "-w\toutput hash in raw format\n"
"-x\toutput hash in hex format\n" "-x\toutput hash in hex format\n"
"-6\toutput hash in base64 format\n" "-6\toutput hash in base64 format\n"
"-B\t# extra bits to add in after string or file input\n" "-B\t# extra bits to add in after string or file input\n"
"-b\textra bits to add (high order bits of #, 0# or 0x#)\n" "-b\textra bits to add (high order bits of #, 0# or 0x#)\n"
"-H\tinput hashstr or randomseed is in hex\n" "-H\tinput hashstr or randomseed is in hex\n"
, argv0, argv0, argv0, argv0); , argv0, argv0, argv0, argv0);
skipping to change at page 107, line 4 skipping to change at page 105, line 52
putchar(hexdigits[Message_Digest[i] & 0xF]); putchar(hexdigits[Message_Digest[i] & 0xF]);
} }
putchar('\n'); putchar('\n');
} else if (printResults == PRINTBASE64) { } else if (printResults == PRINTBASE64) {
unsigned char b; unsigned char b;
char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789+/"; "0123456789+/";
for (i = 0; i < hashsize; i += 3) { for (i = 0; i < hashsize; i += 3) {
putchar(sm[Message_Digest[i] >> 2]); putchar(sm[Message_Digest[i] >> 2]);
b = (Message_Digest[i] & 0x03) << 4; b = (Message_Digest[i] & 0x03) << 4;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (i+1 < hashsize) b |= Message_Digest[i+1] >> 4; if (i+1 < hashsize) b |= Message_Digest[i+1] >> 4;
putchar(sm[b]); putchar(sm[b]);
if (i+1 < hashsize) { if (i+1 < hashsize) {
b = (Message_Digest[i+1] & 0x0f) << 2; b = (Message_Digest[i+1] & 0x0f) << 2;
if (i+2 < hashsize) b |= Message_Digest[i+2] >> 6; if (i+2 < hashsize) b |= Message_Digest[i+2] >> 6;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
putchar(sm[b]); putchar(sm[b]);
} else putchar('='); } else putchar('=');
if (i+2 < hashsize) putchar(sm[Message_Digest[i+2] & 0x3f]); if (i+2 < hashsize) putchar(sm[Message_Digest[i+2] & 0x3f]);
else putchar('='); else putchar('=');
} }
putchar('\n'); putchar('\n');
} }
if (printResults && resultarray) { if (printResults && resultarray) {
printf(" Should match:\n\t"); printf(" Should match:\n\t");
skipping to change at page 108, line 5 skipping to change at page 106, line 53
int printPassFail) int printPassFail)
{ {
USHAContext sha; USHAContext sha;
HMACContext hmac; HMACContext hmac;
HKDFContext hkdf; HKDFContext hkdf;
int err, i; int err, i;
uint8_t Message_Digest_Buf[USHAMaxHashSize]; uint8_t Message_Digest_Buf[USHAMaxHashSize];
uint8_t *Message_Digest = Message_Digest_Buf; uint8_t *Message_Digest = Message_Digest_Buf;
char buf[20]; char buf[20];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (printResults == PRINTTEXT) { if (printResults == PRINTTEXT) {
printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1, printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1,
loopno, repeatcount); loopno, repeatcount);
printstr(testarray, length); printstr(testarray, length);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
printf("'\n\t'"); printf("'\n\t'");
printxstr(testarray, length); printxstr(testarray, length);
printf("'\n"); printf("'\n");
printf(" Length=%d bytes (%d bits), ", length, length * 8); printf(" Length=%d bytes (%d bits), ", length, length * 8);
printf("ExtraBits %d: %2.2x\n", numberExtrabits, extrabits); printf("ExtraBits %d: %2.2x\n", numberExtrabits, extrabits);
} }
if (info) Message_Digest = malloc(okmlen); if (info) Message_Digest = malloc(okmlen);
memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */ memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */
memset(&hmac, '\343', sizeof(hmac)); memset(&hmac, '\343', sizeof(hmac));
skipping to change at page 109, line 4 skipping to change at page 107, line 53
err = info ? hkdfFinalBits(&hkdf, extrabits, numberExtrabits) : err = info ? hkdfFinalBits(&hkdf, extrabits, numberExtrabits) :
keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits, keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits,
numberExtrabits) : numberExtrabits) :
USHAFinalBits(&sha, (uint8_t) extrabits, USHAFinalBits(&sha, (uint8_t) extrabits,
numberExtrabits); numberExtrabits);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hash(): %sFinalBits Error %d.\n", fprintf(stderr, "hash(): %sFinalBits Error %d.\n",
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
err = info ? hkdfResult(&hkdf, 0, info, infolen, err = info ? hkdfResult(&hkdf, 0, info, infolen,
Message_Digest, okmlen) : Message_Digest, okmlen) :
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
keyarray ? hmacResult(&hmac, Message_Digest) : keyarray ? hmacResult(&hmac, Message_Digest) :
USHAResult(&sha, Message_Digest); USHAResult(&sha, Message_Digest);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hash(): %s Result Error %d, could not compute " fprintf(stderr, "hash(): %s Result Error %d, could not compute "
"message digest.\n", "message digest.\n",
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
return err; return err;
} }
sprintf(buf, "%d", testno+1); sprintf(buf, "%d", testno+1);
skipping to change at page 110, line 4 skipping to change at page 108, line 53
printxstr(hkdfhashes[testno].ikmarray, printxstr(hkdfhashes[testno].ikmarray,
hkdfhashes[testno].ikmlength); hkdfhashes[testno].ikmlength);
printf("'\n\tINFO\t'"); printf("'\n\tINFO\t'");
printxstr(hkdfhashes[testno].infoarray, printxstr(hkdfhashes[testno].infoarray,
hkdfhashes[testno].infolength); hkdfhashes[testno].infolength);
printf("'\n"); printf("'\n");
printf(" L=%d bytes\n", hkdfhashes[testno].okmlength); printf(" L=%d bytes\n", hkdfhashes[testno].okmlength);
} }
/* Run hkdf() against the test vectors */ /* Run hkdf() against the test vectors */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
err = hkdf(hkdfhashes[testno].whichSha, err = hkdf(hkdfhashes[testno].whichSha,
(const uint8_t *) hkdfhashes[testno].saltarray, (const uint8_t *) hkdfhashes[testno].saltarray,
hkdfhashes[testno].saltlength, hkdfhashes[testno].saltlength,
(const uint8_t *) hkdfhashes[testno].ikmarray, (const uint8_t *) hkdfhashes[testno].ikmarray,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
hkdfhashes[testno].ikmlength, hkdfhashes[testno].ikmlength,
(const uint8_t *) hkdfhashes[testno].infoarray, (const uint8_t *) hkdfhashes[testno].infoarray,
hkdfhashes[testno].infolength, okm, hkdfhashes[testno].infolength, okm,
hkdfhashes[testno].okmlength); hkdfhashes[testno].okmlength);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashHkdf(): hkdf Error %d.\n", err); fprintf(stderr, "hashHkdf(): hkdf Error %d.\n", err);
return err; return err;
} }
sprintf(buf, "hkdf %d", testno+1); sprintf(buf, "hkdf %d", testno+1);
printResult(okm, hkdfhashes[testno].okmlength, printResult(okm, hkdfhashes[testno].okmlength,
skipping to change at page 111, line 4 skipping to change at page 109, line 53
fprintf(stderr, "hashHkdf(): hkdfExpand Error %d.\n", err); fprintf(stderr, "hashHkdf(): hkdfExpand Error %d.\n", err);
return err; return err;
} }
sprintf(buf, "hkdfExpand %d", testno+1); sprintf(buf, "hkdfExpand %d", testno+1);
printResult(okm, hkdfhashes[testno].okmlength, printResult(okm, hkdfhashes[testno].okmlength,
USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test",
buf, hkdfhashes[testno].okmarray, printResults, printPassFail); buf, hkdfhashes[testno].okmarray, printResults, printPassFail);
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Exercise a hash series of functions. The input is a filename. * Exercise a hash series of functions. The input is a filename.
* If the result is known, it is in resultarray in uppercase hex. * If the result is known, it is in resultarray in uppercase hex.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
int hashfile(int hashno, const char *hashfilename, int bits, int hashfile(int hashno, const char *hashfilename, int bits,
int bitcount, int skipSpaces, const unsigned char *keyarray, int bitcount, int skipSpaces, const unsigned char *keyarray,
int keylen, const unsigned char *info, int infolen, int okmlen, int keylen, const unsigned char *info, int infolen, int okmlen,
const char *resultarray, int hashsize, const char *resultarray, int hashsize,
int printResults, int printPassFail) int printResults, int printPassFail)
{ {
USHAContext sha; USHAContext sha;
HMACContext hmac; HMACContext hmac;
HKDFContext hkdf; HKDFContext hkdf;
skipping to change at page 112, line 4 skipping to change at page 110, line 54
if (skipSpaces) if (skipSpaces)
while ((c = getc(hashfp)) != EOF) { while ((c = getc(hashfp)) != EOF) {
if (!isspace(c)) { if (!isspace(c)) {
cc = (unsigned char)c; cc = (unsigned char)c;
err = info ? hkdfInput(&hkdf, &cc, 1) : err = info ? hkdfInput(&hkdf, &cc, 1) :
keyarray ? hmacInput(&hmac, &cc, 1) : keyarray ? hmacInput(&hmac, &cc, 1) :
USHAInput(&sha, &cc, 1); USHAInput(&sha, &cc, 1);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashfile(): %sInput Error %d.\n", fprintf(stderr, "hashfile(): %sInput Error %d.\n",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
} }
} }
else else
while ((nread = fread(buf, 1, sizeof(buf), hashfp)) > 0) { while ((nread = fread(buf, 1, sizeof(buf), hashfp)) > 0) {
err = info ? hkdfInput(&hkdf, buf, nread) : err = info ? hkdfInput(&hkdf, buf, nread) :
keyarray ? hmacInput(&hmac, buf, nread) : keyarray ? hmacInput(&hmac, buf, nread) :
USHAInput(&sha, buf, nread); USHAInput(&sha, buf, nread);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashfile(): %s Error %d.\n", fprintf(stderr, "hashfile(): %s Error %d.\n",
skipping to change at page 113, line 4 skipping to change at page 111, line 54
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
} }
printResult(Message_Digest, info ? okmlen : hashsize, printResult(Message_Digest, info ? okmlen : hashsize,
hashes[hashno].name, "file", hashfilename, resultarray, hashes[hashno].name, "file", hashfilename, resultarray,
printResults, printPassFail); printResults, printPassFail);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
if (info) free(Message_Digest); if (info) free(Message_Digest);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Exercise a hash series of functions through multiple permutations. * Exercise a hash series of functions through multiple permutations.
* The input is an initial seed. That seed is replicated 3 times. * The input is an initial seed. That seed is replicated 3 times.
* For 1000 rounds, the previous three results are used as the input. * For 1000 rounds, the previous three results are used as the input.
* This result is then checked, and used to seed the next cycle. * This result is then checked, and used to seed the next cycle.
* If the result is known, it is in resultarrays in uppercase hex. * If the result is known, it is in resultarrays in uppercase hex.
*/ */
void randomtest(int hashno, const char *seed, int hashsize, void randomtest(int hashno, const char *seed, int hashsize,
const char **resultarrays, int randomcount, const char **resultarrays, int randomcount,
skipping to change at page 114, line 4 skipping to change at page 112, line 53
} }
/* MDj = Seed = MDi; */ /* MDj = Seed = MDi; */
memcpy(SEED, MD[i-1], hashsize); memcpy(SEED, MD[i-1], hashsize);
/* OUTPUT: MDj */ /* OUTPUT: MDj */
sprintf(buf, "%d", j); sprintf(buf, "%d", j);
printResult(SEED, hashsize, hashes[hashno].name, "random test", printResult(SEED, hashsize, hashes[hashno].name, "random test",
buf, resultarrays ? resultarrays[j] : 0, printResults, buf, resultarrays ? resultarrays[j] : 0, printResults,
(j < RANDOMCOUNT) ? printPassFail : 0); (j < RANDOMCOUNT) ? printPassFail : 0);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Look up a hash name. * Look up a hash name.
*/ */
int findhash(const char *argv0, const char *opt) int findhash(const char *argv0, const char *opt)
{ {
int i; int i;
const char *names[HASHCOUNT][2] = { const char *names[HASHCOUNT][2] = {
{ "0", "sha1" }, { "1", "sha224" }, { "2", "sha256" }, { "0", "sha1" }, { "1", "sha224" }, { "2", "sha256" },
{ "3", "sha384" }, { "4", "sha512" } { "3", "sha384" }, { "4", "sha512" }
skipping to change at page 115, line 4 skipping to change at page 113, line 53
printf ("\nError %d. Should be %d.\n", err, shaStateError); printf ("\nError %d. Should be %d.\n", err, shaStateError);
if ((printPassFail == PRINTPASSFAIL) || if ((printPassFail == PRINTPASSFAIL) ||
((printPassFail == PRINTFAIL) && (err != shaStateError))) ((printPassFail == PRINTFAIL) && (err != shaStateError)))
printf("%s se: %s\n", hashes[hashno].name, printf("%s se: %s\n", hashes[hashno].name,
(err == shaStateError) ? "PASSED" : "FAILED"); (err == shaStateError) ? "PASSED" : "FAILED");
err = USHAFinalBits(&usha, 0x80, 3); err = USHAFinalBits(&usha, 0x80, 3);
if (printResults == PRINTTEXT) if (printResults == PRINTTEXT)
printf ("\nError %d. Should be %d.\n", err, shaStateError); printf ("\nError %d. Should be %d.\n", err, shaStateError);
if ((printPassFail == PRINTPASSFAIL) || if ((printPassFail == PRINTPASSFAIL) ||
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
((printPassFail == PRINTFAIL) && (err != shaStateError))) ((printPassFail == PRINTFAIL) && (err != shaStateError)))
printf("%s se: %s\n", hashes[hashno].name, printf("%s se: %s\n", hashes[hashno].name,
(err == shaStateError) ? "PASSED" : "FAILED"); (err == shaStateError) ? "PASSED" : "FAILED");
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
err = USHAReset(0, hashes[hashno].whichSha); err = USHAReset(0, hashes[hashno].whichSha);
if (printResults == PRINTTEXT) if (printResults == PRINTTEXT)
printf("\nError %d. Should be %d.\n", err, shaNull); printf("\nError %d. Should be %d.\n", err, shaNull);
if ((printPassFail == PRINTPASSFAIL) || if ((printPassFail == PRINTPASSFAIL) ||
((printPassFail == PRINTFAIL) && (err != shaNull))) ((printPassFail == PRINTFAIL) && (err != shaNull)))
printf("%s usha null: %s\n", hashes[hashno].name, printf("%s usha null: %s\n", hashes[hashno].name,
(err == shaNull) ? "PASSED" : "FAILED"); (err == shaNull) ? "PASSED" : "FAILED");
switch (hashno) { switch (hashno) {
case SHA1: err = SHA1Reset(0); break; case SHA1: err = SHA1Reset(0); break;
skipping to change at page 116, line 4 skipping to change at page 114, line 53
printf("\nError: bad hex character '%c'\n", *hexstr); printf("\nError: bad hex character '%c'\n", *hexstr);
} }
if (!*++hexstr) break; if (!*++hexstr) break;
if (isalpha((int)(unsigned char)(*hexstr))) { if (isalpha((int)(unsigned char)(*hexstr))) {
nibble2 = tolower(*hexstr) - 'a' + 10; nibble2 = tolower(*hexstr) - 'a' + 10;
} else if (isdigit((int)(unsigned char)(*hexstr))) { } else if (isdigit((int)(unsigned char)(*hexstr))) {
nibble2 = *hexstr - '0'; nibble2 = *hexstr - '0';
} else { } else {
printf("\nError: bad hex character '%c'\n", *hexstr); printf("\nError: bad hex character '%c'\n", *hexstr);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*o++ = (char)((nibble1 << 4) | nibble2); *o++ = (char)((nibble1 << 4) | nibble2);
len++; len++;
} }
return len; return len;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, err; int i, err;
int loopno, loopnohigh = 1; int loopno, loopnohigh = 1;
int hashno, hashnolow = 0, hashnohigh = HASHCOUNT - 1; int hashno, hashnolow = 0, hashnohigh = HASHCOUNT - 1;
int testno, testnolow = 0, testnohigh; int testno, testnolow = 0, testnohigh;
int ntestnohigh = 0; int ntestnohigh = 0;
int printResults = PRINTTEXT; int printResults = PRINTTEXT;
skipping to change at page 117, line 4 skipping to change at page 115, line 53
case 'F': hashFilename = optarg; break; case 'F': hashFilename = optarg; break;
case 'h': hashnolow = hashnohigh = findhash(argv[0], optarg); case 'h': hashnolow = hashnohigh = findhash(argv[0], optarg);
break; break;
case 'H': strIsHex = 1; break; case 'H': strIsHex = 1; break;
case 'i': info = optarg; infolen = strlen(optarg); break; case 'i': info = optarg; infolen = strlen(optarg); break;
case 'k': hmacKey = optarg; hmaclen = strlen(optarg); break; case 'k': hmacKey = optarg; hmaclen = strlen(optarg); break;
case 'l': loopnohigh = atoi(optarg); break; case 'l': loopnohigh = atoi(optarg); break;
case 'L': okmlen = strtol(optarg, 0, 0); break; case 'L': okmlen = strtol(optarg, 0, 0); break;
case 'm': runHmacTests = 1; break; case 'm': runHmacTests = 1; break;
case 'P': printPassFail = 0; break; case 'P': printPassFail = 0; break;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case 'p': printResults = PRINTNONE; break; case 'p': printResults = PRINTNONE; break;
case 'R': randomcount = atoi(optarg); break; case 'R': randomcount = atoi(optarg); break;
case 'r': randomseedstr = optarg; break; case 'r': randomseedstr = optarg; break;
case 's': hashstr = optarg; hashlen = strlen(hashstr); break; case 's': hashstr = optarg; hashlen = strlen(hashstr); break;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case 'S': resultstr = optarg; break; case 'S': resultstr = optarg; break;
case 't': testnolow = ntestnohigh = atoi(optarg) - 1; break; case 't': testnolow = ntestnohigh = atoi(optarg) - 1; break;
case 'w': printResults = PRINTRAW; break; case 'w': printResults = PRINTRAW; break;
case 'x': printResults = PRINTHEX; break; case 'x': printResults = PRINTHEX; break;
case 'X': printPassFail = 2; break; case 'X': printPassFail = 2; break;
case '6': printResults = PRINTBASE64; break; case '6': printResults = PRINTBASE64; break;
default: usage(argv[0]); default: usage(argv[0]);
} }
if (strIsHex) { if (strIsHex) {
skipping to change at page 118, line 5 skipping to change at page 116, line 54
err = shaSuccess; err = shaSuccess;
for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess); for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess);
++loopno) { ++loopno) {
if (hashstr) if (hashstr)
err = hash(0, loopno, hashno, hashstr, hashlen, 1, err = hash(0, loopno, hashno, hashstr, hashlen, 1,
numberExtrabits, extrabits, (const unsigned char *)hmacKey, numberExtrabits, extrabits, (const unsigned char *)hmacKey,
hmaclen, (const uint8_t *) info, infolen, okmlen, resultstr, hmaclen, (const uint8_t *) info, infolen, okmlen, resultstr,
hashes[hashno].hashsize, printResults, printPassFail); hashes[hashno].hashsize, printResults, printPassFail);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
else if (randomseedstr) else if (randomseedstr)
randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0, randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0,
randomcount, printResults, printPassFail); randomcount, printResults, printPassFail);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
else if (hashfilename) else if (hashfilename)
err = hashfile(hashno, hashfilename, extrabits, err = hashfile(hashno, hashfilename, extrabits,
numberExtrabits, 0, numberExtrabits, 0,
(const unsigned char *)hmacKey, hmaclen, (const unsigned char *)hmacKey, hmaclen,
(const uint8_t *) info, infolen, okmlen, (const uint8_t *) info, infolen, okmlen,
resultstr, hashes[hashno].hashsize, resultstr, hashes[hashno].hashsize,
printResults, printPassFail); printResults, printPassFail);
else if (hashFilename) else if (hashFilename)
err = hashfile(hashno, hashFilename, extrabits, err = hashfile(hashno, hashFilename, extrabits,
skipping to change at page 119, line 4 skipping to change at page 117, line 53
hmachashes[testno].keyarray[1] : hmachashes[testno].keyarray[1] :
hmachashes[testno].keyarray[0]), hmachashes[testno].keyarray[0]),
hmachashes[testno].keylength[hashno] ? hmachashes[testno].keylength[hashno] ?
hmachashes[testno].keylength[hashno] : hmachashes[testno].keylength[hashno] :
hmachashes[testno].keylength[1] ? hmachashes[testno].keylength[1] ?
hmachashes[testno].keylength[1] : hmachashes[testno].keylength[1] :
hmachashes[testno].keylength[0], hmachashes[testno].keylength[0],
0, 0, 0, 0, 0, 0,
hmachashes[testno].resultarray[hashno], hmachashes[testno].resultarray[hashno],
hmachashes[testno].resultlength[hashno], hmachashes[testno].resultlength[hashno],
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
printResults, printPassFail); printResults, printPassFail);
} else if (runHkdfTests) { } else if (runHkdfTests) {
err = hashHkdf(testno, loopno, hashno, err = hashHkdf(testno, loopno, hashno,
printResults, printPassFail); printResults, printPassFail);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} else { /* sha tests */ } else { /* sha tests */
err = hash(testno, loopno, hashno, err = hash(testno, loopno, hashno,
hashes[hashno].tests[testno].testarray, hashes[hashno].tests[testno].testarray,
hashes[hashno].tests[testno].length, hashes[hashno].tests[testno].length,
hashes[hashno].tests[testno].repeatcount, hashes[hashno].tests[testno].repeatcount,
hashes[hashno].tests[testno].numberExtrabits, hashes[hashno].tests[testno].numberExtrabits,
hashes[hashno].tests[testno].extrabits, hashes[hashno].tests[testno].extrabits,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
hashes[hashno].tests[testno].resultarray, hashes[hashno].tests[testno].resultarray,
hashes[hashno].hashsize, hashes[hashno].hashsize,
skipping to change at page 121, line 18 skipping to change at page 120, line 18
RFC Editor Note: All occurances of "RFC NNNN" should be edited to RFC Editor Note: All occurances of "RFC NNNN" should be edited to
replace "NNNN" with this documents RFC number and this note should be replace "NNNN" with this documents RFC number and this note should be
deleted. deleted.
12.1 Normative References 12.1 Normative References
[RFC2104] - Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- [RFC2104] - Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
Hashing for Message Authentication", RFC 2104, February 1997. Hashing for Message Authentication", RFC 2104, February 1997.
[RFC2119] - Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC5869] - Krawczyk, H. and P. Eronen, "HMAC-based Extract-and- [RFC5869] - Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-
Expand Key Derivation Function (HKDF)", RFC 5869, May 2010. Expand Key Derivation Function (HKDF)", RFC 5869, May 2010.
[SHS] - "Secure Hash Standard", United States of American, National [SHS] - "Secure Hash Standard", United States of American, National
Institute of Science and Technology, Federal Information Institute of Science and Technology, Federal Information
Processing Standard (FIPS) 180-3, Processing Standard (FIPS) 180-3,
http://csrc.nist.gov/publications/fips/fips180- http://csrc.nist.gov/publications/fips/fips180-
3/fips180-3_final.pdf. 3/fips180-3_final.pdf.
12.2 Informative References 12.2 Informative References
[RFC2202] - P. Cheng, R. Glenn, "Test Cases for HMAC-MD5 and HMAC-
SHA-1", September 1997.
[RFC3174] - D. Eastlake 3rd, P. Jones, "US Secure Hash Algorithm 1 [RFC3174] - D. Eastlake 3rd, P. Jones, "US Secure Hash Algorithm 1
(SHA1)", September 2001. (SHA1)", September 2001.
[RFC3874] - R. Housley, "A 224-bit One-way Hash Function: SHA-224", [RFC3874] - R. Housley, "A 224-bit One-way Hash Function: SHA-224",
September 2004. September 2004.
[RFC4055] - Schaad, J., Kaliski, B., and R. Housley, "Additional [RFC4055] - Schaad, J., Kaliski, B., and R. Housley, "Additional
Algorithms and Identifiers for RSA Cryptography for use in the Algorithms and Identifiers for RSA Cryptography for use in the
Internet X.509 Public Key Infrastructure Certificate and Internet X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile", RFC 4055, June 2005 Certificate Revocation List (CRL) Profile", RFC 4055, June
2005.
[RFC4086] - D. Eastlake, S. Crocker, J. Schiller, "Randomness [RFC4086] - D. Eastlake, S. Crocker, J. Schiller, "Randomness
Requirements for Security", May 2005. Requirements for Security", May 2005.
[RFC4231] - M. Nystrom, "Identifiers and Test Vectors for HMAC-
SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512",
December 2005.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
[RFC4634] - Eastlake 3rd, D. and T. Hansen, "US Secure Hash [RFC4634] - Eastlake 3rd, D. and T. Hansen, "US Secure Hash
Algorithms (SHA and HMAC-SHA)", RFC 4634, July 2006. Algorithms (SHA and HMAC-SHA)", RFC 4634, July 2006.
[SHAVS] - "The Secure Hash Algorithm Validation System (SHAVS)", [SHAVS] - "The Secure Hash Algorithm Validation System (SHAVS)",
http://csrc.nist.gov/cryptval/shs/SHAVS.pdf. http://csrc.nist.gov/cryptval/shs/SHAVS.pdf.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Appendix: Changes from RFC 4634 Appendix: Changes from RFC 4634
skipping to change at page 123, line 32 skipping to change at page 121, line 32
2.c The previous code for SHA-384 and SHA-512 would stop after 2.c The previous code for SHA-384 and SHA-512 would stop after
2^93 bytes (2^96 bits). The fixed code handles up to 2^125 2^93 bytes (2^96 bits). The fixed code handles up to 2^125
bytes (2^128 bits). bytes (2^128 bits).
2.d Add additional error checking. 2.d Add additional error checking.
3. Update boilerplate, remove special license in [RFC4634] as new 3. Update boilerplate, remove special license in [RFC4634] as new
boilerplate mandates simplified BSD license. boilerplate mandates simplified BSD license.
4. Repalce MIT version of getopt with new code to satisfy IETF 4. Replace MIT version of getopt with new code to satisfy IETF
incoming and outgoing license restrictions. incoming and outgoing license restrictions.
5. Other assorted editorial improvements. 5. Other assorted editorial improvements.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Appendix Z: Edit History Appendix Z: Edit History
RFC Editor, Please delete this Appendix Z on publication. RFC Editor, Please delete this Appendix Z on publication.
skipping to change at page 125, line 5 skipping to change at page 122, line 30
license. license.
Z.3 Changes from -02 to -03 Z.3 Changes from -02 to -03
Problem with MIT getopt is given incompletely in -01 to -02 changes. Problem with MIT getopt is given incompletely in -01 to -02 changes.
Actual problem includes conflict with IETF incoming license Actual problem includes conflict with IETF incoming license
restriction. Also, add this change to Appendix giving changes from restriction. Also, add this change to Appendix giving changes from
RFC 4634. Update to incorporate RFC number for the HKDF RFC. RFC 4634. Update to incorporate RFC number for the HKDF RFC.
Numerous editorial changes. Numerous editorial changes.
Z.4 Changes from -03 to -04
Fix typos and nits.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Author's Address Author's Address
Donald E. Eastlake, 3rd Donald E. Eastlake, 3rd
Stellar Switches Stellar Switches
155 Beaver Street 155 Beaver Street
Milford, MA 01757 USA Milford, MA 01757 USA
Telephone: +1-508-333-2270 Telephone: +1-508-333-2270
 End of changes. 346 change blocks. 
875 lines changed or deleted 809 lines changed or added

This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/