US Secure Hash Algorithms (SHA and HMAC-SHA)

Network Working Group                                    D. Eastlake 3rd
Request for Comments: 4634                                 Motorola Labs
Updates: 3174                                                  T. Hansen
Category: Informational                                        AT&T Labs

Status of This Memo

Copyright Notice

Abstract


Table of Contents


1.  Overview of Contents




1.1.  License


2.  Notation for Bit Strings and Integers






3.  Operations on Words












4.  Message Padding and Parsing


4.1.  SHA-224 and SHA-256








4.2.  SHA-384 and SHA-512








5.  Functions and Constants Used

5.1.  SHA-224 and SHA-256






5.2.  SHA-384 and SHA-512






6.  Computing the Message Digest


6.1.  SHA-224 and SHA-256 Initialization



6.2.  SHA-224 and SHA-256 Processing







6.3.  SHA-384 and SHA-512 Initialization



6.4.  SHA-384 and SHA-512 Processing






7.  SHA-Based HMACs


8.  C Code for SHAs










8.1.  The .h File

#ifndef _SHA_H_
#define _SHA_H_

#include <stdint.h>


#ifndef _SHA_enum_
#define _SHA_enum_
enum {
};
#endif /* _SHA_enum_ */

enum {

};

typedef enum SHAversion {
} SHAversion;

typedef struct SHA1Context {


} SHA1Context;

typedef struct SHA256Context {


} SHA256Context;

typedef struct SHA512Context {
#ifdef USE_32BIT_ONLY
#else /* !USE_32BIT_ONLY */
#endif /* USE_32BIT_ONLY */


} SHA512Context;

typedef struct SHA256Context SHA224Context;

typedef struct SHA512Context SHA384Context;

typedef struct USHAContext {
} USHAContext;

typedef struct HMACContext {
} HMACContext;


extern int SHA1Reset(SHA1Context *);
extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
extern int SHA1FinalBits(SHA1Context *, const uint8_t bits,
extern int SHA1Result(SHA1Context *,

extern int SHA224Reset(SHA224Context *);
extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
extern int SHA224FinalBits(SHA224Context *, const uint8_t bits,
extern int SHA224Result(SHA224Context *,

extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
extern int SHA256FinalBits(SHA256Context *, const uint8_t bits,
extern int SHA256Result(SHA256Context *,

extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
extern int SHA384FinalBits(SHA384Context *, const uint8_t bits,
extern int SHA384Result(SHA384Context *,

extern int SHA512Reset(SHA512Context *);
extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
extern int SHA512FinalBits(SHA512Context *, const uint8_t bits,
extern int SHA512Result(SHA512Context *,

extern int USHAReset(USHAContext *, SHAversion whichSha);
extern int USHAInput(USHAContext *,
extern int USHAFinalBits(USHAContext *,
extern int USHAResult(USHAContext *,
extern int USHABlockSize(enum SHAversion whichSha);
extern int USHAHashSize(enum SHAversion whichSha);
extern int USHAHashSizeBits(enum SHAversion whichSha);

extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */

extern int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
extern int hmacInput(HMACContext *ctx, const unsigned char *text,

extern int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
extern int hmacResult(HMACContext *ctx,

#endif /* _SHA_H_ */

8.2.  The SHA Code


8.2.1.  sha1.c


#include "sha.h"
#include "sha-private.h"

#define SHA1_ROTL(bits,word) \

static uint32_t addTemp;
#define SHA1AddLength(context, length)                     \

static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte);
static void SHA1PadMessage(SHA1Context *, uint8_t Pad_Byte);
static void SHA1ProcessMessageBlock(SHA1Context *);

int SHA1Reset(SHA1Context *context)
{



}

int SHA1Input(SHA1Context *context,
{





}

int SHA1FinalBits(SHA1Context *context, const uint8_t message_bits,
{




}

int SHA1Result(SHA1Context *context,
{



}

static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
{
}


static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
{



}

static void SHA1ProcessMessageBlock(SHA1Context *context)
{






}

8.2.2.  sha224-256.c

#include "sha.h"
#include "sha-private.h"

#define SHA256_SHR(bits,word)      ((word) >> (bits))
#define SHA256_ROTL(bits,word)                         \
#define SHA256_ROTR(bits,word)                         \

#define SHA256_SIGMA0(word)   \
#define SHA256_SIGMA1(word)   \
#define SHA256_sigma0(word)   \
#define SHA256_sigma1(word)   \

static uint32_t addTemp;
#define SHA224_256AddLength(context, length)               \

static void SHA224_256Finalize(SHA256Context *context,
static void SHA224_256PadMessage(SHA256Context *context,
static void SHA224_256ProcessMessageBlock(SHA256Context *context);
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
static int SHA224_256ResultN(SHA256Context *context,

static uint32_t SHA224_H0[SHA256HashSize/4] = {
};

static uint32_t SHA256_H0[SHA256HashSize/4] = {
};

int SHA224Reset(SHA224Context *context)
{
}

int SHA224Input(SHA224Context *context, const uint8_t *message_array,
{
}


int SHA224FinalBits( SHA224Context *context,
{
}

int SHA224Result(SHA224Context *context,
{
}


int SHA256Reset(SHA256Context *context)
{
}

int SHA256Input(SHA256Context *context, const uint8_t *message_array,
{





}

int SHA256FinalBits(SHA256Context *context,
{




}

int SHA256Result(SHA256Context *context, uint8_t Message_Digest[])
{

}

static void SHA224_256Finalize(SHA256Context *context,
{
}


static void SHA224_256PadMessage(SHA256Context *context,
{


}


static void SHA224_256ProcessMessageBlock(SHA256Context *context)
{




}


static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
{


}


static int SHA224_256ResultN(SHA256Context *context,
{



}

8.2.3.  sha384-512.c


#include "sha.h"
#include "sha-private.h"

#ifdef USE_32BIT_ONLY

#define SHA512_SHR(bits, word, ret) (                          \

#define SHA512_SHL(bits, word, ret) (                          \


#define SHA512_OR(word1, word2, ret) (                         \

#define SHA512_XOR(word1, word2, ret) (                        \

#define SHA512_AND(word1, word2, ret) (                        \

#define SHA512_TILDA(word, ret)                                \

#define SHA512_ADD(word1, word2, ret) (                        \

static uint32_t ADDTO4_temp, ADDTO4_temp2;
#define SHA512_ADDTO4(word1, word2) (                          \


static uint32_t ADDTO2_temp;
#define SHA512_ADDTO2(word1, word2) (                          \

static uint32_t ROTR_temp1[2], ROTR_temp2[2];
#define SHA512_ROTR(bits, word, ret) (                         \

static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2],
#define SHA512_SIGMA0(word, ret) (                             \

static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2],
#define SHA512_SIGMA1(word, ret) (                             \


static uint32_t sigma0_temp1[2], sigma0_temp2[2],
#define SHA512_sigma0(word, ret) (                             \

static uint32_t sigma1_temp1[2], sigma1_temp2[2],
#define SHA512_sigma1(word, ret) (                             \

#undef SHA_Ch
#undef SHA_Maj

#ifndef USE_MODIFIED_MACROS
static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2];
#define SHA_Ch(x, y, z, ret) (                                 \
static uint32_t Maj_temp1[2], Maj_temp2[2],
#define SHA_Maj(x, y, z, ret) (                                \

#else /* !USE_32BIT_ONLY */
#define SHA_Ch(x, y, z, ret) (                                 \

#define SHA_Maj(x, y, z, ret) (                                 \
#endif /* USE_MODIFIED_MACROS */

static uint32_t addTemp[4] = { 0, 0, 0, 0 };
#define SHA384_512AddLength(context, length) (                        \

static void SHA384_512Finalize(SHA512Context *context,
static void SHA384_512PadMessage(SHA512Context *context,
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static int SHA384_512Reset(SHA512Context *context, uint32_t H0[]);
static int SHA384_512ResultN( SHA512Context *context,

static uint32_t SHA384_H0[SHA512HashSize/4] = {
};

static uint32_t SHA512_H0[SHA512HashSize/4] = {
};

#else /* !USE_32BIT_ONLY */

#define SHA512_SHR(bits,word)  (((uint64_t)(word)) >> (bits))
#define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \

#define SHA512_SIGMA0(word)   \
#define SHA512_SIGMA1(word)   \
#define SHA512_sigma0(word)   \
#define SHA512_sigma1(word)   \

static uint64_t addTemp;
#define SHA384_512AddLength(context, length)                   \

static void SHA384_512Finalize(SHA512Context *context,
static void SHA384_512PadMessage(SHA512Context *context,
static void SHA384_512ProcessMessageBlock(SHA512Context *context);
static int SHA384_512Reset(SHA512Context *context, uint64_t H0[]);
static int SHA384_512ResultN(SHA512Context *context,

static uint64_t SHA384_H0[] = {

};
static uint64_t SHA512_H0[] = {
};

#endif /* USE_32BIT_ONLY */

int SHA384Reset(SHA384Context *context)
{
}


int SHA384Input(SHA384Context *context,
{
}

int SHA384FinalBits(SHA384Context *context,
{
}


int SHA384Result(SHA384Context *context,
{
}

int SHA512Reset(SHA512Context *context)
{
}


int SHA512Input(SHA512Context *context,
{




}


int SHA512FinalBits(SHA512Context *context,
{



}


static void SHA384_512Finalize(SHA512Context *context,
{
#ifdef USE_32BIT_ONLY    /* and clear length */
#else /* !USE_32BIT_ONLY */
#endif /* USE_32BIT_ONLY */
}


int SHA512Result(SHA512Context *context,
{
}

static void SHA384_512PadMessage(SHA512Context *context,
{


#ifdef USE_32BIT_ONLY

#else /* !USE_32BIT_ONLY */

#endif /* USE_32BIT_ONLY */

}

static void SHA384_512ProcessMessageBlock(SHA512Context *context)
{
#ifdef USE_32BIT_ONLY






#else /* !USE_32BIT_ONLY */




#endif /* USE_32BIT_ONLY */

}


#ifdef USE_32BIT_ONLY
static int SHA384_512Reset(SHA512Context *context, uint32_t H0[])
#else /* !USE_32BIT_ONLY */
static int SHA384_512Reset(SHA512Context *context, uint64_t H0[])
#endif /* USE_32BIT_ONLY */
{

#ifdef USE_32BIT_ONLY

#else /* !USE_32BIT_ONLY */

#endif /* USE_32BIT_ONLY */

}


static int SHA384_512ResultN(SHA512Context *context,
{

#ifdef USE_32BIT_ONLY
#endif /* USE_32BIT_ONLY */


#ifdef USE_32BIT_ONLY
#else /* !USE_32BIT_ONLY */

#endif /* USE_32BIT_ONLY */

}

8.2.4.  usha.c

#include "sha.h"

int USHAReset(USHAContext *ctx, enum SHAversion whichSha)
{

}

int USHAInput(USHAContext *ctx,
{
}

int USHAFinalBits(USHAContext *ctx,
{
}


int USHAResult(USHAContext *ctx,
{
}


int USHABlockSize(enum SHAversion whichSha)
{
}

int USHAHashSize(enum SHAversion whichSha)
{
}


int USHAHashSizeBits(enum SHAversion whichSha)
{
}

8.2.5.  sha-private.h

#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H

#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 */

#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

#include "sha.h"

int hmac(SHAversion whichSha, const unsigned char *text, int text_len,

{
}

int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
{






}


int hmacInput(HMACContext *ctx, const unsigned char *text,
{
}

int hmacFinalBits(HMACContext *ctx,
{

}

int hmacResult(HMACContext *ctx, uint8_t *digest)
{



}

8.4.  The Test Driver


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.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);

#define TEST1    "abc"
#define TEST2_1  \
#define TEST2_2a \
#define TEST2_2b \
#define TEST2_2  TEST2_2a TEST2_2b
#define TEST3    "a"                            /* times 1000000 */
#define TEST4a   "01234567012345670123456701234567"
#define TEST4b   "01234567012345670123456701234567"
#define TEST4   TEST4a TEST4b                   /* times 10 */

#define TEST7_1 \
#define TEST8_1 \
#define TEST9_1 \
#define TEST10_1 \
#define TEST7_224 \
#define TEST8_224 \
#define TEST9_224 \

#define TEST10_224 \
#define TEST7_256 \
#define TEST8_256 \
#define TEST9_256 \
#define TEST10_256 \
#define TEST7_384 \
#define TEST8_384 \
#define TEST9_384 \

#define TEST10_384 \
#define TEST7_512 \
#define TEST8_512 \
#define TEST9_512 \
#define TEST10_512 \
#define SHA1_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2\x3d" \

#define SHA224_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2" \
#define SHA256_SEED "\xf4\x1e\xce\x26\x13\xe4\x57\x39\x15\x69\x6b" \
#define SHA384_SEED "\x82\x40\xbc\x51\xe4\xec\x7e\xf7\x6d\x18\xe3" \
#define SHA512_SEED "\x47\x3f\xf1\xb9\xb3\xff\xdf\xa1\x26\x69\x9a" \

#define TESTCOUNT 10
#define HASHCOUNT 5
#define RANDOMCOUNT 4
#define HMACTESTCOUNT 7

#define PRINTNONE 0
#define PRINTTEXT 1
#define PRINTRAW 2
#define PRINTHEX 3
#define PRINTBASE64 4

#define PRINTPASSFAIL 1
#define PRINTFAIL 2

#define length(x) (sizeof(x)-1)

struct hash {

} hashes[HASHCOUNT] = {



};

struct hmachash {
} hmachashes[HMACTESTCOUNT] = {




};


static const char hexdigits[] = "0123456789ABCDEF";
int checkmatch(const unsigned char *hashvalue,
{
}

void printstr(const char *str, int len)
{
}

void printxstr(const char *str, int len)
{
}

void usage(const char *argv0)
{

}

void printResult(uint8_t *Message_Digest, int hashsize,
{


}

int hash(int testno, int loopno, int hashno,
{






}

int hashfile(int hashno, const char *hashfilename, int bits,
{





}


void randomtest(int hashno, const char *seed, int hashsize,
{


}

int findhash(const char *argv0, const char *opt)
{

}

void testErrors(int hashnolow, int hashnohigh, int printResults,
{



}

int unhexStr(char *hexstr)
{

}

int main(int argc, char **argv)
{









}

int scasecmp(const char *s1, const char *s2)
{
}


char    *xoptarg;
int     xoptind = 1;
int     xopterr = 1;

static int xgetopt(int argc, char **argv, const char *optstring)
{




}

9.  Security Considerations

10.  Normative References


11.  Informative References




Authors' Addresses



Full Copyright Statement


Intellectual Property


Acknowledgement