Commit d8eb745b authored by Niels Möller's avatar Niels Möller

* Makefile.in (nettle_SOURCES): Added sha512.c and sha512-meta.c.

* sha.h: Added SHA-512-related declarations.
* nettle-meta.h: Likewise.

* sha512-meta.c: New file.
* sha512.c: New file.

Rev: nettle/Makefile.in:1.14
Rev: nettle/nettle-meta.h:1.3
Rev: nettle/sha.h:1.2
Rev: nettle/sha512-meta.c:1.1
Rev: nettle/sha512.c:1.1
parent 03bdd346
......@@ -65,6 +65,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
md2.c md2-meta.c md4.c md4-meta.c \
md5.c md5-compress.c md5-compat.c md5-meta.c \
sha1.c sha1-compress.c sha1-meta.c sha256.c sha256-meta.c \
sha512.c sha512-meta.c \
serpent.c serpent-meta.c \
twofish.c twofish-meta.c \
yarrow256.c yarrow_key_event.c \
......
......@@ -138,6 +138,7 @@ extern const struct nettle_hash nettle_md4;
extern const struct nettle_hash nettle_md5;
extern const struct nettle_hash nettle_sha1;
extern const struct nettle_hash nettle_sha256;
extern const struct nettle_hash nettle_sha512;
struct nettle_armor
{
......
......@@ -39,6 +39,9 @@ extern "C" {
#define sha256_init nettle_sha256_init
#define sha256_update nettle_sha256_update
#define sha256_digest nettle_sha256_digest
#define sha512_init nettle_sha512_init
#define sha512_update nettle_sha512_update
#define sha512_digest nettle_sha512_digest
/* SHA1 */
......@@ -103,6 +106,35 @@ sha256_digest(struct sha256_ctx *ctx,
unsigned length,
uint8_t *digest);
/* SHA512 */
#define SHA512_DIGEST_SIZE 64
#define SHA512_DATA_SIZE 128
/* Digest is kept internally as 8 64-bit words. */
#define _SHA512_DIGEST_LENGTH 8
struct sha512_ctx
{
uint64_t state[_SHA512_DIGEST_LENGTH]; /* State variables */
uint64_t count_low, count_high; /* 128-bit block count */
uint8_t block[SHA512_DATA_SIZE]; /* SHA512 data buffer */
unsigned int index; /* index into buffer */
};
void
sha512_init(struct sha512_ctx *ctx);
void
sha512_update(struct sha512_ctx *ctx,
unsigned length,
const uint8_t *data);
void
sha512_digest(struct sha512_ctx *ctx,
unsigned length,
uint8_t *digest);
#ifdef __cplusplus
}
#endif
......
/* sha512-meta.c */
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002, 2010 Niels Möller
*
* The nettle 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 nettle 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 nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "nettle-meta.h"
#include "sha.h"
const struct nettle_hash nettle_sha512
= _NETTLE_HASH(sha512, SHA512);
/* sha512.c
*
* The sha512 hash function FIXME: Add the SHA384 variant.
*
* See http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
/* nettle, low-level cryptographics library
*
* Copyright (C) 2001, 2010 Niels Mller
*
* The nettle 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 nettle 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 nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
/* Modelled after the sha1.c code by Peter Gutmann. */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "sha.h"
#include "macros.h"
/* A block, treated as a sequence of 64-bit words. */
#define SHA512_DATA_LENGTH 16
#define ROTR(n,x) ((x)>>(n) | ((x)<<(64-(n))))
#define SHR(n,x) ((x)>>(n))
/* The SHA512 functions. The Choice function is the same as the SHA1
function f1, and the majority function is the same as the SHA1 f3
function, and the same as for SHA256. */
#define Choice(x,y,z) ( (z) ^ ( (x) & ( (y) ^ (z) ) ) )
#define Majority(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
#define S0(x) (ROTR(28,(x)) ^ ROTR(34,(x)) ^ ROTR(39,(x)))
#define S1(x) (ROTR(14,(x)) ^ ROTR(18,(x)) ^ ROTR(41,(x)))
#define s0(x) (ROTR(1,(x)) ^ ROTR(8,(x)) ^ SHR(7,(x)))
#define s1(x) (ROTR(19,(x)) ^ ROTR(61,(x)) ^ SHR(6,(x)))
/* Generated by the gp script
{
print("obase=16");
for (i = 1,80,
root = prime(i)^(1/3);
fraction = root - floor(root);
print(floor(2^64 * fraction));
);
quit();
}
piped through
|grep -v '^[' | bc \
|awk '{printf("0x%sULL,%s", $1, NR%3 == 0 ? "\n" : "");}'
to convert it to hex.
*/
static const uint64_t
K[80] =
{
0x428A2F98D728AE22ULL,0x7137449123EF65CDULL,
0xB5C0FBCFEC4D3B2FULL,0xE9B5DBA58189DBBCULL,
0x3956C25BF348B538ULL,0x59F111F1B605D019ULL,
0x923F82A4AF194F9BULL,0xAB1C5ED5DA6D8118ULL,
0xD807AA98A3030242ULL,0x12835B0145706FBEULL,
0x243185BE4EE4B28CULL,0x550C7DC3D5FFB4E2ULL,
0x72BE5D74F27B896FULL,0x80DEB1FE3B1696B1ULL,
0x9BDC06A725C71235ULL,0xC19BF174CF692694ULL,
0xE49B69C19EF14AD2ULL,0xEFBE4786384F25E3ULL,
0xFC19DC68B8CD5B5ULL,0x240CA1CC77AC9C65ULL,
0x2DE92C6F592B0275ULL,0x4A7484AA6EA6E483ULL,
0x5CB0A9DCBD41FBD4ULL,0x76F988DA831153B5ULL,
0x983E5152EE66DFABULL,0xA831C66D2DB43210ULL,
0xB00327C898FB213FULL,0xBF597FC7BEEF0EE4ULL,
0xC6E00BF33DA88FC2ULL,0xD5A79147930AA725ULL,
0x6CA6351E003826FULL,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,
0x6F067AA72176FBAULL,0xA637DC5A2C898A6ULL,
0x113F9804BEF90DAEULL,0x1B710B35131C471BULL,
0x28DB77F523047D84ULL,0x32CAAB7B40C72493ULL,
0x3C9EBE0A15C9BEBCULL,0x431D67C49C100D4CULL,
0x4CC5D4BECB3E42B6ULL,0x597F299CFC657E2AULL,
0x5FCB6FAB3AD6FAECULL,0x6C44198C4A475817ULL,
};
/* The initial expanding function. The hash function is defined over
an 64-word expanded input array W, where the first 16 are copies of
the input data, and the remaining 64 are defined by
W[ t ] = s1(W[t-2]) + W[t-7] + s0(W[i-15]) + W[i-16]
This implementation generates these values on the fly in a circular
buffer.
*/
#define EXPAND(W,i) \
( W[(i) & 15 ] += (s1(W[((i)-2) & 15]) + W[((i)-7) & 15] + s0(W[((i)-15) & 15])) )
/* The prototype SHA sub-round. The fundamental sub-round is:
T1 = h + S1(e) + Choice(e,f,g) + K[t] + W[t]
T2 = S0(a) + Majority(a,b,c)
a' = T1+T2
b' = a
c' = b
d' = c
e' = d + T1
f' = e
g' = f
h' = g
but this is implemented by unrolling the loop 8 times and renaming
the variables
( h, a, b, c, d, e, f, g ) = ( a, b, c, d, e, f, g, h ) each
iteration. This code is then replicated 8, using the next 8 values
from the W[] array each time */
/* It's crucial that DATA is only used once, as that argument will
* have side effects. */
#define ROUND(a,b,c,d,e,f,g,h,k,data) do { \
uint64_t T = h + S1(e) + Choice(e,f,g) + k + data; \
d += T; \
h = T + S0(a) + Majority(a,b,c); \
} while (0)
void
sha512_init(struct sha512_ctx *ctx)
{
/* Initial values, generated by the gp script
{
for (i = 1,8,
root = prime(i)^(1/2);
fraction = root - floor(root);
print(floor(2^64 * fraction));
);
}
. */
static const uint64_t H0[_SHA512_DIGEST_LENGTH] =
{
0x6A09E667F3BCC908ULL,0xBB67AE8584CAA73BULL,
0x3C6EF372FE94F82BULL,0xA54FF53A5F1D36F1ULL,
0x510E527FADE682D1ULL,0x9B05688C2B3E6C1FULL,
0x1F83D9ABFB41BD6BULL,0x5BE0CD19137E2179ULL,
};
memcpy(ctx->state, H0, sizeof(H0));
/* Initialize bit count */
ctx->count_low = ctx->count_high = 0;
/* Initialize buffer */
ctx->index = 0;
}
/* Perform the SHA transformation. Note that this function destroys
the data area */
static void
sha512_transform(uint64_t *state, uint64_t *data)
{
/* FIXME: XXX Just copied from sha256. */
uint64_t A, B, C, D, E, F, G, H; /* Local vars */
unsigned i;
const uint64_t *k;
uint64_t *d;
/* Set up first buffer and local data buffer */
A = state[0];
B = state[1];
C = state[2];
D = state[3];
E = state[4];
F = state[5];
G = state[6];
H = state[7];
/* Heavy mangling */
/* First 16 subrounds that act on the original data */
for (i = 0, k = K, d = data; i<16; i+=8, k += 8, d+= 8)
{
ROUND(A, B, C, D, E, F, G, H, k[0], d[0]);
ROUND(H, A, B, C, D, E, F, G, k[1], d[1]);
ROUND(G, H, A, B, C, D, E, F, k[2], d[2]);
ROUND(F, G, H, A, B, C, D, E, k[3], d[3]);
ROUND(E, F, G, H, A, B, C, D, k[4], d[4]);
ROUND(D, E, F, G, H, A, B, C, k[5], d[5]);
ROUND(C, D, E, F, G, H, A, B, k[6], d[6]);
ROUND(B, C, D, E, F, G, H, A, k[7], d[7]);
}
for (; i<80; i += 16, k+= 16)
{
ROUND(A, B, C, D, E, F, G, H, k[ 0], EXPAND(data, 0));
ROUND(H, A, B, C, D, E, F, G, k[ 1], EXPAND(data, 1));
ROUND(G, H, A, B, C, D, E, F, k[ 2], EXPAND(data, 2));
ROUND(F, G, H, A, B, C, D, E, k[ 3], EXPAND(data, 3));
ROUND(E, F, G, H, A, B, C, D, k[ 4], EXPAND(data, 4));
ROUND(D, E, F, G, H, A, B, C, k[ 5], EXPAND(data, 5));
ROUND(C, D, E, F, G, H, A, B, k[ 6], EXPAND(data, 6));
ROUND(B, C, D, E, F, G, H, A, k[ 7], EXPAND(data, 7));
ROUND(A, B, C, D, E, F, G, H, k[ 8], EXPAND(data, 8));
ROUND(H, A, B, C, D, E, F, G, k[ 9], EXPAND(data, 9));
ROUND(G, H, A, B, C, D, E, F, k[10], EXPAND(data, 10));
ROUND(F, G, H, A, B, C, D, E, k[11], EXPAND(data, 11));
ROUND(E, F, G, H, A, B, C, D, k[12], EXPAND(data, 12));
ROUND(D, E, F, G, H, A, B, C, k[13], EXPAND(data, 13));
ROUND(C, D, E, F, G, H, A, B, k[14], EXPAND(data, 14));
ROUND(B, C, D, E, F, G, H, A, k[15], EXPAND(data, 15));
}
/* Update state */
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
state[4] += E;
state[5] += F;
state[6] += G;
state[7] += H;
}
static void
sha512_block(struct sha512_ctx *ctx, const uint8_t *block)
{
uint64_t data[SHA512_DATA_LENGTH];
int i;
/* Update block count */
if (!++ctx->count_low)
++ctx->count_high;
/* Endian independent conversion */
for (i = 0; i<SHA512_DATA_LENGTH; i++, block += 8)
data[i] = READ_UINT64(block);
sha512_transform(ctx->state, data);
}
void
sha512_update(struct sha512_ctx *ctx,
unsigned length, const uint8_t *buffer)
{
if (ctx->index)
{ /* Try to fill partial block */
unsigned left = SHA512_DATA_SIZE - ctx->index;
if (length < left)
{
memcpy(ctx->block + ctx->index, buffer, length);
ctx->index += length;
return; /* Finished */
}
else
{
memcpy(ctx->block + ctx->index, buffer, left);
sha512_block(ctx, ctx->block);
buffer += left;
length -= left;
}
}
while (length >= SHA512_DATA_SIZE)
{
sha512_block(ctx, buffer);
buffer += SHA512_DATA_SIZE;
length -= SHA512_DATA_SIZE;
}
/* Buffer leftovers */
memcpy(ctx->block, buffer, length);
ctx->index = length;
}
/* Final wrapup - pad to SHA1_DATA_SIZE-byte boundary with the bit pattern
1 0* (64-bit count of bits processed, MSB-first) */
static void
sha512_final(struct sha512_ctx *ctx)
{
uint64_t data[SHA512_DATA_LENGTH];
int i;
int words;
i = ctx->index;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
assert(i < SHA512_DATA_SIZE);
ctx->block[i++] = 0x80;
/* Fill rest of word */
for( ; i & 7; i++)
ctx->block[i] = 0;
/* i is now a multiple of the word size 8 */
words = i >> 3;
for (i = 0; i < words; i++)
data[i] = READ_UINT64(ctx->block + 8*i);
if (words > (SHA512_DATA_LENGTH-2))
{ /* No room for length in this block. Process it and
* pad with another one */
for (i = words ; i < SHA512_DATA_LENGTH; i++)
data[i] = 0;
sha512_transform(ctx->state, data);
for (i = 0; i < (SHA512_DATA_LENGTH-2); i++)
data[i] = 0;
}
else
for (i = words ; i < SHA512_DATA_LENGTH - 2; i++)
data[i] = 0;
/* There are 1024 = 2^10 bits in one block */
data[SHA512_DATA_LENGTH-2] = (ctx->count_high << 10) | (ctx->count_low >> 54);
data[SHA512_DATA_LENGTH-1] = (ctx->count_low << 10) | (ctx->index << 3);
sha512_transform(ctx->state, data);
}
void
sha512_digest(struct sha512_ctx *ctx,
unsigned length,
uint8_t *digest)
{
unsigned i;
unsigned words;
unsigned leftover;
assert(length <= SHA512_DIGEST_SIZE);
sha512_final(ctx);
words = length / 8;
leftover = length % 8;
for (i = 0; i < words; i++, digest += 8)
WRITE_UINT64(digest, ctx->state[i]);
if (leftover)
{
uint64_t word;
unsigned j = leftover;
assert(i < _SHA512_DIGEST_LENGTH);
word = ctx->state[i];
switch (leftover)
{
default:
abort();
case 7:
digest[--j] = (word >> 8) & 0xff;
/* Fall through */
case 6:
digest[--j] = (word >> 16) & 0xff;
/* Fall through */
case 5:
digest[--j] = (word >> 24) & 0xff;
/* Fall through */
case 4:
digest[--j] = (word >> 32) & 0xff;
case 3:
digest[--j] = (word >> 40) & 0xff;
/* Fall through */
case 2:
digest[--j] = (word >> 48) & 0xff;
/* Fall through */
case 1:
digest[--j] = (word >> 56) & 0xff;
}
}
sha512_init(ctx);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment