Browse Source

Add sha2 routines based on code by Aaron D. Gifford with minor

massaging and a man page by me.  I used the phk-derived stuff for
sha2hl.c instead of Aaron's for consistency with our other hash
routines.
OPENBSD_3_4
millert 21 years ago
parent
commit
7d1570f34c
5 changed files with 1401 additions and 6 deletions
  1. +92
    -0
      src/include/sha2.h
  2. +12
    -6
      src/lib/libc/hash/Makefile.inc
  3. +226
    -0
      src/lib/libc/hash/sha2.3
  4. +895
    -0
      src/lib/libc/hash/sha2.c
  5. +176
    -0
      src/lib/libc/hash/sha2hl.c

+ 92
- 0
src/include/sha2.h View File

@ -0,0 +1,92 @@
/* $OpenBSD: sha2.h,v 1.1 2003/05/08 23:34:55 millert Exp $ */
/*
* FILE: sha2.h
* AUTHOR: Aaron D. Gifford <me@aarongifford.com>
*
* Copyright (c) 2000-2001, Aaron D. Gifford
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
*/
#ifndef _SHA2_H
#define _SHA2_H
/*** 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)
#define SHA384_BLOCK_LENGTH 128
#define SHA384_DIGEST_LENGTH 48
#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
#define SHA512_BLOCK_LENGTH 128
#define SHA512_DIGEST_LENGTH 64
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
/*** SHA-256/384/512 Context Structures *******************************/
typedef struct _SHA256_CTX {
u_int32_t state[8];
u_int64_t bitcount;
u_int8_t buffer[SHA256_BLOCK_LENGTH];
} SHA256_CTX;
typedef struct _SHA512_CTX {
u_int64_t state[8];
u_int64_t bitcount[2];
u_int8_t buffer[SHA512_BLOCK_LENGTH];
} SHA512_CTX;
typedef SHA512_CTX SHA384_CTX;
#include <sys/cdefs.h>
__BEGIN_DECLS
void SHA256_Init(SHA256_CTX *);
void SHA256_Update(SHA256_CTX *, const u_int8_t *, size_t);
void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX *);
char *SHA256_End(SHA256_CTX *, char[SHA256_DIGEST_STRING_LENGTH]);
char *SHA256_File(char *, char *);
char *SHA256_Data(const u_int8_t *, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
void SHA384_Init(SHA384_CTX *);
void SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t);
void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX *);
char *SHA384_End(SHA384_CTX *, char[SHA384_DIGEST_STRING_LENGTH]);
char *SHA384_File(char *, char *);
char *SHA384_Data(const u_int8_t *, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
void SHA512_Init(SHA512_CTX *);
void SHA512_Update(SHA512_CTX *, const u_int8_t *, size_t);
void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX *);
char *SHA512_End(SHA512_CTX *, char[SHA512_DIGEST_STRING_LENGTH]);
char *SHA512_File(char *, char *);
char *SHA512_Data(const u_int8_t *, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
__END_DECLS
#endif /* _SHA2_H */

+ 12
- 6
src/lib/libc/hash/Makefile.inc View File

@ -1,13 +1,19 @@
# $OpenBSD: Makefile.inc,v 1.13 2003/01/08 19:53:59 millert Exp $
# $OpenBSD: Makefile.inc,v 1.14 2003/05/08 23:34:55 millert Exp $
# hash functions # hash functions
.PATH: ${LIBCSRCDIR}/hash .PATH: ${LIBCSRCDIR}/hash
SRCS+= sha1.c sha1hl.c rmd160.c rmd160hl.c
MAN+= sha1.3 rmd160.3
MLINKS+=sha1.3 SHA1Init.3 sha1.3 SHA1Update.3 sha1.3 SHA1Final.3
MLINKS+=sha1.3 SHA1End.3 sha1.3 SHA1File.3 sha1.3 SHA1Data.3
MLINKS+=sha1.3 SHA1Transform.3
SRCS+= rmd160.c rmd160hl.c sha1.c sha1hl.c sha2.c sha2hl.c
MAN+= rmd160.3 sha1.3 sha2.3
MLINKS+=rmd160.3 RMD160Init.3 rmd160.3 RMD160Update.3 rmd160.3 RMD160Final.3 MLINKS+=rmd160.3 RMD160Init.3 rmd160.3 RMD160Update.3 rmd160.3 RMD160Final.3
MLINKS+=rmd160.3 RMD160End.3 rmd160.3 RMD160File.3 rmd160.3 RMD160Data.3 MLINKS+=rmd160.3 RMD160End.3 rmd160.3 RMD160File.3 rmd160.3 RMD160Data.3
MLINKS+=rmd160.3 RMD160Transform.3 MLINKS+=rmd160.3 RMD160Transform.3
MLINKS+=sha1.3 SHA1Init.3 sha1.3 SHA1Update.3 sha1.3 SHA1Final.3
MLINKS+=sha1.3 SHA1End.3 sha1.3 SHA1File.3 sha1.3 SHA1Data.3
MLINKS+=sha1.3 SHA1Transform.3
MLINKS+=sha2.3 SHA256_Init.3 sha2.3 SHA256_Update.3 sha2.3 SHA256_Final.3
MLINKS+=sha2.3 SHA256_End.3 sha2.3 SHA256_File.3 sha2.3 SHA256_Data.3
MLINKS+=sha2.3 SHA384_Init.3 sha2.3 SHA384_Update.3 sha2.3 SHA384_Final.3
MLINKS+=sha2.3 SHA384_End.3 sha2.3 SHA384_File.3 sha2.3 SHA384_Data.3
MLINKS+=sha2.3 SHA512_Init.3 sha2.3 SHA512_Update.3 sha2.3 SHA512_Final.3
MLINKS+=sha2.3 SHA512_End.3 sha2.3 SHA512_File.3 sha2.3 SHA512_Data.3

+ 226
- 0
src/lib/libc/hash/sha2.3 View File

@ -0,0 +1,226 @@
.\" $OpenBSD: sha2.3,v 1.1 2003/05/08 23:34:55 millert Exp $
.\"
.\" Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" See http://www.nist.gov/sha/ for the detailed standard
.\"
.Dd April 24, 2003
.Dt SHA2 3
.Os
.Sh NAME
.Nm SHA256_Init ,
.Nm SHA256_Update ,
.Nm SHA256_Final ,
.Nm SHA256_End ,
.Nm SHA256_File ,
.Nm SHA256_Data
.Nd calculate the NIST Secure Hash Standard (version 2)
.Sh SYNOPSIS
.Fd #include <sys/types.h>
.Fd #include <sha2.h>
.Ft void
.Fn SHA256_Init "SHA256_CTX *context"
.Ft void
.Fn SHA256_Update "SHA256_CTX *context" "const u_int8_t *data" "size_t len"
.Ft void
.Fn SHA256_Final "u_int8_t digest[SHA256_DIGEST_LENGTH]" "SHA256_CTX *context"
.Ft "char *"
.Fn SHA256_End "SHA256_CTX *context" "char buf[SHA256_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA256_File "char *filename" "char buf[SHA256_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA256_Data "u_int8_t *data" "u_int len" "char buf[SHA256_DIGEST_STRING_LENGTH]"
.Ft void
.Fn SHA384_Init "SHA384_CTX *context"
.Ft void
.Fn SHA384_Update "SHA384_CTX *context" "const u_int8_t *data" "size_t len"
.Ft void
.Fn SHA384_Final "u_int8_t digest[SHA384_DIGEST_LENGTH]" "SHA384_CTX *context"
.Ft "char *"
.Fn SHA384_End "SHA384_CTX *context" "char buf[SHA384_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA384_File "char *filename" "char buf[SHA384_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA384_Data "u_int8_t *data" "size_t len" "char buf[SHA384_DIGEST_STRING_LENGTH]"
.Ft void
.Fn SHA512_Init "SHA512_CTX *context"
.Ft void
.Fn SHA512_Update "SHA512_CTX *context" "const u_int8_t *data" "size_t len"
.Ft void
.Fn SHA512_Final "u_int8_t digest[SHA512_DIGEST_LENGTH]" "SHA512_CTX *context"
.Ft "char *"
.Fn SHA512_End "SHA512_CTX *context" "char buf[SHA512_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA512_File "char *filename" "char buf[SHA512_DIGEST_STRING_LENGTH]"
.Ft "char *"
.Fn SHA512_Data "u_int8_t *data" "size_t len" "char buf[SHA512_DIGEST_STRING_LENGTH]"
.Sh DESCRIPTION
The SHA2 functions implement the NIST Secure Hash Standard,
FIPS PUB 180-2.
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
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.
.Pp
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.
For brevity, only the 256 bit variants are described below.
.Pp
The
.Fn SHA256_Init
function initializes a SHA256_CTX
.Ar context
for use with
.Fn SHA256_Update ,
and
.Fn SHA256_Final .
The
.Fn SHA256_Update
function adds
.Ar data
of length
.Ar len
to the SHA256_CTX specified by
.Ar context .
.Fn SHA256_Final
is called when all data has been added via
.Fn SHA256_Update
and stores a message digest in the
.Ar digest
parameter.
When a null pointer is passed to
.Fn SHA256_Final
as first argument only the final padding will be applied and the
current context can still be used with
.Fn SHA256_Update .
.Pp
The
.Fn SHA256_End
function is a front end for
.Fn SHA256_Final
which converts the digest into an
.Tn ASCII
representation of the digest in hexadecimal.
.Pp
The
.Fn SHA256_File
function calculates the digest for a file and returns the result via
.Fn SHA256_End .
If
.Fn SHA256_File
is unable to open the file a NULL pointer is returned.
.Pp
The
.Fn SHA256_Data
function
calculates the digest of an arbitrary string and returns the result via
.Fn SHA256_End .
.Pp
For each of the
.Fn SHA256_End ,
.Fn SHA256_File ,
and
.Fn SHA256_Data
functions the
.Ar buf
parameter should either be a string large enough to hold the resulting digest
(e.g.
.Ev SHA256_DIGEST_STRING_LENGTH ,
.Ev SHA384_DIGEST_STRING_LENGTH
or
.Ev SHA512_DIGEST_STRING_LENGTH ,
depending on the function being used)
or a NULL pointer.
In the latter case, space will be dynamically allocated via
.Xr malloc 3
and should be freed using
.Xr free 3
when it is no longer needed.
.Sh EXAMPLES
The follow code fragment will calculate the digest for
the string "abc" which is ``0xa9993e36476816aba3e25717850c26c9cd0d89d''.
.Bd -literal -offset indent
SHA256_CTX ctx;
u_int8_t results[SHA256_DIGEST_LENGTH];
char *buf;
int n;
buf = "abc";
n = strlen(buf);
SHA256_Init(&ctx);
SHA256_Update(&ctx, (u_int8_t *)buf, n);
SHA256_Final(results, &ctx);
/* Print the digest as one long hex value */
printf("0x");
for (n = 0; n < SHA256_DIGEST_LENGTH; n++)
printf("%02x", results[n]);
putchar('\en');
.Ed
.Pp
Alternately, the helper functions could be used in the following way:
.Bd -literal -offset indent
SHA256_CTX ctx;
u_int8_t output[SHA256_DIGEST_STRING_LENGTH];
char *buf = "abc";
printf("0x%s\en", SHA256_Data(buf, strlen(buf), output));
.Ed
.Sh CAVEATS
This implementation of the Secure Hash Standard has not been validated by
NIST and as such is not in official compliance with the standard.
.Pp
If a message digest is to be copied to a multi-byte type (ie:
an array of five 32-bit integers) it will be necessary to
perform byte swapping on little endian machines such as the i386, alpha,
and vax.
.Sh AUTHORS
This implementation of the SHA fucntions was written by Aaron D. Gifford.
.Pp
The
.Fn SHA256_End ,
.Fn SHA256_File ,
and
.Fn SHA256_Data
helper functions are derived from code written by Poul-Henning Kamp.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
.Xr rmd160 3 ,
.Xr sha1 3
.Rs
.%T Secure Hash Standard
.%O FIPS PUB 180-2
.Re
.Sh HISTORY
The SHA2 functions appeared in
.Ox 3.4 .

+ 895
- 0
src/lib/libc/hash/sha2.c View File

@ -0,0 +1,895 @@
/* $OpenBSD: sha2.c,v 1.1 2003/05/08 23:34:55 millert Exp $ */
/*
* FILE: sha2.c
* AUTHOR: Aaron D. Gifford <me@aarongifford.com>
*
* Copyright (c) 2000-2001, Aaron D. Gifford
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$OpenBSD: sha2.c,v 1.1 2003/05/08 23:34:55 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <string.h>
#include <sha2.h>
/*
* UNROLLED TRANSFORM LOOP NOTE:
* You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
* loop version for the hash transform rounds (defined using macros
* later in this file). Either define on the command line, for example:
*
* cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
*
* or define below:
*
* #define SHA2_UNROLL_TRANSFORM
*
*/
/*** SHA-256/384/512 Machine Architecture Definitions *****************/
/*
* BYTE_ORDER NOTE:
*
* Please make sure that your system defines BYTE_ORDER. If your
* architecture is little-endian, make sure it also defines
* LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
* equivilent.
*
* If your system does not define the above, then you can do so by
* hand like this:
*
* #define LITTLE_ENDIAN 1234
* #define BIG_ENDIAN 4321
*
* And for little-endian machines, add:
*
* #define BYTE_ORDER LITTLE_ENDIAN
*
* Or for big-endian machines:
*
* #define BYTE_ORDER BIG_ENDIAN
*
* The FreeBSD machine this was written on defines BYTE_ORDER
* appropriately by including <sys/types.h> (which in turn includes
* <machine/endian.h> where the appropriate definitions are actually
* made).
*/
#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
#endif
/*** SHA-256/384/512 Various Length Definitions ***********************/
/* NOTE: Most of these are in sha2.h */
#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)
/*** ENDIAN REVERSAL MACROS *******************************************/
#if BYTE_ORDER == LITTLE_ENDIAN
#define REVERSE32(w,x) { \
u_int32_t tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
}
#define REVERSE64(w,x) { \
u_int64_t tmp = (w); \
tmp = (tmp >> 32) | (tmp << 32); \
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
((tmp & 0x00ff00ff00ff00ffULL) << 8); \
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
((tmp & 0x0000ffff0000ffffULL) << 16); \
}
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/*
* Macro for incrementally adding the unsigned 64-bit integer n to the
* unsigned 128-bit integer (represented using a two-element array of
* 64-bit words):
*/
#define ADDINC128(w,n) { \
(w)[0] += (u_int64_t)(n); \
if ((w)[0] < (n)) { \
(w)[1]++; \
} \
}
/*** THE SIX LOGICAL FUNCTIONS ****************************************/
/*
* 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
* (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): */
#define R(b,x) ((x) >> (b))
/* 32-bit Rotate-right (used in 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: */
#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: */
#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)))
#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
/* Four of six logical functions used in SHA-384 and SHA-512: */
#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
/*** INTERNAL FUNCTION PROTOTYPES *************************************/
/* NOTE: These should not be accessed directly from outside this
* library -- they are intended for private internal visibility/use
* only.
*/
void SHA512_Last(SHA512_CTX *);
void SHA256_Transform(SHA256_CTX *, const u_int32_t *);
void SHA512_Transform(SHA512_CTX *, const u_int64_t *);
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
/* Hash constant words K for SHA-256: */
const static u_int32_t K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
/* Initial hash value H for SHA-256: */
const static u_int32_t sha256_initial_hash_value[8] = {
0x6a09e667UL,
0xbb67ae85UL,
0x3c6ef372UL,
0xa54ff53aUL,
0x510e527fUL,
0x9b05688cUL,
0x1f83d9abUL,
0x5be0cd19UL
};
/* Hash constant words K for SHA-384 and SHA-512: */
const static u_int64_t K512[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
/* Initial hash value H for SHA-384 */
const static u_int64_t sha384_initial_hash_value[8] = {
0xcbbb9d5dc1059ed8ULL,
0x629a292a367cd507ULL,
0x9159015a3070dd17ULL,
0x152fecd8f70e5939ULL,
0x67332667ffc00b31ULL,
0x8eb44a8768581511ULL,
0xdb0c2e0d64f98fa7ULL,
0x47b5481dbefa4fa4ULL
};
/* Initial hash value H for SHA-512 */
const static u_int64_t sha512_initial_hash_value[8] = {
0x6a09e667f3bcc908ULL,
0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL,
0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL,
0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL,
0x5be0cd19137e2179ULL
};
/*** SHA-256: *********************************************************/
void SHA256_Init(SHA256_CTX *context) {
if (context == (SHA256_CTX *)0) {
return;
}
memcpy(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
memset(context->buffer, 0, SHA256_BLOCK_LENGTH);
context->bitcount = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-256 round macros: */
#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE32(*data++, W256[j]); \
T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
K256[j] + W256[j]; \
(d) += T1; \
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
K256[j] + (W256[j] = *data++); \
(d) += T1; \
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND256(a,b,c,d,e,f,g,h) \
s0 = W256[(j+1)&0x0f]; \
s0 = sigma0_256(s0); \
s1 = W256[(j+14)&0x0f]; \
s1 = sigma1_256(s1); \
T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
(W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
(d) += T1; \
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
void SHA256_Transform(SHA256_CTX *context, const u_int32_t *data) {
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, *W256;
int j;
W256 = (u_int32_t *)context->buffer;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
/* Rounds 0 to 15 (unrolled): */
ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
} while (j < 16);
/* Now for the remaining rounds to 64: */
do {
ROUND256(a,b,c,d,e,f,g,h);
ROUND256(h,a,b,c,d,e,f,g);
ROUND256(g,h,a,b,c,d,e,f);
ROUND256(f,g,h,a,b,c,d,e);
ROUND256(e,f,g,h,a,b,c,d);
ROUND256(d,e,f,g,h,a,b,c);
ROUND256(c,d,e,f,g,h,a,b);
ROUND256(b,c,d,e,f,g,h,a);
} while (j < 64);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
}
#else /* SHA2_UNROLL_TRANSFORM */
void SHA256_Transform(SHA256_CTX *context, const u_int32_t *data) {
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, T2, *W256;
int j;
W256 = (u_int32_t *)context->buffer;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
#if BYTE_ORDER == LITTLE_ENDIAN
/* Copy data while converting to host byte order */
REVERSE32(*data++, W256[j]);
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-256 compression function to update a..h with copy */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 16);
do {
/* Part of the message block expansion: */
s0 = W256[(j+1)&0x0f];
s0 = sigma0_256(s0);
s1 = W256[(j+14)&0x0f];
s1 = sigma1_256(s1);
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
(W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 64);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
}
#endif /* SHA2_UNROLL_TRANSFORM */
void SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len) {
unsigned int freespace, usedspace;
if (len == 0) {
/* Calling with no data is valid - we do nothing */
return;
}
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA256_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
/* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace);
context->bitcount += freespace << 3;
len -= freespace;
data += freespace;
SHA256_Transform(context, (u_int32_t *)context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
context->bitcount += len << 3;
/* Clean up: */
usedspace = freespace = 0;
return;
}
}
while (len >= SHA256_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
SHA256_Transform(context, (const u_int32_t *)data);
context->bitcount += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
memcpy(context->buffer, data, len);
context->bitcount += len << 3;
}
/* Clean up: */
usedspace = freespace = 0;
}
void SHA256_Final(u_int8_t digest[], SHA256_CTX *context) {
u_int32_t *d = (u_int32_t *)digest;
unsigned int usedspace;
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (u_int8_t *)0) {
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, (u_int32_t *)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: */
*(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
/* Final transform: */
SHA256_Transform(context, (u_int32_t *)context->buffer);
#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]);
*d++ = context->state[j];
}
}
#else
memcpy(d, context->state, SHA256_DIGEST_LENGTH);
#endif
}
/* Clean up state data: */
memset(context, 0, sizeof(context));
usedspace = 0;
}
/*** SHA-512: *********************************************************/
void SHA512_Init(SHA512_CTX *context) {
if (context == (SHA512_CTX *)0) {
return;
}
memcpy(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
memset(context->buffer, 0, SHA512_BLOCK_LENGTH);
context->bitcount[0] = context->bitcount[1] = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-512 round macros: */
#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE64(*data++, W512[j]); \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
K512[j] + W512[j]; \
(d) += T1, \
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
j++
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
K512[j] + (W512[j] = *data++); \
(d) += T1; \
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512(a,b,c,d,e,f,g,h) \
s0 = W512[(j+1)&0x0f]; \
s0 = sigma0_512(s0); \
s1 = W512[(j+14)&0x0f]; \
s1 = sigma1_512(s1); \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
(d) += T1; \
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
void SHA512_Transform(SHA512_CTX *context, const u_int64_t *data) {
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, *W512 = (u_int64_t *)context->buffer;
int j;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
} while (j < 16);
/* Now for the remaining rounds up to 79: */
do {
ROUND512(a,b,c,d,e,f,g,h);
ROUND512(h,a,b,c,d,e,f,g);
ROUND512(g,h,a,b,c,d,e,f);
ROUND512(f,g,h,a,b,c,d,e);
ROUND512(e,f,g,h,a,b,c,d);
ROUND512(d,e,f,g,h,a,b,c);
ROUND512(c,d,e,f,g,h,a,b);
ROUND512(b,c,d,e,f,g,h,a);
} while (j < 80);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
}
#else /* SHA2_UNROLL_TRANSFORM */
void SHA512_Transform(SHA512_CTX *context, const u_int64_t *data) {
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, T2, *W512 = (u_int64_t *)context->buffer;
int j;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
REVERSE64(*data++, W512[j]);
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-512 compression function to update a..h with copy */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 16);
do {
/* Part of the message block expansion: */
s0 = W512[(j+1)&0x0f];
s0 = sigma0_512(s0);
s1 = W512[(j+14)&0x0f];
s1 = sigma1_512(s1);
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 80);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
}
#endif /* SHA2_UNROLL_TRANSFORM */
void SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len) {
unsigned int freespace, usedspace;
if (len == 0) {
/* Calling with no data is valid - we do nothing */
return;
}
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA512_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
/* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace);
ADDINC128(context->bitcount, freespace << 3);
len -= freespace;
data += freespace;
SHA512_Transform(context, (u_int64_t *)context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
ADDINC128(context->bitcount, len << 3);
/* Clean up: */
usedspace = freespace = 0;
return;
}
}
while (len >= SHA512_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
SHA512_Transform(context, (const u_int64_t *)data);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
memcpy(context->buffer, data, len);
ADDINC128(context->bitcount, len << 3);
}
/* Clean up: */
usedspace = freespace = 0;
}
void SHA512_Last(SHA512_CTX *context) {
unsigned int usedspace;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount[0],context->bitcount[0]);
REVERSE64(context->bitcount[1],context->bitcount[1]);
#endif
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA512_BLOCK_LENGTH) {
memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
SHA512_Transform(context, (u_int64_t *)context->buffer);
/* And set-up for the last transform: */
memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2);
}
} else {
/* Prepare for final transform: */
memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
/* Store the length of input data (in bits): */
*(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
*(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
/* Final transform: */
SHA512_Transform(context, (u_int64_t *)context->buffer);
}
void SHA512_Final(u_int8_t digest[], SHA512_CTX *context) {
u_int64_t *d = (u_int64_t *)digest;
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (u_int8_t *)0) {
SHA512_Last(context);
/* Save the hash data for output: */
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < 8; j++) {
REVERSE64(context->state[j],context->state[j]);
*d++ = context->state[j];
}
}
#else
memcpy(d, context->state, SHA512_DIGEST_LENGTH);
#endif
}
/* Zero out state data */
memset(context, 0, sizeof(context));
}
/*** SHA-384: *********************************************************/
void SHA384_Init(SHA384_CTX *context) {
if (context == (SHA384_CTX *)0) {
return;
}
memcpy(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
memset(context->buffer, 0, SHA384_BLOCK_LENGTH);
context->bitcount[0] = context->bitcount[1] = 0;
}
void SHA384_Update(SHA384_CTX *context, const u_int8_t *data, size_t len) {
SHA512_Update((SHA512_CTX *)context, data, len);
}
void SHA384_Final(u_int8_t digest[], SHA384_CTX *context) {
u_int64_t *d = (u_int64_t *)digest;
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (u_int8_t *)0) {
SHA512_Last((SHA512_CTX *)context);
/* Save the hash data for output: */
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < 6; j++) {
REVERSE64(context->state[j],context->state[j]);
*d++ = context->state[j];
}
}
#else
memcpy(d, context->state, SHA384_DIGEST_LENGTH);
#endif
}
/* Zero out state data */
memset(context, 0, sizeof(context));
}

+ 176
- 0
src/lib/libc/hash/sha2hl.c View File

@ -0,0 +1,176 @@
/* sha2hl.c
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$OpenBSD: sha2hl.c,v 1.1 2003/05/08 23:34:55 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sha2.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
static const char hex[]="0123456789abcdef";
/* ARGSUSED */
char *
SHA256_End(SHA256_CTX *ctx, char buf[SHA256_DIGEST_STRING_LENGTH])
{
int i;
u_int8_t digest[SHA256_DIGEST_LENGTH];
if (buf == NULL && (buf = malloc(SHA256_DIGEST_STRING_LENGTH)) == NULL)
return(NULL);
SHA256_Final(digest, ctx);
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
buf[i + i] = hex[digest[i] >> 4];
buf[i + i + 1] = hex[digest[i] & 0x0f];
}
buf[i + i] = '\0';
memset(digest, 0, sizeof(digest));
return(buf);
}
char *
SHA256_File(char *filename, char buf[SHA256_DIGEST_STRING_LENGTH])
{
u_int8_t buffer[BUFSIZ];
SHA256_CTX ctx;
int fd, num, oerrno;
SHA256_Init(&ctx);
if ((fd = open(filename, O_RDONLY)) < 0)
return(0);
while ((num = read(fd, buffer, sizeof(buffer))) > 0)
SHA256_Update(&ctx, buffer, num);
oerrno = errno;
close(fd);
errno = oerrno;
return(num < 0 ? 0 : SHA256_End(&ctx, buf));
}
char *
SHA256_Data(const u_int8_t *data, size_t len, char buf[SHA256_DIGEST_STRING_LENGTH])
{
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, data, len);
return(SHA256_End(&ctx, buf));
}
/* ARGSUSED */
char *
SHA384_End(SHA384_CTX *ctx, char buf[SHA384_DIGEST_STRING_LENGTH])
{
int i;
u_int8_t digest[SHA384_DIGEST_LENGTH];
if (buf == NULL && (buf = malloc(SHA384_DIGEST_STRING_LENGTH)) == NULL)
return(NULL);
SHA384_Final(digest, ctx);
for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
buf[i + i] = hex[digest[i] >> 4];
buf[i + i + 1] = hex[digest[i] & 0x0f];
}
buf[i + i] = '\0';
memset(digest, 0, sizeof(digest));
return(buf);
}
char *
SHA384_File(char *filename, char buf[SHA384_DIGEST_STRING_LENGTH])
{
u_int8_t buffer[BUFSIZ];
SHA384_CTX ctx;
int fd, num, oerrno;
SHA384_Init(&ctx);
if ((fd = open(filename, O_RDONLY)) < 0)
return(0);
while ((num = read(fd, buffer, sizeof(buffer))) > 0)
SHA384_Update(&ctx, buffer, num);
oerrno = errno;
close(fd);
errno = oerrno;
return(num < 0 ? 0 : SHA384_End(&ctx, buf));
}
char *
SHA384_Data(const u_int8_t *data, size_t len, char buf[SHA384_DIGEST_STRING_LENGTH])
{
SHA384_CTX ctx;
SHA384_Init(&ctx);
SHA384_Update(&ctx, data, len);
return(SHA384_End(&ctx, buf));
}
/* ARGSUSED */
char *
SHA512_End(SHA512_CTX *ctx, char buf[SHA512_DIGEST_STRING_LENGTH])
{
int i;
u_int8_t digest[SHA512_DIGEST_LENGTH];
if (buf == NULL && (buf = malloc(SHA512_DIGEST_STRING_LENGTH)) == NULL)
return(NULL);
SHA512_Final(digest, ctx);
for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
buf[i + i] = hex[digest[i] >> 4];
buf[i + i + 1] = hex[digest[i] & 0x0f];
}
buf[i + i] = '\0';
memset(digest, 0, sizeof(digest));
return(buf);
}
char *
SHA512_File(char *filename, char buf[SHA512_DIGEST_STRING_LENGTH])
{
u_int8_t buffer[BUFSIZ];
SHA512_CTX ctx;
int fd, num, oerrno;
SHA512_Init(&ctx);
if ((fd = open(filename, O_RDONLY)) < 0)
return(0);
while ((num = read(fd, buffer, sizeof(buffer))) > 0)
SHA512_Update(&ctx, buffer, num);
oerrno = errno;
close(fd);
errno = oerrno;
return(num < 0 ? 0 : SHA512_End(&ctx, buf));
}
char *
SHA512_Data(const u_int8_t *data, size_t len, char buf[SHA512_DIGEST_STRING_LENGTH])
{
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx, data, len);
return(SHA512_End(&ctx, buf));
}

Loading…
Cancel
Save