Better crypto hash functions, long, with code

B

Bryan Olson

The current Python standard library provides two cryptographic
hash functions: MD5 and SHA-1 [1]. The authors of MD5 originally
stated:

It is conjectured that it is computationally infeasible to
produce two messages having the same message digest. [2]

That conjecture is false, as demonstrated by Wang, Feng, Lai and
Yu in 2004 [3]. Just recently, Wang, Yu, and Lin showed a short-
cut solution for finding collisions in SHA-1 [4]. Their result
won the best-paper award at Crypto 2005, and a subsequent
improvement reduced the work for collision-search to 2**63 [5].

NIST is looking into what to do about cryptographic hash
functions [6]. The crypto community is generally accepting that
we built them too close to the edge of what we knew how to
break. For the time being, the best candidates appear to be the
more recent members of SHA family [7][8].


I'm a crypto engineer by trade, so I implemented the current SHA
functions for Python. I'd like to get them into the Python
standard library. The implementation consists of two files: an
extension module written in C implementing the low-level bit-
banging, and a Python-language module implementing a new-style
class interface. The interface follows a tweaked version of the
API offered by the current Python library modules 'md5' and
'sha'.

The code for the two files follows my signature below.

I intend the code to be super-portable, and somewhat efficient
and tunable. My cross-platform testing is limited, so I'd be
grateful for results and tweaks that Pythoners can provide.

I'm a bit older than the median for Python programmers, but I'm
trying some of those newfangled features that the kids are into
these days. If there are better ways to do things, let me know.
I like to think I'm not too old a dog to learn new tricks.


References:
[1] http://docs.python.org/lib/crypto.html
[2] RFC 1321 "The MD5 Message-Digest Algorithm"
[3] Xiaoyun Wang, Dengguo Feng, Xuejia Lai, Hongbo Yu;
/Collisions for Hash Functions MD4, MD5, HAVAL-128 and RIPEMD;
http://eprint.iacr.org/2004/199.pdf
[4] Xiaoyun Wang, Yiqun Lisa Yin, and Hongbo Yu; /Finding
Collisions in the Full SHA-1/; Crypto 2005.
[5] http://www.iacr.org/conferences/crypto2005/
[6] http://www.csrc.nist.gov/pki/HashWorkshop/index.html
[7] FIPS 180-2;
http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
[8] FIPS 180-2, Change notice 1;

http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf


--Bryan

---------------------- cut ------------------------------
#!/usr/bin/env python

# smd.py by Bryan G. Olson, 2005.
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Python itself.

"""
smd -- Secure Message Digest algorithms, and utility functions.

In short:

To compute the digest of a message using SHA-256:

digest = smd.SHA256.hash(message)

Or you can pass the message a piece at a time:

hasher = smd.SHA256.new()
hasher.update(message_part_1)
hasher.update(message_part_2)
# ...
hasher.update(message_part_n)
digest = hasher.digest()

The other cryptographic hashes provide the same interface. The
module currently provides:

SHA1 (A.K.A. SHA160), SHA224, SHA256, SHA384, and SHA512

as defined in FIPS 180-2, including Change Notice 1. As of this
writing, SHA-256 is the when-in-doubt-use crypto hash function.


In detail:

The module provides classes and functions. The functions are:

string_to_hex(str): Return a string with two hex digits for
each byte of str, representing the ord() of the byte. The
case of the hex digits A-F/a-f is up to Python's built-in
formatting; Python doc doesn't specify the case, so it may
be either and may change.

oid_to_der(arc_sequence): Return the DER encoding of an OID,
including the encoded tag and length.

smd_from_oid(oid): Look up and return the Secure Message
Digest class corresponding to the oid, or None if no such
class is known. The oid may be a sequence of integer arcs,
or a string holding the DER encoding.


Secure Message Digests are implemented as Python classes. All
the classes and their instances objects have attributes:

digest_size_bits: the size of the digest in bits. For hash
functions that output a user-selected digest size, this is
be the largest available size, up to sys.maxint.

digest_size: the size of the resulting digest in bytes. This
is the smallest number of bytes that can hold the digest,
though all currently popular hash functions output a bit-
size evenly divisible by 8.

A Secure Message Digest will have any of the following
attributes that are defined by standard or convention:

oid: The ASN.1 object identifier. An OID is a sequence of
integer 'arcs', represented here by a tuple of integers.

oid_der: The DER encoding of the OID.

hmac_block_len: The internal bock length, in bytes, of a
Merkle-Damgard hash function, as needed to define HMAC (see
RFC 2104).

The Secure Message Digest classes have class-methods:

hash(message): Return the digest of the message.

new(): Return an instance object.

For backward compatibility, new() can also take a string
parameter to pass to the new instance's update(), but
that usage is deprecated. Future hash functions are
likely to take a string parameter for other reasons, and
we want to avoid any confusion. The major reason that
the old interface accepted a string here was to allow
hashing in one line with something like:

digest = sha.new(message).digest()

That's no longer needed, as we now support one-line
hashing with a classmethod, as in:

digest = SHA1.hash(message)


Instances have the methods:

update(message_part): Update the instance's state with the
next part of the message to be hashed. The entire message is
the concatenation of all the message parts.

digest(): Return the digest of the message passed to
update() so far. The call does not change the state of the
object, so you can still pass more data to update() and
get the digest() of the extended message.

digest([extra_bits=0, n_extra=0]): Actually the same call as
above, but allows hashing of messages that have bit-lengths
that are not multiples of 8. Some hash functions may not
support such lengths. The extra_bits parameter must be an
integer in the range [0, 256), and n_extra must be an
integer in the range [0, 8). The extra bits are taken from
the low-order n_bits of extra_bits, most-significant bit
first. Even when extra bits are passed, the digest() call
does not change the state of the instance.

copy(): Return an instance that has seen the same message,
as passed to update(), so far. After the copy, the two
instances are independent. The method allows efficient
computation of digests of messages that share a common
initial substring.

hexdigest([extra_bits=0, n_extra=0]): This method is
deprecated. It returns
string_to_hex(digest(extra_bits, n_extra)).


The low-level implementation of the hash functions in a
Python extension module, written in C.

If you are implementing a Secure Message Digest and want to
leverage this module, read the string in smd.implementors_doc.
"""

# The actual hash-function implementations are in an extention module
import sha2_ext

# We have one bit of updatable shared data.
try:
import thread
except ImportError:
import dummy_thread as thread


def oid_to_der(arc_sequence):
""" Given the arcs of an OID, return the DER encoding.
"""
def to_base128(n):
bytes = [n & 0x7F]
while n > 127:
n >>= 7
bytes.append(n & 0x7F | 0x80)
bytes.reverse()
return bytes
val = [40 * arc_sequence[0] + arc_sequence[1]]
for arc in arc_sequence[2:]:
val.extend(to_base128(arc))
length = len(val)
if length < 128:
len_encoded = [length]
else:
len_encoded = []
while length:
len_encoded.append(length & 0xFF)
length >>= 8
len_encoded.append(len(len_encoded) | 0x80)
len_encoded.reverse()
bytes = ''.join([chr(ch) for ch in [6] + len_encoded + val])
return bytes


_oid_dict = {}
_oid_dict_lock = thread.allocate_lock()

implementors_doc = """
If you are implementing a Secure Message Digest class, you'll
want to know what behaviors you can count on, to avoid depending
upon implementation details that may change. If you inherit from
SMD_Base:

SMD_Base will implement hexdigest() as it does below, by
calling digest() and converting the result to hex.

SMD_Base will implement the classmethod 'hash(message)' as
it does below. It will instantiate the class, then call
init(), update(message), then return digest().

The SMD_Base new() method will not change in ways that break
your code without good reason.

If your class (not just an object of you class) has an
attribute 'digest_size_bits', the metaclass will
automatically set its 'digest_size' to (digest_size_bits +
7) // 8.

If your class (not just an object of you class) has an
attribute 'oid', the metaclass will automatically set its
'oid_der', and register your OID so that
smd_from_oid(your_OID) will return your class.
"""


class _SMD_Metaclass_ (type):

def __init__(cls, name, bases, dct):
super(_SMD_Metaclass_, cls).__init__(name, bases, dct)
cls.digest_size = (cls.digest_size_bits + 7) // 8
if hasattr(cls, 'oid'):
cls.oid_der = oid_to_der(cls.oid)
_oid_dict_lock.acquire()
_oid_dict[cls.oid_der] = cls
_oid_dict_lock.release()


class SMD_Base (object):

__metaclass__ = _SMD_Metaclass_

digest_size_bits = 0

hmac_block_len = 1

oid = (0, 0, 0)

def __init__(self):
pass

def update(self, string):
pass

def digest(self, extrabits=0, n_extra=0):
return ''

@classmethod
def hash(cls, data_string, extrabits=0, n_extra=0):
hasher = cls()
hasher.update(data_string)
return hasher.digest(extrabits, n_extra)

@classmethod
def new(cls, s=''):
return cls(s)

def hexdigest(self):
# Method is depricated.
digest = string_to_hex(self.digest())


class SHA_Base_(SMD_Base):

def __init__(self, s='', clone=None):
if clone:
assert clone.__class__ == self.__class__
self._hasher = clone._hasher.copy()
else:
self.init_hasher_()
self.update(s)

def update(self, data):
self._hasher.update(data)

def digest(self, extra_bits=0, n_extra=0):
s = self._hasher.digest(0, 0)
return self._hasher.digest(extra_bits, n_extra)[: self.digest_size]

def copy(self):
return self.__class__('', self)


class SHA1 (SHA_Base_):
digest_size_bits = 160
hmac_block_len = 64
oid = (1, 3, 14, 3, 2, 26)

def init_hasher_(self):
self._hasher = sha2_ext.SHA160()
self._hasher.init()

SHA160 = SHA1


class SHA256 (SHA_Base_):

digest_size_bits = 256
hmac_block_len = 64
oid = (2, 16, 840, 1, 101, 3, 4, 2, 1)

def init_hasher_(self):
self._hasher = sha2_ext.SHA256()
self._hasher.init(self.digest_size_bits)


class SHA224 (SHA256):

digest_size_bits = 224
oid = (2, 16, 840, 1, 101, 3, 4, 2, 4)


class SHA512 (SHA_Base_):

digest_size_bits = 512
hmac_block_len = 128
oid = (2, 16, 840, 1, 101, 3, 4, 2, 3)

def init_hasher_(self):
self._hasher = sha2_ext.SHA512()
self._hasher.init(self.digest_size_bits)


class SHA384 (SHA512):

digest_size_bits = 384
oid = (2, 16, 840, 1, 101, 3, 4, 2, 2)

def string_to_hex(str):
return ''.join(['%02x' % ord(ch) for ch in str])


def smd_from_oid(oid):
if type(oid) != type(''):
oid = oid_to_der(oid)
_oid_dict_lock.acquire()
result = _oid_dict.get(oid, None)
_oid_dict_lock.release()
return result


def test():
million_a = 'a' * 1000000

sha1_vectors = [
( 'abc',
'a9993e364706816aba3e25717850c26c9cd0d89d'
),
( 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
'84983e441c3bd26ebaae4aa1f95129e5e54670f1'
),
( million_a,
'34aa973cd4c4daa4f61eeb2bdbad27316534016f'
)]

sha256_vectors = [
( 'abc',

'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
),
( 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',

'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1'
),
( million_a,

'cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0'
)]
sha224_vectors = [
( 'abc',
'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'
),
( 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
'75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525'
),
( million_a,
'20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67'
)]

sha384_vectors = [
( 'abc',

'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'
),
(
'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu',

'09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039'
),
( million_a,

'9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985'
)]

sha512_vectors = [
( 'abc',

'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'
),
(
'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu',

'8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909'
),
( million_a,

'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b'
)]

for (mdf, vectors) in ((SHA1, sha1_vectors), (SHA256,
sha256_vectors), (SHA224, sha224_vectors),
(SHA384, sha384_vectors), (SHA512, sha512_vectors)):
for (preimage, reference_digest) in vectors:
h1 = mdf.new()
h1.update(preimage)
digest = string_to_hex(h1.digest()).lower()
assert digest == reference_digest
if len(preimage) < 99999:
h1 = mdf.new(preimage[: 17])
h2 = h1.copy()
h1.update('some different suffix')
h2.update(preimage[17 :])
digest = string_to_hex(h2.digest()).lower()
assert digest == reference_digest

if __name__ == '__main__':
test()
print "It's all good."

---------------------- cut ------------------------------

/*
* sha2_ext.c, by Bryan Olson, 2002 - 2005.
* This code is free software; you can redistribute it and/or modify
* it under the same terms as Python itself.
*
* Python extention module for the hash functions in FIPS 180-2
* including Change Notice 1.
*
* Designed to be called only from the smd.py module, which then
* provides the hash algorithms to other Python code.
*
*/

/**********************************************************
*
* Some parameters you may wish to tune for your platform.
*/

/* Define as true to build debug version with non-debug Python libs. */
#define LINK_TO_NON_DEBUG_PYTHON 1


/*
Define the following as true to unroll the inner loops of the
various hash algorithms. The unrolled code is larger, but often
faster.

Unrolling SHA-512 is generally a loser on machines that don't
support a 64-bit (or larger) word; support means the hardware,
not just the compiler. UNROLL_SHA_512 has no effect if we cannot
find compiler suport for 64-bit words (see SHA_USE_64_BIT_WORD).
*/
#define UNROLL_SHA_1 1
#define UNROLL_SHA_256 1
#define UNROLL_SHA_512 0


#ifdef _DEBUG
#if LINK_TO_NON_DEBUG_PYTHON
/* Trick to avoid need for debug build of Python */
#undef _DEBUG
#include "Python.h"
#define _DEBUG 1
#endif
#else
#include "Python.h"
#endif

#include <stdlib.h>

/* Need these defined early. */
typedef unsigned long SHA_Word32;
#define MASK32(x) ((x) & 0xFFFFFFFFUL)



/**********************************************************
*
* Some compiler checks.
*/

/* Use compiler-specific 32-bit rotate if available. */

#if defined(_MSC_VER) && (_MSC_VER >= 1200)

/* Microsoft Compiler, version 6 or higher */
#pragma intrinsic(_rotl, _rotr)
#define R32L(x, n) _rotl(x, n)
#define R32R(x, n) _rotr(x, n)

#else

/* Clever compilers will optimize to a rotate. */
#define R32L(x, n) MASK32(((x) << (n)) | ((x) >> (32 - (n))))
#define R32R(x, n) MASK32(((x) >> (n)) | ((x) << (32 - (n))))

#endif


/* Use 64-bit word if available -- a big win for SHA-512/384. */

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

/* Our first choice is standard C99 */
#define SHA_USE_64_BIT_WORD 1
#define SHA_Word64 unsigned long long
#define SHA_UI64(x) x ## ULL

#elif defined(__GNUC__)

/* Gnu C compiler, pre-C99
We should check for the version here.
Need advice on what pre-C99 versions supported "unsigned long
long".
*/
#define SHA_USE_64_BIT_WORD 1
#define SHA_Word64 unsigned long long
#define SHA_UI64(x) x ## ULL

#elif defined(_MSC_VER) && (_MSC_VER >= 1200)

/* Microsoft Compiler, version 6.
Might work with prior versions; need advice. */
#define SHA_USE_64_BIT_WORD 1
#define SHA_Word64 unsigned __int64
#define SHA_UI64(x) x ## ui64

#elif defined(__BCPLUSPLUS__)

/* Borland Compiler.
Not tested; supposed to work like MSVC.
Need advice on what pre-C99 versions support unsigned __int64.
*/
#define SHA_USE_64_BIT_WORD 1
#define SHA_Word64 unsigned __int64
#define SHA_UI64(x) x ## ui64

#else

/* We do not have a 64-bit unsigned integer. Build our own */
#define SHA_USE_64_BIT_WORD 0
typedef SHA_Word32 SHA_Word64[2];

#endif

/* Use compiler-specific 64-bit right-rotate if available. */

#if SHA_USE_64_BIT_WORD

#if 0

/* If you have a compiler with a 64-bit rotate, check for it
and define SHA_ROT64R here. SHA-384/512 never uses left-rotate.
*/

#else

#define SHA_ROT64R(x, n) SHA_MASK64(((x) >> n) | ((x) << (64 -
(n))))

#endif

#endif


/**********************************************************
*
* Hashing state types.
*/

typedef struct SHA160_State {
SHA_Word32 chain[5]; /* Message chain */
SHA_Word32 size[2]; /* 64-bit byte count */
unsigned char buffer[64]; /* input data buffer */
} SHA160_State;

typedef struct SHA256_State {
SHA_Word32 chain[8]; /* Message chain */
SHA_Word32 size[2]; /* 64-bit byte count */
unsigned char buffer[64]; /* input data buffer */
} SHA256_State;

typedef struct SHA512_State {
SHA_Word64 chain[8]; /* Message chain */
SHA_Word32 size[4]; /* 128-bit byte count */
unsigned char buffer[128]; /* input data buffer */
} SHA512_State;


/**********************************************************
*
* Generic utilities.
*/


static void words_to_bytes(const SHA_Word32* p_w,
unsigned char* p_b,
int n_words)
{
while (n_words--) {
*p_b++ = (unsigned char)((*p_w >> 24) & 0xFF);
*p_b++ = (unsigned char)((*p_w >> 16) & 0xFF);
*p_b++ = (unsigned char)((*p_w >> 8) & 0xFF);
*p_b++ = (unsigned char)(*p_w++ & 0xFF);
}
}

static void update_counters(SHA_Word32* p_counts,
int n_counts,
size_t n_bytes,
int n_extra)
{
SHA_Word32 hi, low;

hi = n_bytes >> 29;
low = MASK32(n_bytes << 3) + (unsigned)n_extra;

--n_counts;
p_counts[n_counts] = MASK32(p_counts[n_counts] + low);
if (p_counts[n_counts] < low)
++hi;

while (hi && n_counts > 0) {
--n_counts;
p_counts[n_counts] = MASK32(p_counts[n_counts] + hi);
hi = p_counts[n_counts] >= hi ? 0 : 1;
}
}



/******************************************************************
*
* SHA-1 Compression function.
*/


/* SHA1 initial chaning values */
static const SHA_Word32 SHA_1_chain_inits[5] =
{
0x67452301UL,
0xEFCDAB89UL,
0x98BADCFEUL,
0x10325476UL,
0xC3D2E1F0UL
};

/* SHA-1 Round constants */
#define K1 0x5A827999UL
#define K2 0x6ED9EBA1UL
#define K3 0x8F1BBCDCUL
#define K4 0xCA62C1D6UL

/* The SHA-1 "F" functions */
#define F1(b, c, d) (d ^ (b & (c ^ d)))
#define F2(b, c, d) (b ^ c ^ d)
#define F3(b, c, d) ((b & c) | (d & (b | c)))
#define F4 F2

#define S1W1(i) (w = ((SHA_Word32)p[4*i] << 24) | (p[4*i + 1] << 16)
| (p[4*i + 2] << 8) | p[4*i + 3])
#define S1W2(i) (w[i & 15] = R32L(w[i & 15] ^ w[(i + 2) & 15] ^ w[(i +
8) & 15] ^ w[(i + 13) & 15], 1))


#if UNROLL_SHA_1

#define S1ROUND(k, w, A, B, C, D, E) E = MASK32(E + R32L(A, 5) + F##k(B,
C, D) + w + K##k); B = R32L(B, 30)

/*
* The SHA-1 "compression function"
*/
static void SHA160_block_function(
SHA_Word32 chain[5],
const unsigned char* p,
size_t size)
{
register SHA_Word32 a, b, c, d, e;
SHA_Word32 w[16];
const unsigned char* p_end = p + size;

while (p != p_end) {

/* Copy current values of chaining variables. */
a = chain[0];
b = chain[1];
c = chain[2];
d = chain[3];
e = chain[4];

S1ROUND(1, S1W1(0), a, b, c, d, e);
S1ROUND(1, S1W1(1), e, a, b, c, d);
S1ROUND(1, S1W1(2), d, e, a, b, c);
S1ROUND(1, S1W1(3), c, d, e, a, b);
S1ROUND(1, S1W1(4), b, c, d, e, a);
S1ROUND(1, S1W1(5), a, b, c, d, e);
S1ROUND(1, S1W1(6), e, a, b, c, d);
S1ROUND(1, S1W1(7), d, e, a, b, c);
S1ROUND(1, S1W1(8), c, d, e, a, b);
S1ROUND(1, S1W1(9), b, c, d, e, a);
S1ROUND(1, S1W1(10), a, b, c, d, e);
S1ROUND(1, S1W1(11), e, a, b, c, d);
S1ROUND(1, S1W1(12), d, e, a, b, c);
S1ROUND(1, S1W1(13), c, d, e, a, b);
S1ROUND(1, S1W1(14), b, c, d, e, a);
S1ROUND(1, S1W1(15), a, b, c, d, e);

S1ROUND(1, S1W2(0), e, a, b, c, d);
S1ROUND(1, S1W2(1), d, e, a, b, c);
S1ROUND(1, S1W2(2), c, d, e, a, b);
S1ROUND(1, S1W2(3), b, c, d, e, a);

S1ROUND(2, S1W2(4), a, b, c, d, e);
S1ROUND(2, S1W2(5), e, a, b, c, d);
S1ROUND(2, S1W2(6), d, e, a, b, c);
S1ROUND(2, S1W2(7), c, d, e, a, b);
S1ROUND(2, S1W2(8), b, c, d, e, a);
S1ROUND(2, S1W2(9), a, b, c, d, e);
S1ROUND(2, S1W2(10), e, a, b, c, d);
S1ROUND(2, S1W2(11), d, e, a, b, c);
S1ROUND(2, S1W2(12), c, d, e, a, b);
S1ROUND(2, S1W2(13), b, c, d, e, a);
S1ROUND(2, S1W2(14), a, b, c, d, e);
S1ROUND(2, S1W2(15), e, a, b, c, d);
S1ROUND(2, S1W2(0), d, e, a, b, c);
S1ROUND(2, S1W2(1), c, d, e, a, b);
S1ROUND(2, S1W2(2), b, c, d, e, a);
S1ROUND(2, S1W2(3), a, b, c, d, e);
S1ROUND(2, S1W2(4), e, a, b, c, d);
S1ROUND(2, S1W2(5), d, e, a, b, c);
S1ROUND(2, S1W2(6), c, d, e, a, b);
S1ROUND(2, S1W2(7), b, c, d, e, a);

S1ROUND(3, S1W2(8), a, b, c, d, e);
S1ROUND(3, S1W2(9), e, a, b, c, d);
S1ROUND(3, S1W2(10), d, e, a, b, c);
S1ROUND(3, S1W2(11), c, d, e, a, b);
S1ROUND(3, S1W2(12), b, c, d, e, a);
S1ROUND(3, S1W2(13), a, b, c, d, e);
S1ROUND(3, S1W2(14), e, a, b, c, d);
S1ROUND(3, S1W2(15), d, e, a, b, c);
S1ROUND(3, S1W2(0), c, d, e, a, b);
S1ROUND(3, S1W2(1), b, c, d, e, a);
S1ROUND(3, S1W2(2), a, b, c, d, e);
S1ROUND(3, S1W2(3), e, a, b, c, d);
S1ROUND(3, S1W2(4), d, e, a, b, c);
S1ROUND(3, S1W2(5), c, d, e, a, b);
S1ROUND(3, S1W2(6), b, c, d, e, a);
S1ROUND(3, S1W2(7), a, b, c, d, e);
S1ROUND(3, S1W2(8), e, a, b, c, d);
S1ROUND(3, S1W2(9), d, e, a, b, c);
S1ROUND(3, S1W2(10), c, d, e, a, b);
S1ROUND(3, S1W2(11), b, c, d, e, a);


S1ROUND(4, S1W2(12), a, b, c, d, e);
S1ROUND(4, S1W2(13), e, a, b, c, d);
S1ROUND(4, S1W2(14), d, e, a, b, c);
S1ROUND(4, S1W2(15), c, d, e, a, b);
S1ROUND(4, S1W2(0), b, c, d, e, a);
S1ROUND(4, S1W2(1), a, b, c, d, e);
S1ROUND(4, S1W2(2), e, a, b, c, d);
S1ROUND(4, S1W2(3), d, e, a, b, c);
S1ROUND(4, S1W2(4), c, d, e, a, b);
S1ROUND(4, S1W2(5), b, c, d, e, a);
S1ROUND(4, S1W2(6), a, b, c, d, e);
S1ROUND(4, S1W2(7), e, a, b, c, d);
S1ROUND(4, S1W2(8), d, e, a, b, c);
S1ROUND(4, S1W2(9), c, d, e, a, b);
S1ROUND(4, S1W2(10), b, c, d, e, a);
S1ROUND(4, S1W2(11), a, b, c, d, e);
S1ROUND(4, S1W2(12), e, a, b, c, d);
S1ROUND(4, S1W2(13), d, e, a, b, c);
S1ROUND(4, S1W2(14), c, d, e, a, b);
S1ROUND(4, S1W2(15), b, c, d, e, a);

/* Update chaining variables */
chain[0] = MASK32(chain[0] + a);
chain[1] = MASK32(chain[1] + b);
chain[2] = MASK32(chain[2] + c);
chain[3] = MASK32(chain[3] + d);
chain[4] = MASK32(chain[4] + e);

p += 64;
}
}


#else /* Do not fully unroll SHA-1 */

#define S1ROUND(f, k) \
{ \
temp = MASK32(R32L(a, 5) + (f) + e + w + (k)); \
e = d; \
d = c; \
c = R32L(b, 30); \
b = a; \
a = temp; \
}

static void SHA160_block_function(
SHA_Word32 chain[5],
const unsigned char* p_data,
size_t size)
{
int i;
SHA_Word32 a, b, c, d, e; /* working vars */
SHA_Word32 w[80];
SHA_Word32 temp;
const unsigned char* p_end = p_data + size;

while (p_data != p_end) {

/* Set up first buffer and local data buffer */
a = chain[0];
b = chain[1];
c = chain[2];
d = chain[3];
e = chain[4];

for (i=0; i<16; ++i) {
w = (p_data[0] << 24) | (p_data[1] << 16)
| (p_data[2] << 8) | p_data[3];
p_data += 4;
S1ROUND(d ^ (b & (c ^ d)), K1);
}

for (; i<20; ++i) {
w = R32L(w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3], 1);
S1ROUND(d ^ (b & (c ^ d)), K1);
}

for (; i<40; ++i) {
w = R32L(w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3], 1);
S1ROUND(b ^ c ^ d, K2);
}

for (; i<60; ++i) {
w = R32L(w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3], 1);
S1ROUND((b & c) | (d & (b | c)), K3);
}

for (; i<80; ++i) {
w = R32L(w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3], 1);
S1ROUND(b ^ c ^ d, K4);
}

/* Update chaining variables */
chain[0] = MASK32(chain[0] + a);
chain[1] = MASK32(chain[1] + b);
chain[2] = MASK32(chain[2] + c);
chain[3] = MASK32(chain[3] + d);
chain[4] = MASK32(chain[4] + e);
}
}

#endif /* UNROLL_SHA_1 */



static void SHA_1_256_update(SHA_Word32* p_chain,
unsigned char* buffer,
SHA_Word32* counts,
const unsigned char* p_text,
size_t size,
void block_func(SHA_Word32*, const unsigned char*, size_t))
{
unsigned int i = ((unsigned)counts[1] >> 3) % 64, j = 0;

while (i < 64 && j < size)
buffer[i++] = p_text[j++];

if (i == 64)
block_func(p_chain, buffer, 64);

if (size - j >= 64) {
size_t block_size = (size - j) - ((size - j) % 64);
block_func(p_chain, p_text + j, block_size);
j = j + block_size;
}
for (i = 0; j < size; ++i, ++j)
buffer = p_text[j];
update_counters(counts, 2, size, 0);
}


static void SHA_1_256_digest(SHA_Word32* p_chain,
unsigned char* buffer,
SHA_Word32* counts,
unsigned int extra_bits,
int n_extra,
unsigned char* p_digest,
int digest_words,
void block_func(SHA_Word32*, const unsigned char*, size_t))
{
unsigned int i;

i = ((unsigned)counts[1] >> 3) % 64;
buffer[i++] = (extra_bits << (8 - n_extra)) & 0xFF | (1U << (7 -
n_extra));

if (i > 56) {
for(; i < 64; ++i)
buffer = 0;
block_func(p_chain, buffer, 64U);
i = 0;
}
for (; i < 56; ++i)
buffer = 0;

update_counters(counts, 2, 0, n_extra);
words_to_bytes(counts, buffer + 56, 2);
block_func(p_chain, buffer, 64);
words_to_bytes(p_chain, p_digest, digest_words);
}



static void SHA160_init(SHA160_State* p_state )
{
int i;
for(i=0; i<5; ++i)
p_state->chain = SHA_1_chain_inits;
p_state->size[0] = p_state->size[1] = 0;
}


static void SHA160_update(SHA160_State* p_state,
const unsigned char* p_text,
size_t size)
{
SHA_1_256_update(p_state->chain, p_state->buffer, p_state->size,
p_text, size, SHA160_block_function);
}


static void SHA160_digest(const SHA160_State* p_state,
unsigned char p_digest[20],
unsigned int extra_bits,
int bit_count)
{
SHA160_State state = *p_state;
SHA_1_256_digest(state.chain, state.buffer, state.size,
extra_bits, bit_count, p_digest, 5, SHA160_block_function);
}





/******************************************************************
*
* SHA-256 Compression function
*/


#define Ch(x, y, z) (z ^ (x & (y ^ z)))
/* Eqivalent to (((x) & (y)) | (~(x) & (z))) */

#define Maj(x, y, z) ((x & (y ^ z)) ^ (y & z))
/* Eqivalent to (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) */


#define SIG0(x) (R32R((x), 2) ^ R32R((x), 13) ^ R32R((x), 22))
#define SIG1(x) (R32R((x), 6) ^ R32R((x), 11) ^ R32R((x), 25))

#define sig0(x) (R32R((x), 7) ^ R32R((x), 18) ^ ((x) >> 3))
#define sig1(x) (R32R((x), 17) ^ R32R((x), 19) ^ ((x) >> 10))

static const SHA_Word32 SHA_256_chain_inits[8] =
{
0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
};

static const SHA_Word32 SHA_224_chain_inits[8] =
{
0xc1059ed8UL, 0x367cd507UL, 0x3070dd17UL, 0xf70e5939UL,
0xffc00b31UL, 0x68581511UL, 0x64f98fa7UL, 0xbefa4fa4UL
};



#if UNROLL_SHA_256

/**********************************************************
*
* Loop-unrolled version of SHA256. Bigger and usually faster.
*/

#define S2W1(t) (w[t] = ((SHA_Word32)p_data[(t) * 4] << 24) |
(p_data[(t) * 4 + 1] << 16) \
| (p_data[(t) * 4 + 2] << 8) | p_data[(t) * 4 + 3])

#define S2W2(t) (w[t & 15] = MASK32(sig1(w[(t - 2) & 15]) + w[(t - 7) &
15] + sig0(w[(t - 15) & 15]) + w[(t - 16) & 15]))



#define S2ROUND(k, w, A, B, C, D, E, F, G, H) \
H = MASK32(H + SIG1(E) + Ch(E, F, G) + k + w); \
D = MASK32(D + H); \
H = MASK32(H + SIG0(A) + Maj(A, B, C));



#define S2ROUND_A(k, t, A, B, C, D, E, F, G, H) \
H = MASK32(H + SIG1(E) + Ch(E, F, G) + k + S2W1(t)); \
D = MASK32(D + H); \
H = MASK32(H + SIG0(A) + Maj(A, B, C));



#define S2ROUND_B(A, B, C, D, E, F, G, H, k, t) \
H = MASK32(H + SIG1(E) + Ch(E, F, G) +k + S2W2(t)); \
D = MASK32(D + H); \
H = MASK32(H + SIG0(A) + Maj(A, B, C));


static void SHA256_block_function(
SHA_Word32 chain[8],
const unsigned char* p_data,
size_t size)
{
SHA_Word32 a, b, c, d, e, f, g, h;
SHA_Word32 w[16];
const unsigned char* p_end = p_data + size;

/* assert(size % 64 == 0); */

while (p_data != p_end) {

a = chain[0]; b = chain[1]; c = chain[2]; d = chain[3];
e = chain[4]; f = chain[5]; g = chain[6]; h = chain[7];

S2ROUND(0x428A2F98UL, S2W1(0), a, b, c, d, e, f, g, h);
S2ROUND(0x71374491UL, S2W1(1), h, a, b, c, d, e, f, g);
S2ROUND(0xB5C0FBCFUL, S2W1(2), g, h, a, b, c, d, e, f);
S2ROUND(0xE9B5DBA5UL, S2W1(3), f, g, h, a, b, c, d, e);
S2ROUND(0x3956C25BUL, S2W1(4), e, f, g, h, a, b, c, d);
S2ROUND(0x59F111F1UL, S2W1(5), d, e, f, g, h, a, b, c);
S2ROUND(0x923F82A4UL, S2W1(6), c, d, e, f, g, h, a, b);
S2ROUND(0xAB1C5ED5UL, S2W1(7), b, c, d, e, f, g, h, a);
S2ROUND(0xD807AA98UL, S2W1(8), a, b, c, d, e, f, g, h);
S2ROUND(0x12835B01UL, S2W1(9), h, a, b, c, d, e, f, g);
S2ROUND(0x243185BEUL, S2W1(10), g, h, a, b, c, d, e, f);
S2ROUND(0x550C7DC3UL, S2W1(11), f, g, h, a, b, c, d, e);
S2ROUND(0x72BE5D74UL, S2W1(12), e, f, g, h, a, b, c, d);
S2ROUND(0x80DEB1FEUL, S2W1(13), d, e, f, g, h, a, b, c);
S2ROUND(0x9BDC06A7UL, S2W1(14), c, d, e, f, g, h, a, b);
S2ROUND(0xC19BF174UL, S2W1(15), b, c, d, e, f, g, h, a);

S2ROUND(0xE49B69C1UL, S2W2(16), a, b, c, d, e, f, g, h);
S2ROUND(0xEFBE4786UL, S2W2(17), h, a, b, c, d, e, f, g);
S2ROUND(0x0FC19DC6UL, S2W2(18), g, h, a, b, c, d, e, f);
S2ROUND(0x240CA1CCUL, S2W2(19), f, g, h, a, b, c, d, e);
S2ROUND(0x2DE92C6FUL, S2W2(20), e, f, g, h, a, b, c, d);
S2ROUND(0x4A7484AAUL, S2W2(21), d, e, f, g, h, a, b, c);
S2ROUND(0x5CB0A9DCUL, S2W2(22), c, d, e, f, g, h, a, b);
S2ROUND(0x76F988DAUL, S2W2(23), b, c, d, e, f, g, h, a);
S2ROUND(0x983E5152UL, S2W2(24), a, b, c, d, e, f, g, h);
S2ROUND(0xA831C66DUL, S2W2(25), h, a, b, c, d, e, f, g);
S2ROUND(0xB00327C8UL, S2W2(26), g, h, a, b, c, d, e, f);
S2ROUND(0xBF597FC7UL, S2W2(27), f, g, h, a, b, c, d, e);
S2ROUND(0xC6E00BF3UL, S2W2(28), e, f, g, h, a, b, c, d);
S2ROUND(0xD5A79147UL, S2W2(29), d, e, f, g, h, a, b, c);
S2ROUND(0x06CA6351UL, S2W2(30), c, d, e, f, g, h, a, b);
S2ROUND(0x14292967UL, S2W2(31), b, c, d, e, f, g, h, a);
S2ROUND(0x27B70A85UL, S2W2(32), a, b, c, d, e, f, g, h);
S2ROUND(0x2E1B2138UL, S2W2(33), h, a, b, c, d, e, f, g);
S2ROUND(0x4D2C6DFCUL, S2W2(34), g, h, a, b, c, d, e, f);
S2ROUND(0x53380D13UL, S2W2(35), f, g, h, a, b, c, d, e);
S2ROUND(0x650A7354UL, S2W2(36), e, f, g, h, a, b, c, d);
S2ROUND(0x766A0ABBUL, S2W2(37), d, e, f, g, h, a, b, c);
S2ROUND(0x81C2C92EUL, S2W2(38), c, d, e, f, g, h, a, b);
S2ROUND(0x92722C85UL, S2W2(39), b, c, d, e, f, g, h, a);
S2ROUND(0xA2BFE8A1UL, S2W2(40), a, b, c, d, e, f, g, h);
S2ROUND(0xA81A664BUL, S2W2(41), h, a, b, c, d, e, f, g);
S2ROUND(0xC24B8B70UL, S2W2(42), g, h, a, b, c, d, e, f);
S2ROUND(0xC76C51A3UL, S2W2(43), f, g, h, a, b, c, d, e);
S2ROUND(0xD192E819UL, S2W2(44), e, f, g, h, a, b, c, d);
S2ROUND(0xD6990624UL, S2W2(45), d, e, f, g, h, a, b, c);
S2ROUND(0xF40E3585UL, S2W2(46), c, d, e, f, g, h, a, b);
S2ROUND(0x106AA070UL, S2W2(47), b, c, d, e, f, g, h, a);
S2ROUND(0x19A4C116UL, S2W2(48), a, b, c, d, e, f, g, h);
S2ROUND(0x1E376C08UL, S2W2(49), h, a, b, c, d, e, f, g);
S2ROUND(0x2748774CUL, S2W2(50), g, h, a, b, c, d, e, f);
S2ROUND(0x34B0BCB5UL, S2W2(51), f, g, h, a, b, c, d, e);
S2ROUND(0x391C0CB3UL, S2W2(52), e, f, g, h, a, b, c, d);
S2ROUND(0x4ED8AA4AUL, S2W2(53), d, e, f, g, h, a, b, c);
S2ROUND(0x5B9CCA4FUL, S2W2(54), c, d, e, f, g, h, a, b);
S2ROUND(0x682E6FF3UL, S2W2(55), b, c, d, e, f, g, h, a);
S2ROUND(0x748F82EEUL, S2W2(56), a, b, c, d, e, f, g, h);
S2ROUND(0x78A5636FUL, S2W2(57), h, a, b, c, d, e, f, g);
S2ROUND(0x84C87814UL, S2W2(58), g, h, a, b, c, d, e, f);
S2ROUND(0x8CC70208UL, S2W2(59), f, g, h, a, b, c, d, e);
S2ROUND(0x90BEFFFAUL, S2W2(60), e, f, g, h, a, b, c, d);
S2ROUND(0xA4506CEBUL, S2W2(61), d, e, f, g, h, a, b, c);
S2ROUND(0xBEF9A3F7UL, S2W2(62), c, d, e, f, g, h, a, b);
S2ROUND(0xC67178F2UL, S2W2(63), b, c, d, e, f, g, h, a);

chain[0] = MASK32(chain[0] + a);
chain[1] = MASK32(chain[1] + b);
chain[2] = MASK32(chain[2] + c);
chain[3] = MASK32(chain[3] + d);
chain[4] = MASK32(chain[4] + e);
chain[5] = MASK32(chain[5] + f);
chain[6] = MASK32(chain[6] + g);
chain[7] = MASK32(chain[7] + h);

p_data += 64;
}
}


#else /* Do not fully-unroll SHA-256 */

/**********************************************************
*
* More compact, usually slower version of SHA-256
*/

static const SHA_Word32 constants[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
};



#define S2ROUND(A, B, C, D, E, F, G, H, t) \
H = MASK32(H + SIG1(E) + Ch(E, F, G) + constants[t] + w[t]); \
D = MASK32(D + H); \
H = MASK32(H + SIG0(A) + Maj(A, B, C));


static void SHA256_block_function(
SHA_Word32 chain[8],
const unsigned char* p_data,
size_t size)
{
SHA_Word32 a, b, c, d, e, f, g, h;
SHA_Word32 w[64];
int t;

const unsigned char* p_end = p_data + size;
while (p_data != p_end) {

a = chain[0]; b = chain[1]; c = chain[2]; d = chain[3];
e = chain[4]; f = chain[5]; g = chain[6]; h = chain[7];


for (t = 0; t < 16; ++t) {
w[t] = ((SHA_Word32)p_data[0] << 24) |
((SHA_Word32)p_data[1] << 16)
| ((SHA_Word32)p_data[2] << 8) | p_data[3];
p_data += 4;
}
for (t = 16; t < 64; ++t)
w[t] = MASK32(sig1(w[t - 2]) +
w[t - 7] + sig0(w[t - 15]) + w[t - 16]);

for (t = 0; t <= 56; t += 8) {
S2ROUND(a, b, c, d, e, f, g, h, t);
S2ROUND(h, a, b, c, d, e, f, g, t + 1);
S2ROUND(g, h, a, b, c, d, e, f, t + 2);
S2ROUND(f, g, h, a, b, c, d, e, t + 3);
S2ROUND(e, f, g, h, a, b, c, d, t + 4);
S2ROUND(d, e, f, g, h, a, b, c, t + 5);
S2ROUND(c, d, e, f, g, h, a, b, t + 6);
S2ROUND(b, c, d, e, f, g, h, a, t + 7);
}
chain[0] = MASK32(chain[0] + a);
chain[1] = MASK32(chain[1] + b);
chain[2] = MASK32(chain[2] + c);
chain[3] = MASK32(chain[3] + d);
chain[4] = MASK32(chain[4] + e);
chain[5] = MASK32(chain[5] + f);
chain[6] = MASK32(chain[6] + g);
chain[7] = MASK32(chain[7] + h);
}
}

#endif /* UNROLL_SHA256 */


/**********************************************************
*
* SHA-256/224 API functions
*/

static void SHA256_init(SHA256_State* p_state, int sha_size)
{
int i;
static const SHA_Word32* chain_inits;
chain_inits = sha_size == 224 ? SHA_224_chain_inits :
SHA_256_chain_inits;
for(i=0; i<8; ++i)
p_state->chain = chain_inits;
p_state->size[0] = p_state->size[1] = 0;
}


static void SHA256_update(SHA256_State* p_state,
const unsigned char* p_text,
size_t size)
{
SHA_1_256_update(p_state->chain, p_state->buffer, p_state->size,
p_text, size, SHA256_block_function);
}


static void SHA256_digest(const SHA256_State* p_state,
unsigned char p_digest[32],
unsigned int extra_bits,
int bit_count)
{
SHA256_State state = *p_state;
SHA_1_256_digest(state.chain, state.buffer, state.size,
extra_bits, bit_count, p_digest, 8, SHA256_block_function);
}


/******************************************************************
*
* SHA-384/512
*/

#if SHA_USE_64_BIT_WORD

/**********************************************************************
*
* Version to use when compiler supports 64-bit words.
*/

static const SHA_Word64 SHA384_chain_inits[8] =
{
SHA_UI64(0xcbbb9d5dc1059ed8), SHA_UI64(0x629a292a367cd507),
SHA_UI64(0x9159015a3070dd17), SHA_UI64(0x152fecd8f70e5939),
SHA_UI64(0x67332667ffc00b31), SHA_UI64(0x8eb44a8768581511),
SHA_UI64(0xdb0c2e0d64f98fa7), SHA_UI64(0x47b5481dbefa4fa4)
};

static const SHA_Word64 SHA512_chain_inits[8] =
{
SHA_UI64(0x6a09e667f3bcc908), SHA_UI64(0xbb67ae8584caa73b),
SHA_UI64(0x3c6ef372fe94f82b), SHA_UI64(0xa54ff53a5f1d36f1),
SHA_UI64(0x510e527fade682d1), SHA_UI64(0x9b05688c2b3e6c1f),
SHA_UI64(0x1f83d9abfb41bd6b), SHA_UI64(0x5be0cd19137e2179)
};


#define SHA_MASK64(x) ((x) & SHA_UI64(0xFFFFFFFFFFFFFFFF))
#define MASK64(x) SHA_MASK64(x)

#define SIG0_64(x) (SHA_ROT64R(x, 28) ^ SHA_ROT64R(x, 34) ^
SHA_ROT64R(x, 39))
#define SIG1_64(x) (SHA_ROT64R(x, 14) ^ SHA_ROT64R(x, 18) ^
SHA_ROT64R(x, 41))

#define sig0_64(x) (SHA_ROT64R(x, 1) ^ SHA_ROT64R(x, 8) ^ (x >> 7))
#define sig1_64(x) (SHA_ROT64R(x, 19) ^ SHA_ROT64R(x, 61) ^ (x >> 6))


#if UNROLL_SHA_512


#define ROUND_A(A, B, C, D, E, F, G, H, k, t) \
H = SHA_MASK64(H + SIG1_64(E) + Ch(E, F, G) + k + w[t]); \
D = SHA_MASK64(D + H); \
H = SHA_MASK64(H + SIG0_64(A) + Maj(A, B, C));


#define UPDATED_W(t) (w[t & 15] = (sig1_64(w[(t - 2) & 15]) + w[(t - 7)
& 15] + sig0_64(w[(t - 15) & 15]) + w[(t - 16) & 15]) &
0xFFFFFFFFFFFFFFFFUL)

#define ROUND_B(A, B, C, D, E, F, G, H, k, t) \
H = SHA_MASK64(H + SIG1_64(E) + Ch(E, F, G) + k + UPDATED_W(t)); \
D = SHA_MASK64(D + H); \
H = SHA_MASK64(H + SIG0_64(A) + Maj(A, B, C));


static void SHA512_block_function(
SHA_Word64 chain[8],
const unsigned char* p_data,
size_t size)
{
SHA_Word64 a, b, c, d, e, f, g, h;
SHA_Word64 w[16];
int t;

const unsigned char* p_end = p_data + size;

/* assert(size % 128 == 0); */

while (p_data != p_end) {

a = chain[0]; b = chain[1]; c = chain[2]; d = chain[3];
e = chain[4]; f = chain[5]; g = chain[6]; h = chain[7];

for (t = 0; t < 16; ++t) {
w[t] = (p_data[0] << 24) | (p_data[1] << 16) |
(p_data[2] << 8) | p_data[3];
w[t] <<= 32;
w[t] += (p_data[4] << 24) | (p_data[5] << 16)
| (p_data[6] << 8) | p_data[7];
p_data += 8;
}

ROUND_A(a, b, c, d, e, f, g, h, SHA_UI64(0x428A2F98D728AE22), 0);
ROUND_A(h, a, b, c, d, e, f, g, SHA_UI64(0x7137449123EF65CD), 1);
ROUND_A(g, h, a, b, c, d, e, f, SHA_UI64(0xB5C0FBCFEC4D3B2F), 2);
ROUND_A(f, g, h, a, b, c, d, e, SHA_UI64(0xE9B5DBA58189DBBC), 3);
ROUND_A(e, f, g, h, a, b, c, d, SHA_UI64(0x3956C25BF348B538), 4);
ROUND_A(d, e, f, g, h, a, b, c, SHA_UI64(0x59F111F1B605D019), 5);
ROUND_A(c, d, e, f, g, h, a, b, SHA_UI64(0x923F82A4AF194F9B), 6);
ROUND_A(b, c, d, e, f, g, h, a, SHA_UI64(0xAB1C5ED5DA6D8118), 7);
ROUND_A(a, b, c, d, e, f, g, h, SHA_UI64(0xD807AA98A3030242), 8);
ROUND_A(h, a, b, c, d, e, f, g, SHA_UI64(0x12835B0145706FBE), 9);
ROUND_A(g, h, a, b, c, d, e, f, SHA_UI64(0x243185BE4EE4B28C), 10);
ROUND_A(f, g, h, a, b, c, d, e, SHA_UI64(0x550C7DC3D5FFB4E2), 11);
ROUND_A(e, f, g, h, a, b, c, d, SHA_UI64(0x72BE5D74F27B896F), 12);
ROUND_A(d, e, f, g, h, a, b, c, SHA_UI64(0x80DEB1FE3B1696B1), 13);
ROUND_A(c, d, e, f, g, h, a, b, SHA_UI64(0x9BDC06A725C71235), 14);
ROUND_A(b, c, d, e, f, g, h, a, SHA_UI64(0xC19BF174CF692694), 15);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0xE49B69C19EF14AD2), 16);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0xEFBE4786384F25E3), 17);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0x0FC19DC68B8CD5B5), 18);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0x240CA1CC77AC9C65), 19);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x2DE92C6F592B0275), 20);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0x4A7484AA6EA6E483), 21);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x5CB0A9DCBD41FBD4), 22);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x76F988DA831153B5), 23);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0x983E5152EE66DFAB), 24);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0xA831C66D2DB43210), 25);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0xB00327C898FB213F), 26);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0xBF597FC7BEEF0EE4), 27);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0xC6E00BF33DA88FC2), 28);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0xD5A79147930AA725), 29);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x06CA6351E003826F), 30);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x142929670A0E6E70), 31);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0x27B70A8546D22FFC), 32);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0x2E1B21385C26C926), 33);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0x4D2C6DFC5AC42AED), 34);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0x53380D139D95B3DF), 35);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x650A73548BAF63DE), 36);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0x766A0ABB3C77B2A8), 37);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x81C2C92E47EDAEE6), 38);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x92722C851482353B), 39);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0xA2BFE8A14CF10364), 40);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0xA81A664BBC423001), 41);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0xC24B8B70D0F89791), 42);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0xC76C51A30654BE30), 43);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0xD192E819D6EF5218), 44);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0xD69906245565A910), 45);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0xF40E35855771202A), 46);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x106AA07032BBD1B8), 47);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0x19A4C116B8D2D0C8), 48);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0x1E376C085141AB53), 49);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0x2748774CDF8EEB99), 50);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0x34B0BCB5E19B48A8), 51);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x391C0CB3C5C95A63), 52);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0x4ED8AA4AE3418ACB), 53);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x5B9CCA4F7763E373), 54);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x682E6FF3D6B2B8A3), 55);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0x748F82EE5DEFB2FC), 56);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0x78A5636F43172F60), 57);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0x84C87814A1F0AB72), 58);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0x8CC702081A6439EC), 59);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x90BEFFFA23631E28), 60);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0xA4506CEBDE82BDE9), 61);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0xBEF9A3F7B2C67915), 62);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0xC67178F2E372532B), 63);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0xCA273ECEEA26619C), 64);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0xD186B8C721C0C207), 65);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0xEADA7DD6CDE0EB1E), 66);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0xF57D4F7FEE6ED178), 67);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x06F067AA72176FBA), 68);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0x0A637DC5A2C898A6), 69);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x113F9804BEF90DAE), 70);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x1B710B35131C471B), 71);
ROUND_B(a, b, c, d, e, f, g, h, SHA_UI64(0x28DB77F523047D84), 72);
ROUND_B(h, a, b, c, d, e, f, g, SHA_UI64(0x32CAAB7B40C72493), 73);
ROUND_B(g, h, a, b, c, d, e, f, SHA_UI64(0x3C9EBE0A15C9BEBC), 74);
ROUND_B(f, g, h, a, b, c, d, e, SHA_UI64(0x431D67C49C100D4C), 75);
ROUND_B(e, f, g, h, a, b, c, d, SHA_UI64(0x4CC5D4BECB3E42B6), 76);
ROUND_B(d, e, f, g, h, a, b, c, SHA_UI64(0x597F299CFC657E2A), 77);
ROUND_B(c, d, e, f, g, h, a, b, SHA_UI64(0x5FCB6FAB3AD6FAEC), 78);
ROUND_B(b, c, d, e, f, g, h, a, SHA_UI64(0x6C44198C4A475817), 79);

chain[0] += a; chain[1] += b; chain[2] += c; chain[3] += d;
chain[4] += e; chain[5] += f; chain[6] += g; chain[7] += h;
}
}


#else


static const SHA_Word64 SHA512_round_constants[80] =
{
SHA_UI64(0x428a2f98d728ae22), SHA_UI64(0x7137449123ef65cd),
SHA_UI64(0xb5c0fbcfec4d3b2f),
SHA_UI64(0xe9b5dba58189dbbc), SHA_UI64(0x3956c25bf348b538),
SHA_UI64(0x59f111f1b605d019),
SHA_UI64(0x923f82a4af194f9b), SHA_UI64(0xab1c5ed5da6d8118),
SHA_UI64(0xd807aa98a3030242),
SHA_UI64(0x12835b0145706fbe), SHA_UI64(0x243185be4ee4b28c),
SHA_UI64(0x550c7dc3d5ffb4e2),
SHA_UI64(0x72be5d74f27b896f), SHA_UI64(0x80deb1fe3b1696b1),
SHA_UI64(0x9bdc06a725c71235),
SHA_UI64(0xc19bf174cf692694), SHA_UI64(0xe49b69c19ef14ad2),
SHA_UI64(0xefbe4786384f25e3),
SHA_UI64(0x0fc19dc68b8cd5b5), SHA_UI64(0x240ca1cc77ac9c65),
SHA_UI64(0x2de92c6f592b0275),
SHA_UI64(0x4a7484aa6ea6e483), SHA_UI64(0x5cb0a9dcbd41fbd4),
SHA_UI64(0x76f988da831153b5),
SHA_UI64(0x983e5152ee66dfab), SHA_UI64(0xa831c66d2db43210),
SHA_UI64(0xb00327c898fb213f),
SHA_UI64(0xbf597fc7beef0ee4), SHA_UI64(0xc6e00bf33da88fc2),
SHA_UI64(0xd5a79147930aa725),
SHA_UI64(0x06ca6351e003826f), SHA_UI64(0x142929670a0e6e70),
SHA_UI64(0x27b70a8546d22ffc),
SHA_UI64(0x2e1b21385c26c926), SHA_UI64(0x4d2c6dfc5ac42aed),
SHA_UI64(0x53380d139d95b3df),
SHA_UI64(0x650a73548baf63de), SHA_UI64(0x766a0abb3c77b2a8),
SHA_UI64(0x81c2c92e47edaee6),
SHA_UI64(0x92722c851482353b), SHA_UI64(0xa2bfe8a14cf10364),
SHA_UI64(0xa81a664bbc423001),
SHA_UI64(0xc24b8b70d0f89791), SHA_UI64(0xc76c51a30654be30),
SHA_UI64(0xd192e819d6ef5218),
SHA_UI64(0xd69906245565a910), SHA_UI64(0xf40e35855771202a),
SHA_UI64(0x106aa07032bbd1b8),
SHA_UI64(0x19a4c116b8d2d0c8), SHA_UI64(0x1e376c085141ab53),
SHA_UI64(0x2748774cdf8eeb99),
SHA_UI64(0x34b0bcb5e19b48a8), SHA_UI64(0x391c0cb3c5c95a63),
SHA_UI64(0x4ed8aa4ae3418acb),
SHA_UI64(0x5b9cca4f7763e373), SHA_UI64(0x682e6ff3d6b2b8a3),
SHA_UI64(0x748f82ee5defb2fc),
SHA_UI64(0x78a5636f43172f60), SHA_UI64(0x84c87814a1f0ab72),
SHA_UI64(0x8cc702081a6439ec),
SHA_UI64(0x90befffa23631e28), SHA_UI64(0xa4506cebde82bde9),
SHA_UI64(0xbef9a3f7b2c67915),
SHA_UI64(0xc67178f2e372532b), SHA_UI64(0xca273eceea26619c),
SHA_UI64(0xd186b8c721c0c207),
SHA_UI64(0xeada7dd6cde0eb1e), SHA_UI64(0xf57d4f7fee6ed178),
SHA_UI64(0x06f067aa72176fba),
SHA_UI64(0x0a637dc5a2c898a6), SHA_UI64(0x113f9804bef90dae),
SHA_UI64(0x1b710b35131c471b),
SHA_UI64(0x28db77f523047d84), SHA_UI64(0x32caab7b40c72493),
SHA_UI64(0x3c9ebe0a15c9bebc),
SHA_UI64(0x431d67c49c100d4c), SHA_UI64(0x4cc5d4becb3e42b6),
SHA_UI64(0x597f299cfc657e2a),
SHA_UI64(0x5fcb6fab3ad6faec), SHA_UI64(0x6c44198c4a475817)
};



#define ROUND512(A, B, C, D, E, F, G, H, t) \
H = MASK64(H + SIG1_64(E) + Ch(E, F, G) + SHA512_round_constants[t]
+ w[t]); \
D = MASK64(D + H); \
H = MASK64(H + SIG0_64(A) + Maj(A, B, C))


static void SHA512_block_function(
SHA_Word64 chain[8],
const unsigned char* p_data,
size_t size)
{
SHA_Word64 a, b, c, d, e, f, g, h;
SHA_Word64 w[80];
int t;

const unsigned char* p_end = p_data + size;
while (p_data != p_end) {
a = chain[0]; b = chain[1]; c = chain[2]; d = chain[3];
e = chain[4]; f = chain[5]; g = chain[6]; h = chain[7];

for (t = 0; t < 16; ++t) {
w[t] = (p_data[0] << 24) | (p_data[1] << 16) |
(p_data[2] << 8) | p_data[3];
w[t] <<= 32;
w[t] += (p_data[4] << 24) | (p_data[5] << 16)
| (p_data[6] << 8) | p_data[7];
p_data += 8;
}
for (; t < 80; ++t) {
w[t] = MASK64(sig1_64(w[t - 2]) + w[t - 7] + sig0_64(w[t -
15]) + w[t - 16]);
}

for (t = 0; t < 80; t += 8) {
ROUND512(a, b, c, d, e, f, g, h, t);
ROUND512(h, a, b, c, d, e, f, g, t + 1);
ROUND512(g, h, a, b, c, d, e, f, t + 2);
ROUND512(f, g, h, a, b, c, d, e, t + 3);
ROUND512(e, f, g, h, a, b, c, d, t + 4);
ROUND512(d, e, f, g, h, a, b, c, t + 5);
ROUND512(c, d, e, f, g, h, a, b, t + 6);
ROUND512(b, c, d, e, f, g, h, a, t + 7);
}

chain[0] = MASK64(chain[0] + a);
chain[1] = MASK64(chain[1] + b);
chain[2] = MASK64(chain[2] + c);
chain[3] = MASK64(chain[3] + d);
chain[4] = MASK64(chain[4] + e);
chain[5] = MASK64(chain[5] + f);
chain[6] = MASK64(chain[6] + g);
chain[7] = MASK64(chain[7] + h);
}
}

#endif

static void SHA512_init(SHA512_State* p_state, int sha_size)
{
int i;
static const SHA_Word64* chain_inits;
chain_inits = sha_size == 384 ? SHA384_chain_inits :
SHA512_chain_inits;

for(i=0; i<8; ++i)
p_state->chain = chain_inits;

p_state->size[0] = p_state->size[1] =
p_state->size[2] = p_state->size[3] = 0;
}

static void SHA512_digest(const SHA512_State* p_state,
unsigned char p_digest[64],
unsigned int extra_bits,
int n_extra)
{
unsigned int i;
SHA512_State state = *p_state;

i = ((unsigned)state.size[3] >> 3) % 128;
state.buffer[i++] = (extra_bits << (8 - n_extra)) & 0xFF | (1U <<
(7 - n_extra));

if (i > 112) {
for(; i < 128; ++i)
state.buffer = 0;
SHA512_block_function(state.chain, state.buffer, 128);
i = 0;
}
for (; i < 112; ++i)
state.buffer = 0;

update_counters(state.size, 4, 0, n_extra);
words_to_bytes(state.size, state.buffer + 112, 4);
SHA512_block_function(state.chain, state.buffer, 128);
for (i=0; i<8; ++i) {
int j;
for (j=7; j>=0; --j) {
p_digest[8*i+j] = (unsigned char)(state.chain & 0xFF);
state.chain >>= 8;
}
}
}


#else /* Comiler has no 64-bit words. */

/**********************************************************************
*
* Painful implementation of SHA-512/384 without 64-bit word support.
*/


static const SHA_Word64 SHA384_chain_inits[8] =
{
{0xcbbb9d5dUL, 0xc1059ed8UL}, {0x629a292aUL, 0x367cd507UL},
{0x9159015aUL, 0x3070dd17UL}, {0x152fecd8UL, 0xf70e5939UL},
{0x67332667UL, 0xffc00b31UL}, {0x8eb44a87UL, 0x68581511UL},
{0xdb0c2e0dUL, 0x64f98fa7UL}, {0x47b5481dUL, 0xbefa4fa4UL}
};

static const SHA_Word64 SHA512_chain_inits[8] =
{
{0x6a09e667UL, 0xf3bcc908UL}, {0xbb67ae85UL, 0x84caa73bUL},
{0x3c6ef372UL, 0xfe94f82bUL}, {0xa54ff53aUL, 0x5f1d36f1UL},
{0x510e527fUL, 0xade682d1UL}, {0x9b05688cUL, 0x2b3e6c1fUL},
{0x1f83d9abUL, 0xfb41bd6bUL}, {0x5be0cd19UL, 0x137e2179UL}
};

static const SHA_Word64 SHA512_K[80] =
{
{0x428a2f98UL, 0xd728ae22UL}, {0x71374491UL, 0x23ef65cdUL},
{0xb5c0fbcfUL, 0xec4d3b2fUL}, {0xe9b5dba5UL, 0x8189dbbcUL},
{0x3956c25bUL, 0xf348b538UL}, {0x59f111f1UL, 0xb605d019UL},
{0x923f82a4UL, 0xaf194f9bUL}, {0xab1c5ed5UL, 0xda6d8118UL},
{0xd807aa98UL, 0xa3030242UL}, {0x12835b01UL, 0x45706fbeUL},
{0x243185beUL, 0x4ee4b28cUL}, {0x550c7dc3UL, 0xd5ffb4e2UL},
{0x72be5d74UL, 0xf27b896fUL}, {0x80deb1feUL, 0x3b1696b1UL},
{0x9bdc06a7UL, 0x25c71235UL}, {0xc19bf174UL, 0xcf692694UL},
{0xe49b69c1UL, 0x9ef14ad2UL}, {0xefbe4786UL, 0x384f25e3UL},
{0x0fc19dc6UL, 0x8b8cd5b5UL}, {0x240ca1ccUL, 0x77ac9c65UL},
{0x2de92c6fUL, 0x592b0275UL}, {0x4a7484aaUL, 0x6ea6e483UL},
{0x5cb0a9dcUL, 0xbd41fbd4UL}, {0x76f988daUL, 0x831153b5UL},
{0x983e5152UL, 0xee66dfabUL}, {0xa831c66dUL, 0x2db43210UL},
{0xb00327c8UL, 0x98fb213fUL}, {0xbf597fc7UL, 0xbeef0ee4UL},
{0xc6e00bf3UL, 0x3da88fc2UL}, {0xd5a79147UL, 0x930aa725UL},
{0x06ca6351UL, 0xe003826fUL}, {0x14292967UL, 0xa0e6e70UL},
{0x27b70a85UL, 0x46d22ffcUL}, {0x2e1b2138UL, 0x5c26c926UL},
{0x4d2c6dfcUL, 0x5ac42aedUL}, {0x53380d13UL, 0x9d95b3dfUL},
{0x650a7354UL, 0x8baf63deUL}, {0x766a0abbUL, 0x3c77b2a8UL},
{0x81c2c92eUL, 0x47edaee6UL}, {0x92722c85UL, 0x1482353bUL},
{0xa2bfe8a1UL, 0x4cf10364UL}, {0xa81a664bUL, 0xbc423001UL},
{0xc24b8b70UL, 0xd0f89791UL}, {0xc76c51a3UL, 0x654be30UL},
{0xd192e819UL, 0xd6ef5218UL}, {0xd6990624UL, 0x5565a910UL},
{0xf40e3585UL, 0x5771202aUL}, {0x106aa070UL, 0x32bbd1b8UL},
{0x19a4c116UL, 0xb8d2d0c8UL}, {0x1e376c08UL, 0x5141ab53UL},
{0x2748774cUL, 0xdf8eeb99UL}, {0x34b0bcb5UL, 0xe19b48a8UL},
{0x391c0cb3UL, 0xc5c95a63UL}, {0x4ed8aa4aUL, 0xe3418acbUL},
{0x5b9cca4fUL, 0x7763e373UL}, {0x682e6ff3UL, 0xd6b2b8a3UL},
{0x748f82eeUL, 0x5defb2fcUL}, {0x78a5636fUL, 0x43172f60UL},
{0x84c87814UL, 0xa1f0ab72UL}, {0x8cc70208UL, 0x1a6439ecUL},
{0x90befffaUL, 0x23631e28UL}, {0xa4506cebUL, 0xde82bde9UL},
{0xbef9a3f7UL, 0xb2c67915UL}, {0xc67178f2UL, 0xe372532bUL},
{0xca273eceUL, 0xea26619cUL}, {0xd186b8c7UL, 0x21c0c207UL},
{0xeada7dd6UL, 0xcde0eb1eUL}, {0xf57d4f7fUL, 0xee6ed178UL},
{0x06f067aaUL, 0x72176fbaUL}, {0x0a637dc5UL, 0xa2c898a6UL},
{0x113f9804UL, 0xbef90daeUL}, {0x1b710b35UL, 0x131c471bUL},
{0x28db77f5UL, 0x23047d84UL}, {0x32caab7bUL, 0x40c72493UL},
{0x3c9ebe0aUL, 0x15c9bebcUL}, {0x431d67c4UL, 0x9c100d4cUL},
{0x4cc5d4beUL, 0xcb3e42b6UL}, {0x597f299cUL, 0xfc657e2aUL},
{0x5fcb6fabUL, 0x3ad6faecUL}, {0x6c44198cUL, 0x4a475817UL}
};


#define sig0_64(dh, dl, src) \
dh = ((src[0] >> 1) | (src[1] << 31)) ^ ((src[0] >> 8) | (src[1]
<< 24)) ^ (src[0] >> 7); \
dl = ((src[1] >> 1) | (src[0] << 31)) ^ ((src[1] >> 8) | (src[0]
<< 24)) ^ ((src[1] >> 7) | (src[0] << 25));

#define sig1_64(dh, dl, src) \
dh = ((src[0] >> 19) | (src[1] << 13)) ^ ((src[0] << 3) | (src[1]
>> 29)) ^ (src[0] >> 6); \ dl = ((src[1] >> 19) | (src[0] << 13)) ^ ((src[1] << 3) | (src[0]
>> 29)) ^ ((src[1] >> 6) | (src[0] << 26));


#define SIG0_64(dh, dl, sh, sl) \
dh = MASK32(((sh >> 28) | (sl << 4)) ^ ((sh << 30) | (sl >> 2))
^ ((sh << 25) | (sl >> 7))); \
dl = MASK32(((sl >> 28) | (sh << 4)) ^ ((sl << 30) | (sh >> 2))
^ ((sl << 25) | (sh >> 7))); \


#define SIG1_64(dh, dl, sh, sl) \
dh = MASK32(((sh >> 14) | (sl << 18)) ^ ((sh >> 18) | (sl << 14))
^ ((sh << 23) | (sl >> 9))); \
dl = MASK32(((sl >> 14) | (sh << 18)) ^ ((sl >> 18) | (sh << 14))
^ ((sl << 23) | (sh >> 9)));


#define ADD(ah, al, th, tl) \
al = MASK32(al + tl); \
ah = /*lint -e(514) */ MASK32(ah + th + (al < tl));


#define ROUND512(a, b, c, d, e, f, g, h, t) \
SIG1_64(tH, tL, e##H, e##L); \
ADD(h##H, h##L, tH, tL); \
tH = Ch(e##H, f##H, g##H); \
tL = Ch(e##L, f##L, g##L); \
ADD(h##H, h##L, tH, tL); \
ADD(h##H, h##L, SHA512_K[t][0], SHA512_K[t][1]); \
ADD(h##H, h##L, w[t][0], w[t][1]); \
ADD(d##H, d##L, h##H, h##L); \
SIG0_64(tH, tL, a##H, a##L); \
ADD(h##H, h##L, tH, tL); \
tH = Maj(a##H, b##H, c##H); \
tL = Maj(a##L, b##L, c##L); \
ADD(h##H, h##L, tH, tL);


static void SHA512_block_function(
SHA_Word64 chain[8],
const unsigned char* p_data,
size_t size)
{
int t;
SHA_Word64 w[80];
SHA_Word32* p;

const unsigned char* p_end = p_data + size;

while (p_data != p_end) {
SHA_Word32 tH, tL;
SHA_Word32
aH = chain[0][0], aL = chain[0][1],
bH = chain[1][0], bL = chain[1][1],
cH = chain[2][0], cL = chain[2][1],
dH = chain[3][0], dL = chain[3][1],
eH = chain[4][0], eL = chain[4][1],
fH = chain[5][0], fL = chain[5][1],
gH = chain[6][0], gL = chain[6][1],
hH = chain[7][0], hL = chain[7][1];

p = &w[0][0];
for (t = 0; t < 32; ++t) {
*p++ = ((SHA_Word32)p_data[0] << 24) | (p_data[1] << 16) |
(p_data[2] << 8) | p_data[3];
p_data += 4;
}
for (t = 16; t < 80; ++t) {
sig1_64(w[t][0], w[t][1], w[t - 2]);
sig0_64(tH, tL, w[t - 15]);
ADD(tH, tL, w[t - 7][0], w[t - 7][1]);
ADD(tH, tL, w[t - 16][0], w[t - 16][1]);
ADD(w[t][0], w[t][1], tH, tL);
}
for (t = 0; t <= 72; t += 8) {
ROUND512(a, b, c, d, e, f, g, h, t)
ROUND512(h, a, b, c, d, e, f, g, t + 1)
ROUND512(g, h, a, b, c, d, e, f, t + 2)
ROUND512(f, g, h, a, b, c, d, e, t + 3)
ROUND512(e, f, g, h, a, b, c, d, t + 4)
ROUND512(d, e, f, g, h, a, b, c, t + 5)
ROUND512(c, d, e, f, g, h, a, b, t + 6)
ROUND512(b, c, d, e, f, g, h, a, t + 7)
}
ADD(chain[0][0], chain[0][1], aH, aL);
ADD(chain[1][0], chain[1][1], bH, bL);
ADD(chain[2][0], chain[2][1], cH, cL);
ADD(chain[3][0], chain[3][1], dH, dL);
ADD(chain[4][0], chain[4][1], eH, eL);
ADD(chain[5][0], chain[5][1], fH, fL);
ADD(chain[6][0], chain[6][1], gH, gL);
ADD(chain[7][0], chain[7][1], hH, hL);
}
}

static void SHA512_init(SHA512_State* p_state, int sha_size)
{
int i;
static const SHA_Word64* chain_inits;
chain_inits = sha_size == 384 ? SHA384_chain_inits :
SHA512_chain_inits;
for(i=0; i<8; ++i) {
p_state->chain[0] = chain_inits[0];
p_state->chain[1] = chain_inits[1];
}
p_state->size[0] = p_state->size[1] =
p_state->size[2] = p_state->size[3] = 0;
}

static void SHA512_digest(const SHA512_State* p_state,
unsigned char p_digest[64],
unsigned int extra_bits,
int n_extra)
{
unsigned int i;
SHA512_State state = *p_state;

i = ((unsigned)state.size[3] >> 3) % 128;
state.buffer[i++] = (extra_bits << (8 - n_extra)) & 0xFF | (1U <<
(7 - n_extra));

if (i > 112) {
for(; i < 128; ++i)
state.buffer = 0;
SHA512_block_function(state.chain, state.buffer, 128);
i = 0;
}
for (; i < 112; ++i)
state.buffer = 0;

update_counters(state.size, 4, 0, n_extra);
words_to_bytes(state.size, state.buffer + 112, 4);
SHA512_block_function(state.chain, state.buffer, 128);
words_to_bytes(state.chain[0], p_digest, 16);
}

#endif

/* update function is the same for 64-bit and 32-bit implementations. */

static void SHA512_update(SHA512_State* p_state,
const unsigned char* p_text,
size_t size)
{
unsigned int i = ((unsigned)p_state->size[3] >> 3) % 128;
size_t j = 0;

while (i < 128 && j < size)
p_state->buffer[i++] = p_text[j++];

if (i == 128)
SHA512_block_function(p_state->chain, p_state->buffer, 128);

if (size - j >= 128) {
size_t block_size = (size - j) - ((size - j) % 128);
SHA512_block_function(p_state->chain, p_text + j, block_size);
j = j + block_size;
}
for (i = 0; j < size; ++i, ++j)
p_state->buffer = p_text[j];
update_counters(p_state->size, 4, size, 0);
}



/**********************************************************************
*
* Python extention module stuff
*
* Set all doc strings to NULL. This module is to be called only by
* smd.py, which provides its own doc, and does not expose any doc
* from this extention module.
*/



typedef struct {
PyObject_HEAD
SHA160_State hash_state;
} SHA160_Object;

static PyTypeObject sha160_Type_object;


static void
generic_dealloc(SHA160_Object *self)
{
self->ob_type->tp_free((PyObject*)self);
}

static PyObject*
sha160_init(PyObject *obj, PyObject *args)
{
SHA160_Object* self = (SHA160_Object*)obj;
if (!PyArg_ParseTuple(args, ""))
return NULL;
SHA160_init(&self->hash_state);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject*
sha160_update(PyObject *obj, PyObject *args)
{
SHA160_Object* self = (SHA160_Object*)obj;
unsigned char* preimage = 0;
int size = 0;
if (!PyArg_ParseTuple(args, "|s#", &preimage, &size))
return NULL;
SHA160_update(&self->hash_state, preimage, (size_t)size);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject *
sha160_digest(PyObject *obj, PyObject *args)
{
SHA160_Object* self = (SHA160_Object*)obj;
unsigned char digest[32];
int bits = 0, n_bits = 0;
if (!PyArg_ParseTuple(args, "|ii", &bits, &n_bits))
return NULL;
if (n_bits > 7) {
PyErr_SetString(PyExc_ZeroDivisionError, "digest cannot take
more than 7 bits.");
return NULL;
}
SHA160_digest(&self->hash_state, digest, bits, n_bits);
return Py_BuildValue("s#", digest, 32);
}


static PyObject *
sha160_copy(PyObject *obj, PyObject *args)
{
SHA160_Object* self = (SHA160_Object*)obj;
SHA160_Object* hash_instance;
if (!PyArg_ParseTuple(args, ""))
return NULL;
hash_instance = PyObject_New(SHA160_Object, &sha160_Type_object);
if (hash_instance == NULL)
return NULL;
hash_instance->hash_state = self->hash_state;
return (PyObject*)hash_instance;
}

static PyMethodDef sha160_methods[] = {
{"init", (PyCFunction)sha160_init, METH_VARARGS, NULL},
{"update", (PyCFunction)sha160_update, METH_VARARGS, NULL},
{"digest", (PyCFunction)sha160_digest, METH_VARARGS, NULL},
{"copy", (PyCFunction)sha160_copy, METH_VARARGS, NULL},
{NULL, NULL}
};

static PyObject*
sha160_getattr(PyObject* sha, char* name)
{
return Py_FindMethod(sha160_methods, sha, name);
}

static PyTypeObject sha160_Type_object = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"secure_hash.SHA160", /*tp_name*/
sizeof(SHA160_Object), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)generic_dealloc, /*tp_dealloc*/
0, /*tp_print*/
sha160_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
0, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
};


typedef struct {
PyObject_HEAD
SHA256_State hash_state;
} SHA256_Object;

static PyTypeObject sha256_Type_object;

static PyObject*
sha256_init(PyObject *obj, PyObject *args)
{
int digest_len_bits;
SHA256_Object* self = (SHA256_Object*)obj;
if (!PyArg_ParseTuple(args, "i", &digest_len_bits))
return NULL;
SHA256_init(&self->hash_state, digest_len_bits);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject*
sha256_update(PyObject *obj, PyObject *args)
{
SHA256_Object* self = (SHA256_Object*)obj;
unsigned char* preimage = 0;
int size = 0;
if (!PyArg_ParseTuple(args, "|s#", &preimage, &size))
return NULL;
SHA256_update(&self->hash_state, preimage, (size_t)size);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject *
sha256_digest(PyObject *obj, PyObject *args)
{
SHA256_Object* self = (SHA256_Object*)obj;
unsigned char digest[32];
int bits = 0, n_bits = 0;
if (!PyArg_ParseTuple(args, "|ii", &bits, &n_bits))
return NULL;
if (n_bits > 7) {
PyErr_SetString(PyExc_ZeroDivisionError, "digest cannot take
more than 7 bits.");
return NULL;
}
SHA256_digest(&self->hash_state, digest, bits, n_bits);
return Py_BuildValue("s#", digest, 32);
}


static PyObject *
sha256_copy(PyObject *obj, PyObject *args)
{
SHA256_Object* self = (SHA256_Object*)obj;
SHA256_Object* hash_instance;
if (!PyArg_ParseTuple(args, ""))
return NULL;
hash_instance = PyObject_New(SHA256_Object, &sha256_Type_object);
if (hash_instance == NULL)
return NULL;
hash_instance->hash_state = self->hash_state;
return (PyObject*)hash_instance;
}

static PyMethodDef sha256_methods[] = {
{"init", (PyCFunction)sha256_init, METH_VARARGS, NULL},
{"update", (PyCFunction)sha256_update, METH_VARARGS, NULL},
{"digest", (PyCFunction)sha256_digest, METH_VARARGS, NULL},
{"copy", (PyCFunction)sha256_copy, METH_VARARGS, NULL},
{NULL, NULL}
};

static PyObject*
sha256_getattr(PyObject* sha, char* name)
{
return Py_FindMethod(sha256_methods, sha, name);
}

static PyTypeObject sha256_Type_object = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"secure_hash.SHA256", /*tp_name*/
sizeof(SHA256_Object), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)generic_dealloc, /*tp_dealloc*/
0, /*tp_print*/
sha256_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
0, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
};



typedef struct {
PyObject_HEAD
SHA512_State hash_state;
} SHA512_Object;

static PyTypeObject sha512_Type_object;


static PyObject*
sha512_init(PyObject *obj, PyObject *args)
{
int digest_len_bits;
SHA512_Object* self = (SHA512_Object*)obj;
if (!PyArg_ParseTuple(args, "i", &digest_len_bits))
return NULL;
SHA512_init(&self->hash_state, digest_len_bits);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject*
sha512_update(PyObject *obj, PyObject *args)
{
SHA512_Object* self = (SHA512_Object*)obj;
unsigned char* preimage = 0;
int size = 0;
if (!PyArg_ParseTuple(args, "|s#", &preimage, &size))
return NULL;
SHA512_update(&self->hash_state, preimage, (size_t)size);
Py_INCREF(Py_None);
return Py_None;
}


static PyObject *
sha512_digest(PyObject *obj, PyObject *args)
{
SHA512_Object* self = (SHA512_Object*)obj;
unsigned char digest[64];
int bits = 0, n_bits = 0;
if (!PyArg_ParseTuple(args, "|ii", &bits, &n_bits))
return NULL;
if (n_bits > 7) {
PyErr_SetString(PyExc_ZeroDivisionError, "digest cannot take
more than 7 bits.");
return NULL;
}
SHA512_digest(&self->hash_state, digest, bits, n_bits);
return Py_BuildValue("s#", digest, 64);
}


static PyObject *
sha512_copy(PyObject *obj, PyObject *args)
{
SHA512_Object* self = (SHA512_Object*)obj;
SHA512_Object* hash_instance;
if (!PyArg_ParseTuple(args, ""))
return NULL;
hash_instance = PyObject_New(SHA512_Object, &sha512_Type_object);
if (hash_instance == NULL)
return NULL;
hash_instance->hash_state = self->hash_state;
return (PyObject*)hash_instance;
}

static PyMethodDef sha512_methods[] = {
{"init", (PyCFunction)sha512_init, METH_VARARGS, NULL},
{"update", (PyCFunction)sha512_update, METH_VARARGS, NULL},
{"digest", (PyCFunction)sha512_digest, METH_VARARGS, NULL},
{"copy", (PyCFunction)sha512_copy, METH_VARARGS, NULL},
{NULL, NULL}
};

static PyObject*
sha512_getattr(PyObject* sha, char* name)
{
return Py_FindMethod(sha512_methods, sha, name);
}

static PyTypeObject sha512_Type_object = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"secure_hash.SHA512", /*tp_name*/
sizeof(SHA512_Object), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)generic_dealloc, /*tp_dealloc*/
0, /*tp_print*/
sha512_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
0, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
};


static PyMethodDef module_methods[] = {
{NULL, NULL, 0, NULL} /* No methods, just classes. */
};

PyMODINIT_FUNC
initsha2_ext(void)
{
PyObject* m;

sha160_Type_object.tp_new = PyType_GenericNew;
if (PyType_Ready(&sha160_Type_object) < 0)
return;

sha256_Type_object.tp_new = PyType_GenericNew;
if (PyType_Ready(&sha256_Type_object) < 0)
return;

sha512_Type_object.tp_new = PyType_GenericNew;
if (PyType_Ready(&sha512_Type_object) < 0)
return;

m = Py_InitModule3("sha2_ext", module_methods, "SHA 1(160), 224,
256, 384, 512.");

Py_INCREF(&sha160_Type_object);
PyModule_AddObject(m, "SHA160", (PyObject*)&sha160_Type_object);
Py_INCREF(&sha256_Type_object);
PyModule_AddObject(m, "SHA256", (PyObject*)&sha256_Type_object);
Py_INCREF(&sha512_Type_object);
PyModule_AddObject(m, "SHA512", (PyObject*)&sha512_Type_object);
}
 
P

Paul Rubin

Nice. Note that the Sourceforge bug for this issue indicates that
something is already being done about it. It just happens to have
been updated a day or so ago:

https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1123660&group_id=5470

Note to skeptics: the attacks are pretty serious. Here's a demo of a
meaningful possible fraud resulting from knowing just one md5
collision, possibly found by somebody else:

http://www.cits.rub.de/imperia/md/content/magnus/rump_ec05.pdf

Something similar can be done with SHA1 if a collision gets published.
The work factor for finding an SHA1 collision is now down to O(2**63),
which is within range of a distributed internet search.

The md5 attack relies on the md5's message-extension property (shared
by sha-1): if you find just one collision, you can easily generate an
"infinite" family of colliding messages.

Anyone know if the sha-2 hashes have that property?
 
P

Paul Rubin

Bryan Olson said:
The module provides classes and functions. The functions are:

string_to_hex(str): Return a string with two hex digits for
each byte of str, representing the ord() of the byte. The
case of the hex digits A-F/a-f is up to Python's built-in
formatting; Python doc doesn't specify the case, so it may
be either and may change.

oid_to_der(arc_sequence): Return the DER encoding of an OID,
including the encoded tag and length.

smd_from_oid(oid): Look up and return the Secure Message
Digest class corresponding to the oid, or None if no such
class is known. The oid may be a sequence of integer arcs,
or a string holding the DER encoding.

Note there's a PEP for crypto hash function API's and modules
like hmac.py expect hashes to conform to it:

http://www.python.org/peps/pep-0247.html

You might want to bring your own API closer to it. Also, I think the
PEP should be extended to include those OID lookup functions.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,038
Messages
2,570,372
Members
47,018
Latest member
IrisN51866

Latest Threads

Top