From 225e7b9e75c8bb52230cb6c13494a1d33d00638a Mon Sep 17 00:00:00 2001 From: Allan Jude Date: Sun, 27 Dec 2015 17:33:59 +0000 Subject: Replace sys/crypto/sha2/sha2.c with lib/libmd/sha512c.c cperciva's libmd implementation is 5-30% faster The same was done for SHA256 previously in r263218 cperciva's implementation was lacking SHA-384 which I implemented, validated against OpenSSL and the NIST documentation Extend sbin/md5 to create sha384(1) Chase dependancies on sys/crypto/sha2/sha2.{c,h} and replace them with sha512{c.c,.h} Reviewed by: cperciva, des, delphij Approved by: secteam, bapt (mentor) MFC after: 2 weeks Sponsored by: ScaleEngine Inc. Differential Revision: https://reviews.freebsd.org/D3929 --- cpukit/include/sha256.h | 15 ++++++++-- cpukit/include/sha384.h | 60 ++++++++++++++++++++++++++++++++++++++ cpukit/include/sha512.h | 16 ++++++++-- cpukit/libmd/sha512c.c | 77 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 cpukit/include/sha384.h diff --git a/cpukit/include/sha256.h b/cpukit/include/sha256.h index 1b6a4f4c57..9deed91255 100644 --- a/cpukit/include/sha256.h +++ b/cpukit/include/sha256.h @@ -29,22 +29,31 @@ #ifndef _SHA256_H_ #define _SHA256_H_ +#ifndef _KERNEL #include +#endif + +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) typedef struct SHA256Context { uint32_t state[8]; uint64_t count; - unsigned char buf[64]; + uint8_t buf[SHA256_BLOCK_LENGTH]; } SHA256_CTX; __BEGIN_DECLS + void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX *, const void *, size_t); -void SHA256_Final(unsigned char [32], SHA256_CTX *); +void SHA256_Final(unsigned char [SHA256_DIGEST_LENGTH], SHA256_CTX *); +#ifndef _KERNEL char *SHA256_End(SHA256_CTX *, char *); +char *SHA256_Data(const void *, unsigned int, char *); char *SHA256_File(const char *, char *); char *SHA256_FileChunk(const char *, char *, off_t, off_t); -char *SHA256_Data(const void *, unsigned int, char *); +#endif __END_DECLS #endif /* !_SHA256_H_ */ diff --git a/cpukit/include/sha384.h b/cpukit/include/sha384.h new file mode 100644 index 0000000000..2035d6ff54 --- /dev/null +++ b/cpukit/include/sha384.h @@ -0,0 +1,60 @@ +/*- + * Copyright 2005 Colin Percival + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _SHA384_H_ +#define _SHA384_H_ + +#ifndef _KERNEL +#include +#endif + +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) + +typedef struct SHA384Context { + uint64_t state[8]; + uint64_t count[2]; + uint8_t buf[SHA384_BLOCK_LENGTH]; +} SHA384_CTX; + +__BEGIN_DECLS + +void SHA384_Init(SHA384_CTX *); +void SHA384_Update(SHA384_CTX *, const void *, size_t); +void SHA384_Final(unsigned char [SHA384_DIGEST_LENGTH], SHA384_CTX *); +#ifndef _KERNEL +char *SHA384_End(SHA384_CTX *, char *); +char *SHA384_Data(const void *, unsigned int, char *); +char *SHA384_File(const char *, char *); +char *SHA384_FileChunk(const char *, char *, off_t, off_t); +#endif + +__END_DECLS + +#endif /* !_SHA384_H_ */ diff --git a/cpukit/include/sha512.h b/cpukit/include/sha512.h index 8998f4c5bf..1964562160 100644 --- a/cpukit/include/sha512.h +++ b/cpukit/include/sha512.h @@ -29,22 +29,32 @@ #ifndef _SHA512_H_ #define _SHA512_H_ +#ifndef _KERNEL #include +#endif + +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) typedef struct SHA512Context { uint64_t state[8]; uint64_t count[2]; - unsigned char buf[128]; + uint8_t buf[SHA512_BLOCK_LENGTH]; } SHA512_CTX; __BEGIN_DECLS + void SHA512_Init(SHA512_CTX *); void SHA512_Update(SHA512_CTX *, const void *, size_t); -void SHA512_Final(unsigned char [64], SHA512_CTX *); +void SHA512_Final(unsigned char [SHA512_DIGEST_LENGTH], SHA512_CTX *); +#ifndef _KERNEL char *SHA512_End(SHA512_CTX *, char *); +char *SHA512_Data(const void *, unsigned int, char *); char *SHA512_File(const char *, char *); char *SHA512_FileChunk(const char *, char *, off_t, off_t); -char *SHA512_Data(const void *, unsigned int, char *); +#endif + __END_DECLS #endif /* !_SHA512_H_ */ diff --git a/cpukit/libmd/sha512c.c b/cpukit/libmd/sha512c.c index a4f268045a..7d0e875550 100644 --- a/cpukit/libmd/sha512c.c +++ b/cpukit/libmd/sha512c.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include "sha512.h" +#include "sha384.h" #if BYTE_ORDER == BIG_ENDIAN @@ -104,7 +105,7 @@ be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len) * the 512-bit input block to produce a new state. */ static void -SHA512_Transform(uint64_t * state, const unsigned char block[128]) +SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH]) { uint64_t W[80]; uint64_t S[8]; @@ -112,12 +113,12 @@ SHA512_Transform(uint64_t * state, const unsigned char block[128]) int i; /* 1. Prepare message schedule W. */ - be64dec_vect(W, block, 128); + be64dec_vect(W, block, SHA512_BLOCK_LENGTH); for (i = 16; i < 80; i++) W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; /* 2. Initialize working variables. */ - memcpy(S, state, 64); + memcpy(S, state, SHA512_DIGEST_LENGTH); /* 3. Mix. */ RNDr(S, W, 0, 0x428a2f98d728ae22ULL); @@ -206,7 +207,7 @@ SHA512_Transform(uint64_t * state, const unsigned char block[128]) state[i] += S[i]; } -static const unsigned char PAD[128] = { +static const unsigned char PAD[SHA512_BLOCK_LENGTH] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -279,22 +280,22 @@ SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len) ctx->count[0] += bitlen[0]; /* Handle the case where we don't need to perform any transforms */ - if (len < 128 - r) { + if (len < SHA512_BLOCK_LENGTH - r) { memcpy(&ctx->buf[r], src, len); return; } /* Finish the current block */ - memcpy(&ctx->buf[r], src, 128 - r); + memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r); SHA512_Transform(ctx->state, ctx->buf); - src += 128 - r; - len -= 128 - r; + src += SHA512_BLOCK_LENGTH - r; + len -= SHA512_BLOCK_LENGTH - r; /* Perform complete blocks */ - while (len >= 128) { + while (len >= SHA512_BLOCK_LENGTH) { SHA512_Transform(ctx->state, src); - src += 128; - len -= 128; + src += SHA512_BLOCK_LENGTH; + len -= SHA512_BLOCK_LENGTH; } /* Copy left over data into buffer */ @@ -306,14 +307,64 @@ SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len) * and clears the context state. */ void -SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx) +SHA512_Final(unsigned char digest[SHA512_DIGEST_LENGTH], SHA512_CTX * ctx) { /* Add padding */ SHA512_Pad(ctx); /* Write the hash */ - be64enc_vect(digest, ctx->state, 64); + be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH); + + /* Clear the context state */ + memset((void *)ctx, 0, sizeof(*ctx)); +} + +/*** SHA-384: *********************************************************/ +/* + * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped + */ + +/* SHA-384 initialization. Begins a SHA-384 operation. */ +void +SHA384_Init(SHA384_CTX * ctx) +{ + + /* Zero bits processed so far */ + ctx->count[0] = ctx->count[1] = 0; + + /* Magic initialization constants */ + ctx->state[0] = 0xcbbb9d5dc1059ed8ULL; + ctx->state[1] = 0x629a292a367cd507ULL; + ctx->state[2] = 0x9159015a3070dd17ULL; + ctx->state[3] = 0x152fecd8f70e5939ULL; + ctx->state[4] = 0x67332667ffc00b31ULL; + ctx->state[5] = 0x8eb44a8768581511ULL; + ctx->state[6] = 0xdb0c2e0d64f98fa7ULL; + ctx->state[7] = 0x47b5481dbefa4fa4ULL; +} + +/* Add bytes into the SHA-384 hash */ +void +SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len) +{ + + SHA512_Update((SHA512_CTX *)ctx, in, len); +} + +/* + * SHA-384 finalization. Pads the input data, exports the hash value, + * and clears the context state. + */ +void +SHA384_Final(unsigned char digest[SHA384_DIGEST_LENGTH], SHA384_CTX * ctx) +{ + + /* Add padding */ + SHA512_Pad((SHA512_CTX *)ctx); + + /* Write the hash */ + be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH); /* Clear the context state */ memset((void *)ctx, 0, sizeof(*ctx)); -- cgit v1.2.3