From e648dc1623a4aa23d4113448b0ad6defa75cdfca Mon Sep 17 00:00:00 2001 From: millert <> Date: Mon, 15 Apr 2013 15:54:17 +0000 Subject: [PATCH] SHA-224 is to SHA-256 as SHA-384 is to SHA-512. It was added in a later revision of FIPS-180. OK miod@ jmc@ guenther@ djm@ --- src/include/sha2.h | 24 +++++++++++- src/lib/libc/hash/Makefile.inc | 12 +++++- src/lib/libc/hash/sha2.3 | 27 ++++++++++++-- src/lib/libc/hash/sha2.c | 67 +++++++++++++++++++++++++++++----- 4 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/include/sha2.h b/src/include/sha2.h index d85aabc7..065c30d1 100644 --- a/src/include/sha2.h +++ b/src/include/sha2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sha2.h,v 1.8 2012/12/05 23:19:57 deraadt Exp $ */ +/* $OpenBSD: sha2.h,v 1.9 2013/04/15 15:54:17 millert Exp $ */ /* * FILE: sha2.h @@ -39,6 +39,9 @@ /*** SHA-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) @@ -50,7 +53,7 @@ #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -/*** SHA-256/384/512 Context Structure *******************************/ +/*** SHA-224/256/384/512 Context Structure *******************************/ typedef struct _SHA2_CTX { union { u_int32_t st32[8]; @@ -61,6 +64,23 @@ typedef struct _SHA2_CTX { } SHA2_CTX; __BEGIN_DECLS +void SHA224Init(SHA2_CTX *); +void SHA224Transform(u_int32_t state[8], const u_int8_t [SHA224_BLOCK_LENGTH]); +void SHA224Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA224Pad(SHA2_CTX *); +void SHA224Final(u_int8_t [SHA224_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA224_DIGEST_LENGTH))); +char *SHA224End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA224_DIGEST_STRING_LENGTH))); + void SHA256Init(SHA2_CTX *); void SHA256Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]); void SHA256Update(SHA2_CTX *, const u_int8_t *, size_t) diff --git a/src/lib/libc/hash/Makefile.inc b/src/lib/libc/hash/Makefile.inc index a53bdf3b..f20314c0 100644 --- a/src/lib/libc/hash/Makefile.inc +++ b/src/lib/libc/hash/Makefile.inc @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile.inc,v 1.18 2008/09/06 12:00:19 djm Exp $ +# $OpenBSD: Makefile.inc,v 1.19 2013/04/15 15:54:17 millert Exp $ # hash functions .PATH: ${LIBCSRCDIR}/hash -HELPER= md4hl.c md5hl.c rmd160hl.c sha1hl.c sha256hl.c sha384hl.c sha512hl.c +HELPER= md4hl.c md5hl.c rmd160hl.c sha1hl.c sha224hl.c sha256hl.c sha384hl.c sha512hl.c SRCS+= md4.c md5.c rmd160.c sha1.c sha2.c ${HELPER} MAN+= md4.3 md5.3 rmd160.3 sha1.3 sha2.3 @@ -19,6 +19,9 @@ MLINKS+=rmd160.3 RMD160FileChunk.3 rmd160.3 RMD160Pad.3 rmd160.3 RMD160Data.3 MLINKS+=sha1.3 SHA1Transform.3 sha1.3 SHA1Init.3 sha1.3 SHA1Final.3 MLINKS+=sha1.3 SHA1Update.3 sha1.3 SHA1End.3 sha1.3 SHA1File.3 MLINKS+=sha1.3 SHA1FileChunk.3 sha1.3 SHA1Pad.3 sha1.3 SHA1Data.3 +MLINKS+=sha2.3 SHA224Init.3 sha2.3 SHA224Update.3 sha2.3 SHA224Pad.3 +MLINKS+=sha2.3 SHA224Final.3 sha2.3 SHA224Transform.3 sha2.3 SHA224End.3 +MLINKS+=sha2.3 SHA224File.3 sha2.3 SHA224FileChunk.3 sha2.3 SHA224Data.3 MLINKS+=sha2.3 SHA256Init.3 sha2.3 SHA256Update.3 sha2.3 SHA256Pad.3 MLINKS+=sha2.3 SHA256Final.3 sha2.3 SHA256Transform.3 sha2.3 SHA256End.3 MLINKS+=sha2.3 SHA256File.3 sha2.3 SHA256FileChunk.3 sha2.3 SHA256Data.3 @@ -52,6 +55,11 @@ rmd160hl.c: helper.c sha1hl.c: helper.c sed -e 's/hashinc/sha1.h/g' -e 's/HASH/SHA1/g' $> > $@ +sha224hl.c: helper.c + sed -e 's/hashinc/sha2.h/g' \ + -e 's/HASH/SHA224/g' \ + -e 's/SHA[0-9][0-9][0-9]_CTX/SHA2_CTX/g' $> > $@ + sha256hl.c: helper.c sed -e 's/hashinc/sha2.h/g' \ -e 's/HASH/SHA256/g' \ diff --git a/src/lib/libc/hash/sha2.3 b/src/lib/libc/hash/sha2.3 index f617cc78..f267b438 100644 --- a/src/lib/libc/hash/sha2.3 +++ b/src/lib/libc/hash/sha2.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sha2.3,v 1.17 2012/09/07 23:11:51 tedu Exp $ +.\" $OpenBSD: sha2.3,v 1.18 2013/04/15 15:54:17 millert Exp $ .\" .\" Copyright (c) 2003, 2004 Todd C. Miller .\" @@ -20,7 +20,7 @@ .\" .\" See http://www.nist.gov/sha/ for the detailed standard .\" -.Dd $Mdocdate: September 7 2012 $ +.Dd $Mdocdate: April 15 2013 $ .Dt SHA2 3 .Os .Sh NAME @@ -38,6 +38,24 @@ .Fd #include .Fd #include .Ft void +.Fn SHA224Init "SHA2_CTX *context" +.Ft void +.Fn SHA224Update "SHA2_CTX *context" "const u_int8_t *data" "size_t len" +.Ft void +.Fn SHA224Pad "SHA2_CTX *context" +.Ft void +.Fn SHA224Final "u_int8_t digest[SHA224_DIGEST_LENGTH]" "SHA2_CTX *context" +.Ft void +.Fn SHA224Transform "u_int32_t state[8]" "const u_int8_t buffer[SHA224_BLOCK_LENGTH]" +.Ft "char *" +.Fn SHA224End "SHA2_CTX *context" "char *buf" +.Ft "char *" +.Fn SHA224File "const char *filename" "char *buf" +.Ft "char *" +.Fn SHA224FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length" +.Ft "char *" +.Fn SHA224Data "const u_int8_t *data" "size_t len" "char *buf" +.Ft void .Fn SHA256Init "SHA2_CTX *context" .Ft void .Fn SHA256Update "SHA2_CTX *context" "const u_int8_t *data" "size_t len" @@ -98,7 +116,7 @@ The SHA2 functions are used to generate a condensed representation of a message called a message digest, suitable for use as a digital signature. There are three families of functions, with names corresponding to the number of bits in the resulting message digest. -The SHA-256 functions are limited to processing a message of less +The SHA-224 and SHA-256 functions are limited to processing a message of less than 2^64 bits as input. The SHA-384 and SHA-512 functions can process a message of at most 2^128 - 1 bits as input. @@ -106,7 +124,7 @@ bits as input. The SHA2 functions are considered to be more secure than the .Xr sha1 3 functions with which they share a similar interface. -The 256, 384, and 512-bit versions of SHA2 share the same interface. +The 224, 256, 384, and 512-bit versions of SHA2 share the same interface. For brevity, only the 256-bit variants are described below. .Pp The @@ -204,6 +222,7 @@ functions the .Ar buf parameter should either be a string large enough to hold the resulting digest (e.g.\& +.Ev SHA224_DIGEST_STRING_LENGTH , .Ev SHA256_DIGEST_STRING_LENGTH , .Ev SHA384_DIGEST_STRING_LENGTH , or diff --git a/src/lib/libc/hash/sha2.c b/src/lib/libc/hash/sha2.c index c6d2d46b..f6b98fe2 100644 --- a/src/lib/libc/hash/sha2.c +++ b/src/lib/libc/hash/sha2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sha2.c,v 1.13 2009/04/15 00:55:52 djm Exp $ */ +/* $OpenBSD: sha2.c,v 1.14 2013/04/15 15:54:17 millert Exp $ */ /* * FILE: sha2.c @@ -53,7 +53,7 @@ * */ -/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/*** SHA-224/256/384/512 Machine Architecture Definitions *****************/ /* * BYTE_ORDER NOTE: * @@ -86,8 +86,9 @@ #endif -/*** SHA-256/384/512 Various Length Definitions ***********************/ +/*** SHA-224/256/384/512 Various Length Definitions ***********************/ /* NOTE: Most of these are in sha2.h */ +#define SHA224_SHORT_BLOCK_LENGTH (SHA224_BLOCK_LENGTH - 8) #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) @@ -140,22 +141,22 @@ * Bit shifting and rotation (used by the six SHA-XYZ logical functions: * * NOTE: The naming of R and S appears backwards here (R is a SHIFT and - * S is a ROTATION) because the SHA-256/384/512 description document + * S is a ROTATION) because the SHA-224/256/384/512 description document * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this * same "backwards" definition. */ -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +/* Shift-right (used in SHA-224, SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) -/* 32-bit Rotate-right (used in SHA-256): */ +/* 32-bit Rotate-right (used in SHA-224 and SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) -/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +/* Two of six logical functions used in SHA-224, SHA-256, SHA-384, and SHA-512: */ #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -/* Four of six logical functions used in SHA-256: */ +/* Four of six logical functions used in SHA-224 and SHA-256: */ #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) @@ -169,7 +170,7 @@ /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ -/* Hash constant words K for SHA-256: */ +/* Hash constant words K for SHA-224 and SHA-256: */ const static u_int32_t K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, @@ -189,6 +190,18 @@ const static u_int32_t K256[64] = { 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; +/* Initial hash value H for SHA-224: */ +const static u_int32_t sha224_initial_hash_value[8] = { + 0xc1059ed8UL, + 0x367cd507UL, + 0x3070dd17UL, + 0xf70e5939UL, + 0xffc00b31UL, + 0x68581511UL, + 0x64f98fa7UL, + 0xbefa4fa4UL +}; + /* Initial hash value H for SHA-256: */ const static u_int32_t sha256_initial_hash_value[8] = { 0x6a09e667UL, @@ -269,6 +282,42 @@ const static u_int64_t sha512_initial_hash_value[8] = { 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL }; + +/*** SHA-224: *********************************************************/ +void +SHA224Init(SHA2_CTX *context) +{ + if (context == NULL) + return; + memcpy(context->state.st32, sha224_initial_hash_value, + sizeof(sha224_initial_hash_value)); + memset(context->buffer, 0, sizeof(context->buffer)); + context->bitcount[0] = 0; +} + +__weak_alias(SHA224Transform, SHA256Transform); +__weak_alias(SHA224Update, SHA256Update); +__weak_alias(SHA224Pad, SHA256Pad); + +void +SHA224Final(u_int8_t digest[SHA224_DIGEST_LENGTH], SHA2_CTX *context) +{ + SHA224Pad(context); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != NULL) { +#if BYTE_ORDER == LITTLE_ENDIAN + int i; + + /* Convert TO host byte order */ + for (i = 0; i < 7; i++) + BE_32_TO_8(digest + i * 4, context->state.st32[i]); +#else + memcpy(digest, context->state.st32, SHA224_DIGEST_LENGTH); +#endif + memset(context, 0, sizeof(*context)); + } +} #endif /* SHA256_ONLY */ /*** SHA-256: *********************************************************/