[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Cfrg] SHA1-IME



Please find attached SHA1-IME draft - for review and comments.
 
Thank you!
 
Regards,
Uri
<Disclaimer> Opinions in this e-mail are strictly my personal ones, and not Intel's.

 

GIF image



Network Working Group                Crypto Forum Research Group
INTERNET DRAFT                             Uri Blumenthal, Intel
November 2005                                    C.S. Jutla, IBM
Expiration Date: May 2006               A. C. Patthak, UT Austin

            SHA1-IME: A SHA-1 Variant with Provably Good
                     Message Expansion Code
                <draft-irtf-cfrg-sha1-ime-00.txt>

Status of this Memo

     By submitting this Internet-Draft,  each  author  represents
     that  any  applicable patent or other IPR claims of which he
     or she is aware have been or will be disclosed, and  any  of
     which  he  or she becomes aware will be disclosed, in accor-
     dance with Section 6 of BCP 79.

     This document is an Internet-Draft and is  in  full  confor-
     mance with all provisions of Section 10 of RFC2026.

     Internet-Drafts  are  working  documents  of  the   Internet
     Engineering  Task  Force  (IETF), its areas, and its working
     groups.  Note that other groups may also distribute  working
     documents as Internet-Drafts.

     Internet-Drafts are draft documents valid for a  maximum  of
     six  months  and  may  be updated, replaced, or obsoleted by
     other documents at any time.  It  is  inappropriate  to  use
     Internet- Drafts as reference material or to cite them other
     than as "work in progress."

     The list of  current  Internet-Drafts  can  be  accessed  at
     http://www.ietf.org/ietf/1id-abstracts.txt

     The  list  of  Internet-Draft  Shadow  Directories  can   be
     accessed at http://www.ietf.org/shadow.html.

Abstract

     This document  describes a new cryptographic  hash  function
     SHA1-IME  with input and output parameters identical to SHA-
     1. Further, the specification of SHA1-IME  is  identical  to
     that  of  SHA-1,  except  for  an improved message expansion
     code. The improved  message  expansion  is  proven  to  make
     SHA1-IME  resistant to recent differential attacks and their
     natural extensions.
       Moreover, SHA1-IME has only a 5% overhead when compared to
     SHA-1  in  a software implementation.  The simplicity of the
     design change, compatibility with SHA-1 parameters, and  the
     excellent  speed/security  tradeoff makes it an ideal candi-
     date for SHA-1 replacement.





BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          1










                        Table of Contents




1. Introduction ............................................    3

2. BIT STRINGS AND INTEGERS ................................    4

3. OPERATIONS ON WORDS .....................................    4

4. MESSAGE PADDING .........................................    5

5. FUNCTIONS USED ..........................................    6

6. CONSTANTS USED ..........................................    7

7. COMPUTING THE MESSAGE DIGEST ............................    7

8. Intellectual Property Issues ............................    8

9. TEST VECTORS ............................................    8

10. Acknowledgments ........................................    9

11. References .............................................    9

12. Authors' Address .......................................    9

13. Copyright Notice .......................................   10

APPENDIX  A, B & C (Reference Implementation) 






















BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          2





Internet Draft                                           Nov 2005


1.  Introduction

     In this document we propose a new cryptographic  hash  func-
     tion  SHA1-IME (SHA-1 with Improved Message Expansion). This
     document will closely  follow  the  specification  of  SHA-1
     given in FIPS PUB 180-1 ([SHA1]).

     As for SHA-1, the hash function SHA1-IME is used to  compute
     a  condensed  representation of a message or a data file. In
     fact, SHA1-IME so closely  resembles  SHA-1,  except  for  a
     small  modification  in  the  code, that its usage in single
     block, and in multi block settings is  identical  to  SHA-1.
     The  small  modification in the code leads to a huge gain in
     security over SHA-1 w.r.t. differential attacks,  making  it
     an  ideal  candidate  for a SHA-1 replacement. Moreover, the
     security claims are based on actual proofs (see [JP1], [JP2]
     for extensive security analysis and proofs).

     In a software implementation, SHA1-IME has only a  5%  over-
     head  when compared to SHA-1. In a high performance hardware
     implementation, we expect SHA1-IME to have  a  10%  overhead
     (comparable to SHA-256 [SHA2]). Further, there are no Intel-
     lectual Property claims on  the new hash function SHA1-IME.

     To give a brief overview of SHA1-IME, recall that in  SHA-1,
     a  message expansion code is used to expand 512 bits (packed
     in 16 words) to 80 words. This linear expansion  code,  how-
     ever  turned  out  to  have  a  much smaller minimum hamming
     weight than expected. This fact is an integral part  of  the
     recent  attack  of  Wang et al ([WYY]) on SHA-1. The message
     expansion code in SHA1-IME (which is the only place where it
     differs  from SHA-1) has been proven to have a large minimum
     hamming weight([JP1]). Further, it has been shown  in  [JP2]
     that  when  the  message  expansion code has a large minimum
     hamming weight then differential attacks (including Wang  et
     al  [WYY] and its natural extensions) cannot be used to find
     collisions.

     The specification of SHA1-IME differs  from  SHA-1  in  ONLY
     step (b) of section 7 "Computing the Message Digest" of FIPS
     PUB 180-1. This corresponds to step (b) of section 7 of this
     document.  Thus, replacing step (b) of section 7 of FIPS PUB
     180-1  by step (b) of section  7  of  the  current  document
     would  lead  to  a  correct implementation of SHA1-IME. Test
     Vectors for SHA1-IME are  provided  in  section  9.   It  is
     noteworthy  that  the description of SHA-1 in FIPS PUB 180-2
     is identical to the description of SHA-1 in FIPS PUB  180-1.
     A Reference Implementation is given in the appendix.



BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          3





Internet Draft                                           Nov 2005


     For a message of length < 2^64 bits, SHA1-IME produces a 160
     bit message digest.

2.  BIT STRINGS AND INTEGERS

     The  following  terminology  related  to  bit  strings   and
     integers will be used:

     a.    A hex digit is an element of the set {0, 1, ...  ,  9,
          A,  ... , F}. A hex digit is the representation of a 4-
          bit string.

     b.    A word equals a 32-bit string which may be represented
          as  a  sequence of 8 hex digits. To convert a word to 8
          hex digits each 4-bit string is converted  to  its  hex
          equivalent as described in (a) above.

     c.   An integer between 0 and 2^32  -  1  inclusive  may  be
          represented  as a word. The least significant four bits
          of the integer are represented by  the  right-most  hex
          digit of the word representation. If z is an integer, 0
          <= z < 2^64, then z = 2^32x + y where 0 <= 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 of words (X,Y).

     d.   block = 512-bit string. A block  may be represented  as
          a sequence of 16 words.

3.  OPERATIONS ON WORDS

     The following logical operators will be applied to words:

     a.
          X AND Y         =  bitwise logical "and" 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.

          NOT  X          =  bitwise logical "complement" of X.

     b.   The operation X + Y is defined as follows: words X  and
          Y represent integers x and y, where 0 <= x < 2^32 and 0
          <= y < 2^32. For positive integers n and m, let n mod m
          be the remainder upon dividing n by m. Compute z = (x +
          y) mod 2^32.




BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          4





Internet Draft                                           Nov 2005


          Then 0 <= z < 2^32. Convert z to a word, Z, and  define
          Z = X + Y.

     c.   The circular left shift operation ROLn(X),  where X  is
          a word  and n is an integer with 0 <= n^32, is defined
          by ROLn(X) = (X << n) OR (X >> 32-n). 
	  E.g. ROL21(A) = (A << 21) OR (A >> 11)

          In the above, X << n is obtained  as  follows:  discard
          the  left-most n bits of X and then pad the result with
          n zeroes on the right (the  result  will  still  be  32
          bits).  X >> n is obtained by discarding the right-most
          n bits of X and then padding the result with  n  zeroes
          on  the  left. Thus ROLn(X) is equivalent to a circular
          shift of X by n positions to the left.

4.  MESSAGE PADDING

     The SHA1-IME is used to compute a message digest for a  mes-
     sage  or data file that is provided as input. The message or
     data file should be considered  to  be  a  bit  string.  The
     length  of  the message is the number of bits in the message
     (the empty message has length 0). If the number of bits in a
     message is a multiple of 8, for compactness we can represent
     the message in hex. The purpose of  message  padding  is  to
     make the total length of a padded message a multiple of 512.
     The SHA1-IME sequentially processes blocks of 512 bits  when
     computing  the  message  digest. The following specifies how
     this padding shall be performed. As a summary,  a  "1"  fol-
     lowed by m "0"s followed by a 64-bit integer are appended to
     the end of the message to produce a padded message of length
     512 * n. The 64-bit integer is l, the length of the original
     message. The padded message is then processed by  the  SHA1-
     IME as n 512-bit blocks.

     Suppose a message has length l < 2^64. Before it is input to
     the SHA1-IME, the message is padded on the right as follows:

     a.   "1" is appended. Example: if the  original  message  is
          "01010000", this is padded to "010100001".

     b.   "0"s are appended. The number of "0"s  will  depend  on
          the original length of the message. The last 64 bits of
          the last 512-bit block are reserved for the length l of
          the  original  message.  Example:  Suppose the original
          message is the bit string

               01100001 01100010 01100011 01100100 01100101.



BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          5





Internet Draft                                           Nov 2005


          After step (a) this gives

               01100001 01100010 01100011 01100100 01100101 1.

          Since l = 40, the number of bits in the above is 41 and
          407  "0"s  are appended, making the total now 448. This
          gives (in hex)
               61626364 65800000 00000000 00000000
               00000000 00000000 00000000 00000000
               00000000 00000000 00000000 00000000
               00000000 00000000.

     c.   Obtain the 2-word representation of l,  the  number  of
          bits  in  the  original  message.  If l < 2^32 then the
          first word is all zeroes. Append these two words to the
          padded  message.  Example: Suppose the original message
          is as in (b). Then l = 40  (note  that  l  is  computed
          before  any padding). The two-word representation of 40
          is hex 00000000 00000028. Hence the final  padded  mes-
          sage is hex
               61626364 65800000 00000000 00000000
               00000000 00000000 00000000 00000000
               00000000 00000000 00000000 00000000
               00000000 00000000 00000000 00000028.

          The padded message will contain 16 * n words for some n
          >  0. The padded message is regarded as a sequence of n
          blocks M(1) , M(2), ... , M(n), where  each  M(i)  con-
          tains  16  words and M(1) contains the first characters
          (or bits) of the message.


5.

     A sequence of logical functions f_0, f_1,..., f_{79} is used
     in  the  SHA1-IME. Each f_t, 0 <= t <= 79, operates on three
     32-bit words B, C, D and produces a 32-bit word  as  output.
     f_t(B,C,D) is defined as follows: for words B, C, D,













BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          6





Internet Draft                                           Nov 2005


     f_t(B,C,D) = (B AND C) OR ((NOT B) AND D) ( 0 <= t <= 19)


     f_t(B,C,D) = B XOR C XOR D (20 <= t <= 39)


     f_t(B,C,D) = (B AND C) OR (B AND D) OR (C AND D) (40 <= t <= 59)


     f_t(B,C,D) = B XOR C XOR D (60 <= t <= 79).

6.  CONSTANTS USED

     A sequence of constant words K(0), K(1), ... , K(79) is used
     in the SHA1-IME. In hex these are given by

          K(t) = 5A827999 ( 0 <= t <= 19)

          K(t) = 6ED9EBA1 (20 <= t <= 39)

          K(t) = 8F1BBCDC (40 <= t <= 59)

          K(t) = CA62C1D6 (60 <= t <= 79).

7.  COMPUTING THE MESSAGE DIGEST

     The message digest is computed using the final  padded  mes-
     sage.  The  computation uses two buffers, each consisting of
     five 32-bit words, and a sequence of  eighty  32-bit  words.
     The  words of the first 5-word buffer are labeled A,B,C,D,E.
     The words of the second 5-word buffer are  labeled  H0,  H1,
     H2,  H3,  H4.  The words of the 80-word sequence are labeled
     W(0), W(1),..., W(79). A single word  buffer  TEMP  is  also
     employed.

     To generate the message digest,  the  16-word  blocks  M(1),
     M(2),...,  M(n) defined in Section 4 are processed in order.
     The processing of each M(i) involves 80 steps.

     Before processing any blocks, the {Hi}  are  initialized  as
     follows: in hex,

          H0 = 67452301

          H1 = EFCDAB89

          H2 = 98BADCFE




BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          7





Internet Draft                                           Nov 2005


          H3 = 10325476

          H4 = C3D2E1F0.

     Now M(1), M(2), ... , M(n) are processed. To  process  M(i),
     we proceed as follows:

     a.   Divide M(i) into 16 words  W(0),  W(1),  ...  ,  W(15),
          where W(0) is the left-most word.

     b.   For t = 16 to 35 let
          W(t) = (W(t-3) XOR W(t-8) XOR W(t- 14) XOR W(t-16)) XOR
                 ROL13(W(i-1) XOR W(i-2) XOR W(i-15)).

          For t = 36 to 79 let
          W(t) = (W(t-3) XOR W(t-8) XOR W(t- 14) XOR W(t-16)) XOR
                 ROL13(W(i-1) XOR W(i-2) XOR W(i-15) XOR W(i-20)).

c.   Let A = H0, B = H1, C = H2, D = H3, E = H4.

d.   For t = 0 to 79 do
             TEMP = ROL5(A) + f_t(B,C,D) + E + W(t) + K(t);
             E = D; D = C; C = ROL30(B); B = A; A = TEMP;

e.   Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, 
         H4 = H4 + E.

     After processing M(n), the message  digest  is  the  160-bit
     string represented by the 5 words H0 H1 H2 H3 H4.

8.  Intellectual Property Issues

     There is no intellectual property filed on SHA1-IME.

9.  TEST VECTORS

A.   Let the message be the ASCII  binary-coded  form  of  "abc",
     i.e.,
          01100001 01100010 01100011
     The Message Digest using  the above  SHA1-IME  specification
     is
          3eae191e 555c3d4c 314bfcd7 09875b6e 518003f5

B.   Let the message be the binary coded form of the ASCII string
     "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".
     The Message Digest is
          e4b0ece7 052e65ed 6f52b66b b23d9f3d 1dcc177a

C.   Let the message be the binary coded form of the ASCII string


BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          8





Internet Draft                                           Nov 2005


     which consists of 1,000,000 repetitions of "a".
     The Message digest is
          3c006258 340db10b a3682770 a4cb6f30 efbc265c

10.  Acknowledgments

     The authors would like to thank  Pankaj Rohatgi, Arjen Lens-
     tra, Ron Rivest, and Hugo Krawczyk for helpful comments. 
     Source code of SHA1 provided by D. Eastlake [DE] was modified
     to provide this reference code.

11.  References

[SHA1] FIPS PUB 180-1, "Secure Hash Standard", May 1993.

[SHA2] FIPS PUB 180-2, "Secure Hash Standard", Aug 2002.

[JP1] C. S. Jutla, A. C. Patthak, "A  Simple  and  Provably  Good
     Code   for  SHA  Message  Expansion",  IACR  eprint  archive
     2005/247, July 2005.

[JP2] C. S. Jutla, A. C. Patthak, "Is SHA-1 Conceptually Sound?",
     IACR eprint archive 2005/350, Oct 2005.

[WYY] X. Wang, H. Yu, Y.L. Yin, "Finding Collisions in  the  full
     SHA-1", Proc. Crypto 2005.

[DE] D. Eastlake, 3rd, P. Jones,  "US Secure Hash Algorithm 1 (SHA1)",
     RFC 3174, September 2001.

12.  Author's Address

             Uri Blumenthal
             Intel Corporation
             1515 State Route 10,
             3PY1-3.536
             Parsippany, NJ  07054
             USA
             Phone: +1.973.967.6446
             Email: uri DOT blumenthal AT intel DOT com

             Charanjit S. Jutla
             IBM T.J. Watson Research Center,
             Yorktown Heights, NY 10598-704.
             Phone: 914-784-7890
             Email: csjutla AT us DOT ibm DOT com











BJP        <draft-irtf-cfrg-sha1-ime-00.txt>          9





Internet Draft                                           Nov 2005


             Anindya Patthak
             Department of Computer Science,
             The University of Texas at Austin,
             1 University Station C0500
             Austin, TX 78712
             Phone: (512) 471-9572.
             Email: anindya AT cs DOT utexas DOT edu

     Comments should be sent to C. S. Jutla at his
     e-mail address above.

13. COPYRIGHT NOTICE

     Copyright (C) The Internet Society (2005).

     This document is subject to the rights,  licenses  and  res-
     trictions  contained  in  BCP  78,  and  except as set forth
     therein, the authors retain all their rights.

     This document and the information contained herein are  pro-
     vided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZA-
     TION HE/SHE REPRESENTS OR IS  SPONSORED  BY  (IF  ANY),  THE
     INTERNET  SOCIETY  AND  THE  INTERNET ENGINEERING TASK FORCE
     DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,  INCLUDING  BUT
     NOT  LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
     HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY  IMPLIED  WARRAN-
     TIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
























BJP        <draft-irtf-cfrg-sha1-ime-00.txt>         10



Appendix A. sha1ime.h

/*
 *  sha1ime.h
 *
 *  Description:
 *      This is the header file for code which implements the IME
 *      modification of Secure Hashing Algorithm 1 as defined in 
 *      FIPS PUB 180-1 and 180-2. 
 *
 *      Please read the file sha1ime.c for more information.
 *
 */

#ifndef _SHA1IME_H_
#define _SHA1IME_H_

#include <stdint.h>
/*
 * If you do not have the ISO standard stdint.h header file, then you
 * must typdef the following:
 *    name              meaning
 *  uint32_t         unsigned 32 bit integer
 *  uint8_t          unsigned 8 bit integer (i.e., unsigned char)
 *  int_least16_t    integer of >= 16 bits
 *
 */

#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
    shaSuccess = 0,
    shaNull,            /* Null pointer parameter */
    shaInputTooLong,    /* input data too long */
    shaStateError       /* called Input after Result */
};
#endif
#define SHA1IMEHashSize 20

/*
 *  This structure will hold context information for the SHA-1
 *  hashing operation
 */
typedef struct SHA1IMEContext
{
    uint32_t Intermediate_Hash[SHA1IMEHashSize/4]; /* Message Digest  */

    uint32_t Length_Low;            /* Message length in bits      */
    uint32_t Length_High;           /* Message length in bits      */

                               /* Index into message block array   */
    int_least16_t Message_Block_Index;
    uint8_t Message_Block[64];      /* 512-bit message blocks      */

    int Computed;               /* Is the digest computed?         */
    int Corrupted;             /* Is the message digest corrupted? */
} SHA1IMEContext;

/*
 *  Function Prototypes
 */

int SHA1IMEReset(  SHA1IMEContext *);
int SHA1IMEInput(  SHA1IMEContext *,
                const uint8_t *,
                unsigned int);
int SHA1IMEResult( SHA1IMEContext *,
                uint8_t Message_Digest[SHA1IMEHashSize]);

#endif


Appendix B. sha1ime.c

/*
 *  sha1ime.c
 *
 *  Description:
 *      This file implements the IME modification to Secure Hashing
 *      Algorithm 1 as defined in FIPS PUB 180-1 and 180-2.
 *
 *      The SHA1-IME, produces a 160-bit message digest for a given
 *      data stream.  It should take about 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 digest,
 *      when n is the digest size in bits.  Therefore, this
 *      algorithm can serve as a means of providing a
 *      "fingerprint" for a message.
 *
 *  Portability Issues:
 *      SHA1-IME is defined in terms of 32-bit "words".  This code
 *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
 *      bit unsigned integer types.  If your C compiler does not
 *      support 32 bit unsigned integers, this code is not
 *      appropriate.
 *
 *  Caveats:
 *      SHA1-IME like SHA-1, is designed to work with messages less
 *      than 2^64 bits long.  Although SHA1-IME allows a message digest
 *      to be generated for messages of any number of bits less than 2^64,
 *      this implementation only works with messages with a length that is
 *      a multiple of the size of an 8-bit character.
 *
 */

#include "sha1ime.h"

/*
 *  Define the SHA1-IME circular left shift macro
 */
#define SHA1IMECircularShift(bits,word) \
                (((word) << (bits)) | ((word) >> (32-(bits))))

/* Local Function Prototyptes */
void SHA1IMEPadMessage(SHA1IMEContext *);
void SHA1IMEProcessMessageBlock(SHA1IMEContext *);

/*
 *  SHA1IMEReset
 *
 *  Description:
 *      This function will initialize the SHA1IMEContext in
 *	preparation for computing a new SHA1-IME message digest.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to reset.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1IMEReset(SHA1IMEContext *context)
{
    if (!context)
    {
        return shaNull;
    }

    context->Length_Low             = 0;
    context->Length_High            = 0;
    context->Message_Block_Index    = 0;

    context->Intermediate_Hash[0]   = 0x67452301;
    context->Intermediate_Hash[1]   = 0xEFCDAB89;
    context->Intermediate_Hash[2]   = 0x98BADCFE;
    context->Intermediate_Hash[3]   = 0x10325476;
    context->Intermediate_Hash[4]   = 0xC3D2E1F0;

    context->Computed   = 0;
    context->Corrupted  = 0;

    return shaSuccess;
}

/*
 *  SHA1IMEResult
 *
 *  Description:
 *      This function will return the 160-bit message digest into the
 *      Message_Digest array  provided by the caller.
 *      NOTE: The first octet of hash is stored in the 0th element,
 *            the last octet of hash in the 19th element.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to use to calculate the SHA-1 hash.
 *      Message_Digest: [out]
 *          Where the digest is returned.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1IMEResult( SHA1IMEContext *context,
                   uint8_t Message_Digest[SHA1IMEHashSize])
{
    int i;

    if (!context || !Message_Digest)
    {
        return shaNull;
    }

    if (context->Corrupted)
    {
        return context->Corrupted;
    }

    if (!context->Computed)
    {
        SHA1IMEPadMessage(context);
        for(i=0; i<64; ++i)
        {
            /* message may be sensitive, clear it out */
            context->Message_Block[i] = 0;
        }
        context->Length_Low = 0;    /* and clear length */
        context->Length_High = 0;
        context->Computed = 1;

    }

    for(i = 0; i < SHA1IMEHashSize; ++i)
    {
        Message_Digest[i] = context->Intermediate_Hash[i>>2]
                            >> 8 * ( 3 - ( i & 0x03 ) );
    }

    return shaSuccess;
}

/*
 *  SHA1IMEInput
 *
 *  Description:
 *      This function accepts an array of octets as the next portion
 *      of the message.
 *
 *  Parameters:
 *      context: [in/out]
 *          The SHA1-IME context to update
 *      message_array: [in]
 *          An array of characters representing the next portion of
 *          the message.
 *      length: [in]
 *          The length of the message in message_array
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1IMEInput(    SHA1IMEContext    *context,
                     const uint8_t     *message_array,
                     unsigned          length)
{
    if (!length)
    {
        return shaSuccess;
    }

    if (!context || !message_array)
    {
        return shaNull;
    }

    if (context->Computed)
    {
        context->Corrupted = shaStateError;

        return shaStateError;
    }

    if (context->Corrupted)
    {
         return context->Corrupted;
    }
    while(length-- && !context->Corrupted)
    {
    context->Message_Block[context->Message_Block_Index++] =
                    (*message_array & 0xFF);

    context->Length_Low += 8;
    if (context->Length_Low == 0)
    {
        context->Length_High++;
        if (context->Length_High == 0)
        {
            /* Message is too long */
            context->Corrupted = 1;
        }
    }

    if (context->Message_Block_Index == 64)
    {
        SHA1IMEProcessMessageBlock(context);
    }

    message_array++;
    }

    return shaSuccess;
}

/*
 *  SHA1IMEProcessMessageBlock
 *
 *  Description:
 *      This function will process the next 512 bits of the message
 *      stored in the Message_Block array.
 *
 *  Parameters:
 *      None.
 *
 *  Returns:
 *      Nothing.
 *
 *  Comments:

 *      Many of the variable names in this code, especially the
 *      single character names, were used because those were the
 *      names used in the publication.
 *
 *
 */
void SHA1IMEProcessMessageBlock(SHA1IMEContext *context)
{
    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
                            0x5A827999,
                            0x6ED9EBA1,
                            0x8F1BBCDC,
                            0xCA62C1D6
                            };
    int           t;                 /* Loop counter                */
    uint32_t      temp;              /* Temporary word value        */
    uint32_t      W[80];             /* Word sequence               */
    uint32_t      A, B, C, D, E;     /* Word buffers                */

    /*
     *  Initialize the first 16 words in the array W
     */
    for(t = 0; t < 16; t++)
    {
        W[t] = context->Message_Block[t * 4] << 24;
        W[t] |= context->Message_Block[t * 4 + 1] << 16;
        W[t] |= context->Message_Block[t * 4 + 2] << 8;
        W[t] |= context->Message_Block[t * 4 + 3];
    }

    for(t = 16; t < 36; t++)
    {
       W[t] = (W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]) ^
              SHA1IMECircularShift(13, 
	           (W[t-1] ^ W[t-2] ^ W[t-15]));
    }
    for(t = 36; t < 80; t++)
    {
       W[t] = (W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]) ^
              SHA1IMECircularShift(13, 
		   (W[t-1] ^ W[t-2] ^ W[t-15] ^ W[t-20]));
    }

    A = context->Intermediate_Hash[0];
    B = context->Intermediate_Hash[1];
    C = context->Intermediate_Hash[2];
    D = context->Intermediate_Hash[3];
    E = context->Intermediate_Hash[4];

    for(t = 0; t < 20; t++)
    {
        temp =  SHA1IMECircularShift(5,A) +
                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
        E = D;
        D = C;
        C = SHA1IMECircularShift(30,B);

        B = A;
        A = temp;
    }

    for(t = 20; t < 40; t++)
    {
        temp = SHA1IMECircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
        E = D;
        D = C;
        C = SHA1IMECircularShift(30,B);
        B = A;
        A = temp;
    }

    for(t = 40; t < 60; t++)
    {
        temp = SHA1IMECircularShift(5,A) +
               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
        E = D;
        D = C;
        C = SHA1IMECircularShift(30,B);
        B = A;
        A = temp;
    }

    for(t = 60; t < 80; t++)
    {
        temp = SHA1IMECircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
        E = D;
        D = C;
        C = SHA1IMECircularShift(30,B);
        B = A;
        A = temp;
    }

    context->Intermediate_Hash[0] += A;
    context->Intermediate_Hash[1] += B;
    context->Intermediate_Hash[2] += C;
    context->Intermediate_Hash[3] += D;
    context->Intermediate_Hash[4] += E;

    context->Message_Block_Index = 0;
}

/*
 *  SHA1IMEPadMessage
 *

 *  Description:
 *      According to the standard, the message must be padded to an even
 *      512 bits.  The first padding bit must be a '1'.  The last 64
 *      bits represent the length of the original message.  All bits in
 *      between should be 0.  This function will pad the message
 *      according to those rules by filling the Message_Block array
 *      accordingly.  It will also call the ProcessMessageBlock function
 *      provided appropriately.  When it returns, it can be assumed that
 *      the message digest has been computed.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to pad
 *      ProcessMessageBlock: [in]
 *          The appropriate SHA*ProcessMessageBlock function
 *  Returns:
 *      Nothing.
 *
 */

void SHA1IMEPadMessage(SHA1IMEContext *context)
{
    /*
     *  Check to see if the current message block is too small to hold
     *  the initial padding bits and length.  If so, we will pad the
     *  block, process it, and then continue padding into a second
     *  block.
     */
    if (context->Message_Block_Index > 55)
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 64)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }

        SHA1IMEProcessMessageBlock(context);

        while(context->Message_Block_Index < 56)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }
    else
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 56)
        {

            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }

    /*
     *  Store the message length as the last 8 octets
     */
    context->Message_Block[56] = context->Length_High >> 24;
    context->Message_Block[57] = context->Length_High >> 16;
    context->Message_Block[58] = context->Length_High >> 8;
    context->Message_Block[59] = context->Length_High;
    context->Message_Block[60] = context->Length_Low >> 24;
    context->Message_Block[61] = context->Length_Low >> 16;
    context->Message_Block[62] = context->Length_Low >> 8;
    context->Message_Block[63] = context->Length_Low;

    SHA1IMEProcessMessageBlock(context);
}


Appendix C. sha1ime_test.c

/*
 *  sha1ime_test.c
 *
 *  Description:
 *      This file will exercise the SHA-1 code performing the three
 *      tests documented in FIPS PUB 180-1 plus one which calls
 *      SHA1Input with an exact multiple of 512 bits, plus a few
 *      error test checks.
 *
 *  Portability Issues:
 *      None.
 *
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sha1ime.h"

/*
 *  Define patterns for testing
 */
#define TEST1   "abc"
#define TEST2a  "abcdbcdecdefdefgefghfghighijhi"

#define TEST2b  "jkijkljklmklmnlmnomnopnopq"
#define TEST2   TEST2a TEST2b
#define TEST3   "a"
#define TEST4a  "01234567012345670123456701234567"
#define TEST4b  "01234567012345670123456701234567"
    /* an exact multiple of 512 bits */
#define TEST4   TEST4a TEST4b
char *testarray[4] =
{
    TEST1,
    TEST2,
    TEST3,
    TEST4
};
long int repeatcount[4] = { 1, 1, 1000000, 10 };
char *resultarray[4] = {
    "3E AE 19 1E 55 5C 3D 4C 31 4B FC D7 09 87 5B 6E 51 80 03 F5", 
    "E4 B0 EC E7 05 2E 65 ED 6F 52 B6 6B B2 3D 9F 3D 1D CC 17 7A",
    "3C 00 62 58 34 0D B1 0B A3 68 27 70 A4 CB 6F 30 EF BC 26 5C",
    "11 FD 36 AA 29 F6 9C 4C 90 4D 92 2C A3 7B FB C2 AA 63 5E 27"
};

int main()
{
    SHA1IMEContext sha;
    int i, j, err;
    uint8_t Message_Digest[20];

    /*
     *  Perform SHA1-IME tests
     */
    for(j = 0; j < 4; ++j)
    {
        printf( "\nTest %d: %d, '%s'\n",
                j+1,
                repeatcount[j],
                testarray[j]);

        err = SHA1IMEReset(&sha);
        if (err)
        {
            fprintf(stderr, "SHA1IMEReset Error %d.\n", err );
            break;    /* out of for j loop */
        }

        for(i = 0; i < repeatcount[j]; ++i)
        {

            err = SHA1IMEInput(&sha,
                  (const unsigned char *) testarray[j],
                  strlen(testarray[j]));
            if (err)
            {
                fprintf(stderr, "SHA1IMEInput Error %d.\n", err );
                break;    /* out of for i loop */
            }
        }

        err = SHA1IMEResult(&sha, Message_Digest);
        if (err)
        {
            fprintf(stderr,
            "SHA1IMEResult Error %d, could not compute message digest.\n",
            err );
        }
        else
        {
            printf("\t");
            for(i = 0; i < 20 ; ++i)
            {
                printf("%02X ", Message_Digest[i]);
            }
            printf("\n");
        }
        printf("Should match:\n");
        printf("\t%s\n", resultarray[j]);
    }

    /* Test some error returns */
    err = SHA1IMEInput(&sha,(const unsigned char *) testarray[1], 1);
    printf ("\nError %d. Should be %d.\n", err, shaStateError );
    err = SHA1IMEReset(0);
    printf ("\nError %d. Should be %d.\n", err, shaNull );
    return 0;
}

_______________________________________________
Cfrg mailing list
Cfrg at ietf.org
https://www1.ietf.org/mailman/listinfo/cfrg