Thread: [patch 3/9] Add support for SHA224

[patch 3/9] Add support for SHA224

From
Marko Kreen
Date:
SHA224 is cut-down SHA256 with different init vector,
let the sha2.c provide it also.

New revision of DSA standard includes SHA224, thus also upcoming
update to RFC2440 (OpenPGP).

Therefore, it is good to have it available.


Index: pgsql/contrib/pgcrypto/sha2.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/sha2.c
--- pgsql/contrib/pgcrypto/sha2.c
*************** static const uint32 K256[64] = {
*** 189,194 ****
--- 189,206 ----
      0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
  };

+ /* Initial hash value H for SHA-224: */
+ static const uint32 sha224_initial_hash_value[8] = {
+     0xc1059ed8UL,
+     0x367cd507UL,
+     0x3070dd17UL,
+     0xf70e5939UL,
+     0xffc00b31UL,
+     0x68581511UL,
+     0x64f98fa7UL,
+     0xbefa4fa4UL
+ };
+
  /* Initial hash value H for SHA-256: */
  static const uint32 sha256_initial_hash_value[8] = {
      0x6a09e667UL,
*************** SHA256_Update(SHA256_CTX * context, cons
*** 521,575 ****
      usedspace = freespace = 0;
  }

! void
! SHA256_Final(uint8 digest[], SHA256_CTX * context)
  {
      unsigned int usedspace;

!     /* If no digest buffer is passed, we don't bother doing this: */
!     if (digest != NULL)
!     {
!         usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
  #if BYTE_ORDER == LITTLE_ENDIAN
!         /* Convert FROM host byte order */
!         REVERSE64(context->bitcount, context->bitcount);
  #endif
!         if (usedspace > 0)
!         {
!             /* Begin padding with a 1 bit: */
!             context->buffer[usedspace++] = 0x80;
!
!             if (usedspace <= SHA256_SHORT_BLOCK_LENGTH)
!             {
!                 /* Set-up for the last transform: */
!                 memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace);
!             }
!             else
!             {
!                 if (usedspace < SHA256_BLOCK_LENGTH)
!                 {
!                     memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace);
!                 }
!                 /* Do second-to-last transform: */
!                 SHA256_Transform(context, context->buffer);

!                 /* And set-up for the last transform: */
!                 memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
!             }
          }
          else
          {
!             /* Set-up for the last transform: */
!             memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);

!             /* Begin padding with a 1 bit: */
!             *context->buffer = 0x80;
          }
!         /* Set the bit count: */
!         *(uint64 *) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;

!         /* Final transform: */
!         SHA256_Transform(context, context->buffer);

  #if BYTE_ORDER == LITTLE_ENDIAN
          {
--- 533,593 ----
      usedspace = freespace = 0;
  }

! static void
! SHA256_Last(SHA256_CTX *context)
  {
      unsigned int usedspace;

!     usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
  #if BYTE_ORDER == LITTLE_ENDIAN
!     /* Convert FROM host byte order */
!     REVERSE64(context->bitcount, context->bitcount);
  #endif
!     if (usedspace > 0)
!     {
!         /* Begin padding with a 1 bit: */
!         context->buffer[usedspace++] = 0x80;

!         if (usedspace <= SHA256_SHORT_BLOCK_LENGTH)
!         {
!             /* Set-up for the last transform: */
!             memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace);
          }
          else
          {
!             if (usedspace < SHA256_BLOCK_LENGTH)
!             {
!                 memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace);
!             }
!             /* Do second-to-last transform: */
!             SHA256_Transform(context, context->buffer);

!             /* And set-up for the last transform: */
!             memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
          }
!     }
!     else
!     {
!         /* Set-up for the last transform: */
!         memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
!
!         /* Begin padding with a 1 bit: */
!         *context->buffer = 0x80;
!     }
!     /* Set the bit count: */
!     *(uint64 *) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;

!     /* Final transform: */
!     SHA256_Transform(context, context->buffer);
! }
!
! void
! SHA256_Final(uint8 digest[], SHA256_CTX * context)
! {
!     /* If no digest buffer is passed, we don't bother doing this: */
!     if (digest != NULL)
!     {
!         SHA256_Last(context);

  #if BYTE_ORDER == LITTLE_ENDIAN
          {
*************** SHA256_Final(uint8 digest[], SHA256_CTX
*** 587,593 ****

      /* Clean up state data: */
      memset(context, 0, sizeof(*context));
-     usedspace = 0;
  }


--- 605,610 ----
*************** SHA384_Final(uint8 digest[], SHA384_CTX
*** 963,965 ****
--- 980,1026 ----
      /* Zero out state data */
      memset(context, 0, sizeof(*context));
  }
+
+ /*** SHA-224: *********************************************************/
+ void
+ SHA224_Init(SHA224_CTX * context)
+ {
+     if (context == NULL)
+         return;
+     memcpy(context->state, sha224_initial_hash_value, SHA256_DIGEST_LENGTH);
+     memset(context->buffer, 0, SHA256_BLOCK_LENGTH);
+     context->bitcount = 0;
+ }
+
+ void
+ SHA224_Update(SHA224_CTX * context, const uint8 *data, size_t len)
+ {
+     SHA256_Update((SHA256_CTX *) context, data, len);
+ }
+
+ void
+ SHA224_Final(uint8 digest[], SHA224_CTX * context)
+ {
+     /* If no digest buffer is passed, we don't bother doing this: */
+     if (digest != NULL)
+     {
+         SHA256_Last(context);
+
+ #if BYTE_ORDER == LITTLE_ENDIAN
+         {
+             /* Convert TO host byte order */
+             int            j;
+
+             for (j = 0; j < 8; j++)
+             {
+                 REVERSE32(context->state[j], context->state[j]);
+             }
+         }
+ #endif
+         memcpy(digest, context->state, SHA224_DIGEST_LENGTH);
+     }
+
+     /* Clean up state data: */
+     memset(context, 0, sizeof(*context));
+ }
+
Index: pgsql/contrib/pgcrypto/sha2.h
===================================================================
*** pgsql.orig/contrib/pgcrypto/sha2.h
--- pgsql/contrib/pgcrypto/sha2.h
***************
*** 49,55 ****
  #define SHA512_Update pg_SHA512_Update
  #define SHA512_Final pg_SHA512_Final

! /*** SHA-256/384/512 Various Length Definitions ***********************/
  #define SHA256_BLOCK_LENGTH        64
  #define SHA256_DIGEST_LENGTH        32
  #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
--- 49,58 ----
  #define SHA512_Update pg_SHA512_Update
  #define SHA512_Final pg_SHA512_Final

! /*** SHA-224/256/384/512 Various Length Definitions ***********************/
! #define SHA224_BLOCK_LENGTH        64
! #define SHA224_DIGEST_LENGTH        28
! #define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
  #define SHA256_BLOCK_LENGTH        64
  #define SHA256_DIGEST_LENGTH        32
  #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
*************** typedef struct _SHA512_CTX
*** 75,82 ****
--- 78,90 ----
      uint8        buffer[SHA512_BLOCK_LENGTH];
  }    SHA512_CTX;

+ typedef SHA256_CTX SHA224_CTX;
  typedef SHA512_CTX SHA384_CTX;

+ void        SHA224_Init(SHA224_CTX *);
+ void        SHA224_Update(SHA224_CTX *, const uint8 *, size_t);
+ void        SHA224_Final(uint8[SHA224_DIGEST_LENGTH], SHA224_CTX *);
+
  void        SHA256_Init(SHA256_CTX *);
  void        SHA256_Update(SHA256_CTX *, const uint8 *, size_t);
  void        SHA256_Final(uint8[SHA256_DIGEST_LENGTH], SHA256_CTX *);
Index: pgsql/contrib/pgcrypto/internal.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/internal.c
--- pgsql/contrib/pgcrypto/internal.c
***************
*** 77,82 ****
--- 77,83 ----

  static void init_md5(PX_MD * h);
  static void init_sha1(PX_MD * h);
+ static void init_sha224(PX_MD * h);
  static void init_sha256(PX_MD * h);
  static void init_sha384(PX_MD * h);
  static void init_sha512(PX_MD * h);
*************** static const struct int_digest
*** 91,96 ****
--- 92,98 ----
              int_digest_list[] = {
      {"md5", init_md5},
      {"sha1", init_sha1},
+     {"sha224", init_sha224},
      {"sha256", init_sha256},
      {"sha384", init_sha384},
      {"sha512", init_sha512},
*************** int_sha1_free(PX_MD * h)
*** 193,198 ****
--- 195,248 ----
      px_free(h);
  }

+ /* SHA224 */
+
+ static unsigned
+ int_sha224_len(PX_MD * h)
+ {
+     return SHA224_DIGEST_LENGTH;
+ }
+
+ static unsigned
+ int_sha224_block_len(PX_MD * h)
+ {
+     return SHA224_BLOCK_LENGTH;
+ }
+
+ static void
+ int_sha224_update(PX_MD * h, const uint8 *data, unsigned dlen)
+ {
+     SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
+
+     SHA224_Update(ctx, data, dlen);
+ }
+
+ static void
+ int_sha224_reset(PX_MD * h)
+ {
+     SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
+
+     SHA224_Init(ctx);
+ }
+
+ static void
+ int_sha224_finish(PX_MD * h, uint8 *dst)
+ {
+     SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
+
+     SHA224_Final(dst, ctx);
+ }
+
+ static void
+ int_sha224_free(PX_MD * h)
+ {
+     SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
+
+     memset(ctx, 0, sizeof(*ctx));
+     px_free(ctx);
+     px_free(h);
+ }
+
  /* SHA256 */

  static unsigned
*************** init_sha1(PX_MD * md)
*** 380,385 ****
--- 430,455 ----
  }

  static void
+ init_sha224(PX_MD * md)
+ {
+     SHA224_CTX *ctx;
+
+     ctx = px_alloc(sizeof(*ctx));
+     memset(ctx, 0, sizeof(*ctx));
+
+     md->p.ptr = ctx;
+
+     md->result_size = int_sha224_len;
+     md->block_size = int_sha224_block_len;
+     md->reset = int_sha224_reset;
+     md->update = int_sha224_update;
+     md->finish = int_sha224_finish;
+     md->free = int_sha224_free;
+
+     md->reset(md);
+ }
+
+ static void
  init_sha256(PX_MD * md)
  {
      SHA256_CTX *ctx;
Index: pgsql/contrib/pgcrypto/expected/sha2.out
===================================================================
*** pgsql.orig/contrib/pgcrypto/expected/sha2.out
--- pgsql/contrib/pgcrypto/expected/sha2.out
***************
*** 1,6 ****
--- 1,37 ----
  --
  -- SHA2 family
  --
+ -- SHA224
+ SELECT encode(digest('', 'sha224'), 'hex');
+                           encode
+ ----------------------------------------------------------
+  d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f
+ (1 row)
+
+ SELECT encode(digest('a', 'sha224'), 'hex');
+                           encode
+ ----------------------------------------------------------
+  abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5
+ (1 row)
+
+ SELECT encode(digest('abc', 'sha224'), 'hex');
+                           encode
+ ----------------------------------------------------------
+  23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7
+ (1 row)
+
+ SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha224'), 'hex');
+                           encode
+ ----------------------------------------------------------
+  75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525
+ (1 row)
+
+ SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha224'),
'hex');
+                           encode
+ ----------------------------------------------------------
+  b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e
+ (1 row)
+
  -- SHA256
  SELECT encode(digest('', 'sha256'), 'hex');
                                encode
Index: pgsql/contrib/pgcrypto/sql/sha2.sql
===================================================================
*** pgsql.orig/contrib/pgcrypto/sql/sha2.sql
--- pgsql/contrib/pgcrypto/sql/sha2.sql
***************
*** 2,7 ****
--- 2,14 ----
  -- SHA2 family
  --

+ -- SHA224
+ SELECT encode(digest('', 'sha224'), 'hex');
+ SELECT encode(digest('a', 'sha224'), 'hex');
+ SELECT encode(digest('abc', 'sha224'), 'hex');
+ SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha224'), 'hex');
+ SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha224'),
'hex');
+
  -- SHA256
  SELECT encode(digest('', 'sha256'), 'hex');
  SELECT encode(digest('a', 'sha256'), 'hex');
Index: pgsql/contrib/pgcrypto/README.pgcrypto
===================================================================
*** pgsql.orig/contrib/pgcrypto/README.pgcrypto
--- pgsql/contrib/pgcrypto/README.pgcrypto
*************** There are some other differences with an
*** 49,55 ****
  ----------------------------------------------------
   MD5                          yes       yes
   SHA1                         yes       yes
!  SHA256/384/512               yes       since 0.9.8
   Any other digest algo        no        yes (1)
   Blowfish                     yes       yes
   AES                          yes       yes (2)
--- 49,55 ----
  ----------------------------------------------------
   MD5                          yes       yes
   SHA1                         yes       yes
!  SHA224/256/384/512           yes       since 0.9.8
   Any other digest algo        no        yes (1)
   Blowfish                     yes       yes
   AES                          yes       yes (2)

--