< draft-eastlake-sha2b-05.txt   draft-eastlake-sha2b-06.txt >
Network Working Group Donald Eastlake 3rd Network Working Group Donald Eastlake
INTERNET-DRAFT Huawei INTERNET-DRAFT Huawei
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: June 19, 2011 December 20, 2010 Expires: July 15, 2011 January 16, 2011
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-05.txt> <draft-eastlake-sha2b-06.txt>
Abstract Abstract
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. This document makes open source code SHA-256, SHA-384, and SHA-512. This document makes open source code
performing the SHA hash functions conveniently available to the performing the SHA hash functions conveniently available to the
Internet community. The sample code supports input strings of Internet community. The sample code supports input strings of
arbitrary bit length. Much of the text herein was adapted by the arbitrary bit length. Much of the text herein was adapted by the
authors from FIPS 180-2. authors from FIPS 180-2.
skipping to change at page 2, line 34 skipping to change at page 2, line 34
6.3 SHA-384 and SHA-512 Initialization....................14 6.3 SHA-384 and SHA-512 Initialization....................14
6.4 SHA-384 and SHA-512 Processing........................15 6.4 SHA-384 and SHA-512 Processing........................15
7. HKDF and SHA Based HMACs...............................17 7. HKDF and SHA Based HMACs...............................17
7.1 SHA-Based HMACs.......................................17 7.1 SHA-Based HMACs.......................................17
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 stdint-example.h....................................29
8.2 The SHA Code..........................................29 8.1.3 sha-private.h.......................................29
8.2.1 sha1.c..............................................29 8.2 The SHA Code..........................................30
8.2.2 sha224-256.c........................................38 8.2.1 sha1.c..............................................30
8.2.2 sha224-256.c........................................39
8.2.3 sha384-512.c........................................50 8.2.3 sha384-512.c........................................50
8.2.4 usha.c..............................................70 8.2.4 usha.c..............................................71
8.3 The HMAC Code.........................................76 8.3 The HMAC Code.........................................77
8.4 The HKDF Code.........................................81 8.4 The HKDF Code.........................................82
8.5 The Test Driver.......................................88 8.5 The Test Driver.......................................89
9. IANA Considerations...................................119 9. IANA Considerations...................................120
10. Security Considerations..............................119 10. Security Considerations..............................120
11. Acknowledgements.....................................119 11. Acknowledgements.....................................120
12. References...........................................120
12.1 Normative References................................120
12.2 Informative References..............................120
Appendix: Changes from RFC 4634..........................121 12. References...........................................121
Appendix Z: RFC Editor Note, Edit History................122 12.1 Normative References................................121
12.2 Informative References..............................121
Appendix: Changes from RFC 4634..........................122
Appendix Z: RFC Editor Note, Edit History................123
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
1. Overview of Contents 1. Overview of Contents
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
Hash Algorithms (SHAs), code to implement the SHAs, code to implement Hash Algorithms (SHAs), code to implement the SHAs, code to implement
HMACs based on the SHAs, and code to implement HKDF based on HMAC. HMACs based on the SHAs, and code to implement HKDF based on HMAC.
Specifications for HMAC and HKDF are not included as they appear Specifications for HMAC and HKDF are not included as they appear
skipping to change at page 21, line 44 skipping to change at page 21, line 44
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)
This combined interface performs both HKDF extraction and This combined interface performs both HKDF extraction and
expansion. The variables are the same as in hkdfExtract() expansion. The variables are the same as in hkdfExtract()
and hkdfExpand(). and hkdfExpand().
8.1 The Header Files 8.1 The Header Files
8.1.1 The .h file 8.1.1 The .h file
The following sha.h file, as stated in the comments within the file,
assumes that <stdint.h> is available on your system. If it is not,
you should change to including <stdint-example.h>, provided in
Section 8.1.2, or the like.
/**************************** sha.h ****************************/ /**************************** sha.h ****************************/
/***************** 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
authors of the code. All rights reserved. authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the the documentation and/or other materials provided with the
distribution. distribution.
* Neither the name of Internet Society, IETF or IETF Trust, nor the * Neither the name of Internet Society, IETF or IETF Trust, nor the
names of specific contributors, may be used to endorse or promote names of specific contributors, may be used to endorse or promote
skipping to change at page 22, line 51 skipping to change at page 23, line 4
* Publication (FIPS PUB) 180-3 published in October 2008 * Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1 * and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2. * 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 * 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* These files may be compiled with two options: * These files may be compiled with two options:
* USE_32BIT_ONLY - use 32-bit arithmetic only, for systems * USE_32BIT_ONLY - use 32-bit arithmetic only, for systems
* without 64-bit integers * without 64-bit integers
* *
* USE_MODIFIED_MACROS - use alternate form of the SHA_Ch() * USE_MODIFIED_MACROS - use alternate form of the SHA_Ch()
* and SHA_Maj() macros that are equivalent * and SHA_Maj() macros that are equivalent
* and potentially faster on many systems * and potentially faster on many systems
* *
*/ */
#include <stdint.h> #include <stdint.h>
/* /*
* If you do not have the ISO standard stdint.h header file, then you * If you do not have the ISO standard stdint.h header file, then you
* must typedef the following: * must typedef the following:
* name meaning * name meaning
* uint64_t unsigned 64 bit integer * uint64_t unsigned 64 bit integer
* uint32_t unsigned 32 bit integer * uint32_t unsigned 32 bit integer
* uint8_t unsigned 8 bit integer (i.e., unsigned char) * uint8_t unsigned 8 bit integer (i.e., unsigned char)
* int_least16_t integer of >= 16 bits * int_least16_t integer of >= 16 bits
* *
* See stdint-example.h
*/ */
#ifndef _SHA_enum_ #ifndef _SHA_enum_
#define _SHA_enum_ #define _SHA_enum_
/* /*
* All SHA functions return one of these values. * All SHA functions return one of these values.
*/ */
enum { enum {
shaSuccess = 0, shaSuccess = 0,
shaNull, /* Null pointer parameter */ shaNull, /* Null pointer parameter */
skipping to change at page 23, line 50 skipping to change at page 24, line 4
}; };
#endif /* _SHA_enum_ */ #endif /* _SHA_enum_ */
/* /*
* These constants hold size information for each of the SHA * These constants hold size information for each of the SHA
* hashing operations * hashing operations
*/ */
enum { enum {
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64, SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128, SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SHA512_Message_Block_Size = 128, SHA512_Message_Block_Size = 128,
USHA_Max_Message_Block_Size = SHA512_Message_Block_Size, USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32, SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
SHA384HashSize = 48, SHA512HashSize = 64, SHA384HashSize = 48, SHA512HashSize = 64,
USHAMaxHashSize = SHA512HashSize, USHAMaxHashSize = SHA512HashSize,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224, SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256, SHA384HashSizeBits = 384, SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
}; };
/* /*
* These constants are used in the USHA (unified sha) functions. * These constants are used in the USHA (unified sha) functions.
*/ */
typedef enum SHAversion { typedef enum SHAversion {
SHA1, SHA224, SHA256, SHA384, SHA512 SHA1, SHA224, SHA256, SHA384, SHA512
skipping to change at page 24, line 51 skipping to change at page 25, line 5
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_High; /* Message length in bits */ uint32_t Length_High; /* Message length in bits */
uint32_t Length_Low; /* 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];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int Computed; /* Is the hash computed? */ int Computed; /* Is the hash computed? */
int Corrupted; /* Cumulative corruption code */ 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
* 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_High, Length_Low; /* Message length in bits */ uint64_t Length_High, Length_Low; /* Message length in bits */
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
skipping to change at page 25, line 50 skipping to change at page 26, line 4
* hashing operations. * hashing operations.
*/ */
typedef struct USHAContext { typedef struct USHAContext {
int whichSha; /* which SHA is being used */ int whichSha; /* which SHA is being used */
union { union {
SHA1Context sha1Context; SHA1Context sha1Context;
SHA224Context sha224Context; SHA256Context sha256Context; SHA224Context sha224Context; SHA256Context sha256Context;
SHA384Context sha384Context; SHA512Context sha512Context; SHA384Context sha384Context; SHA512Context sha512Context;
} ctx; } ctx;
} USHAContext; } USHAContext;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* This structure will hold context information for the HMAC * This structure will hold context information for the HMAC
* keyed hashing operation. * keyed hashing operation.
*/ */
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
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 MAC computed? */ int Computed; /* Is the MAC computed? */
int Corrupted; /* Cumulative corruption code */ int Corrupted; /* Cumulative corruption code */
} HMACContext; } HMACContext;
skipping to change at page 26, line 49 skipping to change at page 27, line 4
extern int SHA1FinalBits(SHA1Context *, uint8_t bits, extern int SHA1FinalBits(SHA1Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA1Result(SHA1Context *, extern int SHA1Result(SHA1Context *,
uint8_t Message_Digest[SHA1HashSize]); uint8_t Message_Digest[SHA1HashSize]);
/* SHA-224 */ /* SHA-224 */
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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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 *);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
extern int SHA256Input(SHA256Context *, const uint8_t *bytes, 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,
skipping to change at page 27, line 50 skipping to change at page 28, line 4
extern int USHAHashSize(enum SHAversion whichSha); extern int USHAHashSize(enum SHAversion whichSha);
extern int USHAHashSizeBits(enum SHAversion whichSha); extern int USHAHashSizeBits(enum SHAversion whichSha);
extern const char *USHAHashName(enum SHAversion whichSha); extern const char *USHAHashName(enum SHAversion whichSha);
/* /*
* 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 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 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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
/* /*
* 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,
skipping to change at page 28, line 52 skipping to change at page 29, line 5
const unsigned char *salt, int salt_len); const unsigned char *salt, int salt_len);
extern int hkdfInput(HKDFContext *context, const unsigned char *ikm, extern int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len); int ikm_len);
extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits, extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count); unsigned int ikm_bit_count);
extern int hkdfResult(HKDFContext *context, extern 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,
uint8_t okm[USHAMaxHashSize], int okm_len); uint8_t okm[USHAMaxHashSize], int okm_len);
#endif /* _SHA_H_ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8.1.2 sha-private.h #endif /* _SHA_H_ */
8.1.2 stdint-example.h
If you system does not have <stdint.h>, the following should be
adequate as a substitute for compiling the other code in this
document.
/*********************** stdint-example.h **********************/
/**** Use this file if your system does not have a stdint.h. ***/
/***************** See RFC NNNN for details. *******************/
#ifndef STDINT_H
#define STDINT_H
typedef unsigned long long uint64_t; /* unsigned 64 bit integer */
typedef unsigned int uint32_t; /* unsigned 32 bit integer */
typedef unsigned char uint8_t; /* unsigned 8 bit integer */
/* (i.e., unsigned char) */
typedef int int_least32_t; /* integer of >= 32 bits */
typedef short int_least16_t; /* integer of >= 16 bits */
#endif /* STDINT_H */
8.1.3 sha-private.h
The sha-private.h header file contains definitions that should only
be needed internally in the other code in this document. These
definitions should not be needed in application code calling the code
provided in this document.
/************************ 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-3, 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-3 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)))
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#else /* USE_MODIFIED_MACROS */ #else /* USE_MODIFIED_MACROS */
/* /*
* The following definitions are equivalent and potentially faster. * The following definitions are equivalent and potentially faster.
*/ */
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z)) #define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) #define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */ #endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z)) #define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#endif /* _SHA_PRIVATE__H */ #endif /* _SHA_PRIVATE__H */
8.2 The SHA Code 8.2 The SHA Code
This code is primarily intended as expository and could be optimized This code is primarily intended as expository reference code and
further. For example, the assignment rotations through the variables could be optimized further. For example, the assignment rotations
a, b, ..., h could be treated as a cycle and the loop unrolled, through the variables a, b, ..., h could be treated as a cycle and
rather than doing the explicit copying. the loop unrolled, rather than doing the explicit copying.
Note that there are alternative representations of the Ch() and Maj() Note that there are alternative representations of the Ch() and Maj()
functions controlled by an ifdef. functions controlled by an ifdef.
8.2.1 sha1.c 8.2.1 sha1.c
/**************************** sha1.c ***************************/ /**************************** sha1.c ***************************/
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
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 U.S. 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-3 published in October 2008 * Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1 * and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2. * 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 * 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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:
* SHA-1 is defined in terms of 32-bit "words". This code * SHA-1 is defined in terms of 32-bit "words". This code
* uses <stdint.h> (included via "sha.h") to define 32 and 8 * uses <stdint.h> (included via "sha.h") to define 32 and 8
skipping to change at page 31, line 4 skipping to change at page 31, line 39
#include "sha.h" #include "sha.h"
#include "sha-private.h" #include "sha-private.h"
/* /*
* Define the SHA1 circular left shift macro * Define the SHA1 circular left shift macro
*/ */
#define SHA1_ROTL(bits,word) \ #define SHA1_ROTL(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits)))) (((word) << (bits)) | ((word) >> (32-(bits))))
/* /*
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 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 \
: (context)->Corrupted ) : (context)->Corrupted )
/* Local Function Prototypes */ /* Local Function Prototypes */
static void SHA1ProcessMessageBlock(SHA1Context *context); 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);
/* /*
* SHA1Reset * SHA1Reset
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* 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:
skipping to change at page 32, line 4 skipping to change at page 32, line 39
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 = shaSuccess; context->Corrupted = shaSuccess;
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:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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 (!context) return shaNull; if (!context) return shaNull;
if (!length) return shaSuccess; if (!length) return shaSuccess;
if (!message_array) return shaNull; if (!message_array) return shaNull;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
skipping to change at page 33, line 4 skipping to change at page 33, line 40
return context->Corrupted; return context->Corrupted;
} }
/* /*
* 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)
{ {
static uint8_t masks[8] = { static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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
}; };
static 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
}; };
skipping to change at page 34, line 4 skipping to change at page 34, line 40
/* /*
* 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) return shaNull; if (!context) return shaNull;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (!Message_Digest) 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 ) )));
skipping to change at page 35, line 4 skipping to change at page 35, line 40
* *
* 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 Secure Hash Standard. * 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-3, 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
*/ */
for (t = 0; t < 16; t++) { for (t = 0; t < 16; t++) {
W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24; W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24;
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16; W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16;
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8; W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]); W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]);
} }
for (t = 16; t < 80; t++) for (t = 16; t < 80; t++)
W[t] = SHA1_ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); W[t] = SHA1_ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
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];
skipping to change at page 36, line 4 skipping to change at page 36, line 40
E = D; E = D;
D = C; D = C;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
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;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
A = temp; A = temp;
} }
context->Intermediate_Hash[0] += A; context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B; context->Intermediate_Hash[1] += B;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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 * SHA1Finalize
* *
skipping to change at page 37, line 4 skipping to change at page 37, line 40
* sha Error Code. * sha Error Code.
* *
*/ */
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte) static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
{ {
int i; int i;
SHA1PadMessage(context, Pad_Byte); SHA1PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */ /* message may be sensitive, clear it out */
for (i = 0; i < SHA1_Message_Block_Size; ++i) for (i = 0; i < SHA1_Message_Block_Size; ++i)
context->Message_Block[i] = 0; context->Message_Block[i] = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Length_High = 0; /* and clear length */ context->Length_High = 0; /* and clear length */
context->Length_Low = 0; context->Length_Low = 0;
context->Computed = 1; context->Computed = 1;
} }
/* /*
* SHA1PadMessage * SHA1PadMessage
* *
* Description: * Description:
* According to the standard, the message must be padded to the next * 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'. * even multiple of 512 bits. The first padding bit must be a '1'.
* The last 64 bits represent the length of the original message. * The last 64 bits represent the length of the original message.
* All bits in between should be 0. This helper function will pad * All bits in between should be 0. This helper function will pad
* the message according to those rules by filling the Message_Block * the message according to those rules by filling the Message_Block
* array accordingly. When it returns, it can be assumed that the * array accordingly. When it returns, it can be assumed that the
* message digest has been computed. * message digest has been computed.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to pad * The context to pad
* Pad_Byte: [in] * Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding * The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message * and length. This will contain the last bits of the message
* followed by another single bit. If the message was an * followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80. * exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
skipping to change at page 38, line 4 skipping to change at page 38, line 40
context->Message_Block[context->Message_Block_Index++] = 0; context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context); SHA1ProcessMessageBlock(context);
} else } else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte; context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8)) while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0; context->Message_Block[context->Message_Block_Index++] = 0;
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Store the message length as the last 8 octets * Store the message length as the last 8 octets
*/ */
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24); context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16); context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8); context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High); context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24); context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16); context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8); context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low); context->Message_Block[63] = (uint8_t) (context->Length_Low);
SHA1ProcessMessageBlock(context); SHA1ProcessMessageBlock(context);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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. */
/* /*
skipping to change at page 39, line 4 skipping to change at page 39, line 40
* 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.
*/ */
#include "sha.h" #include "sha.h"
#include "sha-private.h" #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 SHA256_SHR(bits,word) ((word) >> (bits)) #define SHA256_SHR(bits,word) ((word) >> (bits))
#define SHA256_ROTL(bits,word) \ #define SHA256_ROTL(bits,word) \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
(((word) << (bits)) | ((word) >> (32-(bits)))) (((word) << (bits)) | ((word) >> (32-(bits))))
#define SHA256_ROTR(bits,word) \ #define SHA256_ROTR(bits,word) \
(((word) >> (bits)) | ((word) << (32-(bits)))) (((word) >> (bits)) | ((word) << (32-(bits))))
/* Define the SHA SIGMA and sigma macros */ /* Define the SHA SIGMA and sigma macros */
#define SHA256_SIGMA0(word) \ #define SHA256_SIGMA0(word) \
(SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word)) (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
#define SHA256_SIGMA1(word) \ #define SHA256_SIGMA1(word) \
(SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word)) (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
#define SHA256_sigma0(word) \ #define SHA256_sigma0(word) \
skipping to change at page 40, line 5 skipping to change at page 40, line 41
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0); static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
static void SHA224_256ProcessMessageBlock(SHA256Context *context); 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 int SHA224_256ResultN(SHA256Context *context, static int SHA224_256ResultN(SHA256Context *context,
uint8_t Message_Digest[ ], int HashSize); uint8_t Message_Digest[ ], int HashSize);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Initial Hash Values: FIPS 180-3 section 5.3.2 */ /* 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-3 section 5.3.3 */ /* 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
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Description: * Description:
* This function will initialize the SHA224Context in preparation * This function will initialize the SHA224Context in preparation
* for computing a new SHA224 message digest. * for computing a new SHA224 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.
skipping to change at page 41, line 4 skipping to change at page 41, line 42
* 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
* *
* 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]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
skipping to change at page 42, line 4 skipping to change at page 42, line 42
* 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
* *
* Description: * Description:
* This function will initialize the SHA256Context in preparation * This function will initialize the SHA256Context in preparation
* for computing a new SHA256 message digest. * for computing a new SHA256 message digest.
* *
* Parameters: * Parameters:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA256Reset(SHA256Context *context) int SHA256Reset(SHA256Context *context)
{ {
return SHA224_256Reset(context, SHA256_H0); return SHA224_256Reset(context, SHA256_H0);
} }
skipping to change at page 43, line 4 skipping to change at page 43, line 42
* 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 (!context) return shaNull; if (!context) return shaNull;
if (!length) return shaSuccess; if (!length) return shaSuccess;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (!message_array) return shaNull; if (!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--) { while (length--) {
context->Message_Block[context->Message_Block_Index++] = context->Message_Block[context->Message_Block_Index++] =
*message_array; *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++;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return context->Corrupted; return context->Corrupted;
} }
/* /*
* 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.
* *
skipping to change at page 44, line 4 skipping to change at page 44, line 42
{ {
static 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
}; };
static 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 (!context) return shaNull; if (!context) return shaNull;
if (!length) return shaSuccess; if (!length) return shaSuccess;
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 (length >= 8) return context->Corrupted = shaBadParam; if (length >= 8) return context->Corrupted = shaBadParam;
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
* SHA256Result * SHA256Result
* *
* 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,
skipping to change at page 45, line 4 skipping to change at page 45, line 42
} }
/* /*
* SHA224_256Reset * SHA224_256Reset
* *
* Description: * Description:
* This helper function will initialize the SHA256Context in * This helper function will initialize the SHA256Context in
* preparation for computing a new SHA-224 or SHA-256 message digest. * preparation for computing a new SHA-224 or SHA-256 message digest.
* *
* Parameters: * Parameters:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* H0[ ]: [in] * H0[ ]: [in]
* The initial hash value array to use. * The initial hash value array to use.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0) static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
{ {
if (!context) return shaNull; if (!context) return shaNull;
context->Length_High = context->Length_Low = 0; context->Length_High = context->Length_Low = 0;
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Intermediate_Hash[0] = H0[0]; context->Intermediate_Hash[0] = H0[0];
context->Intermediate_Hash[1] = H0[1]; context->Intermediate_Hash[1] = H0[1];
context->Intermediate_Hash[2] = H0[2]; context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3]; context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4]; context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5]; context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6]; context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7]; context->Intermediate_Hash[7] = H0[7];
context->Computed = 0; context->Computed = 0;
skipping to change at page 46, line 4 skipping to change at page 46, line 42
* *
* 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 Secure Hash Standard. * 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-3, 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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
}; };
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
*/ */
skipping to change at page 47, line 4 skipping to change at page 47, line 42
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
} }
/* /*
* SHA224_256Finalize * SHA224_256Finalize
* *
* Description: * Description:
* This helper function finishes off the digest calculations. * This helper function finishes off the digest calculations.
* *
* Parameters: * Parameters:
skipping to change at page 48, line 4 skipping to change at page 48, line 40
{ {
int i; int i;
SHA224_256PadMessage(context, Pad_Byte); SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */ /* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i) for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0; context->Message_Block[i] = 0;
context->Length_High = 0; /* and clear length */ context->Length_High = 0; /* and clear length */
context->Length_Low = 0; context->Length_Low = 0;
context->Computed = 1; context->Computed = 1;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* SHA224_256PadMessage * SHA224_256PadMessage
* *
* Description: * Description:
* According to the standard, the message must be padded to the next * 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'. * even multiple of 512 bits. The first padding bit must be a '1'.
* The last 64 bits represent the length of the original message. * The last 64 bits represent the length of the original message.
* All bits in between should be 0. This helper function will pad * All bits in between should be 0. This helper function will pad
* the message according to those rules by filling the * the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be * Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed. * assumed that the message digest has been computed.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to pad * The context to pad
* Pad_Byte: [in] * Pad_Byte: [in]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The last byte to add to the message block before the 0-padding * The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message * and length. This will contain the last bits of the message
* followed by another single bit. If the message was an * followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80. * exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* Nothing. * Nothing.
*/ */
static void SHA224_256PadMessage(SHA256Context *context, static void SHA224_256PadMessage(SHA256Context *context,
uint8_t Pad_Byte) uint8_t Pad_Byte)
skipping to change at page 49, line 4 skipping to change at page 49, line 41
while (context->Message_Block_Index < (SHA256_Message_Block_Size-8)) while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
context->Message_Block[context->Message_Block_Index++] = 0; context->Message_Block[context->Message_Block_Index++] = 0;
/* /*
* Store the message length as the last 8 octets * Store the message length as the last 8 octets
*/ */
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24); context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16); context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8); context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block[59] = (uint8_t)(context->Length_High); context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24); context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16); context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8); context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low); context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context); 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:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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/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.
skipping to change at page 50, line 4 skipping to change at page 50, line 39
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 U.S. 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-3 published in October 2008 * Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1 * and formerly defined in its predecessors, FIPS PUB 180-1
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* and FIP PUB 180-2. * 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 * 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
skipping to change at page 51, line 4 skipping to change at page 51, line 42
* 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"
#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)) : \
((bits) == 32) ? (word)[0] : \ ((bits) == 32) ? (word)[0] : \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
((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) ? \
(((word)[0] << (bits)) | \ (((word)[0] << (bits)) | \
skipping to change at page 52, line 5 skipping to change at page 52, line 43
(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], \
(word1)[1] += (word2)[1] + ((word1)[2] < ADDTO4_temp2), \ (word1)[1] += (word2)[1] + ((word1)[2] < ADDTO4_temp2), \
skipping to change at page 53, line 4 skipping to change at page 53, line 42
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 4 skipping to change at page 54, line 42
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)) )
#ifndef USE_MODIFIED_MACROS #ifndef USE_MODIFIED_MACROS
/* /*
* These definitions are the ones used in FIPS 180-3, 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];
#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), \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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-3, 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)
skipping to change at page 55, line 5 skipping to change at page 55, line 43
* 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 : \ ((context)->Length[0] == 0)) ? shaInputTooLong : \
(context)->Corrupted ) (context)->Corrupted )
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA384_512Reset(SHA512Context *context, static int SHA384_512Reset(SHA512Context *context,
uint32_t H0[SHA512HashSize/4]); uint32_t H0[SHA512HashSize/4]);
static void SHA384_512ProcessMessageBlock(SHA512Context *context); 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 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-3 sections 5.3.4 and 5.3.5 */ /* Initial Hash Values: FIPS 180-3 sections 5.3.4 and 5.3.5 */
static uint32_t SHA384_H0[SHA512HashSize/4] = { static uint32_t SHA384_H0[SHA512HashSize/4] = {
0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A, 0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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
skipping to change at page 56, line 4 skipping to change at page 56, line 43
#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) ? shaInputTooLong : \ (++context->Length_High == 0) ? shaInputTooLong : \
(context)->Corrupted) (context)->Corrupted)
/* Local Function Prototypes */ /* Local Function Prototypes */
static int SHA384_512Reset(SHA512Context *context, static int SHA384_512Reset(SHA512Context *context,
uint64_t H0[SHA512HashSize/8]); uint64_t H0[SHA512HashSize/8]);
static void SHA384_512ProcessMessageBlock(SHA512Context *context); static void SHA384_512ProcessMessageBlock(SHA512Context *context);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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 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-3 sections 5.3.4 and 5.3.5 */ /* 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,
skipping to change at page 57, line 4 skipping to change at page 57, line 42
* 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]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
* *
skipping to change at page 58, line 4 skipping to change at page 58, line 43
* 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:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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]
* 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:
skipping to change at page 59, line 4 skipping to change at page 59, line 43
* 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]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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 SHA512Input(SHA512Context *context, int SHA512Input(SHA512Context *context,
skipping to change at page 60, line 4 skipping to change at page 60, line 43
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.
* *
* Returns: * Returns:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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)
{ {
static 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,
skipping to change at page 61, line 4 skipping to change at page 61, line 43
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;
} }
/* /*
* SHA512Result * SHA512Result
* *
* Description: * Description:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
*/ */
int SHA512Result(SHA512Context *context, int SHA512Result(SHA512Context *context,
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_512Reset * SHA384_512Reset
skipping to change at page 62, line 5 skipping to change at page 62, line 44
static int SHA384_512Reset(SHA512Context *context, static int SHA384_512Reset(SHA512Context *context,
uint32_t H0[SHA512HashSize/4]) uint32_t H0[SHA512HashSize/4])
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
static int SHA384_512Reset(SHA512Context *context, static int SHA384_512Reset(SHA512Context *context,
uint64_t H0[SHA512HashSize/8]) uint64_t H0[SHA512HashSize/8])
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
{ {
int i; int i;
if (!context) return shaNull; if (!context) return shaNull;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
context->Length[0] = context->Length[1] = context->Length[0] = context->Length[1] =
context->Length[2] = context->Length[3] = 0; context->Length[2] = context->Length[3] = 0;
for (i = 0; i < SHA512HashSize/4; i++) for (i = 0; i < SHA512HashSize/4; i++)
context->Intermediate_Hash[i] = H0[i]; context->Intermediate_Hash[i] = H0[i];
#else /* !USE_32BIT_ONLY */ #else /* !USE_32BIT_ONLY */
context->Length_High = context->Length_Low = 0; context->Length_High = context->Length_Low = 0;
for (i = 0; i < SHA512HashSize/8; i++) for (i = 0; i < SHA512HashSize/8; i++)
context->Intermediate_Hash[i] = H0[i]; context->Intermediate_Hash[i] = H0[i];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
context->Computed = 0; context->Computed = 0;
context->Corrupted = shaSuccess; context->Corrupted = shaSuccess;
return shaSuccess; return shaSuccess;
} }
/* /*
* SHA384_512ProcessMessageBlock * SHA384_512ProcessMessageBlock
skipping to change at page 63, line 4 skipping to change at page 63, line 44
* *
*/ */
static void SHA384_512ProcessMessageBlock(SHA512Context *context) static void SHA384_512ProcessMessageBlock(SHA512Context *context)
{ {
#ifdef USE_32BIT_ONLY #ifdef USE_32BIT_ONLY
/* Constants defined in FIPS 180-3, section 4.2.3 */ /* 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,
0x46D22FFC, 0x2E1B2138, 0x5C26C926, 0x4D2C6DFC, 0x5AC42AED, 0x46D22FFC, 0x2E1B2138, 0x5C26C926, 0x4D2C6DFC, 0x5AC42AED,
0x53380D13, 0x9D95B3DF, 0x650A7354, 0x8BAF63DE, 0x766A0ABB, 0x53380D13, 0x9D95B3DF, 0x650A7354, 0x8BAF63DE, 0x766A0ABB,
0x3C77B2A8, 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B, 0x3C77B2A8, 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, 0xC24B8B70, 0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, 0xC24B8B70,
0xD0F89791, 0xC76C51A3, 0x0654BE30, 0xD192E819, 0xD6EF5218, 0xD0F89791, 0xC76C51A3, 0x0654BE30, 0xD192E819, 0xD6EF5218,
0xD6990624, 0x5565A910, 0xF40E3585, 0x5771202A, 0x106AA070, 0xD6990624, 0x5565A910, 0xF40E3585, 0x5771202A, 0x106AA070,
0x32BBD1B8, 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53, 0x32BBD1B8, 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53,
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,
skipping to change at page 64, line 4 skipping to change at page 64, line 44
((((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);
SHA512_ADD(temp2, temp3, &W[t2]); SHA512_ADD(temp2, temp3, &W[t2]);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
A[0] = context->Intermediate_Hash[0]; A[0] = context->Intermediate_Hash[0];
A[1] = context->Intermediate_Hash[1]; A[1] = context->Intermediate_Hash[1];
B[0] = context->Intermediate_Hash[2]; B[0] = context->Intermediate_Hash[2];
B[1] = context->Intermediate_Hash[3]; B[1] = context->Intermediate_Hash[3];
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];
skipping to change at page 65, line 4 skipping to change at page 65, line 44
/* /*
* 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);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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 */ /* 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,
skipping to change at page 66, line 5 skipping to change at page 66, line 45
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) |
((uint64_t)(context->Message_Block[t8 + 6]) << 8) | ((uint64_t)(context->Message_Block[t8 + 6]) << 8) |
((uint64_t)(context->Message_Block[t8 + 7])); ((uint64_t)(context->Message_Block[t8 + 7]));
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
for (t = 16; t < 80; t++) for (t = 16; t < 80; t++)
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];
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];
skipping to change at page 67, line 4 skipping to change at page 67, line 44
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_512Finalize * SHA384_512Finalize
* *
* Description: * Description:
* This helper function finishes off the digest calculations. * This helper function finishes off the digest calculations.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* Pad_Byte: [in] * Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding * The last byte to add to the message block before the 0-padding
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* and length. This will contain the last bits of the message * and length. This will contain the last bits of the message
* followed by another single bit. If the message was an * followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80. * exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
static void SHA384_512Finalize(SHA512Context *context, static void SHA384_512Finalize(SHA512Context *context,
uint8_t Pad_Byte) uint8_t Pad_Byte)
skipping to change at page 68, line 4 skipping to change at page 68, line 44
* *
* Description: * Description:
* According to the standard, the message must be padded to the next * 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'. * even multiple of 1024 bits. The first padding bit must be a '1'.
* The last 128 bits represent the length of the original message. * The last 128 bits represent the length of the original message.
* All bits in between should be 0. This helper function will * All bits in between should be 0. This helper function will
* pad the message according to those rules by filling the * pad the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be * Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed. * assumed that the message digest has been computed.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to pad * The context to pad
* Pad_Byte: [in] * Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding * The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message * and length. This will contain the last bits of the message
* followed by another single bit. If the message was an * followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80. * exact multiple of 8-bits long, Pad_Byte will be 0x80.
* *
* Returns: * Returns:
* Nothing. * Nothing.
* *
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
static void SHA384_512PadMessage(SHA512Context *context, static void SHA384_512PadMessage(SHA512Context *context,
uint8_t Pad_Byte) uint8_t Pad_Byte)
{ {
/* /*
* Check to see if the current message block is too small to hold * 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 * the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second * block, process it, and then continue padding into a second
* block. * block.
*/ */
if (context->Message_Block_Index >= (SHA512_Message_Block_Size-16)) { if (context->Message_Block_Index >= (SHA512_Message_Block_Size-16)) {
skipping to change at page 69, line 4 skipping to change at page 69, line 44
context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8); context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8);
context->Message_Block[115] = (uint8_t)(context->Length[0]); context->Message_Block[115] = (uint8_t)(context->Length[0]);
context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24); context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24);
context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16); context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16);
context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8); context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8);
context->Message_Block[119] = (uint8_t)(context->Length[1]); context->Message_Block[119] = (uint8_t)(context->Length[1]);
context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24); context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24);
context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16); context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16);
context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8); 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[123] = (uint8_t)(context->Length[2]);
context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24); context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24);
context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16); context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16);
context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8); context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8);
context->Message_Block[127] = (uint8_t)(context->Length[3]); 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->Message_Block[112] = (uint8_t)(context->Length_High >> 56);
context->Message_Block[113] = (uint8_t)(context->Length_High >> 48); context->Message_Block[113] = (uint8_t)(context->Length_High >> 48);
context->Message_Block[114] = (uint8_t)(context->Length_High >> 40); context->Message_Block[114] = (uint8_t)(context->Length_High >> 40);
context->Message_Block[115] = (uint8_t)(context->Length_High >> 32); context->Message_Block[115] = (uint8_t)(context->Length_High >> 32);
context->Message_Block[116] = (uint8_t)(context->Length_High >> 24); context->Message_Block[116] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[117] = (uint8_t)(context->Length_High >> 16); context->Message_Block[117] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[118] = (uint8_t)(context->Length_High >> 8); context->Message_Block[118] = (uint8_t)(context->Length_High >> 8);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block[119] = (uint8_t)(context->Length_High); context->Message_Block[119] = (uint8_t)(context->Length_High);
context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56); context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56);
context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48); context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48);
context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40); context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40);
context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32); context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32);
context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24); context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16); context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8); context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[127] = (uint8_t)(context->Length_Low); context->Message_Block[127] = (uint8_t)(context->Length_Low);
skipping to change at page 70, line 4 skipping to change at page 70, line 44
* 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.
* *
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
static int SHA384_512ResultN(SHA512Context *context, static int SHA384_512ResultN(SHA512Context *context,
uint8_t Message_Digest[ ], int HashSize) 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) return shaNull; if (!context) return shaNull;
if (!Message_Digest) 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)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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++]);
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);
skipping to change at page 71, line 5 skipping to change at page 71, line 42
/***************** 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 a unified interface to the SHA algorithms. * This file implements a unified interface to the SHA algorithms.
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#include "sha.h" #include "sha.h"
/* /*
* USHAReset * USHAReset
* *
* Description: * Description:
* This function will initialize the SHA Context in preparation * This function will initialize the SHA Context in preparation
* for computing a new SHA message digest. * for computing a new SHA 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
* 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) return shaNull; if (!context) return shaNull;
context->whichSha = whichSha; context->whichSha = whichSha;
skipping to change at page 72, line 4 skipping to change at page 72, line 44
* 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:
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) return shaNull; 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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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);
skipping to change at page 73, line 4 skipping to change at page 73, line 44
* 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 USHAFinalBits(USHAContext *context, int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count) uint8_t bits, unsigned int bit_count)
{ {
if (!context) return shaNull; if (!context) return shaNull;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
switch (context->whichSha) { switch (context->whichSha) {
case SHA1: case SHA1:
return SHA1FinalBits((SHA1Context*)&context->ctx, bits, return SHA1FinalBits((SHA1Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA224: case SHA224:
return SHA224FinalBits((SHA224Context*)&context->ctx, bits, return SHA224FinalBits((SHA224Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA256: case SHA256:
return SHA256FinalBits((SHA256Context*)&context->ctx, bits, return SHA256FinalBits((SHA256Context*)&context->ctx, bits,
bit_count); bit_count);
case SHA384: case SHA384:
return SHA384FinalBits((SHA384Context*)&context->ctx, bits, return SHA384FinalBits((SHA384Context*)&context->ctx, bits,
bit_count); bit_count);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case SHA512: case SHA512:
return SHA512FinalBits((SHA512Context*)&context->ctx, bits, return SHA512FinalBits((SHA512Context*)&context->ctx, bits,
bit_count); bit_count);
default: return shaBadParam; default: return shaBadParam;
} }
} }
/* /*
* USHAResult * USHAResult
* *
skipping to change at page 74, line 4 skipping to change at page 74, line 44
uint8_t Message_Digest[USHAMaxHashSize]) uint8_t Message_Digest[USHAMaxHashSize])
{ {
if (!context) return shaNull; if (!context) return shaNull;
switch (context->whichSha) { switch (context->whichSha) {
case SHA1: case SHA1:
return SHA1Result((SHA1Context*)&context->ctx, Message_Digest); return SHA1Result((SHA1Context*)&context->ctx, Message_Digest);
case SHA224: case SHA224:
return SHA224Result((SHA224Context*)&context->ctx, return SHA224Result((SHA224Context*)&context->ctx,
Message_Digest); Message_Digest);
case SHA256: case SHA256:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return SHA256Result((SHA256Context*)&context->ctx, return SHA256Result((SHA256Context*)&context->ctx,
Message_Digest); Message_Digest);
case SHA384: case SHA384:
return SHA384Result((SHA384Context*)&context->ctx, return SHA384Result((SHA384Context*)&context->ctx,
Message_Digest); Message_Digest);
case SHA512: case SHA512:
return SHA512Result((SHA512Context*)&context->ctx, return SHA512Result((SHA512Context*)&context->ctx,
Message_Digest); Message_Digest);
default: return shaBadParam; default: return shaBadParam;
} }
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
* *
* Parameters: * Parameters:
* whichSha: * whichSha:
* which SHA algorithm to query * which SHA algorithm to query
* *
skipping to change at page 75, line 4 skipping to change at page 75, line 43
* 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;
case SHA384: return SHA384HashSize; case SHA384: return SHA384HashSize;
default: default:
case SHA512: return SHA512HashSize; case SHA512: return SHA512HashSize;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
} }
/* /*
* USHAHashSizeBits * USHAHashSizeBits
* *
* Description: * Description:
* This function will return the hashsize for the given SHA * This function will return the hashsize for the given SHA
* algorithm, expressed in bits. * algorithm, expressed in bits.
* *
skipping to change at page 76, line 4 skipping to change at page 76, line 44
} }
} }
/* /*
* 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)
{ {
switch (whichSha) { switch (whichSha) {
case SHA1: return "SHA1"; case SHA1: return "SHA1";
case SHA224: return "SHA224"; case SHA224: return "SHA224";
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case SHA256: return "SHA256"; case SHA256: return "SHA256";
case SHA384: return "SHA384"; case SHA384: return "SHA384";
default: default:
case SHA512: return "SHA512"; case SHA512: return "SHA512";
} }
} }
8.3 The HMAC Code 8.3 The HMAC Code
/**************************** hmac.c ***************************/ /**************************** hmac.c ***************************/
skipping to change at page 77, line 4 skipping to change at page 77, line 42
* 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
* message_array[ ]: [in] * message_array[ ]: [in]
* An array of octets representing the message. * An array of octets representing the message.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Note: in RFC 2104, this parameter is known * 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.
* 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.
* digest[ ]: [out] * digest[ ]: [out]
* Where the digest is to be returned. * 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.
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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,
uint8_t digest[USHAMaxHashSize]) uint8_t digest[USHAMaxHashSize])
{ {
HMACContext context; HMACContext context;
skipping to change at page 78, line 4 skipping to change at page 78, line 44
* 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];
if (!context) return shaNull; if (!context) return shaNull;
context->Computed = 0; context->Computed = 0;
context->Corrupted = shaSuccess; context->Corrupted = shaSuccess;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
blocksize = context->blockSize = USHABlockSize(whichSha); blocksize = context->blockSize = USHABlockSize(whichSha);
hashsize = context->hashSize = USHAHashSize(whichSha); hashsize = context->hashSize = USHAHashSize(whichSha);
context->whichSha = whichSha; context->whichSha = whichSha;
/* /*
* If key is longer than the hash blocksize, * If key is longer than the hash blocksize,
* reset it to key = HASH(key). * reset it to key = HASH(key).
*/ */
if (key_len > blocksize) { if (key_len > blocksize) {
skipping to change at page 79, line 4 skipping to change at page 79, line 43
* 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 */
USHAInput(&context->shaContext, k_ipad, blocksize); USHAInput(&context->shaContext, k_ipad, blocksize);
return context->Corrupted = ret; return context->Corrupted = ret;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* 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]
skipping to change at page 80, line 4 skipping to change at page 80, line 42
/* 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.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int hmacFinalBits(HMACContext *context, int hmacFinalBits(HMACContext *context,
uint8_t bits, unsigned int bit_count) uint8_t bits, unsigned int 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;
/* then final bits of datagram */ /* then final bits of datagram */
return context->Corrupted = return context->Corrupted =
USHAFinalBits(&context->shaContext, bits, bit_count); USHAFinalBits(&context->shaContext, bits, bit_count);
} }
skipping to change at page 81, line 5 skipping to change at page 81, line 44
* 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 */
USHAInput(&context->shaContext, context->k_opad, USHAInput(&context->shaContext, context->k_opad,
context->blockSize) || context->blockSize) ||
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* then results of 1st hash */ /* then results of 1st hash */
USHAInput(&context->shaContext, digest, context->hashSize) || USHAInput(&context->shaContext, digest, context->hashSize) ||
/* finish up 2nd pass */ /* finish up 2nd pass */
USHAResult(&context->shaContext, digest); USHAResult(&context->shaContext, digest);
context->Computed = 1; context->Computed = 1;
return context->Corrupted = ret; return context->Corrupted = ret;
} }
skipping to change at page 82, line 4 skipping to change at page 82, line 42
#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 generate keying material using HKDF. * 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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
skipping to change at page 83, line 4 skipping to change at page 83, line 44
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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* prk[ ]: [out] * prk[ ]: [out]
* Array 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,
skipping to change at page 84, line 4 skipping to change at page 84, line 44
* 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
* prk[ ]: [in] * prk[ ]: [in]
* The pseudorandom key to be expanded; either obtained * The pseudorandom key to be expanded; either obtained
* directly from a cryptographically strong, uniformly * directly from a cryptographically strong, uniformly
* distributed pseudorandom number generator, or as the * distributed pseudorandom number generator, or as the
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* output from hkdfExtract(). * output from hkdfExtract().
* prk_len: [in] * prk_len: [in]
* The length of the pseudorandom key in prk; * The length of the pseudorandom key in prk;
* should at least be equal to USHAHashSize(whichSHA). * should at least be equal to 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]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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,
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)
skipping to change at page 85, line 4 skipping to change at page 85, line 44
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;
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, prk_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;
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* hkdfReset * hkdfReset
* *
* Description: * Description:
* This function will initialize the hkdfContext in preparation * This function will initialize the hkdfContext in preparation
* for key derivation using the modular HKDF interface 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.
skipping to change at page 86, line 5 skipping to change at page 86, line 43
if (!context) return shaNull; if (!context) return shaNull;
context->whichSha = whichSha; context->whichSha = whichSha;
context->hashSize = USHAHashSize(whichSha); context->hashSize = USHAHashSize(whichSha);
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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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.
* *
*/ */
skipping to change at page 87, line 4 skipping to change at page 87, line 44
* 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
* 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);
} }
/* /*
* hkdfResult * hkdfResult
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* 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.
skipping to change at page 88, line 4 skipping to change at page 88, line 44
*/ */
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,
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;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8.5 The Test Driver 8.5 The Test Driver
The following code is a main program test driver to exercise the code The following code is a main program test driver to exercise the code
in sha1.c, sha224-256.c, sha384-512.c, hmac.c, and hkdf.c. The test in sha1.c, sha224-256.c, sha384-512.c, hmac.c, and hkdf.c. The test
driver can also be used as a standalone program for generating the driver can also be used as a standalone program for generating the
hashes. hashes. Note that the tests assume that character values are as in
[US-ASCII] and a run time check warns if the code appears to have
been compiled with some other character system.
See also [SHAVS]. See also [SHAVS].
/************************** 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. */
/* /*
skipping to change at page 89, line 4 skipping to change at page 89, line 44
* *
* These tests have subsequently been moved to pages linked from * These tests have subsequently been moved to pages linked from
* http://csrc.nist.gov/groups/ST/toolkit/examples.html * 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].
* *
* 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.
* *
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <unistd.h> /* defines getopt() and optarg */ #include <unistd.h> /* defines getopt() and optarg */
#include "sha.h" #include "sha.h"
static int scasecmp(const char *s1, const char *s2); static int scasecmp(const char *s1, const char *s2);
skipping to change at page 90, line 4 skipping to change at page 90, line 44
#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" \
"\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" \
"\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \ "\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \
"\xcd\xbb\xfb" "\xcd\xbb\xfb"
#define TEST7_224 \ #define TEST7_224 \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\xf0\x70\x06\xf2\x5a\x0b\xea\x68\xcd\x76\xa2\x95\x87\xc2\x8d" "\xf0\x70\x06\xf2\x5a\x0b\xea\x68\xcd\x76\xa2\x95\x87\xc2\x8d"
#define TEST8_224 \ #define TEST8_224 \
"\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29\x9d\x6f\x9d\x93\xdf\x62" "\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29\x9d\x6f\x9d\x93\xdf\x62"
#define TEST9_224 \ #define TEST9_224 \
"\xa2\xbe\x6e\x46\x32\x81\x09\x02\x94\xd9\xce\x94\x82\x65\x69\x42" \ "\xa2\xbe\x6e\x46\x32\x81\x09\x02\x94\xd9\xce\x94\x82\x65\x69\x42" \
"\x3a\x3a\x30\x5e\xd5\xe2\x11\x6c\xd4\xa4\xc9\x87\xfc\x06\x57\x00" \ "\x3a\x3a\x30\x5e\xd5\xe2\x11\x6c\xd4\xa4\xc9\x87\xfc\x06\x57\x00" \
"\x64\x91\xb1\x49\xcc\xd4\xb5\x11\x30\xac\x62\xb1\x9d\xc2\x48\xc7" \ "\x64\x91\xb1\x49\xcc\xd4\xb5\x11\x30\xac\x62\xb1\x9d\xc2\x48\xc7" \
"\x44\x54\x3d\x20\xcd\x39\x52\xdc\xed\x1f\x06\xcc\x3b\x18\xb9\x1f" \ "\x44\x54\x3d\x20\xcd\x39\x52\xdc\xed\x1f\x06\xcc\x3b\x18\xb9\x1f" \
"\x3f\x55\x63\x3e\xcc\x30\x85\xf4\x90\x70\x60\xd2" "\x3f\x55\x63\x3e\xcc\x30\x85\xf4\x90\x70\x60\xd2"
#define TEST10_224 \ #define TEST10_224 \
skipping to change at page 91, line 4 skipping to change at page 91, line 43
"\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" \
"\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"
#define TEST9_384 \ #define TEST9_384 \
"\x68\xf5\x01\x79\x2d\xea\x97\x96\x76\x70\x22\xd9\x3d\xa7\x16\x79" \ "\x68\xf5\x01\x79\x2d\xea\x97\x96\x76\x70\x22\xd9\x3d\xa7\x16\x79" \
"\x30\x99\x20\xfa\x10\x12\xae\xa3\x57\xb2\xb1\x33\x1d\x40\xa1\xd0" \ "\x30\x99\x20\xfa\x10\x12\xae\xa3\x57\xb2\xb1\x33\x1d\x40\xa1\xd0" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\x3c\x41\xc2\x40\xb3\xc9\xa7\x5b\x48\x92\xf4\xc0\x72\x4b\x68\xc8" \ "\x3c\x41\xc2\x40\xb3\xc9\xa7\x5b\x48\x92\xf4\xc0\x72\x4b\x68\xc8" \
"\x75\x32\x1a\xb8\xcf\xe5\x02\x3b\xd3\x75\xbc\x0f\x94\xbd\x89\xfe" \ "\x75\x32\x1a\xb8\xcf\xe5\x02\x3b\xd3\x75\xbc\x0f\x94\xbd\x89\xfe" \
"\x04\xf2\x97\x10\x5d\x7b\x82\xff\xc0\x02\x1a\xeb\x1c\xcb\x67\x4f" \ "\x04\xf2\x97\x10\x5d\x7b\x82\xff\xc0\x02\x1a\xeb\x1c\xcb\x67\x4f" \
"\x52\x44\xea\x34\x97\xde\x26\xa4\x19\x1c\x5f\x62\xe5\xe9\xa2\xd8" \ "\x52\x44\xea\x34\x97\xde\x26\xa4\x19\x1c\x5f\x62\xe5\xe9\xa2\xd8" \
"\x08\x2f\x05\x51\xf4\xa5\x30\x68\x26\xe9\x1c\xc0\x06\xce\x1b\xf6" \ "\x08\x2f\x05\x51\xf4\xa5\x30\x68\x26\xe9\x1c\xc0\x06\xce\x1b\xf6" \
"\x0f\xf7\x19\xd4\x2f\xa5\x21\xc8\x71\xcd\x23\x94\xd9\x6e\xf4\x46" \ "\x0f\xf7\x19\xd4\x2f\xa5\x21\xc8\x71\xcd\x23\x94\xd9\x6e\xf4\x46" \
"\x8f\x21\x96\x6b\x41\xf2\xba\x80\xc2\x6e\x83\xa9" "\x8f\x21\x96\x6b\x41\xf2\xba\x80\xc2\x6e\x83\xa9"
#define TEST10_384 \ #define TEST10_384 \
"\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb\x69\x12\xec\x10\xff\xcf" \ "\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb\x69\x12\xec\x10\xff\xcf" \
"\x74\x79\x03\x49\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21\xdb\x0f" \ "\x74\x79\x03\x49\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21\xdb\x0f" \
skipping to change at page 92, line 4 skipping to change at page 92, line 44
#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" \
"\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" \
"\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \ "\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \
"\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \ "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \
"\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \ "\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \ "\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \
"\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \ "\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \
"\xfb\x40\xd2" "\xfb\x40\xd2"
#define SHA1_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2\x3d" \ #define SHA1_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2\x3d" \
"\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d" "\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d"
#define SHA224_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2" \ #define SHA224_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2" \
"\x3d\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d\x66\xa9\xca\x99\xc9\xce\xb0" \ "\x3d\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d\x66\xa9\xca\x99\xc9\xce\xb0" \
"\x27" "\x27"
#define SHA256_SEED "\xf4\x1e\xce\x26\x13\xe4\x57\x39\x15\x69\x6b" \ #define SHA256_SEED "\xf4\x1e\xce\x26\x13\xe4\x57\x39\x15\x69\x6b" \
"\x5a\xdc\xd5\x1c\xa3\x28\xbe\x3b\xf5\x66\xa9\xca\x99\xc9\xce\xb0" \ "\x5a\xdc\xd5\x1c\xa3\x28\xbe\x3b\xf5\x66\xa9\xca\x99\xc9\xce\xb0" \
skipping to change at page 93, line 4 skipping to change at page 93, line 44
#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
#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;
int extrabits; int extrabits;
int numberExtrabits; int numberExtrabits;
const char *resultarray; const char *resultarray;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} tests[TESTCOUNT]; } tests[TESTCOUNT];
const char *randomtest; const char *randomtest;
const char *randomresults[RANDOMCOUNT]; const char *randomresults[RANDOMCOUNT];
} hashes[HASHCOUNT] = { } hashes[HASHCOUNT] = {
{ "SHA1", SHA1, SHA1HashSize, { "SHA1", SHA1, SHA1HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"A9993E364706816ABA3E25717850C26C9CD0D89D" }, "A9993E364706816ABA3E25717850C26C9CD0D89D" },
/* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0,
"84983E441C3BD26EBAAE4AA1F95129E5E54670F1" }, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1" },
skipping to change at page 94, line 4 skipping to change at page 94, line 45
"DB1F9050BB863DFEF4CE37186044E2EEB17EE013", "DB1F9050BB863DFEF4CE37186044E2EEB17EE013",
"127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B" "127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B"
} }, } },
{ "SHA224", SHA224, SHA224HashSize, { "SHA224", SHA224, SHA224HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"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,
"DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC388E56191DB1" }, "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC388E56191DB1" },
/* 9 */ { TEST9_224, length(TEST9_224), 1, 0xE0, 3, /* 9 */ { TEST9_224, length(TEST9_224), 1, 0xE0, 3,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" }, "54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" },
/* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0, /* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0,
"0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" } "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" }
}, SHA224_SEED, { "100966A5B4FDE0B42E2A6C5953D4D7F41BA7CF79FD" }, SHA224_SEED, { "100966A5B4FDE0B42E2A6C5953D4D7F41BA7CF79FD"
"2DF431416734BE", "1DCA396B0C417715DEFAAE9641E10A2E99D55A" "2DF431416734BE", "1DCA396B0C417715DEFAAE9641E10A2E99D55A"
"BCB8A00061EB3BE8BD", "1864E627BDB2319973CD5ED7D68DA71D8B" "BCB8A00061EB3BE8BD", "1864E627BDB2319973CD5ED7D68DA71D8B"
"F0F983D8D9AB32C34ADB34", "A2406481FC1BCAF24DD08E6752E844" "F0F983D8D9AB32C34ADB34", "A2406481FC1BCAF24DD08E6752E844"
"709563FB916227FED598EB621F" "709563FB916227FED598EB621F"
} }, } },
{ "SHA256", SHA256, SHA256HashSize, { "SHA256", SHA256, SHA256HashSize,
skipping to change at page 95, line 4 skipping to change at page 95, line 45
"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"
"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" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0, /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
"2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A70" "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A70"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" }, "BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" },
/* 5 */ { "", 0, 0, 0x10, 5, /* 5 */ { "", 0, 0, 0x10, 5,
"8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399" "8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399"
"5F7D1149E09143AC1FFCFC56820E469F3878D957A15A3FE4" }, "5F7D1149E09143AC1FFCFC56820E469F3878D957A15A3FE4" },
/* 6 */ { "\xb9", 1, 1, 0, 0, /* 6 */ { "\xb9", 1, 1, 0, 0,
"BC8089A19007C0B14195F4ECC74094FEC64F01F90929282C" "BC8089A19007C0B14195F4ECC74094FEC64F01F90929282C"
"2FB392881578208AD466828B1C6C283D2722CF0AD1AB6938" }, "2FB392881578208AD466828B1C6C283D2722CF0AD1AB6938" },
/* 7 */ { TEST7_384, length(TEST7_384), 1, 0xA0, 3, /* 7 */ { TEST7_384, length(TEST7_384), 1, 0xA0, 3,
"D8C43B38E12E7C42A7C9B810299FD6A770BEF30920F17532" "D8C43B38E12E7C42A7C9B810299FD6A770BEF30920F17532"
"A898DE62C7A07E4293449C0B5FA70109F0783211CFC4BCE3" }, "A898DE62C7A07E4293449C0B5FA70109F0783211CFC4BCE3" },
skipping to change at page 96, line 4 skipping to change at page 96, line 45
{ {
/* 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,
"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"
"1B22A84CC03BF8CE4845F34DD5BDBAD4" }, "1B22A84CC03BF8CE4845F34DD5BDBAD4" },
/* 6 */ { "\xD0", 1, 1, 0, 0, /* 6 */ { "\xD0", 1, 1, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"9992202938E882E73E20F6B69E68A0A7149090423D93C81B" "9992202938E882E73E20F6B69E68A0A7149090423D93C81B"
"AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A" "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A"
"D6E74CECE9631BFA8A549B4AB3FBBA15" }, "D6E74CECE9631BFA8A549B4AB3FBBA15" },
/* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3, /* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3,
"ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71" "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71"
"5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B" "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B"
"7359B43E64F8BEC3C1F237119986BBB6" }, "7359B43E64F8BEC3C1F237119986BBB6" },
/* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0, /* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0,
"CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD" "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD"
"D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398" "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398"
skipping to change at page 97, line 4 skipping to change at page 97, line 45
} }
} }
}; };
/* Test arrays for HMAC. */ /* Test arrays for HMAC. */
struct hmachash { struct hmachash {
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 */
"B617318655057264E28BC0B6FB378C8EF146BE00", "B617318655057264E28BC0B6FB378C8EF146BE00",
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22", "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32" "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32"
"CFF7", "CFF7",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB" "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB"
"C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6", "C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1" "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1"
"7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20" "7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20"
skipping to change at page 98, line 4 skipping to change at page 98, line 45
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322" "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322"
"445E8E2240CA5E69E2C78B3239ECFAB21649", "445E8E2240CA5E69E2C78B3239ECFAB21649",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25" "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25"
"05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A" "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A"
"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 }, {
/* HMAC-SHA-1 */ /* HMAC-SHA-1 */
"125D7342B9AC11CD91A39AF48AA17B4F63F175D3", "125D7342B9AC11CD91A39AF48AA17B4F63F175D3",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA", "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5" "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5"
"65FE", "65FE",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966" "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966"
"144B2A5AB39DC13814B94E3AB6E101A34F27", "144B2A5AB39DC13814B94E3AB6E101A34F27",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227" "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227"
skipping to change at page 99, line 4 skipping to change at page 99, line 45
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729" "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729"
"665B", "665B",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57" "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57"
"3B4E6801DD23C4A7D679CCF8A386C674CFFB", "3B4E6801DD23C4A7D679CCF8A386C674CFFB",
/* 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 */
"4C1A03424B55E07FE7F27BE1", "4C1A03424B55E07FE7F27BE1",
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"0E2AEA68A90C8D37C988BCDB9FCA6FA8", "0E2AEA68A90C8D37C988BCDB9FCA6FA8",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"A3B6167473100EE06E0C796C2955552B", "A3B6167473100EE06E0C796C2955552B",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"3ABF34C3503B2A23A46EFC619BAEF897", "3ABF34C3503B2A23A46EFC619BAEF897",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"415FAD6271580A531D4179BC891D87A6" "415FAD6271580A531D4179BC891D87A6"
}, { 12, 16, 16, 16, 16 } }, { 12, 16, 16, 16, 16 }
}, },
{ /* 6 */ { { /* 6 */ {
skipping to change at page 100, line 4 skipping to change at page 100, line 45
"7F54", "7F54",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A" "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A"
"C4C60C2EF6AB4030FE8296248DF163F44952", "C4C60C2EF6AB4030FE8296248DF163F44952",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8" "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8"
"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"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
}, { 80, 131 }, { }, { 80, 131 }, {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"Test Using Larger Than Block-Size Key and " "Test Using Larger Than Block-Size Key and "
"Larger Than One Block-Size Data", "Larger Than One Block-Size Data",
"\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20" "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20"
"\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" "\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
"\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65" "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65"
"\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" "\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
"\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73" "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73"
"\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" "\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
"\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20" "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20"
"\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" "\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
skipping to change at page 101, line 4 skipping to change at page 101, line 45
"E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD" "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD"
"C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440" "C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440"
"FA8C6A58" "FA8C6A58"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
} }
}; };
/* 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;
const char *okmarray; const char *okmarray;
} hkdfhashes[HKDFTESTCOUNT] = { } hkdfhashes[HKDFTESTCOUNT] = {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ /* RFC 5869 A.1. Test Case 1 */ { /* RFC 5869 A.1. Test Case 1 */
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",
13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
32, "077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844A" 32, "077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844A"
"D7C2B3E5", "D7C2B3E5",
42, "3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56" 42, "3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56"
"ECC4C5BF34007208D5B887185865" "ECC4C5BF34007208D5B887185865"
skipping to change at page 102, line 4 skipping to change at page 102, line 44
"\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"
"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",
42, "8DA4E775A563C18F715F802A063C5A31" 42, "8DA4E775A563C18F715F802A063C5A31"
"B8A11F5C5EE1879EC3454E5F3C738D2D" "B8A11F5C5EE1879EC3454E5F3C738D2D"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"9D201395FAA4B61A96C8" "9D201395FAA4B61A96C8"
}, },
{ /* RFC 5869 A.4. Test Case 4 */ { /* RFC 5869 A.4. Test Case 4 */
SHA1, SHA1,
11, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 11, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 13, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 10, "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
20, "9B6C18C432A7BF8F0E71C8EB88F4B30BAA2BA243", 20, "9B6C18C432A7BF8F0E71C8EB88F4B30BAA2BA243",
42, "085A01EA1B10F36933068B56EFA5AD81" 42, "085A01EA1B10F36933068B56EFA5AD81"
"A4F14B822F5B091568A9CDD4F155FDA2" "A4F14B822F5B091568A9CDD4F155FDA2"
skipping to change at page 103, line 4 skipping to change at page 103, line 45
"\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"
"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"
"B9AE52057220A306E07B6B87E8DF21D0" "B9AE52057220A306E07B6B87E8DF21D0"
"EA00033DE03984D34918" "EA00033DE03984D34918"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}, },
{ /* RFC 5869 A.7. Test Case 7. */ { /* RFC 5869 A.7. Test Case 7. */
SHA1, SHA1,
22, "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" 22, "\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",
0, 0, 0, 0,
0, "", 0, "",
20, "2ADCCADA18779E7C2077AD2EB19D3F3E731385DD", 20, "2ADCCADA18779E7C2077AD2EB19D3F3E731385DD",
42, "2C91117204D745F3500D636A62F64F0A" 42, "2C91117204D745F3500D636A62F64F0A"
"B3BAE548AA53D423B0D1F27EBBA6F5E5" "B3BAE548AA53D423B0D1F27EBBA6F5E5"
skipping to change at page 104, line 4 skipping to change at page 104, line 45
} }
/* /*
* 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)
{ {
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]);
sep = " "; sep = " ";
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
* Print a usage message. * Print a usage message.
*/ */
void usage(const char *argv0) void usage(const char *argv0)
{ {
fprintf(stderr, fprintf(stderr,
"Usage:\n" "Usage:\n"
"Common options: [-h hash] [-w|-x|-6] [-H]\n" "Common options: [-h hash] [-w|-x|-6] [-H]\n"
skipping to change at page 105, line 4 skipping to change at page 105, line 46
"-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"
"-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);
exit(1); exit(1);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
* Print the results and PASS/FAIL. * Print the results and PASS/FAIL.
*/ */
void printResult(uint8_t *Message_Digest, int hashsize, void printResult(uint8_t *Message_Digest, int hashsize,
const char *hashname, const char *testtype, const char *testname, const char *hashname, const char *testtype, const char *testname,
const char *resultarray, int printResults, int printPassFail) const char *resultarray, int printResults, int printPassFail)
{ {
int i, k; int i, k;
skipping to change at page 106, line 4 skipping to change at page 106, line 46
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;
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");
for (i = 0, k = 0; i < hashsize; i++, k += 2) { for (i = 0, k = 0; i < hashsize; i++, k += 2) {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
putchar(resultarray[k]); putchar(resultarray[k]);
putchar(resultarray[k+1]); putchar(resultarray[k+1]);
putchar(' '); putchar(' ');
} }
putchar('\n'); putchar('\n');
} }
if (printPassFail && resultarray) { if (printPassFail && resultarray) {
int ret = checkmatch(Message_Digest, resultarray, hashsize); int ret = checkmatch(Message_Digest, resultarray, hashsize);
if ((printPassFail == PRINTPASSFAIL) || !ret) if ((printPassFail == PRINTPASSFAIL) || !ret)
skipping to change at page 107, line 4 skipping to change at page 107, line 46
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];
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));
memset(&hkdf, '\343', sizeof(hkdf)); memset(&hkdf, '\343', sizeof(hkdf));
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
err = info ? hkdfReset(&hkdf, hashes[hashno].whichSha, err = info ? hkdfReset(&hkdf, hashes[hashno].whichSha,
keyarray, keylen) : keyarray, keylen) :
keyarray ? hmacReset(&hmac, hashes[hashno].whichSha, keyarray ? hmacReset(&hmac, hashes[hashno].whichSha,
keyarray, keylen) : keyarray, keylen) :
USHAReset(&sha, hashes[hashno].whichSha); USHAReset(&sha, hashes[hashno].whichSha);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hash(): %sReset Error %d.\n", fprintf(stderr, "hash(): %sReset Error %d.\n",
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
return err; return err;
} }
skipping to change at page 108, line 4 skipping to change at page 108, line 46
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;
} }
} }
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);
printResult(Message_Digest, info ? okmlen : hashsize, printResult(Message_Digest, info ? okmlen : hashsize,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
hashes[hashno].name, info ? "hkdf standard test" : hashes[hashno].name, info ? "hkdf standard test" :
keyarray ? "hmac standard test" : "sha standard test", buf, keyarray ? "hmac standard test" : "sha standard test", buf,
resultarray, printResults, printPassFail); resultarray, printResults, printPassFail);
return err; return err;
} }
/* /*
* Exercise an HKDF series. The input is the testarray, * Exercise an HKDF series. The input is the testarray,
* repeated repeatcount times, followed by the extrabits. If the * repeated repeatcount times, followed by the extrabits. If the
skipping to change at page 109, line 4 skipping to change at page 109, line 46
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 */
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,
USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
buf, hkdfhashes[testno].okmarray, printResults, printPassFail); buf, hkdfhashes[testno].okmarray, printResults, printPassFail);
/* Now run hkdfExtract() by itself against the test vectors */ /* Now run hkdfExtract() by itself against the test vectors */
/* to verify the intermediate results. */ /* to verify the intermediate results. */
err = hkdfExtract(hkdfhashes[testno].whichSha, err = hkdfExtract(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,
hkdfhashes[testno].ikmlength, prk); hkdfhashes[testno].ikmlength, prk);
if (err != shaSuccess) { if (err != shaSuccess) {
skipping to change at page 110, line 4 skipping to change at page 110, line 46
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;
} }
/* /*
* 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;
int err, nread, c; int err, nread, c;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
unsigned char buf[4096]; unsigned char buf[4096];
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;
unsigned char cc; unsigned char cc;
FILE *hashfp = (strcmp(hashfilename, "-") == 0) ? stdin : FILE *hashfp = (strcmp(hashfilename, "-") == 0) ? stdin :
fopen(hashfilename, "r"); fopen(hashfilename, "r");
if (!hashfp) { if (!hashfp) {
fprintf(stderr, "cannot open file '%s'\n", hashfilename); fprintf(stderr, "cannot open file '%s'\n", hashfilename);
return shaStateError; return shaStateError;
skipping to change at page 111, line 4 skipping to change at page 111, line 46
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",
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",
info ? "hkdf" : keyarray ? "hmacInput" : info ? "hkdf" : keyarray ? "hmacInput" :
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"shaInput", err); "shaInput", err);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
} }
} }
if (bitcount > 0) if (bitcount > 0)
err = info ? hkdfFinalBits(&hkdf, bits, bitcount) : err = info ? hkdfFinalBits(&hkdf, bits, bitcount) :
keyarray ? hmacFinalBits(&hmac, bits, bitcount) : keyarray ? hmacFinalBits(&hmac, bits, bitcount) :
USHAFinalBits(&sha, bits, bitcount); USHAFinalBits(&sha, bits, bitcount);
skipping to change at page 112, line 4 skipping to change at page 112, line 45
} }
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);
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,
int printResults, int printPassFail) int printResults, int printPassFail)
{ {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int i, j; char buf[20]; int i, j; char buf[20];
unsigned char SEED[USHAMaxHashSize], MD[1003][USHAMaxHashSize]; unsigned char SEED[USHAMaxHashSize], MD[1003][USHAMaxHashSize];
/* INPUT: Seed - A random seed n bits long */ /* INPUT: Seed - A random seed n bits long */
memcpy(SEED, seed, hashsize); memcpy(SEED, seed, hashsize);
if (printResults == PRINTTEXT) { if (printResults == PRINTTEXT) {
printf("%s random test seed= '", hashes[hashno].name); printf("%s random test seed= '", hashes[hashno].name);
printxstr(seed, hashsize); printxstr(seed, hashsize);
printf("'\n"); printf("'\n");
} }
skipping to change at page 113, line 4 skipping to change at page 113, line 44
/* 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
/* /*
* 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" }
}; };
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
for (i = 0; i < HASHCOUNT; i++) for (i = 0; i < HASHCOUNT; i++)
if ((strcmp(opt, names[i][0]) == 0) || if ((strcmp(opt, names[i][0]) == 0) ||
(scasecmp(opt, names[i][1]) == 0)) (scasecmp(opt, names[i][1]) == 0))
return i; return i;
fprintf(stderr, "%s: Unknown hash name: '%s'\n", argv0, opt); fprintf(stderr, "%s: Unknown hash name: '%s'\n", argv0, opt);
usage(argv0); usage(argv0);
return 0; return 0;
} }
skipping to change at page 114, line 5 skipping to change at page 114, line 47
(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) ||
((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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case SHA224: err = SHA224Reset(0); break; case SHA224: err = SHA224Reset(0); break;
case SHA256: err = SHA256Reset(0); break; case SHA256: err = SHA256Reset(0); break;
case SHA384: err = SHA384Reset(0); break; case SHA384: err = SHA384Reset(0); break;
case SHA512: err = SHA512Reset(0); break; case SHA512: err = SHA512Reset(0); break;
} }
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 sha null: %s\n", hashes[hashno].name, printf("%s sha null: %s\n", hashes[hashno].name,
skipping to change at page 115, line 4 skipping to change at page 115, line 47
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);
} }
*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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
int printPassFail = 1; int printPassFail = 1;
int checkErrors = 0; int checkErrors = 0;
char *hashstr = 0; char *hashstr = 0;
int hashlen = 0; int hashlen = 0;
const char *resultstr = 0; const char *resultstr = 0;
char *randomseedstr = 0; char *randomseedstr = 0;
int runHmacTests = 0; int runHmacTests = 0;
int runHkdfTests = 0; int runHkdfTests = 0;
char *hmacKey = 0; char *hmacKey = 0;
int hmaclen = 0; int hmaclen = 0;
char *info = 0; char *info = 0;
int infolen = 0, okmlen = 0; int infolen = 0, okmlen = 0;
int randomcount = RANDOMCOUNT; int randomcount = RANDOMCOUNT;
const char *hashfilename = 0; const char *hashfilename = 0;
const char *hashFilename = 0; const char *hashFilename = 0;
int extrabits = 0, numberExtrabits = 0; int extrabits = 0, numberExtrabits = 0;
int strIsHex = 0; int strIsHex = 0;
if ('A' != 0x41) {
fprintf(stderr, "%s: ASCII is required for these tests\n", argv[0]);
}
while ((i = getopt(argc, argv, while ((i = getopt(argc, argv,
"6b:B:def:F:h:i:Hk:l:L:mpPr:R:s:S:t:wxX")) != -1) "6b:B:def:F:h:i:Hk:l:L:mpPr:R:s:S:t:wxX")) != -1)
switch (i) { switch (i) {
case 'b': extrabits = strtol(optarg, 0, 0); break; case 'b': extrabits = strtol(optarg, 0, 0); break;
case 'B': numberExtrabits = atoi(optarg); break; case 'B': numberExtrabits = atoi(optarg); break;
case 'd': runHkdfTests = 1; break; case 'd': runHkdfTests = 1; break;
case 'e': checkErrors = 1; break; case 'e': checkErrors = 1; break;
case 'f': hashfilename = optarg; break; case 'f': hashfilename = optarg; break;
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);
skipping to change at page 116, line 4 skipping to change at page 116, line 51
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;
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
default: usage(argv[0]); default: usage(argv[0]);
} }
if (strIsHex) { if (strIsHex) {
hashlen = unhexStr(hashstr); hashlen = unhexStr(hashstr);
unhexStr(randomseedstr); unhexStr(randomseedstr);
hmaclen = unhexStr(hmacKey); hmaclen = unhexStr(hmacKey);
infolen = unhexStr(info); infolen = unhexStr(info);
} }
testnohigh = (ntestnohigh != 0) ? ntestnohigh: testnohigh = (ntestnohigh != 0) ? ntestnohigh:
skipping to change at page 117, line 5 skipping to change at page 117, line 52
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);
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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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,
numberExtrabits, 1, numberExtrabits, 1,
(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);
skipping to change at page 118, line 4 skipping to change at page 118, line 52
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],
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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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,
printResults, printPassFail); printResults, printPassFail);
} }
} }
if (!runHmacTests && !runHkdfTests) { if (!runHmacTests && !runHkdfTests) {
randomtest(hashno, hashes[hashno].randomtest, randomtest(hashno, hashes[hashno].randomtest,
skipping to change at page 120, line 25 skipping to change at page 121, line 25
[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.
[US-ASCII] - ANSI, "USA Standard Code for Information Interchange",
X3.4, American National Standards Institute: New York, 1968.
12.2 Informative References 12.2 Informative References
[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
skipping to change at page 121, line 14 skipping to change at page 122, line 14
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Appendix: Changes from RFC 4634 Appendix: Changes from RFC 4634
The following changes were made to RFC 4634 to produce this document: The following changes were made to RFC 4634 to produce this document:
1. Add code for HKDF and brief text about HKDF with pointer to 1. Add code for HKDF and brief text about HKDF with pointer to
[RFC5869]. [RFC5869].
2. Fix numerous errata filed against [RFC4634] as below. Note that in 2. Fix numerous errata filed against [RFC4634] as included below.
no case did the old code return an incorrect hash value. Note that in no case did the old code return an incorrect hash
value.
2.a Correct some of the error return values which has erroneously 2.a Correct some of the error return values which has erroneously
been "shaNull" to the correct "shaInputTooLong" error. been "shaNull" to the correct "shaInputTooLong" error.
2.b Update comments and variable names within the code for 2.b Update comments and variable names within the code for
consistency and clarity and other editorial changes. consistency and clarity and other editorial changes.
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 including a run time check in
the test driver to detect attempts to run the test driver
after compilation using some other character set instead of
[US-ASCII].
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. Replace 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
skipping to change at page 123, line 9 skipping to change at page 124, line 9
Z.5 Changes from -04 to -05 Z.5 Changes from -04 to -05
Resolve AD Review comments: Re-order some Abstract and Introduction Resolve AD Review comments: Re-order some Abstract and Introduction
material. Make the RFC Editor notes more prominent. material. Make the RFC Editor notes more prominent.
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 Eastlake
Huawei Huawei
155 Beaver Street 155 Beaver Street
Milford, MA 01757 USA Milford, MA 01757 USA
Telephone: +1-508-333-2270 Telephone: +1-508-333-2270
EMail: d3e3e3@gmail.com EMail: d3e3e3@gmail.com
Tony Hansen Tony Hansen
AT&T Laboratories AT&T Laboratories
200 Laurel Ave. 200 Laurel Ave.
Middletown, NJ 07748 USA Middletown, NJ 07748 USA
Telephone: +1-732-420-8934 Telephone: +1-732-420-8934
EMail: tony+shs@maillennium.att.com EMail: tony+shs@maillennium.att.com
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Copyright, Disclaimer, and Additional IPR Provisions Copyright, Disclaimer, and Additional IPR Provisions
Copyright (c) 2010 IETF Trust and the persons identified as the Copyright (c) 2011 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of (http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
 End of changes. 212 change blocks. 
280 lines changed or deleted 340 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/