< draft-eastlake-sha2b-02.txt   draft-eastlake-sha2b-03.txt >
Network Working Group Donald Eastlake 3rd Network Working Group Donald Eastlake 3rd
INTERNET-DRAFT Stellar Switches INTERNET-DRAFT Stellar Switches
Obsoletes: 4634 Tony Hansen Obsoletes: 4634 Tony Hansen
Updates: 3174 AT&T Labs Updates: 3174 AT&T Labs
Intended Status: Informational Intended Status: Informational
Expires: November 8, 2010 May 9, 2010 Expires: January 29, 2011 July 30, 2010
US Secure Hash Algorithms US Secure Hash Algorithms
(SHA and SHA based HMAC and HKDF) (SHA and SHA based HMAC and HKDF)
<draft-eastlake-sha2b-02.txt> <draft-eastlake-sha2b-03.txt>
Abstract Abstract
This document is an update of [RFC4634] to fix errata and to add code This document is an update of RFC 4634 to fix errata and to add code
for an HMAC-based extract-and-expand key derivation function. for an HMAC-based extract-and-expand key derivation function.
The United States of America has adopted a suite of secure hash The United States of America has adopted a suite of secure hash
algorithms (SHAs), including four beyond SHA-1, as part of a Federal algorithms (SHAs), including four beyond SHA-1, as part of a Federal
Information Processing Standard (FIPS), specifically SHA-224, Information Processing Standard (FIPS), specifically SHA-224,
SHA-256, SHA-384, and SHA-512. The purpose of this document is to SHA-256, SHA-384, and SHA-512. The purpose of this document is to
make open source code performing the SHA hash functions conveniently make open source code performing the SHA hash functions conveniently
available to the Internet community. The sample code supports input available to the Internet community. The sample code supports input
strings of arbitrary bit length. Much of the text herein was adapted strings of arbitrary bit length. Much of the text herein was adapted
by the authors from FIPS 180-2. by the authors from FIPS 180-2.
As with [RFC4634], code to perform SHA based HMACs is included and, As with RFC 4634, code to perform SHA based HMACs is included and,
new in this version, code for HKDF is included. new in this version, code for HKDF (RFC 5869) is included.
Status of This Memo Status of This Memo
This Internet-Draft is submitted to IETF in full conformance with the This Internet-Draft is submitted to IETF in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
Distribution of this document is unlimited. Comments should be sent Distribution of this document is unlimited. Comments should be sent
to the authors. to the authors.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
skipping to change at page 2, line 28 skipping to change at page 2, line 28
5.1 SHA-224 and SHA-256...................................10 5.1 SHA-224 and SHA-256...................................10
5.2 SHA-384 and SHA-512...................................11 5.2 SHA-384 and SHA-512...................................11
6. Computing the Message Digest...........................12 6. Computing the Message Digest...........................12
6.1 SHA-224 and SHA-256 Initialization....................12 6.1 SHA-224 and SHA-256 Initialization....................12
6.2 SHA-224 and SHA-256 Processing........................12 6.2 SHA-224 and SHA-256 Processing........................12
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 .h file...........................................21 8.1 The Header Files......................................21
8.2 The SHA Code..........................................28 8.1.1 The .h file.........................................21
8.1.2 sha-private.h.......................................29
8.2 The SHA Code..........................................29
8.2.1 sha1.c..............................................29 8.2.1 sha1.c..............................................29
8.2.2 sha224-256.c........................................37 8.2.2 sha224-256.c........................................38
8.2.3 sha384-512.c........................................49 8.2.3 sha384-512.c........................................50
8.2.4 usha.c..............................................70 8.2.4 usha.c..............................................71
8.2.5 sha-private.h.......................................76
8.3 The HMAC Code.........................................77 8.3 The HMAC Code.........................................77
8.4 The HKDF Code.........................................82 8.4 The HKDF Code.........................................82
8.5 The Test Driver.......................................89 8.5 The Test Driver.......................................89
9. IANA Considerations...................................122 9. IANA Considerations...................................120
10. Security Considerations..............................122 10. Security Considerations..............................120
11. Acknowledgements.....................................122 11. Acknowledgements.....................................120
12. References...........................................123 12. References...........................................121
12.1 Normative References................................123 12.1 Normative References................................121
12.2 Informative References..............................123 12.2 Informative References..............................121
Appendix: Changes from RFC 4634..........................125 Appendix: Changes from RFC 4634..........................123
Edit History.............................................126 Appendix Z: Edit History.................................124
Changes from -00 to -01..................................126 Z.1 Changes from -00 to -01..............................124
Changes from -01 to -02..................................126 Z.2 Changes from -01 to -02..............................124
Z.3 Changes from -02 to -03..............................124
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
1. Overview of Contents 1. Overview of Contents
This document obsoletes [RFC4634] and the changes from that RFC are This document obsoletes [RFC4634]; and the changes from that RFC are
summarized in the Appendix below. summarized in the Appendix.
This document includes specifications for the United States of This document includes specifications for the United States of
America (USA) Federal Information Processing Standard (FIPS) Secure America (USA) Federal Information Processing Standard (FIPS) Secure
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
elsewhere in the RFC series [RFC2104] [RFChkdf]. elsewhere in the RFC series [RFC2104] [RFC5869].
NOTE: Much of the text below is taken from [FIPS 180-2] and the NOTE: Much of the text below is taken from [SHS] and the assertions
assertions of the security of the hash algorithms described therein of the security of the hash algorithms described therein are made by
are made by the US Government, the author of [FIPS 180-2], not by the the US Government, the author of [SHS], not by the authors of this
authors of this document. document.
The text below specifies Secure Hash Algorithms, SHA-224 [RFC3874], The text below specifies Secure Hash Algorithms, SHA-224 [RFC3874],
SHA-256, SHA-384, and SHA-512, for computing a condensed SHA-256, SHA-384, and SHA-512, for computing a condensed
representation of a message or a data file. (SHA-1 is specified in representation of a message or a data file. (SHA-1 is specified in
[RFC3174].) When a message of any length < 2^64 bits (for SHA-224 and [RFC3174].) When a message of any length < 2^64 bits (for SHA-224 and
SHA-256) or < 2^128 bits (for SHA-384 and SHA-512) is input to one of SHA-256) or < 2^128 bits (for SHA-384 and SHA-512) is input to one of
these algorithms, the result is an output called a message digest. these algorithms, the result is an output called a message digest.
The message digests range in length from 224 to 512 bits, depending The message digests range in length from 224 to 512 bits, depending
on the algorithm. Secure hash algorithms are typically used with on the algorithm. Secure hash algorithms are typically used with
other cryptographic algorithms, such as digital signature algorithms other cryptographic algorithms, such as digital signature algorithms
and keyed hash authentication codes, the generation or random numbers and keyed hash authentication codes, the generation of random numbers
[RFC4086], or in key derivation functions. [RFC4086], or in key derivation functions.
The four algorithms specified in this document are called secure The four algorithms specified in this document are called secure
because it is computationally infeasible to (1) find a message which because it is computationally infeasible to (1) find a message which
corresponds to a given message digest, or (2) to find two different corresponds to a given message digest, or (2) to find two different
messages that produce the same message digest. Any change to a messages that produce the same message digest. Any change to a
message in transit will, with very high probability, result in a message in transit will, with very high probability, result in a
different message digest. This will result in a verification failure different message digest. This will result in a verification failure
when the secure hash algorithm is used with a digital signature when the secure hash algorithm is used with a digital signature
algorithm or a keyed-hash message authentication algorithm. algorithm or a keyed-hash message authentication algorithm.
skipping to change at page 4, line 26 skipping to change at page 4, line 26
id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2)
country(16) us(840) organization(1) gov(101) country(16) us(840) organization(1) gov(101)
csor(3) nistalgorithm(4) hashalgs(2) 3 } csor(3) nistalgorithm(4) hashalgs(2) 3 }
Section 2 below defines the terminology and functions used as Section 2 below defines the terminology and functions used as
building blocks to form these algorithms. Section 3 describes the building blocks to form these algorithms. Section 3 describes the
fundamental operations on words from which these algorithms are fundamental operations on words from which these algorithms are
built. Section 4 describes how messages are padded up to an integral built. Section 4 describes how messages are padded up to an integral
multiple of the required block size and then parsed into blocks. multiple of the required block size and then parsed into blocks.
Section 5 defines the constants and the composite functions used to Section 5 defines the constants and the composite functions used to
specify these algorithms. Section 6 gives the actual specification specify the hash algorithms. Section 6 gives the actual specification
for the SHA-224, SHA-256, SHA-384, and SHA-512 functions. Section 7 for the SHA-224, SHA-256, SHA-384, and SHA-512 functions. Section 7
provides pointers to the specification of HMAC keyed message provides pointers to the specification of HMAC keyed message
authentication codes and to the specification of an extract-and- authentication codes and to the specification of an extract-and-
expand key derivation function based on HMAC. expand key derivation function based on HMAC.
Section 8 gives sample code for the SHA algorithms, for SHA based Section 8 gives sample code for the SHA algorithms, for SHA based
HMACs, and for HMAC-based extract-and-expand key derivation function. HMACs, and for HMAC-based extract-and-expand key derivation function.
2. Notation for Bit Strings and Integers 2. Notation for Bit Strings and Integers
skipping to change at page 4, line 53 skipping to change at page 4, line 53
b. A word equals a 32-bit or 64-bit string that may be represented b. A word equals a 32-bit or 64-bit string that may be represented
as a sequence of 8 or 16 hex digits, respectively. To convert a as a sequence of 8 or 16 hex digits, respectively. To convert a
word to hex digits, each 4-bit string is converted to its hex word to hex digits, each 4-bit string is converted to its hex
equivalent as described in (a) above. Example: equivalent as described in (a) above. Example:
1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23. 1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23.
Throughout this document, the "big-endian" convention is used Throughout this document, the "big-endian" convention is used
when expressing both 32-bit and 64-bit words, so that within when expressing both 32-bit and 64-bit words, so that within
each word the most significant bit is shown in the left-most bit each word the most significant bit is shown in the leftmost bit
position. position.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
c. An integer may be represented as a word or pair of words. c. An integer may be represented as a word or pair of words.
An integer between 0 and 2^32 - 1 inclusive may be represented An integer between 0 and 2^32 - 1 inclusive may be represented
as a 32-bit word. The least significant four bits of the as a 32-bit word. The least significant four bits of the
integer are represented by the right-most hex digit of the word integer are represented by the rightmost hex digit of the word
representation. Example: the integer 291 = 2^8+2^5+2^1+2^0 = representation. Example: the integer 291 = 2^8+2^5+2^1+2^0 =
256+32+2+1 is represented by the hex word, 00000123. 256+32+2+1 is represented by the hex word, 00000123.
The same holds true for an integer between 0 and 2^64-1 The same holds true for an integer between 0 and 2^64-1
inclusive, which may be represented as a 64-bit word. inclusive, which may be represented as a 64-bit word.
If Z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0 If Z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0
<= x < 2^32 and 0 <= y < 2^32. Since x and y can be represented <= x < 2^32 and 0 <= y < 2^32. Since x and y can be represented
as words X and Y, respectively, z can be represented as the pair as words X and Y, respectively, z can be represented as the pair
of words (X,Y). of words (X,Y).
Again, the "big-endian" convention is used and the most Again, the "big-endian" convention is used and the most
significant word is in the left-most word position for values significant word is in the leftmost word position for values
represented by multiple-words. represented by multiple-words.
d. block = 512-bit or 1024-bit string. A block (e.g., B) may be d. block = 512-bit or 1024-bit string. A block (e.g., B) may be
represented as a sequence of 32-bit or 64-bit words. represented as a sequence of 32-bit or 64-bit words.
3. Operations on Words 3. Operations on Words
The following logical operators will be applied to words in all four The following logical operators will be applied to words in all four
hash operations specified herein. SHA-224 and SHA-256 operate on hash operations specified herein. SHA-224 and SHA-256 operate on
32-bit words while SHA-384 and SHA-512 operate on 64-bit words. 32-bit words while SHA-384 and SHA-512 operate on 64-bit words.
In the operations below, x<<n is obtained as follows: discard the In the operations below, x<<n is obtained as follows: discard the
left-most n bits of x and then pad the result with n zeroed bits on leftmost n bits of x and then pad the result with n zeroed bits on
the right (the result will still be the same number of bits). the right (the result will still be the same number of bits).
Similarly, x>>n is obtained as follows: discard the right-most n bits Similarly, x>>n is obtained as follows: discard the rightmost n bits
of x and then prepend the result with n zeroed bits on the left (the of x and then prepend the result with n zeroed bits on the left (the
result will still be the same number of bits). result will still be the same number of bits).
a. Bitwise logical word operations a. Bitwise logical word operations
X AND Y = bitwise logical "and" of X and Y. X AND Y = bitwise logical "and" of X and Y.
X OR Y = bitwise logical "inclusive-or" of X and Y. X OR Y = bitwise logical "inclusive-or" of X and Y.
X XOR Y = bitwise logical "exclusive-or" of X and Y. X XOR Y = bitwise logical "exclusive-or" of X and Y.
skipping to change at page 17, line 10 skipping to change at page 17, line 10
of the blocks in the message, the final output is calculated. For of the blocks in the message, the final output is calculated. For
SHA-512, this is the concatenation of all of H(N)0, H(N)1, through SHA-512, this is the concatenation of all of H(N)0, H(N)1, through
H(N)7. For SHA-384, this is the concatenation of H(N)0, H(N)1, H(N)7. For SHA-384, this is the concatenation of H(N)0, H(N)1,
through H(N)5. through H(N)5.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
7. HKDF and SHA Based HMACs 7. HKDF and SHA Based HMACs
Below are brief descriptions and pointers to more complete Below are brief descriptions and pointers to more complete
descriptions and code for (1) an HMAC-based extract-and-expand key descriptions and code for (1) SHA-based HMACs and (2) an HMAC-based
derivation function and (2) SHA based HMACs. Both HKDF and HMAC were extract-and-expand key derivation function. Both HKDF and HMAC were
devised by Hugo Krawczyk. devised by Hugo Krawczyk.
7.1 SHA Based HMACs 7.1 SHA-Based HMACs
HMAC is a method for computing a keyed MAC (message authentication HMAC is a method for computing a keyed MAC (message authentication
code) using a hash function as described in [RFC2104]. It uses a key code) using a hash function as described in [RFC2104]. It uses a key
to mix in with the input text to produce the final hash. to mix in with the input text to produce the final hash.
Sample code is also provided, in Section 8.3 below, to perform HMAC Sample code is also provided, in Section 8.3 below, to perform HMAC
based on any of the SHA algorithms described herein. The sample code based on any of the SHA algorithms described herein. The sample code
found in [RFC2104] was written in terms of a specified text size. found in [RFC2104] was written in terms of a specified text size.
Since SHA is defined in terms of an arbitrary number of bits, the Since SHA is defined in terms of an arbitrary number of bits, the
sample HMAC code has been written to allow the text input to HMAC to sample HMAC code has been written to allow the text input to HMAC to
have an arbitrary number of octets and bits. A fixed length interface have an arbitrary number of octets and bits. A fixed length interface
is also provided. is also provided.
7.2 HKDF 7.2 HKDF
HKDF is a specific key derivation function (KDF), that is, a function HKDF is a specific key derivation function (KDF), that is, a function
of initial keying material from which the KDF derives one or more of initial keying material from which the KDF derives one or more
cryptographically strong secret keys. HKDF, which is described in cryptographically strong secret keys. HKDF, which is described in
[RFChkdf], is based on HMAC. [RFC5869], is based on HMAC.
Sample code for HKDF is provided in Section 8.4 below. Sample code for HKDF is provided in Section 8.4 below.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8. C Code for SHAs, HMAC, and HKDF 8. C Code for SHAs, HMAC, and HKDF
Below is a demonstration implementation of these secure hash Below is a demonstration implementation of these secure hash
functions in C. Section 8.1 contains the header file sha.h that functions in C. Section 8.1 contains the header file sha.h that
declares all constants, structures and functions used by the sha and declares all constants, structures and functions used by the sha and
hmac functions. Section 8.2 contains the C code for sha1.c, hmac functions. It includes conditionals based on the state of
sha224-256.c, sha384-512.c, and usha.c along with sha-private.h that definition of USE_32BIT_ONLY which, if that symbol is defined at
provides some declarations common to all the sha functions. Section compile time, avoids 64-bit operations. It also contains sha-
8.3 contains the C code for the HMAC functions and Section 8.4 private.h that provides some declarations common to all the sha
contains the C code for HKDF. Section 8.5 contains a test driver to functions. Section 8.2 contains the C code for sha1.c, sha224-256.c,
exercise the code. sha384-512.c, and usha.c. Section 8.3 contains the C code for the
HMAC functions and Section 8.4 contains the C code for HKDF. Section
8.5 contains a test driver to exercise the code.
For each of the digest length $$$, there are the following set of For each of the digest lengths $$$, there are the following set of
constants, a structure, and functions: constants, a structure, and functions:
Constants: Constants:
SHA$$$HashSize number of octets in the hash SHA$$$HashSize number of octets in the hash
SHA$$$HashSizeBits number of bits in the hash SHA$$$HashSizeBits number of bits in the hash
SHA$$$_Message_Block_Size SHA$$$_Message_Block_Size
number of octets used in the intermediate number of octets used in the intermediate
message blocks message blocks
shaSuccess = 0 constant returned by each function on success Most functions return an enum value that is one of:
shaNull = 1 constant returned by each function when shaSuccess(0) on success
presented with a null pointer parameter shaNull(1) when presented with a null pointer parameter
shaInputTooLong = 2 constant returned by each function when the shaInputTooLong(2) when the input data is too long
input data is too long shaStateError(3) when SHA$$$Input is called after
shaStateError = 3 constant returned by each function when SHA$$$FinalBits or SHA$$$Result.
SHA$$$Input is called after SHA$$$FinalBits or
SHA$$$Result.
Structure: Structure:
typedef SHA$$$Context typedef SHA$$$Context
an opaque structure holding the complete state an opaque structure holding the complete state
for producing the hash for producing the hash
Functions: Functions:
int SHA$$$Reset(SHA$$$Context *context); int SHA$$$Reset(SHA$$$Context *context);
Reset the hash context state Reset the hash context state
int SHA$$$Input(SHA$$$Context *context, const uint8_t *octets, int SHA$$$Input(SHA$$$Context *context, const uint8_t *octets,
skipping to change at page 19, line 12 skipping to change at page 19, line 12
Do the final calculations on the hash and copy the value Do the final calculations on the hash and copy the value
into Message_Digest. into Message_Digest.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
In addition, functions with the prefix USHA are provided that take a In addition, functions with the prefix USHA are provided that take a
SHAversion value (SHA$$$) to select the SHA function suite. They add SHAversion value (SHA$$$) to select the SHA function suite. They add
the following constants, structure and function: the following constants, structure and function:
Constants: Constants:
shaBadParam constant returned by USHA functions when shaBadParam(4) constant returned by USHA functions when
presented with a bad SHAversion (SHA$$$) presented with a bad SHAversion (SHA$$$)
parameter or other illegal parameter values parameter or other illegal parameter values
USAMaxHashSize maximumof the SHA has sizes
SHA$$$ SHAversion enumeration values, used by usha, SHA$$$ SHAversion enumeration values, used by usha,
hmac and hkdf functions to select the SHA hmac and hkdf functions to select the SHA
function suite function suite
Structure: Structure:
typedef USHAContext typedef USHAContext
an opaque structure holding the complete state an opaque structure holding the complete state
for producing the hash for producing the hash
Functions: Functions:
skipping to change at page 19, line 53 skipping to change at page 19, line 54
The internal block size for the given hash. The internal block size for the given hash.
const char *USHAHashName(enum SHAversion whichSha); const char *USHAHashName(enum SHAversion whichSha);
This function will return the name of the given SHA This function will return the name of the given SHA
algorithm as a string. algorithm as a string.
The hmac functions follow the same pattern to allow any length of The hmac functions follow the same pattern to allow any length of
text input to be used. text input to be used.
Structures: Structures:
typedef HMACContext an opaque structure holding the complete state typedef HMACContext an opaque structure holding the complete state
for producing the hash for producing the keyed message digest (MAC)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Functions: Functions:
int hmacReset(HMACContext *ctx, enum SHAversion whichSha, int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
const unsigned char *key, int key_len); const unsigned char *key, int key_len);
Reset the hash context state. Reset the MAC context state.
int hmacInput(HMACContext *ctx, const unsigned char *text, int hmacInput(HMACContext *ctx, const unsigned char *text,
int text_len); int text_len);
Incorporate text_len octets into the hash. Incorporate text_len octets into the MAC.
int hmacFinalBits(HMACContext *ctx, const uint8_t bits, int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
unsigned int bitcount); unsigned int bitcount);
Incorporate bitcount bits into the hash. Incorporate bitcount bits into the MAC.
int hmacResult(HMACContext *ctx, int hmacResult(HMACContext *ctx,
uint8_t Message_Digest[USHAMaxHashSize]); uint8_t Message_Digest[USHAMaxHashSize]);
Do the final calculations on the hash and copy the value Do the final calculations on the MAC and copy the value into
into Message_Digest. Octets in Message_Digest beyond Message_Digest. Octets in Message_Digest beyond
USHAHashSize(whichSha) are left untouched. USHAHashSize(whichSha) are left untouched.
In addition, a combined interface is provided, similar to that shown In addition, a combined interface is provided, similar to that shown
in [RFC2104], that allows a fixed-length text input to be used. in [RFC2104], that allows a fixed-length text input to be used.
int hmac(SHAversion whichSha, int hmac(SHAversion whichSha,
const unsigned char *text, int text_len, const unsigned char *text, int text_len,
const unsigned char *key, int key_len, const unsigned char *key, int key_len,
uint8_t Message_Digest[USHAMaxHashSize]); uint8_t Message_Digest[USHAMaxHashSize]);
Calculate the given digest for the given text and key, and Calculate the given digest for the given text and key, and
return the resulting hash. Octets in Message_Digest beyond return the resulting MAC. Octets in Message_Digest beyond
USHAHashSize(whichSha) are left untouched. USHAHashSize(whichSha) are left untouched.
The hkdf functions follow the same pattern to allow any length of The hkdf functions follow the same pattern to allow any length of
text input to be used. text input to be used.
Structures: Structures:
typedef HKDFContext an opaque structure holding the complete state typedef HKDFContext an opaque structure holding the complete state
for producing the hash for producing the keying material
Functions: Functions:
int hkdfReset(HKDFContext *context, enum SHAversion whichSha, int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len) const unsigned char *salt, int salt_len)
Reset the hash context state and initialize it with the Reset the key derivation state and initialize it with the
salt_len octets of the optional salt. salt_len octets of the optional salt.
int hkdfInput(HKDFContext *context, const unsigned char *ikm, int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len) int ikm_len)
Incorporate ikm_len octets into the hash. Incorporate ikm_len octets into the entropy extractor.
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)
Incorporate ikm_bit_count bits into the hash. Incorporate ikm_bit_count bits into the entropy extractor.
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)
Finish the HKDF extraction and perform the final HKDF Finish the HKDF extraction and perform the final HKDF
expansion, storing the okm_len octets into okm. Optionally expansion, storing the okm_len octets into okm. Optionally
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
store the pseudo-random key (prk) that is generated store the pseudo-random key (prk) that is generated
internally. internally.
In addition, combined interfaces are provided, similar to that shown In addition, combined interfaces are provided, similar to that shown
in [RFChkdf], that allows a fixed-length text input to be used. in [RFC5869], that allows a fixed-length text input to be used.
int hkdfExtract(SHAversion whichSha, int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len, const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len, const unsigned char *ikm, int ikm_len,
uint8_t prk[USHAMaxHashSize]) uint8_t prk[USHAMaxHashSize])
Perform HKDF extraction, combining the salt_len octets of Perform HKDF extraction, combining the salt_len octets of
the optional salt with the ikm_len octets of the input the optional salt with the ikm_len octets of the input
keying material (ikm) to form the pseudo-random key prk. keying material (ikm) to form the pseudo-random key prk.
The output prk must be large enough to hold the octets The output prk must be large enough to hold the octets
appropriate for the given hash type. appropriate for the given hash type.
skipping to change at page 21, line 40 skipping to change at page 21, line 40
int hkdf(SHAversion whichSha, int hkdf(SHAversion whichSha,
const unsigned char *salt, int salt_len, const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len, const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len) uint8_t okm[ ], int okm_len)
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 .h file 8.1 The Header Files
8.1.1 The .h file
/**************************** 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
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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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
products derived from this software without specific prior products derived from this software without specific prior
written permission. written permission.
skipping to change at page 22, line 52 skipping to change at page 22, line 55
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-2/fips180-2withchangenotice.pdf
* *
* The five hashes are defined in these sizes: * The five hashes are defined in these sizes:
* SHA-1 20 byte / 160 bit * SHA-1 20 byte / 160 bit
* SHA-224 28 byte / 224 bit * SHA-224 28 byte / 224 bit
* SHA-256 32 byte / 256 bit * SHA-256 32 byte / 256 bit
* SHA-384 48 byte / 384 bit * SHA-384 48 byte / 384 bit
* SHA-512 64 byte / 512 bit * SHA-512 64 byte / 512 bit
*
* Compilation Note:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* These files may be compiled with two options:
* USE_32BIT_ONLY - use 32-bit arithmetic only, for systems
* without 64-bit integers
*
* USE_MODIFIED_MACROS - use alternate form of the SHA_Ch()
* and SHA_Maj() macros that are equivalent
* 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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
* *
*/ */
#ifndef _SHA_enum_ #ifndef _SHA_enum_
skipping to change at page 23, line 44 skipping to change at page 24, line 5
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,
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
} SHAversion; } SHAversion;
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* This structure will hold context information for the SHA-1 * This structure will hold context information for the SHA-1
* hashing operation. * hashing operation.
*/ */
typedef struct SHA1Context { typedef struct SHA1Context {
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */ uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */ uint32_t Length_High; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
skipping to change at page 24, line 43 skipping to change at page 25, line 4
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */ /* 512-bit message blocks */
uint8_t Message_Block[SHA256_Message_Block_Size]; uint8_t Message_Block[SHA256_Message_Block_Size];
int Computed; /* Is the digest computed? */ int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Is the digest corrupted? */
} 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_Low, Length_High; /* Message length in bits */ uint64_t Length_Low, Length_High; /* Message length in bits */
#endif /* USE_32BIT_ONLY */ #endif /* USE_32BIT_ONLY */
int_least16_t Message_Block_Index; /* Message_Block array index */ int_least16_t Message_Block_Index; /* Message_Block array index */
/* 1024-bit message blocks */ /* 1024-bit message blocks */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t Message_Block[SHA512_Message_Block_Size]; uint8_t Message_Block[SHA512_Message_Block_Size];
int Computed; /* Is the digest computed?*/ int Computed; /* Is the digest computed?*/
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Is the digest corrupted? */
} SHA512Context; } SHA512Context;
/* /*
* This structure will hold context information for the SHA-224 * This structure will hold context information for the SHA-224
* hashing operation. It uses the SHA-256 structure for computation. * hashing operation. It uses the SHA-256 structure for computation.
*/ */
skipping to change at page 25, line 44 skipping to change at page 26, line 4
SHA384Context sha384Context; SHA512Context sha512Context; SHA384Context sha384Context; SHA512Context sha512Context;
} ctx; } ctx;
} USHAContext; } USHAContext;
/* /*
* 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 digest computed? */ int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Is the digest corrupted? */
} HMACContext; } HMACContext;
/* /*
* This structure will hold context information for the HKDF * This structure will hold context information for the HKDF
* Extract-and-Expand Key Derivation functions. * Extract-and-Expand Key Derivation functions.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
typedef struct HKDFContext { typedef struct HKDFContext {
int whichSha; /* which SHA is being used */ int whichSha; /* which SHA is being used */
HMACContext hmacContext; HMACContext hmacContext;
int hashSize; /* hash size of SHA being used */ int hashSize; /* hash size of SHA being used */
unsigned char prk[USHAMaxHashSize]; unsigned char prk[USHAMaxHashSize];
/* Pseudo Random Key - output of hkdfInput */ /* Pseudo Random Key - output of hkdfInput */
int Computed; /* Is the digest computed? */ int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */ int Corrupted; /* Is the digest corrupted? */
} HKDFContext; } HKDFContext;
skipping to change at page 26, line 43 skipping to change at page 27, line 4
extern int SHA224Input(SHA224Context *, const uint8_t *bytes, extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
extern int SHA224FinalBits(SHA224Context *, uint8_t bits, extern int SHA224FinalBits(SHA224Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA224Result(SHA224Context *, extern int SHA224Result(SHA224Context *,
uint8_t Message_Digest[SHA224HashSize]); uint8_t Message_Digest[SHA224HashSize]);
/* SHA-256 */ /* SHA-256 */
extern int SHA256Reset(SHA256Context *); extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t *bytes, extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
unsigned int bytecount); unsigned int bytecount);
extern int SHA256FinalBits(SHA256Context *, uint8_t bits, extern int SHA256FinalBits(SHA256Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA256Result(SHA256Context *, extern int SHA256Result(SHA256Context *,
uint8_t Message_Digest[SHA256HashSize]); uint8_t Message_Digest[SHA256HashSize]);
/* SHA-384 */ /* SHA-384 */
extern int SHA384Reset(SHA384Context *); extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t *bytes, extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
extern int SHA384FinalBits(SHA384Context *, uint8_t bits, extern int SHA384FinalBits(SHA384Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA384Result(SHA384Context *, extern int SHA384Result(SHA384Context *,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t Message_Digest[SHA384HashSize]); uint8_t Message_Digest[SHA384HashSize]);
/* SHA-512 */ /* SHA-512 */
extern int SHA512Reset(SHA512Context *); extern int SHA512Reset(SHA512Context *);
extern int SHA512Input(SHA512Context *, const uint8_t *bytes, extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
unsigned int bytecount); unsigned int bytecount);
extern int SHA512FinalBits(SHA512Context *, uint8_t bits, extern int SHA512FinalBits(SHA512Context *, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int SHA512Result(SHA512Context *, extern int SHA512Result(SHA512Context *,
uint8_t Message_Digest[SHA512HashSize]); uint8_t Message_Digest[SHA512HashSize]);
skipping to change at page 27, line 31 skipping to change at page 27, line 44
extern int USHAFinalBits(USHAContext *context, extern int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count); uint8_t bits, unsigned int bit_count);
extern int USHAResult(USHAContext *context, extern int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize]); uint8_t Message_Digest[USHAMaxHashSize]);
extern int USHABlockSize(enum SHAversion whichSha); extern int USHABlockSize(enum SHAversion whichSha);
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, RFC2104, * 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 */
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 */
/* /*
* HMAC Keyed-Hashing for Message Authentication, RFC2104, INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* HMAC Keyed-Hashing for Message Authentication, RFC 2104,
* for all SHAs. * for all SHAs.
* This interface allows any length of text input to be used. * This interface allows any length of text input to be used.
*/ */
extern int hmacReset(HMACContext *context, enum SHAversion whichSha, extern int hmacReset(HMACContext *context, enum SHAversion whichSha,
const unsigned char *key, int key_len); const unsigned char *key, int key_len);
extern int hmacInput(HMACContext *context, const unsigned char *text, extern int hmacInput(HMACContext *context, const unsigned char *text,
int text_len); int text_len);
extern int hmacFinalBits(HMACContext *context, uint8_t bits, extern int hmacFinalBits(HMACContext *context, uint8_t bits,
unsigned int bit_count); unsigned int bit_count);
extern int hmacResult(HMACContext *context, extern int hmacResult(HMACContext *context,
uint8_t digest[USHAMaxHashSize]); uint8_t digest[USHAMaxHashSize]);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* HKDF HMAC-based Extract-and-Expand Key Derivation Function, * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
* RFCXXXX, for all SHAs. * RFC 5869, for all SHAs.
*/ */
extern int hkdf(SHAversion whichSha, const unsigned char *salt, extern int hkdf(SHAversion whichSha, const unsigned char *salt,
int salt_len, const unsigned char *ikm, int ikm_len, int salt_len, const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len); uint8_t okm[ ], int okm_len);
extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt, extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt,
int salt_len, const unsigned char *ikm, int salt_len, const unsigned char *ikm,
int ikm_len, uint8_t prk[USHAMaxHashSize]); int ikm_len, uint8_t prk[USHAMaxHashSize]);
extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
int prk_len, const unsigned char *info, int prk_len, const unsigned char *info,
int info_len, uint8_t okm[ ], int okm_len); int info_len, uint8_t okm[ ], int okm_len);
/* /*
* HKDF HMAC-based Extract-and-Expand Key Derivation Function, * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
* RFCXXXX, for all SHAs. * RFC 5869, 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 hkdfReset(HKDFContext *context, enum SHAversion whichSha, extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
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_ */ #endif /* _SHA_H_ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
8.1.2 sha-private.h
/************************ sha-private.h ************************/
/***************** See RFC NNNN for details. *******************/
#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H
/*
* These definitions are defined in FIPS-180-2, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2 and 4.1.3.
*
* The definitions used in FIPS-180-2 are as follows:
*/
#ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* USE_MODIFIED_MACROS */
/*
* The following definitions are equivalent and potentially faster.
*/
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#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 and could be optimized
further. For example, the assignment rotations through the variables further. For example, the assignment rotations through the variables
a, b, ..., h could be treated as a cycle and the loop unrolled, a, b, ..., h could be treated as a cycle and the loop unrolled,
rather than doing the explicit copying. 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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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 National Institute of Standards * as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2 * Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
skipping to change at page 30, line 4 skipping to change at page 30, line 52
* optionally uses SHA1FinalBits() to hash the final few bits of * optionally uses SHA1FinalBits() to hash the final few bits of
* the input. * the input.
*/ */
#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
*/ */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#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 \
: shaSuccess ) : shaSuccess )
skipping to change at page 31, line 5 skipping to change at page 31, line 53
context->Length_High = 0; context->Length_High = 0;
context->Message_Block_Index = 0; context->Message_Block_Index = 0;
/* Initial Hash Values: FIPS-180-2 section 5.3.1 */ /* Initial Hash Values: FIPS-180-2 section 5.3.1 */
context->Intermediate_Hash[0] = 0x67452301; context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89; context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE; context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476; context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0; context->Intermediate_Hash[4] = 0xC3D2E1F0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Computed = 0; context->Computed = 0;
context->Corrupted = 0; context->Corrupted = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return shaSuccess; return shaSuccess;
} }
/* /*
* 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.
* *
skipping to change at page 32, line 4 skipping to change at page 32, line 54
(*message_array & 0xFF); (*message_array & 0xFF);
if ((SHA1AddLength(context, 8) == shaSuccess) && if ((SHA1AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA1_Message_Block_Size)) (context->Message_Block_Index == SHA1_Message_Block_Size))
SHA1ProcessMessageBlock(context); SHA1ProcessMessageBlock(context);
message_array++; message_array++;
} }
return context->Corrupted; return context->Corrupted;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* SHA1FinalBits * SHA1FinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
* 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
skipping to change at page 33, line 5 skipping to change at page 33, line 54
return shaNull; return shaNull;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
if ((length >= 8) || (length == 0)) if ((length >= 8) || (length == 0))
return context->Corrupted = shaBadParam; return context->Corrupted = shaBadParam;
if (context->Corrupted) if (context->Corrupted)
return context->Corrupted; return context->Corrupted;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
SHA1AddLength(context, length); SHA1AddLength(context, length);
SHA1Finalize(context, SHA1Finalize(context,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
(uint8_t) ((message_bits & masks[length]) | markbit[length])); (uint8_t) ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted; return context->Corrupted;
} }
/* /*
* SHA1Result * SHA1Result
* *
* Description: * Description:
* This function will return the 160-bit message digest * This function will return the 160-bit message digest
skipping to change at page 34, line 4 skipping to change at page 34, line 55
for (i = 0; i < SHA1HashSize; ++i) for (i = 0; i < SHA1HashSize; ++i)
Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2] Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2]
>> 8 * ( 3 - ( i & 0x03 ) )); >> 8 * ( 3 - ( i & 0x03 ) ));
return shaSuccess; return shaSuccess;
} }
/* /*
* SHA1Finalize * SHA1Finalize
*
* Description:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*
* 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 digest before the 0-padding * The last byte to add to the digest 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.
skipping to change at page 35, line 4 skipping to change at page 35, line 55
* *
* 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 digest before the 0-padding * The last byte to add to the digest 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:
* Nothing.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Returns:
* Nothing.
*/ */
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte) static void SHA1PadMessage(SHA1Context *context, 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 >= (SHA1_Message_Block_Size - 8)) { if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) {
skipping to change at page 36, line 4 skipping to change at page 36, line 55
* *
* Description: * Description:
* This helper function will process the next 512 bits of the * This helper function will process the next 512 bits of the
* message stored in the Message_Block array. * message stored in the Message_Block array.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* *
* Returns: * Returns:
* Nothing.
*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Nothing.
*
* Comments: * Comments:
* Many of the variable names in this code, especially the * Many of the variable names in this code, especially the
* single character names, were used because those were the * single character names, were used because those were the
* names used in the publication. * names used in the publication.
*/ */
static void SHA1ProcessMessageBlock(SHA1Context *context) static void SHA1ProcessMessageBlock(SHA1Context *context)
{ {
/* Constants defined in FIPS-180-2, section 4.2.1 */ /* Constants defined in FIPS-180-2, section 4.2.1 */
const uint32_t K[4] = { const uint32_t K[4] = {
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
skipping to change at page 37, line 4 skipping to change at page 37, line 55
D = C; D = C;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
A = temp; A = temp;
} }
for (t = 20; t < 40; t++) { for (t = 20; t < 40; t++) {
temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1]; temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
E = D; E = D;
D = C; D = C;
C = SHA1_ROTL(30,B);
B = A;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
C = SHA1_ROTL(30,B);
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;
D = C; D = C;
C = SHA1_ROTL(30,B); C = SHA1_ROTL(30,B);
B = A; B = A;
A = temp; A = temp;
skipping to change at page 38, line 4 skipping to change at page 38, line 53
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithms SHA-224 and * This file implements the Secure Hash Algorithms SHA-224 and
* SHA-256 as defined in the National Institute of Standards * SHA-256 as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-2 published on August 1, 2002, and * Publication (FIPS PUB) 180-2 published on August 1, 2002, and
* the FIPS PUB 180-2 Change Notice published on February 28, 2004. * the FIPS PUB 180-2 Change Notice published on February 28, 2004.
* *
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-2/fips180-2withchangenotice.pdf
* *
* The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
* message digests for a given data stream. It should take about * message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given * 2**n steps to find a message with the same digest as a given
* message and 2**(n/2) to find any two messages with the same * message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this * digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a * algorithm can serve as a means of providing a
* "fingerprint" for a message. * "fingerprint" for a message.
* *
skipping to change at page 39, line 4 skipping to change at page 39, line 55
#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) \
(SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word)) (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
#define SHA256_sigma1(word) \ #define SHA256_sigma1(word) \
(SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word)) (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
/* /*
* Add "length" to the length. * Add "length" to the length.
* Set Corrupted when overflow has occurred. * Set Corrupted when overflow has occurred.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
static uint32_t addTemp; static uint32_t addTemp;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define SHA224_256AddLength(context, length) \ #define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \ (addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \ (((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong : \ (++(context)->Length_High == 0) ? shaInputTooLong : \
shaSuccess ) shaSuccess )
/* Local Function Prototypes */ /* Local Function Prototypes */
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,
skipping to change at page 40, line 4 skipping to change at page 40, line 54
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
int SHA224Reset(SHA224Context *context) int SHA224Reset(SHA224Context *context)
{ {
return SHA224_256Reset(context, SHA224_H0); return SHA224_256Reset(context, SHA224_H0);
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* SHA224Input * SHA224Input
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
skipping to change at page 41, line 4 skipping to change at page 41, line 54
* 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 SHA224FinalBits(SHA224Context *context, int SHA224FinalBits(SHA224Context *context,
uint8_t message_bits, unsigned int length) uint8_t message_bits, unsigned int length)
{ {
return SHA256FinalBits(context, message_bits, length); return SHA256FinalBits(context, message_bits, length);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* SHA224Result * SHA224Result
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Description: * Description:
* This function will return the 224-bit message digest * This function will return the 224-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 27. * the last octet of hash in the element with index 27.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
skipping to change at page 42, line 4 skipping to change at page 42, line 55
{ {
return SHA224_256Reset(context, SHA256_H0); return SHA224_256Reset(context, SHA256_H0);
} }
/* /*
* SHA256Input * SHA256Input
* *
* Description: * Description:
* This function accepts an array of octets as the next portion * This function accepts an array of octets as the next portion
* of the message. * of the message.
*
* Parameters:
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*
* Parameters:
* context: [in/out] * context: [in/out]
* The SHA context to update * The SHA context to update
* message_array: [in] * message_array: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the message. * the message.
* length: [in] * length: [in]
* The length of the message in message_array * The length of the message in message_array
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
skipping to change at page 43, line 4 skipping to change at page 43, line 55
} }
/* /*
* SHA256FinalBits * SHA256FinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* Parameters: * Parameters:
* context: [in/out]
* The SHA context to update
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* context: [in/out]
* 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 44, line 4 skipping to change at page 44, line 54
if (context->Corrupted) if (context->Corrupted)
return context->Corrupted; return context->Corrupted;
SHA224_256AddLength(context, length); SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t) SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length])); ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted; return context->Corrupted;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* SHA256Result * SHA256Result
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Description: * Description:
* This function will return the 256-bit message digest * This function will return the 256-bit message digest
* into the Message_Digest array provided by the caller. * into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0, * The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 31. * the last octet of hash in the element with index 31.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
skipping to change at page 45, line 4 skipping to change at page 45, line 55
* Returns: * Returns:
* sha Error Code. * sha Error Code.
*/ */
static void SHA224_256Finalize(SHA256Context *context, static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte) uint8_t Pad_Byte)
{ {
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->Length_Low = 0; /* and clear length */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block[i] = 0;
context->Length_Low = 0; /* and clear length */
context->Length_High = 0; context->Length_High = 0;
context->Computed = 1; context->Computed = 1;
} }
/* /*
* 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'.
skipping to change at page 46, line 5 skipping to change at page 46, line 55
context->Message_Block[context->Message_Block_Index++] = Pad_Byte; context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size) while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0; context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context); SHA224_256ProcessMessageBlock(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 < (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;
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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
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);
skipping to change at page 47, line 4 skipping to change at page 47, line 55
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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
*/ */
for (t = t4 = 0; t < 16; t++, t4 += 4) for (t = t4 = 0; t < 16; t++, t4 += 4)
W[t] = (((uint32_t)context->Message_Block[t4]) << 24) | W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
skipping to change at page 48, line 5 skipping to change at page 48, line 56
context->Intermediate_Hash[0] += A; context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B; context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C; context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D; context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E; context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F; context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G; context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H; context->Intermediate_Hash[7] += H;
context->Message_Block_Index = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
context->Message_Block_Index = 0;
} }
/* /*
* 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:
skipping to change at page 49, line 4 skipping to change at page 49, line 56
return shaSuccess; return shaSuccess;
} }
/* /*
* SHA224_256ResultN * SHA224_256ResultN
* *
* Description: * Description:
* This helper function will return the 224-bit or 256-bit message * This helper function will return the 224-bit or 256-bit message
* digest into the Message_Digest array provided by the caller. * digest into the Message_Digest array provided by the caller.
* NOTE: * NOTE:
* The first octet of hash is stored in the element with index 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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 54
/***************** See RFC NNNN for details. *******************/ /***************** See RFC NNNN for details. *******************/
/* Copyright (c) 2010 IETF Trust and the persons identified as */ /* Copyright (c) 2010 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */ /* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */ /* See sha.h for terms of use and redistribution. */
/* /*
* Description: * Description:
* This file implements the Secure Hash Algorithms SHA-384 and * This file implements the Secure Hash Algorithms SHA-384 and
* SHA-512 as defined in the National Institute of Standards * SHA-512 as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards * and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-2 published on August 1, 2002, and
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* Publication (FIPS PUB) 180-2 published on August 1, 2002, and
* the FIPS PUB 180-2 Change Notice published on February 28, 2004. * the FIPS PUB 180-2 Change Notice published on February 28, 2004.
* *
* A combined document showing all algorithms is available at * A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/ * http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf * fips180-2/fips180-2withchangenotice.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 56
* 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)) : \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
(ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) : \
((bits) == 32) ? (word)[0] : \ ((bits) == 32) ? (word)[0] : \
((bits) >= 0) ? \ ((bits) >= 0) ? \
(((word)[0] << (32 - (bits))) | \ (((word)[0] << (32 - (bits))) | \
((word)[1] >> (bits))) : 0 ) ((word)[1] >> (bits))) : 0 )
#define SHA512_SHL(bits, word, ret) ( \ #define SHA512_SHL(bits, word, ret) ( \
/* (((uint64_t)(word)) << (bits)) */ \ /* (((uint64_t)(word)) << (bits)) */ \
(ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \ (ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \
((bits) == 32) ? (word)[1] : \ ((bits) == 32) ? (word)[1] : \
((bits) >= 0) ? \ ((bits) >= 0) ? \
skipping to change at page 76, line 38 skipping to change at page 77, line 38
switch (whichSha) { switch (whichSha) {
case SHA1: return "SHA1"; case SHA1: return "SHA1";
case SHA224: return "SHA224"; case SHA224: return "SHA224";
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.2.5 sha-private.h
/************************ sha-private.h ************************/
/***************** See RFC NNNN for details. *******************/
#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H
/*
* These definitions are defined in FIPS-180-2, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2 and 4.1.3.
*
* The definitions used in FIPS-180-2 are as follows:
*/
#ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#else /* USE_MODIFIED_MACROS */
/*
* The following definitions are equivalent and potentially faster.
*/
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#endif /* _SHA_PRIVATE__H */
8.3 The HMAC Code 8.3 The HMAC Code
/**************************** hmac.c ***************************/ /**************************** hmac.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 HMAC algorithm (Keyed-Hashing for * This file implements the HMAC algorithm (Keyed-Hashing for
* Message Authentication, [RFC2104]), expressed in terms of the * Message Authentication, [RFC 2104]), expressed in terms of
* various SHA algorithms. * the various SHA algorithms.
*/ */
#include "sha.h" #include "sha.h"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* hmac * hmac
* *
* Description: * Description:
* This function will compute an HMAC message digest. * This function will compute an HMAC message digest.
* *
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* key: [in] * 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.
* message_array: [in] * message_array: [in]
* An array of octets representing the message. * An array of octets representing the message.
* Note: in RFC 2109, this parameter is known * Note: in RFC 2109, this parameter is known
* as 'text'. * as 'text'.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* length: [in] * length: [in]
* The length of the message in message_array. * The length of the message in message_array.
* digest: [out] * digest: [out]
* Where the digest is returned. * Where the digest is returned.
* NOTE: The length of the digest is determined by * NOTE: The length of the digest is determined by
* the value of whichSha. * the value of whichSha.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
skipping to change at page 78, line 40 skipping to change at page 79, line 4
* hmacReset * hmacReset
* *
* Description: * Description:
* This function will initialize the hmacContext in preparation * This function will initialize the hmacContext in preparation
* for computing a new HMAC message digest. * for computing a new HMAC message digest.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to reset. * The context to reset.
* whichSha: [in] * whichSha: [in]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* key: [in] * key: [in]
* The secret shared key. * The secret shared key.
* key_len: [in] * key_len: [in]
* The length of the secret shared key. * The length of the secret shared key.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacReset(HMACContext *context, enum SHAversion whichSha, int hmacReset(HMACContext *context, enum SHAversion whichSha,
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];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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;
blocksize = context->blockSize = USHABlockSize(whichSha); blocksize = context->blockSize = USHABlockSize(whichSha);
hashsize = context->hashSize = USHAHashSize(whichSha); hashsize = context->hashSize = USHAHashSize(whichSha);
skipping to change at page 79, line 39 skipping to change at page 80, line 4
key = tempkey; key = tempkey;
key_len = hashsize; key_len = hashsize;
} }
/* /*
* The HMAC transform looks like: * The HMAC transform looks like:
* *
* SHA(K XOR opad, SHA(K XOR ipad, text)) * SHA(K XOR opad, SHA(K XOR ipad, text))
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* where K is an n byte key, 0-padded to a total of blocksize bytes, * where K is an n byte key, 0-padded to a total of blocksize bytes,
* ipad is the byte 0x36 repeated blocksize times, * ipad is the byte 0x36 repeated blocksize times,
* opad is the byte 0x5c repeated blocksize times, * opad is the byte 0x5c repeated blocksize times,
* and text is the data being protected. * and text is the data being protected.
*/ */
/* store key into the pads, XOR'd with ipad and opad values */ /* store key into the pads, XOR'd with ipad and opad values */
for (i = 0; i < key_len; i++) { for (i = 0; i < key_len; i++) {
k_ipad[i] = key[i] ^ 0x36; k_ipad[i] = key[i] ^ 0x36;
context->k_opad[i] = key[i] ^ 0x5c; context->k_opad[i] = key[i] ^ 0x5c;
} }
/* 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 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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;
} }
/* /*
* hmacInput * hmacInput
* *
skipping to change at page 80, line 39 skipping to change at page 81, line 4
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacInput(HMACContext *context, const unsigned char *text, int hmacInput(HMACContext *context, const unsigned char *text,
int text_len) int text_len)
{ {
if (!context) return shaNull; if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
/* then text of datagram */ /* then text of datagram */
return context->Corrupted = return context->Corrupted =
USHAInput(&context->shaContext, text, text_len); USHAInput(&context->shaContext, text, text_len);
} }
/* /*
* hmacFinalBits * hmacFinalBits
* *
* Description: * Description:
* This function will add in any final bits of the message. * This function will add in any final bits of the message.
* *
* 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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 hmacFinalBits(HMACContext *context, int hmacFinalBits(HMACContext *context,
uint8_t bits, unsigned int bit_count) uint8_t bits, unsigned int bit_count)
{ {
skipping to change at page 81, line 39 skipping to change at page 82, line 4
* This function will return the N-byte message digest into the * This function will return the N-byte message digest into the
* Message_Digest array provided by the caller. * Message_Digest array provided by the caller.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The context to use to calculate the HMAC hash. * The context to use to calculate the HMAC hash.
* digest: [out] * digest: [out]
* Where the digest is returned. * Where the digest is returned.
* NOTE 2: The length of the hash is determined by the value of * NOTE 2: The length of the hash is determined by the value of
* whichSha that was passed to hmacReset(). * whichSha that was passed to hmacReset().
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hmacResult(HMACContext *context, uint8_t *digest) int hmacResult(HMACContext *context, uint8_t *digest)
{ {
int ret; int ret;
if (!context) return shaNull; if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted; if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError; if (context->Computed) return context->Corrupted = shaStateError;
/* 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 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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) ||
/* then results of 1st hash */ /* then results of 1st hash */
USHAInput(&context->shaContext, digest, context->hashSize) || USHAInput(&context->shaContext, digest, context->hashSize) ||
skipping to change at page 82, line 35 skipping to change at page 82, line 53
/**************************** hkdf.c ***************************/ /**************************** hkdf.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 HKDF algorithm (HMAC-based * This file implements the HKDF algorithm (HMAC-based
* Extract-and-Expand Key Derivation Function, RFCXXXX), * Extract-and-Expand Key Derivation Function, RFC 5869),
* expressed in terms of the various SHA algorithms. * expressed in terms of the various SHA algorithms.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*/ */
#include "sha.h" #include "sha.h"
#include <memory.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/* /*
* hkdf * hkdf
* *
* Description: * Description:
* This function will compute an HKDF message digest. * This function will compute an HKDF message digest.
* *
* 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* to a string of HashLen(whichSha) zeros. * to a string of HashLen(whichSha) zeros.
* salt_len: [in] * salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.) * The length of the salt value. (Ignored if salt == NULL.)
* ikm: [in] * ikm: [in]
* Input keying material. * Input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of the input keying material. * The length of the input keying material.
* info: [in] * info: [in]
* The optional context and application specific information. * The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored. * If info == NULL or a zero-length string, it is ignored.
skipping to change at page 83, line 39 skipping to change at page 84, line 4
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdf(SHAversion whichSha, int hkdf(SHAversion whichSha,
const unsigned char *salt, int salt_len, const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len, const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len) uint8_t okm[ ], int okm_len)
{ {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t prk[USHAMaxHashSize]; uint8_t prk[USHAMaxHashSize];
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) || return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
info_len, okm, okm_len); info_len, okm, okm_len);
} }
/* /*
* hkdfExtract * hkdfExtract
* *
* Description: * Description:
* This function will perform HKDF extraction. * This function will perform HKDF extraction.
* *
* 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
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* to a string of HashLen(whichSha) zeros. * to a string of HashLen(whichSha) zeros.
* salt_len: [in] * salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.) * The length of the salt value. (Ignored if salt == NULL.)
* ikm: [in] * ikm: [in]
* Input keying material. * Input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of the input keying material. * The length of the input keying material.
* prk: [out] * prk: [out]
* Where the HKDF extraction is to be stored. * Where the HKDF extraction is to be stored.
* Must be larger than USHAHashSize(whichSha); * Must be larger than USHAHashSize(whichSha);
skipping to change at page 84, line 39 skipping to change at page 85, line 4
salt = nullSalt; salt = nullSalt;
salt_len = USHAHashSize(whichSha); salt_len = USHAHashSize(whichSha);
memset(nullSalt, '\0', salt_len); memset(nullSalt, '\0', salt_len);
} else if (salt_len < 0) { } else if (salt_len < 0) {
return shaBadParam; return shaBadParam;
} }
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk); return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* hkdfExpand * hkdfExpand
* *
* Description: * Description:
* This function will perform HKDF expansion. * This function will perform HKDF expansion.
* *
* Parameters: * Parameters:
* whichSha: [in] * whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512 * One of SHA1, SHA224, SHA256, SHA384, SHA512
* info: [in] * 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.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* 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)
{ {
int hash_len, N; int hash_len, N;
unsigned char T[USHAMaxHashSize]; unsigned char T[USHAMaxHashSize];
int Tlen, where, i; int Tlen, where, i;
if (info == 0) { if (info == 0) {
info = ""; info = (const unsigned char *)"";
info_len = 0; info_len = 0;
} else if (info_len < 0) { } else if (info_len < 0) {
return shaBadParam; return shaBadParam;
} else if (prk_len < 0) { } else if (prk_len < 0) {
return shaBadParam; return shaBadParam;
} else if (!okm) { } else if (!okm) {
return shaBadParam; return shaBadParam;
} }
hash_len = USHAHashSize(whichSha); hash_len = USHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam; if (prk_len < hash_len) return shaBadParam;
N = okm_len / hash_len; N = okm_len / hash_len;
if ((okm_len % hash_len) != 0) N++; if ((okm_len % hash_len) != 0) N++;
if (N > 255) return shaBadParam; if (N > 255) return shaBadParam;
Tlen = 0; Tlen = 0;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
where = 0; where = 0;
for (i = 1; i <= N; i++) { for (i = 1; i <= N; i++) {
HMACContext context; HMACContext context;
unsigned char c = i; unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, hash_len) || int ret = hmacReset(&context, whichSha, prk, hash_len) ||
hmacInput(&context, T, Tlen) || hmacInput(&context, T, Tlen) ||
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 computing a new HKDF message digest. It is used for * for computing a new HKDF message digest. It is used for
* arbitrary length inputs. * arbitrary length inputs.
* *
* Parameters: * Parameters:
skipping to change at page 86, line 38 skipping to change at page 87, line 4
* *
*/ */
int hkdfReset(HKDFContext *context, enum SHAversion whichSha, int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len) const unsigned char *salt, int salt_len)
{ {
unsigned char nullSalt[USHAMaxHashSize]; unsigned char nullSalt[USHAMaxHashSize];
if (!context) return shaNull; if (!context) return shaNull;
context->whichSha = whichSha; context->whichSha = whichSha;
context->hashSize = USHAHashSize(whichSha); context->hashSize = USHAHashSize(whichSha);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (salt == 0) { if (salt == 0) {
salt = nullSalt; salt = nullSalt;
salt_len = context->hashSize; salt_len = context->hashSize;
memset(nullSalt, '\0', salt_len); memset(nullSalt, '\0', salt_len);
} }
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]
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* The HKDF context to update. * The HKDF context to update.
* ikm: [in] * ikm: [in]
* An array of octets representing the next portion of * An array of octets representing the next portion of
* the input keying material. * the input keying material.
* ikm_len: [in] * ikm_len: [in]
* The length of ikm. * The length of ikm.
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
skipping to change at page 87, line 39 skipping to change at page 88, line 4
* *
* Description: * Description:
* This function will add in any final bits of the * This function will add in any final bits of the
* input keying material. * input keying material.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HKDF context to update * The HKDF context to update
* ikm_bits: [in] * ikm_bits: [in]
* The final bits of the input keying material, in the upper * The final bits of the input keying material, in the upper
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* portion of the byte. (Use 0b###00000 instead of 0b00000### * portion of the byte. (Use 0b###00000 instead of 0b00000###
* to input the three bits ###.) * to input the three bits ###.)
* ikm_bit_count: [in] * ikm_bit_count: [in]
* The number of bits in message_bits, between 1 and 7. * The number of bits in message_bits, between 1 and 7.
* *
* Returns: * Returns:
* 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);
} }
/* /*
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* hkdfResult * hkdfResult
* *
* Description: * Description:
* This function will finish the HKDF extraction and perform the * This function will finish the HKDF extraction and perform the
* final HKDF expansion. * final HKDF expansion.
* *
* Parameters: * Parameters:
* context: [in/out] * context: [in/out]
* The HKDF context to use to calculate the HKDF hash. * The HKDF context to use to calculate the HKDF hash.
* prk: [out] * prk: [out]
skipping to change at page 88, line 38 skipping to change at page 89, line 4
* The length of the buffer to hold okm. * The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha) * okm_len must be <= 255 * USHABlockSize(whichSha)
* *
* Returns: * Returns:
* sha Error Code. * sha Error Code.
* *
*/ */
int hkdfResult(HKDFContext *context, int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize], uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len, const unsigned char *info, int info_len,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
uint8_t okm[ ], int okm_len) uint8_t okm[ ], int okm_len)
{ {
uint8_t prkbuf[USHAMaxHashSize]; uint8_t prkbuf[USHAMaxHashSize];
int ret; int ret;
if (!context) return shaNull; if (!context) return shaNull;
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.
See also [SHAVS]. See also [SHAVS].
skipping to change at page 89, line 34 skipping to change at page 89, line 53
* the three tests documented in FIPS PUB 180-2 * the three tests documented in FIPS PUB 180-2
* (http://csrc.nist.gov/publications/fips/ * (http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf) * fips180-2/fips180-2withchangenotice.pdf)
* one that calls SHAInput with an exact multiple of 512 bits * one that calls SHAInput with an exact multiple of 512 bits
* the seven tests documented for each algorithm in * the seven tests documented for each algorithm in
* "The Secure Hash Algorithm Validation System (SHAVS)" * "The Secure Hash Algorithm Validation System (SHAVS)"
* (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf), * (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf),
* three of which are bit-level tests * three of which are bit-level tests
* *
* This file will exercise the HMAC SHA1 code performing * This file will exercise the HMAC SHA1 code performing
* the seven tests documented in RFCs [RFC2202] and [RFC4231]. * the seven tests documented in RFCs [RFC 2202] and [RFC 4231].
* *
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
* This file will exercise the HKDF code performing * This file will exercise the HKDF code performing
* the six tests documented in RFC XXXX. * the seven tests documented in RFC 4869.
* *
* 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.
* *
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#include <ctype.h> #include <ctype.h>
#include <unistd.h> /* defines getopt() and optarg */
#include "sha.h" #include "sha.h"
static int xgetopt(int argc, char **argv, const char *optstring);
extern char *xoptarg;
static int scasecmp(const char *s1, const char *s2); static int scasecmp(const char *s1, const char *s2);
/* /*
* Define patterns for testing * Define patterns for testing
*/ */
#define TEST1 "abc" #define TEST1 "abc"
#define TEST2_1 \ #define TEST2_1 \
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
#define TEST2_2a \ #define TEST2_2a \
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
skipping to change at page 90, line 37 skipping to change at page 91, line 4
/* an exact multiple of 512 bits */ /* an exact multiple of 512 bits */
#define TEST4 TEST4a TEST4b /* times 10 */ #define TEST4 TEST4a TEST4b /* times 10 */
#define TEST7_1 \ #define TEST7_1 \
"\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8" "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8"
#define TEST8_1 \ #define TEST8_1 \
"\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46" "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46"
#define TEST9_1 \ #define TEST9_1 \
"\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \ "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \
"\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \ "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \ "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \
"\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \ "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \
"\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a" "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a"
#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 \
"\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"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#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 \
"\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52\x06\x22\xd1\xac\x97\xd5" \ "\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52\x06\x22\xd1\xac\x97\xd5" \
"\xcd\xbe\x8c\xb3\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba\x09\xab" \ "\xcd\xbe\x8c\xb3\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba\x09\xab" \
"\xc8\x53\x3c\x52\x50\x88\x7a\x43\xbe\xbb\xac\x90\x6c\x2e\x18\x37" \ "\xc8\x53\x3c\x52\x50\x88\x7a\x43\xbe\xbb\xac\x90\x6c\x2e\x18\x37" \
skipping to change at page 91, line 38 skipping to change at page 92, line 4
"\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52" "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52"
#define TEST9_256 \ #define TEST9_256 \
"\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \ "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \
"\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \ "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \
"\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \ "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \
"\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \ "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \
"\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3" "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3"
#define TEST10_256 \ #define TEST10_256 \
"\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \ "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \
"\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \ "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \ "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \
"\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \ "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \
"\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \ "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \
"\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" \
"\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" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\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" \
"\x3e\x7d\xc8\x7f\x82\x32\x64\xbb\xe4\x0d\x18\x11\xc9\xea\x20\x61" \ "\x3e\x7d\xc8\x7f\x82\x32\x64\xbb\xe4\x0d\x18\x11\xc9\xea\x20\x61" \
"\xe1\xc8\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02\xfc\x3f\x50\x42" \ "\xe1\xc8\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02\xfc\x3f\x50\x42" \
"\xe6\xbf\x58\xcb\xa8\xa2\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" \ "\xe6\xbf\x58\xcb\xa8\xa2\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" \
skipping to change at page 92, line 38 skipping to change at page 93, line 4
"\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70" "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70"
#define TEST8_512 \ #define TEST8_512 \
"\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0" "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0"
#define TEST9_512 \ #define TEST9_512 \
"\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \ "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \
"\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \ "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \
"\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \ "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \
"\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \ "\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \
"\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \ "\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \
"\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \ "\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \ "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \
"\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \ "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \
"\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06" "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06"
#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" \
"\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"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#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" \
"\x27\x9c\x1c\xb0\xa7" "\x27\x9c\x1c\xb0\xa7"
#define SHA384_SEED "\x82\x40\xbc\x51\xe4\xec\x7e\xf7\x6d\x18\xe3" \ #define SHA384_SEED "\x82\x40\xbc\x51\xe4\xec\x7e\xf7\x6d\x18\xe3" \
"\x52\x04\xa1\x9f\x51\xa5\x21\x3a\x73\xa8\x1d\x6f\x94\x46\x80\xd3" \ "\x52\x04\xa1\x9f\x51\xa5\x21\x3a\x73\xa8\x1d\x6f\x94\x46\x80\xd3" \
skipping to change at page 93, line 38 skipping to change at page 94, line 4
#define HMACTESTCOUNT 7 #define HMACTESTCOUNT 7
#define HKDFTESTCOUNT 7 #define HKDFTESTCOUNT 7
#define PRINTNONE 0 #define PRINTNONE 0
#define PRINTTEXT 1 #define PRINTTEXT 1
#define PRINTRAW 2 #define PRINTRAW 2
#define PRINTHEX 3 #define PRINTHEX 3
#define PRINTBASE64 4 #define PRINTBASE64 4
#define PRINTPASSFAIL 1 #define PRINTPASSFAIL 1
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
#define PRINTFAIL 2 #define PRINTFAIL 2
#define length(x) (sizeof(x)-1) #define length(x) (sizeof(x)-1)
/* 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;
} tests[TESTCOUNT]; } tests[TESTCOUNT];
const char *randomtest; const char *randomtest;
const char *randomresults[RANDOMCOUNT]; const char *randomresults[RANDOMCOUNT];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} 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" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" }, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0, /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
skipping to change at page 94, line 38 skipping to change at page 95, line 4
/* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0, /* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0,
"CB0082C8F197D260991BA6A460E76E202BAD27B3" } "CB0082C8F197D260991BA6A460E76E202BAD27B3" }
}, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4", }, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4",
"A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC", "A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC",
"DB1F9050BB863DFEF4CE37186044E2EEB17EE013", "DB1F9050BB863DFEF4CE37186044E2EEB17EE013",
"127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B" "127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B"
} }, } },
{ "SHA224", SHA224, SHA224HashSize, { "SHA224", SHA224, SHA224HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" }, "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" },
/* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0,
"75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" }, "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
"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,
"54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" }, "54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" },
/* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0, /* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0,
"0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" } "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}, 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,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141" /* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141"
"40DE5DAE2223B00361A396177A9CB410FF61F20015AD" }, "40DE5DAE2223B00361A396177A9CB410FF61F20015AD" },
skipping to change at page 95, line 38 skipping to change at page 96, line 4
"9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" }, "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" },
/* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA" /* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA"
"9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" }, "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" },
/* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646" /* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646"
"8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" }, "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" },
/* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D" /* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D"
"F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" }, "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" },
}, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44" }, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44"
"EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399" "EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399"
"5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7" "5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408" "25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408"
"E31536B70FF906EC51B00447CA97D7DD97C12411F4" "E31536B70FF906EC51B00447CA97D7DD97C12411F4"
} }, } },
{ "SHA384", SHA384, SHA384HashSize, { "SHA384", SHA384, SHA384HashSize,
{ {
/* 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"
"BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" }, "BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" },
/* 5 */ { "", 0, 0, 0x10, 5, /* 5 */ { "", 0, 0, 0x10, 5,
"8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399" "8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"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" },
/* 8 */ { TEST8_384, length(TEST8_384), 1, 0, 0, /* 8 */ { TEST8_384, length(TEST8_384), 1, 0, 0,
"C9A68443A005812256B8EC76B00516F0DBB74FAB26D66591" "C9A68443A005812256B8EC76B00516F0DBB74FAB26D66591"
"3F194B6FFB0E91EA9967566B58109CBC675CC208E4C823F7" }, "3F194B6FFB0E91EA9967566B58109CBC675CC208E4C823F7" },
skipping to change at page 96, line 38 skipping to change at page 97, line 4
"638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2" "638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2"
"5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7" "5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7"
} }, } },
{ "SHA512", SHA512, SHA512HashSize, { "SHA512", SHA512, SHA512HashSize,
{ {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2"
"0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD"
"454D4423643CE80E2A9AC94FA54CA49F" }, "454D4423643CE80E2A9AC94FA54CA49F" },
/* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0, /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1"
"7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A"
"C7D329EEB6DD26545E96E55B874BE909" }, "C7D329EEB6DD26545E96E55B874BE909" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
"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,
"9992202938E882E73E20F6B69E68A0A7149090423D93C81B" "9992202938E882E73E20F6B69E68A0A7149090423D93C81B"
"AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A" "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A"
"D6E74CECE9631BFA8A549B4AB3FBBA15" }, "D6E74CECE9631BFA8A549B4AB3FBBA15" },
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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"
"8213EB1B16F517AD0DE4B2F0C95C90F8" }, "8213EB1B16F517AD0DE4B2F0C95C90F8" },
/* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3, /* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3,
"32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6" "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6"
skipping to change at page 97, line 38 skipping to change at page 98, line 4
"92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B" "92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B"
"6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D" "6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D"
"19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877" "19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877"
"6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F" "6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F"
} }
} }
}; };
/* Test arrays for HMAC. */ /* Test arrays for HMAC. */
struct hmachash { struct hmachash {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
const char *keyarray[5]; const char *keyarray[5];
int keylength[5]; int keylength[5];
const char *dataarray[5]; const char *dataarray[5];
int datalength[5]; int datalength[5];
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 */
"896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22", "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32" "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"CFF7", "CFF7",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB" "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB"
"C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6", "C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1" "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1"
"7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20" "7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20"
"3A126854" "3A126854"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
skipping to change at page 98, line 38 skipping to change at page 99, line 4
"A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44", "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC" "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC"
"3843", "3843",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322" "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322"
"445E8E2240CA5E69E2C78B3239ECFAB21649", "445E8E2240CA5E69E2C78B3239ECFAB21649",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25" "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25"
"05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A" "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"38BCE737" "38BCE737"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
}, },
{ /* 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",
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA", "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5" "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5"
"65FE", "65FE",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966" "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966"
"144B2A5AB39DC13814B94E3AB6E101A34F27", "144B2A5AB39DC13814B94E3AB6E101A34F27",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227" "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227"
"9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859" "9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859"
"E13292FB" "E13292FB"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
skipping to change at page 99, line 38 skipping to change at page 100, line 4
/* HMAC-SHA-1 */ /* HMAC-SHA-1 */
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA", "4C9007F4026250C6BC8414F9BF50C86C2D7235DA",
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A", "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729" "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729"
"665B", "665B",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57" "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57"
"3B4E6801DD23C4A7D679CCF8A386C674CFFB", "3B4E6801DD23C4A7D679CCF8A386C674CFFB",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E" "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E"
"E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB" "E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB"
"10A298DD" "10A298DD"
}, { 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 */
"0E2AEA68A90C8D37C988BCDB9FCA6FA8", "0E2AEA68A90C8D37C988BCDB9FCA6FA8",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"A3B6167473100EE06E0C796C2955552B", "A3B6167473100EE06E0C796C2955552B",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* 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 */ {
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
skipping to change at page 100, line 38 skipping to change at page 101, line 4
/* HMAC-SHA-224 */ /* HMAC-SHA-224 */
"95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E", "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E",
/* HMAC-SHA-256 */ /* HMAC-SHA-256 */
"60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3" "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3"
"7F54", "7F54",
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A" "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A"
"C4C60C2EF6AB4030FE8296248DF163F44952", "C4C60C2EF6AB4030FE8296248DF163F44952",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8" "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98" "F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98"
"5D786598" "5D786598"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
}, },
{ /* 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 }, {
"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"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\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"
"\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68" "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68"
"\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" "\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
"\x6d\x2e" "\x6d\x2e"
skipping to change at page 101, line 38 skipping to change at page 102, line 4
/* HMAC-SHA-384 */ /* HMAC-SHA-384 */
"6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E" "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E"
"99C5A678CC31E799176D3860E6110C46523E", "99C5A678CC31E799176D3860E6110C46523E",
/* HMAC-SHA-512 */ /* HMAC-SHA-512 */
"E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD" "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD"
"C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440" "C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440"
"FA8C6A58" "FA8C6A58"
}, { SHA1HashSize, SHA224HashSize, SHA256HashSize, }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
SHA384HashSize, SHA512HashSize } SHA384HashSize, SHA512HashSize }
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
}; };
/* Test arrays for HKDF. */ /* Test arrays for HKDF. */
struct hkdfhash { struct hkdfhash {
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] = {
{ /* 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"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"\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"
}, },
{ /* A.2. Test Case 2 */ { /* RFC 5869 A.2. Test Case 2 */
SHA256, SHA256,
80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" 80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d"
"\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b"
"\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29"
"\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37"
"\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45"
"\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d" 80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d"
"\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b" "\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b"
"\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89"
skipping to change at page 102, line 38 skipping to change at page 103, line 4
"\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
80, "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd" 80, "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd"
"\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb" "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb"
"\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9"
"\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
"\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5" "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5"
"\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
32, "06A6B88C5853361A06104C9CEB35B45C" 32, "06A6B88C5853361A06104C9CEB35B45C"
"EF760014904671014A193F40C15FC244", "EF760014904671014A193F40C15FC244",
82, "B11E398DC80327A1C8E7F78C596A4934" 82, "B11E398DC80327A1C8E7F78C596A4934"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"4F012EDA2D4EFAD8A050CC4C19AFA97C" "4F012EDA2D4EFAD8A050CC4C19AFA97C"
"59045A99CAC7827271CB41C65E590E09" "59045A99CAC7827271CB41C65E590E09"
"DA3275600C2F09B8367793A9ACA3DB71" "DA3275600C2F09B8367793A9ACA3DB71"
"CC30C58179EC3E87C14C01D5C1F3434F" "CC30C58179EC3E87C14C01D5C1F3434F"
"1D87" "1D87"
}, },
{ /* 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"
"9D201395FAA4B61A96C8" "9D201395FAA4B61A96C8"
}, },
{ /* A.4. Test Case 4 */ { /* RFC 5869 A.4. Test Case 4 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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"
"C22E422478D305F3F896" "C22E422478D305F3F896"
}, },
{ /* A.5. Test Case 5 */ { /* RFC 5869 A.5. Test Case 5 */
SHA1, SHA1,
80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" 80, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d"
"\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b"
"\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29"
"\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37"
"\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45"
"\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D" 80, "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D"
"\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B" "\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B"
"\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" "\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89"
skipping to change at page 103, line 38 skipping to change at page 104, line 4
"\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5" "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5"
"\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", "\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF",
80, "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD" 80, "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD"
"\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB" "\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB"
"\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9" "\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9"
"\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7" "\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7"
"\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5" "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5"
"\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", "\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF",
20, "8ADAE09A2A307059478D309B26C4115A224CFAF6", 20, "8ADAE09A2A307059478D309B26C4115A224CFAF6",
82, "0BD770A74D1160F7C9F12CD5912A06EB" 82, "0BD770A74D1160F7C9F12CD5912A06EB"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"FF6ADCAE899D92191FE4305673BA2FFE" "FF6ADCAE899D92191FE4305673BA2FFE"
"8FA3F1A4E5AD79F3F334B3B202B2173C" "8FA3F1A4E5AD79F3F334B3B202B2173C"
"486EA37CE3D397ED034C7F9DFEB15C5E" "486EA37CE3D397ED034C7F9DFEB15C5E"
"927336D0441F4C4300E2CFF0D0900B52" "927336D0441F4C4300E2CFF0D0900B52"
"D3B4" "D3B4"
}, },
{ /* 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"
}, },
{ /* A.7. Test Case 7. */ { /* RFC 5869 A.7. Test Case 7. */
SHA1, SHA1,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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"
"673A081D70CCE7ACFC48" "673A081D70CCE7ACFC48"
} }
}; };
skipping to change at page 104, line 38 skipping to change at page 105, line 4
return 0; return 0;
if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0; if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0;
} }
return 1; return 1;
} }
/* /*
* Print the string, converting non-printable characters to "." * Print the string, converting non-printable characters to "."
*/ */
void printstr(const char *str, int len) void printstr(const char *str, int len)
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
{ {
for ( ; len-- > 0; str++) for ( ; len-- > 0; str++)
putchar(isprint((unsigned char)*str) ? *str : '.'); putchar(isprint((unsigned char)*str) ? *str : '.');
} }
/* /*
* 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"
"Hash a string:\n" "Hash a string:\n"
"\t%s [-S expectedresult] -s hashstr [-k key] " "\t%s [-S expectedresult] -s hashstr [-k key] "
"[-i info -L okm-len]\n" "[-i info -L okm-len]\n"
skipping to change at page 105, line 37 skipping to change at page 106, line 4
"\t%s [-m | -d] [-l loopcount] [-t test#] [-e]\n" "\t%s [-m | -d] [-l loopcount] [-t test#] [-e]\n"
"\t\t[-r randomseed] [-R randomloop-count] " "\t\t[-r randomseed] [-R randomloop-count] "
"[-p] [-P|-X]\n" "[-p] [-P|-X]\n"
"-h\thash to test: " "-h\thash to test: "
"0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n" "0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n"
"-m\tperform hmac standard tests\n" "-m\tperform hmac standard tests\n"
"-k\tkey for hmac test\n" "-k\tkey for hmac test\n"
"-d\tperform hkdf standard tests\n" "-d\tperform hkdf standard tests\n"
"-t\ttest case to run, 1-10\n" "-t\ttest case to run, 1-10\n"
"-l\thow many times to run the test\n" "-l\thow many times to run the test\n"
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
"-e\ttest error returns\n" "-e\ttest error returns\n"
"-p\tdo not print results\n" "-p\tdo not print results\n"
"-P\tdo not print PASSED/FAILED\n" "-P\tdo not print PASSED/FAILED\n"
"-X\tprint FAILED, but not PASSED\n" "-X\tprint FAILED, but not PASSED\n"
"-r\tseed for random test\n" "-r\tseed for random test\n"
"-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;
if (printResults == PRINTTEXT) { if (printResults == PRINTTEXT) {
printf("\nhashsize=%d\n", hashsize); printf("\nhashsize=%d\n", hashsize);
putchar('\t'); putchar('\t');
skipping to change at page 106, line 37 skipping to change at page 107, line 4
putchar(hexdigits[Message_Digest[i] & 0xF]); putchar(hexdigits[Message_Digest[i] & 0xF]);
} }
putchar('\n'); putchar('\n');
} else if (printResults == PRINTBASE64) { } else if (printResults == PRINTBASE64) {
unsigned char b; unsigned char b;
char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789+/"; "0123456789+/";
for (i = 0; i < hashsize; i += 3) { for (i = 0; i < hashsize; i += 3) {
putchar(sm[Message_Digest[i] >> 2]); putchar(sm[Message_Digest[i] >> 2]);
b = (Message_Digest[i] & 0x03) << 4; b = (Message_Digest[i] & 0x03) << 4;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (i+1 < hashsize) b |= Message_Digest[i+1] >> 4; if (i+1 < hashsize) b |= Message_Digest[i+1] >> 4;
putchar(sm[b]); putchar(sm[b]);
if (i+1 < hashsize) { if (i+1 < hashsize) {
b = (Message_Digest[i+1] & 0x0f) << 2; b = (Message_Digest[i+1] & 0x0f) << 2;
if (i+2 < hashsize) b |= Message_Digest[i+2] >> 6; if (i+2 < hashsize) b |= Message_Digest[i+2] >> 6;
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) {
putchar(resultarray[k]); putchar(resultarray[k]);
putchar(resultarray[k+1]); putchar(resultarray[k+1]);
putchar(' '); putchar(' ');
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
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)
printf("%s %s %s: %s\n", hashname, testtype, testname, printf("%s %s %s: %s\n", hashname, testtype, testname,
ret ? "PASSED" : "FAILED"); ret ? "PASSED" : "FAILED");
} }
skipping to change at page 107, line 39 skipping to change at page 108, line 5
int printPassFail) int printPassFail)
{ {
USHAContext sha; USHAContext sha;
HMACContext hmac; HMACContext hmac;
HKDFContext hkdf; HKDFContext hkdf;
int err, i; int err, i;
uint8_t Message_Digest_Buf[USHAMaxHashSize]; uint8_t Message_Digest_Buf[USHAMaxHashSize];
uint8_t *Message_Digest = Message_Digest_Buf; uint8_t *Message_Digest = Message_Digest_Buf;
char buf[20]; char buf[20];
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (printResults == PRINTTEXT) { if (printResults == PRINTTEXT) {
printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1, printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1,
loopno, repeatcount); loopno, repeatcount);
printstr(testarray, length); printstr(testarray, length);
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));
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,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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;
} }
for (i = 0; i < repeatcount; ++i) { for (i = 0; i < repeatcount; ++i) {
err = info ? hkdfInput(&hkdf, testarray, length) : err = info ? hkdfInput(&hkdf, (const uint8_t *)testarray, length) :
keyarray ? hmacInput(&hmac, (const uint8_t *) testarray, keyarray ? hmacInput(&hmac, (const uint8_t *) testarray,
length) : length) :
USHAInput(&sha, (const uint8_t *) testarray, USHAInput(&sha, (const uint8_t *) testarray,
length); length);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hash(): %sInput Error %d.\n", fprintf(stderr, "hash(): %sInput 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 39 skipping to change at page 109, line 4
err = info ? hkdfFinalBits(&hkdf, extrabits, numberExtrabits) : err = info ? hkdfFinalBits(&hkdf, extrabits, numberExtrabits) :
keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits, keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits,
numberExtrabits) : numberExtrabits) :
USHAFinalBits(&sha, (uint8_t) extrabits, USHAFinalBits(&sha, (uint8_t) extrabits,
numberExtrabits); numberExtrabits);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hash(): %sFinalBits Error %d.\n", fprintf(stderr, "hash(): %sFinalBits Error %d.\n",
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
err = info ? hkdfResult(&hkdf, 0, info, infolen, err = info ? hkdfResult(&hkdf, 0, info, infolen,
Message_Digest, okmlen) : Message_Digest, okmlen) :
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,
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);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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
* result is known, it is in resultarray in uppercase hex. * result is known, it is in resultarray in uppercase hex.
*/ */
int hashHkdf(int testno, int loopno, int hashno, int hashHkdf(int testno, int loopno, int hashno,
int printResults, int printPassFail) int printResults, int printPassFail)
skipping to change at page 109, line 38 skipping to change at page 110, line 4
printxstr(hkdfhashes[testno].ikmarray, printxstr(hkdfhashes[testno].ikmarray,
hkdfhashes[testno].ikmlength); hkdfhashes[testno].ikmlength);
printf("'\n\tINFO\t'"); printf("'\n\tINFO\t'");
printxstr(hkdfhashes[testno].infoarray, printxstr(hkdfhashes[testno].infoarray,
hkdfhashes[testno].infolength); hkdfhashes[testno].infolength);
printf("'\n"); printf("'\n");
printf(" L=%d bytes\n", hkdfhashes[testno].okmlength); printf(" L=%d bytes\n", hkdfhashes[testno].okmlength);
} }
/* Run hkdf() against the test vectors */ /* Run hkdf() against the test vectors */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
err = hkdf(hkdfhashes[testno].whichSha, err = hkdf(hkdfhashes[testno].whichSha,
hkdfhashes[testno].saltarray, (const uint8_t *) hkdfhashes[testno].saltarray,
hkdfhashes[testno].saltlength, hkdfhashes[testno].saltlength,
hkdfhashes[testno].ikmarray, (const uint8_t *) hkdfhashes[testno].ikmarray,
hkdfhashes[testno].ikmlength, hkdfhashes[testno].ikmlength,
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",
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. */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
err = hkdfExtract(hkdfhashes[testno].whichSha, err = hkdfExtract(hkdfhashes[testno].whichSha,
hkdfhashes[testno].saltarray, (const uint8_t *) hkdfhashes[testno].saltarray,
hkdfhashes[testno].saltlength, hkdfhashes[testno].saltlength,
hkdfhashes[testno].ikmarray, (const uint8_t *) hkdfhashes[testno].ikmarray,
hkdfhashes[testno].ikmlength, prk); hkdfhashes[testno].ikmlength, prk);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashHkdf(): hkdfExtract Error %d.\n", err); fprintf(stderr, "hashHkdf(): hkdfExtract Error %d.\n", err);
return err; return err;
} }
sprintf(buf, "hkdfExtract %d", testno+1); sprintf(buf, "hkdfExtract %d", testno+1);
printResult(prk, USHAHashSize(hkdfhashes[testno].whichSha), printResult(prk, USHAHashSize(hkdfhashes[testno].whichSha),
USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test",
buf, hkdfhashes[testno].prkarray, printResults, printPassFail); buf, hkdfhashes[testno].prkarray, printResults, printPassFail);
/* Now run hkdfExpand() by itself against the test vectors */ /* Now run hkdfExpand() by itself against the test vectors */
/* using the intermediate results from hkdfExtract. */ /* using the intermediate results from hkdfExtract. */
err = hkdfExpand(hkdfhashes[testno].whichSha, prk, err = hkdfExpand(hkdfhashes[testno].whichSha, prk,
USHAHashSize(hkdfhashes[testno].whichSha), USHAHashSize(hkdfhashes[testno].whichSha),
hkdfhashes[testno].infoarray, hkdfhashes[testno].infolength, (const uint8_t *)hkdfhashes[testno].infoarray,
okm, hkdfhashes[testno].okmlength); hkdfhashes[testno].infolength, okm, hkdfhashes[testno].okmlength);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashHkdf(): hkdfExpand Error %d.\n", err); fprintf(stderr, "hashHkdf(): hkdfExpand Error %d.\n", err);
return err; return err;
} }
sprintf(buf, "hkdfExpand %d", testno+1); sprintf(buf, "hkdfExpand %d", testno+1);
printResult(okm, hkdfhashes[testno].okmlength, printResult(okm, hkdfhashes[testno].okmlength,
USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test", USHAHashName(hkdfhashes[testno].whichSha), "hkdf standard test",
buf, hkdfhashes[testno].okmarray, printResults, printPassFail); buf, hkdfhashes[testno].okmarray, printResults, printPassFail);
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
/* /*
* Exercise a hash series of functions. The input is a filename. * Exercise a hash series of functions. The input is a filename.
* If the result is known, it is in resultarray in uppercase hex. * If the result is known, it is in resultarray in uppercase hex.
*/ */
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;
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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;
} }
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 */
skipping to change at page 111, line 39 skipping to change at page 112, line 4
if (skipSpaces) if (skipSpaces)
while ((c = getc(hashfp)) != EOF) { while ((c = getc(hashfp)) != EOF) {
if (!isspace(c)) { if (!isspace(c)) {
cc = (unsigned char)c; cc = (unsigned char)c;
err = info ? hkdfInput(&hkdf, &cc, 1) : err = info ? hkdfInput(&hkdf, &cc, 1) :
keyarray ? hmacInput(&hmac, &cc, 1) : keyarray ? hmacInput(&hmac, &cc, 1) :
USHAInput(&sha, &cc, 1); USHAInput(&sha, &cc, 1);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashfile(): %sInput Error %d.\n", fprintf(stderr, "hashfile(): %sInput Error %d.\n",
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
info ? "hkdf" : keyarray ? "hmac" : "sha", err); info ? "hkdf" : keyarray ? "hmac" : "sha", err);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
} }
} }
} }
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" :
"shaInput", err); "shaInput", err);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
} }
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);
if (err != shaSuccess) { if (err != shaSuccess) {
fprintf(stderr, "hashfile(): %s Error %d.\n", fprintf(stderr, "hashfile(): %s Error %d.\n",
info ? "hkdf" : keyarray ? "hmacFinalBits" : info ? "hkdf" : keyarray ? "hmacFinalBits" :
"shaFinalBits", err); "shaFinalBits", err);
skipping to change at page 112, line 39 skipping to change at page 113, line 4
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
return err; return err;
} }
printResult(Message_Digest, info ? okmlen : hashsize, printResult(Message_Digest, info ? okmlen : hashsize,
hashes[hashno].name, "file", hashfilename, resultarray, hashes[hashno].name, "file", hashfilename, resultarray,
printResults, printPassFail); printResults, printPassFail);
if (hashfp != stdin) fclose(hashfp); if (hashfp != stdin) fclose(hashfp);
if (info) free(Message_Digest); if (info) free(Message_Digest);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
return err; return err;
} }
/* /*
* 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)
{ {
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 */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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");
} }
for (j = 0; j < randomcount; j++) { for (j = 0; j < randomcount; j++) {
/* MD0 = MD1 = MD2 = Seed; */ /* MD0 = MD1 = MD2 = Seed; */
memcpy(MD[0], SEED, hashsize); memcpy(MD[0], SEED, hashsize);
skipping to change at page 113, line 39 skipping to change at page 114, line 4
} }
/* 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" }
}; };
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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;
} }
/* /*
* Run some tests that should invoke errors. * Run some tests that should invoke errors.
*/ */
void testErrors(int hashnolow, int hashnohigh, int printResults, void testErrors(int hashnolow, int hashnohigh, int printResults,
int printPassFail) int printPassFail)
skipping to change at page 114, line 38 skipping to change at page 115, line 4
printf ("\nError %d. Should be %d.\n", err, shaStateError); printf ("\nError %d. Should be %d.\n", err, shaStateError);
if ((printPassFail == PRINTPASSFAIL) || if ((printPassFail == PRINTPASSFAIL) ||
((printPassFail == PRINTFAIL) && (err != shaStateError))) ((printPassFail == PRINTFAIL) && (err != shaStateError)))
printf("%s se: %s\n", hashes[hashno].name, printf("%s se: %s\n", hashes[hashno].name,
(err == shaStateError) ? "PASSED" : "FAILED"); (err == shaStateError) ? "PASSED" : "FAILED");
err = USHAFinalBits(&usha, 0x80, 3); err = USHAFinalBits(&usha, 0x80, 3);
if (printResults == PRINTTEXT) if (printResults == PRINTTEXT)
printf ("\nError %d. Should be %d.\n", err, shaStateError); printf ("\nError %d. Should be %d.\n", err, shaStateError);
if ((printPassFail == PRINTPASSFAIL) || if ((printPassFail == PRINTPASSFAIL) ||
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
((printPassFail == PRINTFAIL) && (err != shaStateError))) ((printPassFail == PRINTFAIL) && (err != shaStateError)))
printf("%s se: %s\n", hashes[hashno].name, printf("%s se: %s\n", hashes[hashno].name,
(err == shaStateError) ? "PASSED" : "FAILED"); (err == shaStateError) ? "PASSED" : "FAILED");
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;
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;
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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,
(err == shaNull) ? "PASSED" : "FAILED"); (err == shaNull) ? "PASSED" : "FAILED");
} }
} }
/* replace a hex string in place with its value */ /* replace a hex string in place with its value */
skipping to change at page 115, line 38 skipping to change at page 116, line 4
printf("\nError: bad hex character '%c'\n", *hexstr); printf("\nError: bad hex character '%c'\n", *hexstr);
} }
if (!*++hexstr) break; if (!*++hexstr) break;
if (isalpha((int)(unsigned char)(*hexstr))) { if (isalpha((int)(unsigned char)(*hexstr))) {
nibble2 = tolower(*hexstr) - 'a' + 10; nibble2 = tolower(*hexstr) - 'a' + 10;
} else if (isdigit((int)(unsigned char)(*hexstr))) { } else if (isdigit((int)(unsigned char)(*hexstr))) {
nibble2 = *hexstr - '0'; nibble2 = *hexstr - '0';
} else { } else {
printf("\nError: bad hex character '%c'\n", *hexstr); printf("\nError: bad hex character '%c'\n", *hexstr);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
*o++ = (char)((nibble1 << 4) | nibble2); *o++ = (char)((nibble1 << 4) | nibble2);
len++; len++;
} }
return len; return len;
} }
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;
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;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
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;
while ((i = xgetopt(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(xoptarg, 0, 0); break; case 'b': extrabits = strtol(optarg, 0, 0); break;
case 'B': numberExtrabits = atoi(xoptarg); 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 = xoptarg; break; case 'f': hashfilename = optarg; break;
case 'F': hashFilename = xoptarg; break; case 'F': hashFilename = optarg; break;
case 'h': hashnolow = hashnohigh = findhash(argv[0], xoptarg); case 'h': hashnolow = hashnohigh = findhash(argv[0], optarg);
break; break;
case 'H': strIsHex = 1; break; case 'H': strIsHex = 1; break;
case 'i': info = xoptarg; infolen = strlen(xoptarg); break; case 'i': info = optarg; infolen = strlen(optarg); break;
case 'k': hmacKey = xoptarg; hmaclen = strlen(xoptarg); break; case 'k': hmacKey = optarg; hmaclen = strlen(optarg); break;
case 'l': loopnohigh = atoi(xoptarg); break; case 'l': loopnohigh = atoi(optarg); break;
case 'L': okmlen = strtol(xoptarg, 0, 0); break; case 'L': okmlen = strtol(optarg, 0, 0); break;
case 'm': runHmacTests = 1; break; case 'm': runHmacTests = 1; break;
case 'P': printPassFail = 0; break; case 'P': printPassFail = 0; break;
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
case 'p': printResults = PRINTNONE; break; case 'p': printResults = PRINTNONE; break;
case 'R': randomcount = atoi(xoptarg); break; case 'R': randomcount = atoi(optarg); break;
case 'r': randomseedstr = xoptarg; break; case 'r': randomseedstr = optarg; break;
case 's': hashstr = xoptarg; hashlen = strlen(hashstr); break; case 's': hashstr = optarg; hashlen = strlen(hashstr); break;
case 'S': resultstr = xoptarg; break; case 'S': resultstr = optarg; break;
case 't': testnolow = ntestnohigh = atoi(xoptarg) - 1; break; case 't': testnolow = ntestnohigh = atoi(optarg) - 1; break;
case 'w': printResults = PRINTRAW; break; case 'w': printResults = PRINTRAW; break;
case 'x': printResults = PRINTHEX; break; case 'x': printResults = PRINTHEX; break;
case 'X': printPassFail = 2; break; case 'X': printPassFail = 2; break;
case '6': printResults = PRINTBASE64; break; case '6': printResults = PRINTBASE64; break;
default: usage(argv[0]); default: usage(argv[0]);
} }
if (strIsHex) { if (strIsHex) {
hashlen = unhexStr(hashstr); hashlen = unhexStr(hashstr);
unhexStr(randomseedstr); unhexStr(randomseedstr);
hmaclen = unhexStr(hmacKey); hmaclen = unhexStr(hmacKey);
infolen = unhexStr(info); infolen = unhexStr(info);
} }
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
testnohigh = (ntestnohigh != 0) ? ntestnohigh: testnohigh = (ntestnohigh != 0) ? ntestnohigh:
runHmacTests ? (HMACTESTCOUNT-1) : runHmacTests ? (HMACTESTCOUNT-1) :
runHkdfTests ? (HKDFTESTCOUNT-1) : runHkdfTests ? (HKDFTESTCOUNT-1) :
(TESTCOUNT-1); (TESTCOUNT-1);
if ((testnolow < 0) || if ((testnolow < 0) ||
(testnohigh >= (runHmacTests ? HMACTESTCOUNT : TESTCOUNT)) || (testnohigh >= (runHmacTests ? HMACTESTCOUNT : TESTCOUNT)) ||
(hashnolow < 0) || (hashnohigh >= HASHCOUNT) || (hashnolow < 0) || (hashnohigh >= HASHCOUNT) ||
(hashstr && (testnolow == testnohigh)) || (hashstr && (testnolow == testnohigh)) ||
(randomcount < 0) || (randomcount < 0) ||
(resultstr && (!hashstr && !hashfilename && !hashFilename)) || (resultstr && (!hashstr && !hashfilename && !hashFilename)) ||
skipping to change at page 117, line 36 skipping to change at page 117, line 55
for (hashno = hashnolow; hashno <= hashnohigh; ++hashno) { for (hashno = hashnolow; hashno <= hashnohigh; ++hashno) {
if (printResults == PRINTTEXT) if (printResults == PRINTTEXT)
printf("Hash %s\n", hashes[hashno].name); printf("Hash %s\n", hashes[hashno].name);
err = shaSuccess; err = shaSuccess;
for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess); for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess);
++loopno) { ++loopno) {
if (hashstr) if (hashstr)
err = hash(0, loopno, hashno, hashstr, hashlen, 1, err = hash(0, loopno, hashno, hashstr, hashlen, 1,
numberExtrabits, extrabits, (const unsigned char *)hmacKey, numberExtrabits, extrabits, (const unsigned char *)hmacKey,
hmaclen, info, infolen, okmlen, resultstr, hmaclen, (const uint8_t *) info, infolen, okmlen, resultstr,
hashes[hashno].hashsize, printResults, printPassFail); hashes[hashno].hashsize, printResults, printPassFail);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
else if (randomseedstr) else if (randomseedstr)
randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0, randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0,
randomcount, printResults, printPassFail); randomcount, printResults, printPassFail);
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,
info, infolen, okmlen, resultstr, (const uint8_t *) info, infolen, okmlen,
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,
info, infolen, okmlen, resultstr, (const uint8_t *) info, infolen, okmlen,
hashes[hashno].hashsize, resultstr, hashes[hashno].hashsize,
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
printResults, printPassFail); printResults, printPassFail);
else /* standard tests */ { else /* standard tests */ {
for (testno = testnolow; for (testno = testnolow;
(testno <= testnohigh) && (err == shaSuccess); ++testno) { (testno <= testnohigh) && (err == shaSuccess); ++testno) {
if (runHmacTests) { if (runHmacTests) {
err = hash(testno, loopno, hashno, err = hash(testno, loopno, hashno,
hmachashes[testno].dataarray[hashno] ? hmachashes[testno].dataarray[hashno] ?
hmachashes[testno].dataarray[hashno] : hmachashes[testno].dataarray[hashno] :
hmachashes[testno].dataarray[1] ? hmachashes[testno].dataarray[1] ?
skipping to change at page 118, line 39 skipping to change at page 119, line 4
hmachashes[testno].keyarray[1] : hmachashes[testno].keyarray[1] :
hmachashes[testno].keyarray[0]), hmachashes[testno].keyarray[0]),
hmachashes[testno].keylength[hashno] ? hmachashes[testno].keylength[hashno] ?
hmachashes[testno].keylength[hashno] : hmachashes[testno].keylength[hashno] :
hmachashes[testno].keylength[1] ? hmachashes[testno].keylength[1] ?
hmachashes[testno].keylength[1] : hmachashes[testno].keylength[1] :
hmachashes[testno].keylength[0], hmachashes[testno].keylength[0],
0, 0, 0, 0, 0, 0,
hmachashes[testno].resultarray[hashno], hmachashes[testno].resultarray[hashno],
hmachashes[testno].resultlength[hashno], hmachashes[testno].resultlength[hashno],
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
printResults, printPassFail); printResults, printPassFail);
} else if (runHkdfTests) { } else if (runHkdfTests) {
err = hashHkdf(testno, loopno, hashno, err = hashHkdf(testno, loopno, hashno,
printResults, printPassFail); printResults, printPassFail);
} else { /* sha tests */ } else { /* sha tests */
err = hash(testno, loopno, hashno, err = hash(testno, loopno, hashno,
hashes[hashno].tests[testno].testarray, hashes[hashno].tests[testno].testarray,
hashes[hashno].tests[testno].length, hashes[hashno].tests[testno].length,
hashes[hashno].tests[testno].repeatcount, hashes[hashno].tests[testno].repeatcount,
hashes[hashno].tests[testno].numberExtrabits, hashes[hashno].tests[testno].numberExtrabits,
hashes[hashno].tests[testno].extrabits, hashes[hashno].tests[testno].extrabits,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
hashes[hashno].tests[testno].resultarray, hashes[hashno].tests[testno].resultarray,
hashes[hashno].hashsize, hashes[hashno].hashsize,
printResults, printPassFail); printResults, printPassFail);
} }
} }
if (!runHmacTests && !runHkdfTests) { if (!runHmacTests && !runHkdfTests) {
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
randomtest(hashno, hashes[hashno].randomtest, randomtest(hashno, hashes[hashno].randomtest,
hashes[hashno].hashsize, hashes[hashno].randomresults, hashes[hashno].hashsize, hashes[hashno].randomresults,
RANDOMCOUNT, printResults, printPassFail); RANDOMCOUNT, printResults, printPassFail);
} }
} }
} }
} }
/* Test some error returns */ /* Test some error returns */
if (checkErrors) { if (checkErrors) {
skipping to change at page 119, line 38 skipping to change at page 120, line 4
{ {
for (;;) { for (;;) {
char u1 = tolower(*s1++); char u1 = tolower(*s1++);
char u2 = tolower(*s2++); char u2 = tolower(*s2++);
if (u1 != u2) if (u1 != u2)
return u1 - u2; return u1 - u2;
if (u1 == '\0') if (u1 == '\0')
return 0; return 0;
} }
} }
/*
* This is a copy of getopt provided for those systems that do not
* have it. The name was changed to xgetopt to not conflict on those
* systems that do have it. Similarly, optarg, optopt, optind and
* opterr were renamed to xoptarg, xoptopt, xoptind and xopterr,
* respectively.
*/
int xoptind = 1; /* location in argv */
char *xoptarg = 0; /* argument to option */
int xoptopt = 0; /* current option */
int xopterr = 1; /* print error messages */
static int xoptplace = 0; /* internal state */
int xgetopt(int argc, char **argv, const char *optstring)
{
char *p;
xoptarg = 0; /* reset argument */
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (xoptind == argc) { /* end of options */
return -1;
}
if (xoptplace == 0) { /* at beginning of an option */
if (argv[xoptind][0] != '-') { /* hit a non-option */
xoptplace = 0;
return -1;
}
if (argv[xoptind][1] == '-') { /* found --, skip past, end */
xoptind++;
xoptplace = 0;
return -1;
}
xoptplace = 1;
xoptopt = argv[xoptind][xoptplace];
p = strchr(optstring, xoptopt);
if (p == 0) { /* option unknown */
if (xopterr) fprintf(stderr, "Unknown option: %c\n",
xoptopt);
xoptind++; /* prevent infinite loop */
xoptplace = 0;
return '?';
}
if (p[1] == ':') { /* need an argument */
if (argv[xoptind][xoptplace+1]) { /* arg inline */
xoptarg = argv[xoptind] + xoptplace + 1;
xoptind++;
xoptplace = 0;
return xoptopt;
}
if (xoptind == argc) {
if (xopterr) fprintf(stderr,
"Option -%c requires an argument\n", xoptopt);
return '?';
}
xoptarg = argv[++xoptind]; /* next is arg */
xoptind++; /* and move past it */
xoptplace = 0;
return xoptopt;
}
if (argv[xoptind][xoptplace+1]) { /* more inline */
xoptplace++;
return xoptopt;
}
xoptind++; /* move forward one */
xoptplace = 0;
return xoptopt;
}
xoptopt = argv[xoptind][xoptplace];
p = strchr(optstring, xoptopt);
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
if (p == 0) { /* option unknown */
if (xopterr) fprintf(stderr, "Unknown option: %c\n", xoptopt);
xoptind++; /* prevent infinite loop */
xoptplace = 0;
return '?';
}
if (p[1] == ':') { /* need an argument */
if (xopterr) fprintf(stderr,
"Option -%c with argument must not be part of "
"multi-character option list\n", xoptopt);
xoptind++;
xoptplace = 0;
return '?';
}
if (argv[xoptind][xoptplace+1]) { /* more inline */
xoptplace++;
return xoptopt;
}
xoptind++; /* move forward one */
xoptplace = 0;
return xoptopt;
}
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
9. IANA Considerations 9. IANA Considerations
This document requires no IANA Actions. The RFC Editor should delete This document requires no IANA Actions. The RFC Editor should delete
this section before publication. this section before publication.
10. Security Considerations 10. Security Considerations
This document is intended to provide convenient open source access by This document is intended to provide convenient open source access by
the Internet community to the United States of America Federal the Internet community to the United States of America Federal
Information Processing Standard Secure Hash Algorithms (SHAs) [FIPS Information Processing Standard Secure Hash Algorithms (SHAs) [FIPS
180-2], HMACs based thereon, and HKDF. No independent assertion of 180-2], HMACs based thereon, and HKDF. No independent assertion of
the security of these functions by the authors for any particular use the security of these functions by the authors for any particular use
is intended. is intended.
11. Acknowledgements 11. Acknowledgements
Thanks for the corrections to [RFC4634] that were provided by Alfred Thanks for the corrections to [RFC4634] that were provided by Alfred
Hoenes and Jan Andres that are incorporated herein. Hoenes and Jan Andres and to Alfred's comments on the drafts hereof.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
12. References 12. References
RFC Editor Note: All occurances of RFChkdf should be edited to have RFC Editor Note: All occurances of "RFC NNNN" should be edited to
the HKDF RFC number instead of "hkdf". All occurances of "RFC NNNN" replace "NNNN" with this documents RFC number and this note should be
should be edited to replace "NNNN" with this documents RFC number. deleted.
And this note should be deleted.
12.1 Normative References 12.1 Normative References
[FIPS 180-2] - "Secure Hash Standard", United States of American,
National Institute of Science and Technology, Federal
Information Processing Standard (FIPS) 180-2,
http://csrc.nist.gov/publications/fips/fips180-2/fips180-
2withchangenotice.pdf.
[RFC2104] - Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- [RFC2104] - Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
Hashing for Message Authentication", RFC 2104, February 1997. Hashing for Message Authentication", RFC 2104, February 1997.
[RFC2119] - Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] - Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997. Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFChkdf] - Krawczyk, H. and P. Eronen, "HMAC-based Extract-and- [RFC5869] - Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-
Expand Key Derivation Function (HKDF)", draft-krawczyk-hkdf in Expand Key Derivation Function (HKDF)", RFC 5869, May 2010.
RFC Editor queue, January 2010.
[SHS] - "Secure Hash Standard", United States of American, National
Institute of Science and Technology, Federal Information
Processing Standard (FIPS) 180-3,
http://csrc.nist.gov/publications/fips/fips180-
3/fips180-3_final.pdf.
12.2 Informative References 12.2 Informative References
[RFC2202] - P. Cheng, R. Glenn, "Test Cases for HMAC-MD5 and HMAC- [RFC2202] - P. Cheng, R. Glenn, "Test Cases for HMAC-MD5 and HMAC-
SHA-1", September 1997. SHA-1", September 1997.
[RFC3174] - D. Eastlake 3rd, P. Jones, "US Secure Hash Algorithm 1 [RFC3174] - D. Eastlake 3rd, P. Jones, "US Secure Hash Algorithm 1
(SHA1)", September 2001. (SHA1)", September 2001.
[RFC3874] - R. Housley, "A 224-bit One-way Hash Function: SHA-224", [RFC3874] - R. Housley, "A 224-bit One-way Hash Function: SHA-224",
skipping to change at page 124, line 4 skipping to change at page 121, line 51
[RFC4055] - Schaad, J., Kaliski, B., and R. Housley, "Additional [RFC4055] - Schaad, J., Kaliski, B., and R. Housley, "Additional
Algorithms and Identifiers for RSA Cryptography for use in the Algorithms and Identifiers for RSA Cryptography for use in the
Internet X.509 Public Key Infrastructure Certificate and Internet X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile", RFC 4055, June 2005 Certificate Revocation List (CRL) Profile", RFC 4055, June 2005
[RFC4086] - D. Eastlake, S. Crocker, J. Schiller, "Randomness [RFC4086] - D. Eastlake, S. Crocker, J. Schiller, "Randomness
Requirements for Security", May 2005. Requirements for Security", May 2005.
[RFC4231] - M. Nystrom, "Identifiers and Test Vectors for HMAC- [RFC4231] - M. Nystrom, "Identifiers and Test Vectors for HMAC-
SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512", SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512",
December 2005.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
December 2005.
[RFC4634] - Eastlake 3rd, D. and T. Hansen, "US Secure Hash [RFC4634] - Eastlake 3rd, D. and T. Hansen, "US Secure Hash
Algorithms (SHA and HMAC-SHA)", RFC 4634, July 2006. Algorithms (SHA and HMAC-SHA)", RFC 4634, July 2006.
[SHAVS] - "The Secure Hash Algorithm Validation System (SHAVS)", [SHAVS] - "The Secure Hash Algorithm Validation System (SHAVS)",
http://csrc.nist.gov/cryptval/shs/SHAVS.pdf. http://csrc.nist.gov/cryptval/shs/SHAVS.pdf.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Appendix: Changes from RFC 4634 Appendix: Changes from RFC 4634
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
[RFChkdf]. [RFC5869].
2. Fix numerous errata filed against [RFC4634] as below. Note that in 2. Fix numerous errata filed against [RFC4634] as below. Note that in
no case did the old code return an incorrect hash value. 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.
3. Update boilerplate, remove special license in [RFC4634] as new 3. Update boilerplate, remove special license in [RFC4634] as new
boilerplate mandates simplified BSD license. boilerplate mandates simplified BSD license.
4. Repalce MIT version of getopt with new code to satisfy IETF
incoming and outgoing license restrictions.
5. Other assorted editorial improvements.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Edit History Appendix Z: Edit History
RFC Editor, Please delete this section on publication. RFC Editor, Please delete this Appendix Z on publication.
Changes from -00 to -01 Z.1 Changes from -00 to -01
Add hash function OIDs and informational reference to [RFC4055]. A Add hash function OIDs and informational reference to [RFC4055]. A
few Editorial changes and typo fixes. few Editorial changes and typo fixes.
Changes from -01 to -02 Z.2 Changes from -01 to -02
In shatest.c, replace MIT getopt (xgetopt) code with new code to In shatest.c, replace MIT getopt (xgetopt) code with new code to
avoid possible conflict between MIT license and IETF required BSD avoid possible conflict between MIT license and IETF required BSD
license. license.
Z.3 Changes from -02 to -03
Problem with MIT getopt is given incompletely in -01 to -02 changes.
Actual problem includes conflict with IETF incoming license
restriction. Also, add this change to Appendix giving changes from
RFC 4634. Update to incorporate RFC number for the HKDF RFC.
Numerous editorial changes.
INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF INTERNET-DRAFT SHAs, HMAC-SHAs, and HKDF
Author's Address Author's Address
Donald E. Eastlake, 3rd Donald E. Eastlake, 3rd
Stellar Switches Stellar Switches
155 Beaver Street 155 Beaver Street
Milford, MA 01757 USA Milford, MA 01757 USA
Telephone: +1-508-333-2270 Telephone: +1-508-333-2270
 End of changes. 232 change blocks. 
443 lines changed or deleted 375 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/