From patchwork Fri Mar 27 17:43:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Landden X-Patchwork-Id: 455538 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5C3F014007D for ; Sat, 28 Mar 2015 04:43:52 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=sourceware.org header.i=@sourceware.org header.b=Ub4BYEOZ; dkim-adsp=none (unprotected policy); dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=kvJoENdkr1XG4QilSvB8OSbVSfTDOfw HoykUdbLv0cu+a8w/RsNiLqM7bZiBHbn318yuuo529VLQc/lEC3tB5L2m12EAZ6z NgpCH6RhkNoMDt3rgy0IA2V9CV/KPqeNcO4vEDSWbmrjBc577nvXePl7Dp/v8VGh byB3nD1c5XKg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=c4L84raA1r1z7DXeApGZC9gpi7s=; b=Ub4BY EOZqEyPY8FK7v5o0xx0zWuoUiIewwTAfBP0f3BBpi2eOmrno0RR5Y8uZFi0LkriB QxRj0n7a06YaqcZv0+vXUSsE1k194aEymq6rt+dxvHLWagvXZjLGg7O7OBc9IVm/ 9Jo2gCbCCt/Nts9vanCJdDdTYJtBT3uFLl7z58= Received: (qmail 129677 invoked by alias); 27 Mar 2015 17:43:44 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 129665 invoked by uid 89); 27 Mar 2015 17:43:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=3.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_FROM_URIBL_PCCC, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-pd0-f180.google.com X-Received: by 10.68.220.227 with SMTP id pz3mr37234836pbc.72.1427478219410; Fri, 27 Mar 2015 10:43:39 -0700 (PDT) From: Shawn Landden To: libc-alpha@sourceware.org Cc: Shawn Landden Subject: [PATCH] sha2: new header Date: Fri, 27 Mar 2015 10:43:31 -0700 Message-Id: <1427478211-368567-1-git-send-email-shawn@churchofgit.com> In-Reply-To: <87mw31thl3.fsf@mid.deneb.enyo.de> References: <87mw31thl3.fsf@mid.deneb.enyo.de> Export the SHA2 family of functions. I cannot figure out how to make these symbols not be stripped. --- crypt/Makefile | 6 ++-- crypt/align.h | 31 +++++++++++++++++ crypt/sha2.h | 52 ++++++++++++++++++++++++++++ crypt/sha256-block.c | 4 +-- crypt/sha256-crypt.c | 6 ++-- crypt/sha256.c | 97 +++++++++++++++++++++++++++------------------------- crypt/sha256.h | 22 +++++++----- crypt/sha256test.c | 11 +++--- crypt/sha512-block.c | 4 +-- crypt/sha512-crypt.c | 6 ++-- crypt/sha512.c | 89 +++++++++++++++++++++++++++-------------------- crypt/sha512.h | 22 ++++++++---- crypt/sha512test.c | 9 +++-- 13 files changed, 237 insertions(+), 122 deletions(-) create mode 100644 crypt/align.h create mode 100644 crypt/sha2.h diff --git a/crypt/Makefile b/crypt/Makefile index 34c4dd7..3f839fc 100644 --- a/crypt/Makefile +++ b/crypt/Makefile @@ -22,13 +22,13 @@ subdir := crypt include ../Makeconfig -headers := crypt.h +headers := crypt.h sha2.h extra-libs := libcrypt extra-libs-others := $(extra-libs) libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ - crypt_util + crypt_util sha256 sha512 tests := cert md5c-test sha256c-test sha512c-test badsalttest @@ -42,7 +42,7 @@ CPPFLAGS-sha512-crypt.c = -DUSE_NSS -I$(shell nss-config --includedir) CPPFLAGS-md5-crypt.c = -DUSE_NSS -I$(shell nss-config --includedir) LDLIBS-crypt.so = -lfreebl3 else -libcrypt-routines += md5 sha256 sha512 +libcrypt-routines += md5 tests += md5test sha256test sha512test diff --git a/crypt/align.h b/crypt/align.h new file mode 100644 index 0000000..957e1e8 --- /dev/null +++ b/crypt/align.h @@ -0,0 +1,31 @@ +#pragma once + +#if defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64) || \ + defined(__ppc__) || defined(__ppc64__) || \ + defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__s390__) || defined(__s390x__) + +#define put_be32(p, v) do { *(uint32_t *)(p) = be32toh(v); } while (0) +#define put_be64(p, v) do { *(uint64_t *)(p) = be64toh(v); } while (0) + +#else + +#define put_be32(p, v) do { \ + unsigned int __v = (v); \ + *((unsigned char *)(p) + 0) = __v >> 24; \ + *((unsigned char *)(p) + 1) = __v >> 16; \ + *((unsigned char *)(p) + 2) = __v >> 8; \ + *((unsigned char *)(p) + 3) = __v >> 0; } while (0) +#define put_be64(p, v) do { \ + unsigned int __v = (v); \ + *((unsigned char *)(p) + 0) = __v >> 56; \ + *((unsigned char *)(p) + 1) = __v >> 48; \ + *((unsigned char *)(p) + 2) = __v >> 40; \ + *((unsigned char *)(p) + 3) = __v >> 32; \ + *((unsigned char *)(p) + 4) = __v >> 24; \ + *((unsigned char *)(p) + 5) = __v >> 16; \ + *((unsigned char *)(p) + 6) = __v >> 8; \ + *((unsigned char *)(p) + 7) = __v >> 0; } while (0) + +#endif diff --git a/crypt/sha2.h b/crypt/sha2.h new file mode 100644 index 0000000..ab4021c --- /dev/null +++ b/crypt/sha2.h @@ -0,0 +1,52 @@ +/* + * SHA2: The SHA2 family of cryptographic functions + * + * Copyright (C) 2015 Free Software Foundation, Inc. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * . + */ + +#ifndef _SHA2_H +#define _SHA2_H + +#include + +typedef struct { + char __internal_state[176]; +} sha256_ctx __attribute__((aligned(16))); + +/* 256 bits is 32 bytes + * 224 bits is 28 bytes + */ +void *sha256(const void *__restrict d, size_t n, void *__restrict md); +void sha256_init(sha256_ctx *s); +const void *sha256_update(sha256_ctx *__restrict s, const void *__restrict d, size_t n); +void sha256_finish(sha256_ctx *__restrict s, void *__restrict md); +void sha224_finish(sha256_ctx *__restrict s, void *__restrict md); + +typedef struct { + char __internal_state[352]; +} sha512_ctx __attribute__((aligned(16))); + +/* 512 bits is 64 bytes + * 384 bits is 48 bytes + */ +void *sha512(const void *__restrict d, size_t n, void *__restrict md); +void sha512_init(sha512_ctx *s); +const void *sha512_update(sha512_ctx *__restrict s, const void *__restrict d, size_t n); +void *sha512_finish(sha512_ctx *__restrict s, void *__restrict md); +void *sha384_finish(sha512_ctx *__restrict s, void *__restrict md); + +#endif diff --git a/crypt/sha256-block.c b/crypt/sha256-block.c index 8a77096..4fbf04b 100644 --- a/crypt/sha256-block.c +++ b/crypt/sha256-block.c @@ -3,7 +3,7 @@ /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void -sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx) +sha256_process_block (const void *buffer, size_t len, sha256_ctx *ctx) { const uint32_t *words = buffer; size_t nwords = len / sizeof (uint32_t); @@ -50,7 +50,7 @@ sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx) /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ for (unsigned int t = 0; t < 16; ++t) { - W[t] = SWAP (*words); + W[t] = be32toh (*words); ++words; } for (unsigned int t = 16; t < 64; ++t) diff --git a/crypt/sha256-crypt.c b/crypt/sha256-crypt.c index d90e291..cdefa60 100644 --- a/crypt/sha256-crypt.c +++ b/crypt/sha256-crypt.c @@ -68,7 +68,7 @@ typedef int PRBool; __sha256_init_ctx (ctxp) # define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \ - __sha256_process_bytes(buf, len, ctxp) + __sha256_process_bytes(ctxp, buf, len) # define sha256_finish_ctx(ctxp, nss_ctxp, result) \ __sha256_finish_ctx (ctxp, result) @@ -189,8 +189,8 @@ __sha256_crypt_r (key, salt, buffer, buflen) NSSLOWHASHContext *nss_ctx = NULL; NSSLOWHASHContext *nss_alt_ctx = NULL; #else - struct sha256_ctx ctx; - struct sha256_ctx alt_ctx; + sha256_ctx ctx; + sha256_ctx alt_ctx; #endif /* Prepare for the real work. */ diff --git a/crypt/sha256.c b/crypt/sha256.c index b6db8b2..f8e2810 100644 --- a/crypt/sha256.c +++ b/crypt/sha256.c @@ -30,30 +30,7 @@ #include #include "sha256.h" - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# ifdef _LIBC -# include -# define SWAP(n) bswap_32 (n) -# define SWAP64(n) bswap_64 (n) -# else -# define SWAP(n) \ - (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -# define SWAP64(n) \ - (((n) << 56) \ - | (((n) & 0xff00) << 40) \ - | (((n) & 0xff0000) << 24) \ - | (((n) & 0xff000000) << 8) \ - | (((n) >> 8) & 0xff000000) \ - | (((n) >> 24) & 0xff0000) \ - | (((n) >> 40) & 0xff00) \ - | ((n) >> 56)) -# endif -#else -# define SWAP(n) (n) -# define SWAP64(n) (n) -#endif - +#include "align.h" /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (FIPS 180-2:5.1.1) */ @@ -82,13 +59,13 @@ static const uint32_t K[64] = }; void -sha256_process_block (const void *, size_t, struct sha256_ctx *); +sha256_process_block (const void *, size_t, sha256_ctx *); /* Initialize structure containing state of computation. (FIPS 180-2:5.3.2) */ void __sha256_init_ctx (ctx) - struct sha256_ctx *ctx; + sha256_ctx *ctx; { ctx->H[0] = 0x6a09e667; ctx->H[1] = 0xbb67ae85; @@ -102,17 +79,10 @@ __sha256_init_ctx (ctx) ctx->total64 = 0; ctx->buflen = 0; } +weak_alias(__sha256_init_ctx, sha256_init) - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -__sha256_finish_ctx (ctx, resbuf) - struct sha256_ctx *ctx; - void *resbuf; +static void +__sha256_finish_ctx_generic (sha256_ctx *ctx) { /* Take yet unprocessed bytes into account. */ uint32_t bytes = ctx->buflen; @@ -125,30 +95,51 @@ __sha256_finish_ctx (ctx, resbuf) memcpy (&ctx->buffer[bytes], fillbuf, pad); /* Put the 64-bit file length in *bits* at the end of the buffer. */ -#if _STRING_ARCH_unaligned - ctx->buffer64[(bytes + pad) / 8] = SWAP64 (ctx->total64 << 3); -#else - ctx->buffer32[(bytes + pad + 4) / 4] = SWAP (ctx->total[TOTAL64_low] << 3); - ctx->buffer32[(bytes + pad) / 4] = SWAP ((ctx->total[TOTAL64_high] << 3) | - (ctx->total[TOTAL64_low] >> 29)); -#endif + ctx->buffer64[(bytes + pad) / 8] = be64toh (ctx->total64 << 3); /* Process last bytes. */ sha256_process_block (ctx->buffer, bytes + pad + 8, ctx); +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +__sha256_finish_ctx (ctx, resbuf) + sha256_ctx *ctx; + void *resbuf; +{ + __sha256_finish_ctx_generic (ctx); /* Put result from CTX in first 32 bytes following RESBUF. */ for (unsigned int i = 0; i < 8; ++i) - ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]); + put_be32 (((uint32_t *) resbuf) + i, ctx->H[i]); return resbuf; } +weak_alias(__sha256_finish_ctx, sha256_finish) +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +__sha224_finish_ctx (ctx, resbuf) + sha256_ctx *ctx; + void *resbuf; +{ + __sha256_finish_ctx_generic (ctx); -void -__sha256_process_bytes (buffer, len, ctx) + /* Put result from CTX in first 28 bytes following RESBUF. */ + for (unsigned int i = 0; i < 7; ++i) + put_be32 (((uint32_t *) resbuf) + i, ctx->H[i]); + + return resbuf; +} +weak_alias(__sha224_finish_ctx, sha224_finish) + +const void * +__sha256_process_bytes (ctx, buffer, len) + sha256_ctx *ctx; const void *buffer; size_t len; - struct sha256_ctx *ctx; { /* When we already have some bits in our internal buffer concatenate both inputs first. */ @@ -216,6 +207,18 @@ __sha256_process_bytes (buffer, len, ctx) } ctx->buflen = left_over; } + + return buffer; } +weak_alias(__sha256_process_bytes, sha256_update) + +extern void *__sha256(const void *__restrict d, size_t n, void *__restrict md) { + sha256_ctx ctx; + sha256_init(&ctx); + sha256_update(&ctx, d, n); + sha256_finish(&ctx, md); + return md; +} +weak_alias(__sha256, sha256) #include diff --git a/crypt/sha256.h b/crypt/sha256.h index 27e0fe6..5960648 100644 --- a/crypt/sha256.h +++ b/crypt/sha256.h @@ -27,7 +27,7 @@ /* Structure to save state of computation between the single steps. */ -struct sha256_ctx +typedef struct { uint32_t H[8]; @@ -38,32 +38,38 @@ struct sha256_ctx #define TOTAL64_high (BYTE_ORDER == LITTLE_ENDIAN) uint32_t total[2]; }; - uint32_t buflen; union { char buffer[128]; uint32_t buffer32[32]; uint64_t buffer64[16]; }; -}; + uint32_t buflen; +} sha256_ctx __attribute__((aligned(16))); /* Initialize structure containing state of computation. (FIPS 180-2: 5.3.2) */ -extern void __sha256_init_ctx (struct sha256_ctx *ctx) __THROW; +extern void __sha256_init_ctx (sha256_ctx *__restrict ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ -extern void __sha256_process_bytes (const void *buffer, size_t len, - struct sha256_ctx *ctx) __THROW; +extern const void *__sha256_process_bytes (sha256_ctx *__restrict ctx, + const void *__restrict buffer, size_t len) __THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 32 bytes following RESBUF. */ +extern void *__sha256_finish_ctx (sha256_ctx *__restrict ctx, void *__restrict resbuf) + __THROW; /* Process the remaining bytes in the buffer and put result from CTX - in first 32 bytes following RESBUF. + in first 28 bytes following RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ -extern void *__sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf) +extern void *__sha224_finish_ctx (sha256_ctx *__restrict ctx, void *__restrict resbuf) __THROW; +extern void *__sha256(const void *__restrict d, size_t n, void *__restrict md) __THROW; #endif /* sha256.h */ diff --git a/crypt/sha256test.c b/crypt/sha256test.c index 39e8030..be46f69 100644 --- a/crypt/sha256test.c +++ b/crypt/sha256test.c @@ -44,7 +44,7 @@ static const struct int main (void) { - struct sha256_ctx ctx; + sha256_ctx ctx; char sum[32]; int result = 0; int cnt; @@ -52,8 +52,7 @@ main (void) for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt) { __sha256_init_ctx (&ctx); - __sha256_process_bytes (tests[cnt].input, strlen (tests[cnt].input), - &ctx); + __sha256_process_bytes (&ctx, tests[cnt].input, strlen (tests[cnt].input)); __sha256_finish_ctx (&ctx, sum); if (memcmp (tests[cnt].result, sum, 32) != 0) { @@ -63,7 +62,7 @@ main (void) __sha256_init_ctx (&ctx); for (int i = 0; tests[cnt].input[i] != '\0'; ++i) - __sha256_process_bytes (&tests[cnt].input[i], 1, &ctx); + __sha256_process_bytes (&ctx, &tests[cnt].input[i], 1); __sha256_finish_ctx (&ctx, sum); if (memcmp (tests[cnt].result, sum, 32) != 0) { @@ -77,7 +76,7 @@ main (void) memset (buf, 'a', sizeof (buf)); __sha256_init_ctx (&ctx); for (int i = 0; i < 1000; ++i) - __sha256_process_bytes (buf, sizeof (buf), &ctx); + __sha256_process_bytes (&ctx, buf, sizeof (buf)); __sha256_finish_ctx (&ctx, sum); static const char expected[32] = "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" @@ -90,7 +89,7 @@ main (void) __sha256_init_ctx (&ctx); for (int i = 0; i < 100000; ++i) - __sha256_process_bytes (buf, 10, &ctx); + __sha256_process_bytes (&ctx, buf, 10); __sha256_finish_ctx (&ctx, sum); if (memcmp (expected, sum, 32) != 0) { diff --git a/crypt/sha512-block.c b/crypt/sha512-block.c index c542db1..45c2049 100644 --- a/crypt/sha512-block.c +++ b/crypt/sha512-block.c @@ -3,7 +3,7 @@ /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 128 == 0. */ void -sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx) +sha512_process_block (const void *buffer, size_t len, sha512_ctx *ctx) { const uint64_t *words = buffer; size_t nwords = len / sizeof (uint64_t); @@ -57,7 +57,7 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx) /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ for (unsigned int t = 0; t < 16; ++t) { - W[t] = SWAP (*words); + W[t] = be64toh (*words); ++words; } for (unsigned int t = 16; t < 80; ++t) diff --git a/crypt/sha512-crypt.c b/crypt/sha512-crypt.c index 9c581ab..4cfecea 100644 --- a/crypt/sha512-crypt.c +++ b/crypt/sha512-crypt.c @@ -68,7 +68,7 @@ typedef int PRBool; __sha512_init_ctx (ctxp) # define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \ - __sha512_process_bytes(buf, len, ctxp) + __sha512_process_bytes(ctxp, buf, len) # define sha512_finish_ctx(ctxp, nss_ctxp, result) \ __sha512_finish_ctx (ctxp, result) @@ -188,8 +188,8 @@ __sha512_crypt_r (key, salt, buffer, buflen) NSSLOWHASHContext *nss_ctx = NULL; NSSLOWHASHContext *nss_alt_ctx = NULL; #else - struct sha512_ctx ctx; - struct sha512_ctx alt_ctx; + sha512_ctx ctx; + sha512_ctx alt_ctx; #endif /* Prepare for the real work. */ diff --git a/crypt/sha512.c b/crypt/sha512.c index 608de82..7dc4238 100644 --- a/crypt/sha512.c +++ b/crypt/sha512.c @@ -30,25 +30,7 @@ #include #include "sha512.h" - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# ifdef _LIBC -# include -# define SWAP(n) bswap_64 (n) -# else -# define SWAP(n) \ - (((n) << 56) \ - | (((n) & 0xff00) << 40) \ - | (((n) & 0xff0000) << 24) \ - | (((n) & 0xff000000) << 8) \ - | (((n) >> 8) & 0xff000000) \ - | (((n) >> 24) & 0xff0000) \ - | (((n) >> 40) & 0xff00) \ - | ((n) >> 56)) -# endif -#else -# define SWAP(n) (n) -#endif +#include "align.h" /* This array contains the bytes used to pad the buffer to the next @@ -102,13 +84,13 @@ static const uint64_t K[80] = }; void -sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx); +sha512_process_block (const void *buffer, size_t len, sha512_ctx *ctx); /* Initialize structure containing state of computation. (FIPS 180-2:5.3.3) */ void __sha512_init_ctx (ctx) - struct sha512_ctx *ctx; + sha512_ctx *ctx; { ctx->H[0] = UINT64_C (0x6a09e667f3bcc908); ctx->H[1] = UINT64_C (0xbb67ae8584caa73b); @@ -122,17 +104,10 @@ __sha512_init_ctx (ctx) ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } +weak_alias(__sha512_init_ctx, sha512_init) - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -__sha512_finish_ctx (ctx, resbuf) - struct sha512_ctx *ctx; - void *resbuf; +static void +__sha512_finish_ctx_generic (sha512_ctx *ctx) { /* Take yet unprocessed bytes into account. */ uint64_t bytes = ctx->buflen; @@ -151,26 +126,53 @@ __sha512_finish_ctx (ctx, resbuf) memcpy (&ctx->buffer[bytes], fillbuf, pad); /* Put the 128-bit file length in *bits* at the end of the buffer. */ - ctx->buffer64[(bytes + pad + 8) / 8] = SWAP (ctx->total[TOTAL128_low] << 3); - ctx->buffer64[(bytes + pad) / 8] = SWAP ((ctx->total[TOTAL128_high] << 3) | + ctx->buffer64[(bytes + pad + 8) / 8] = be64toh (ctx->total[TOTAL128_low] << 3); + ctx->buffer64[(bytes + pad) / 8] = be64toh ((ctx->total[TOTAL128_high] << 3) | (ctx->total[TOTAL128_low] >> 61)); /* Process last bytes. */ sha512_process_block (ctx->buffer, bytes + pad + 16, ctx); +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +__sha512_finish_ctx (ctx, resbuf) + sha512_ctx *ctx; + void *resbuf; +{ + __sha512_finish_ctx_generic (ctx); /* Put result from CTX in first 64 bytes following RESBUF. */ for (unsigned int i = 0; i < 8; ++i) - ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]); + put_be64(((uint64_t *) resbuf) + i, ctx->H[i]); return resbuf; } +weak_alias(__sha512_finish_ctx, sha512_finish) + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +__sha384_finish_ctx (ctx, resbuf) + sha512_ctx *ctx; + void *resbuf; +{ + __sha512_finish_ctx_generic (ctx); + /* Put result from CTX in first 48 bytes following RESBUF. */ + for (unsigned int i = 0; i < 6; ++i) + put_be64(((uint64_t *) resbuf) + i, ctx->H[i]); -void -__sha512_process_bytes (buffer, len, ctx) + return resbuf; +} +weak_alias(__sha384_finish_ctx, sha384_finish) + +const void * +__sha512_process_bytes (ctx, buffer, len) + sha512_ctx *ctx; const void *buffer; size_t len; - struct sha512_ctx *ctx; { /* When we already have some bits in our internal buffer concatenate both inputs first. */ @@ -239,6 +241,19 @@ __sha512_process_bytes (buffer, len, ctx) } ctx->buflen = left_over; } + + return buffer; +} +weak_alias(__sha512_process_bytes, sha512_update) + +extern void *__sha512(const void *__restrict d, size_t n, void *__restrict md) { + sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, d, n); + sha512_finish(&ctx, md); + return md; } +weak_alias(__sha512, sha512) #include diff --git a/crypt/sha512.h b/crypt/sha512.h index 159f000..359ea37 100644 --- a/crypt/sha512.h +++ b/crypt/sha512.h @@ -28,7 +28,7 @@ /* Structure to save state of computation between the single steps. */ -struct sha512_ctx +typedef struct { uint64_t H[8]; @@ -43,30 +43,40 @@ struct sha512_ctx uint64_t total[2]; }; uint64_t buflen; + uint8_t __padding[8]; union { char buffer[256]; uint64_t buffer64[32]; }; -}; +} sha512_ctx __attribute__((aligned(16))); /* Initialize structure containing state of computation. (FIPS 180-2: 5.3.3) */ -extern void __sha512_init_ctx (struct sha512_ctx *ctx) __THROW; +extern void __sha512_init_ctx (sha512_ctx *__restrict ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 128. */ -extern void __sha512_process_bytes (const void *buffer, size_t len, - struct sha512_ctx *ctx) __THROW; +extern const void *__sha512_process_bytes (sha512_ctx *__restrict ctx, + const void *__restrict buffer, size_t len) __THROW; /* Process the remaining bytes in the buffer and put result from CTX in first 64 bytes following RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 64 bits value. */ -extern void *__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) +extern void *__sha512_finish_ctx (sha512_ctx *ctx, void *__restrict resbuf) __THROW; +/* Process the remaining bytes in the buffer and put result from CTX + in first 48 bytes following RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 64 bits value. */ +extern void *__sha384_finish_ctx (sha512_ctx *ctx, void *__restrict resbuf) + __THROW; + +extern void *__sha512(const void *__restrict d, size_t n, void *__restrict md) __THROW; #endif /* sha512.h */ diff --git a/crypt/sha512test.c b/crypt/sha512test.c index 792e9a7..296ce89 100644 --- a/crypt/sha512test.c +++ b/crypt/sha512test.c @@ -63,7 +63,7 @@ static const struct int main (void) { - struct sha512_ctx ctx; + sha512_ctx ctx; char sum[64]; int result = 0; int cnt; @@ -71,8 +71,7 @@ main (void) for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt) { __sha512_init_ctx (&ctx); - __sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input), - &ctx); + __sha512_process_bytes (&ctx, tests[cnt].input, strlen (tests[cnt].input)); __sha512_finish_ctx (&ctx, sum); if (memcmp (tests[cnt].result, sum, 64) != 0) { @@ -82,7 +81,7 @@ main (void) __sha512_init_ctx (&ctx); for (int i = 0; tests[cnt].input[i] != '\0'; ++i) - __sha512_process_bytes (&tests[cnt].input[i], 1, &ctx); + __sha512_process_bytes (&ctx, &tests[cnt].input[i], 1); __sha512_finish_ctx (&ctx, sum); if (memcmp (tests[cnt].result, sum, 64) != 0) { @@ -96,7 +95,7 @@ main (void) memset (buf, 'a', sizeof (buf)); __sha512_init_ctx (&ctx); for (int i = 0; i < 1000; ++i) - __sha512_process_bytes (buf, sizeof (buf), &ctx); + __sha512_process_bytes (&ctx, buf, sizeof (buf)); __sha512_finish_ctx (&ctx, sum); static const char expected[64] = "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"