#include "../gskdebug.h"
#include "gskhash.h"
#include "../gskghelpers.h"
#include "../gskmacros.h"
#include <string.h>
/* --- macros which we might later expose for efficiency --- */
#define GSK_HASH_FEED(hash, data, len) \
G_STMT_START{ \
(*(hash)->feed) (hash, data, len); \
}G_STMT_END
#define GSK_HASH_DONE(hash) \
G_STMT_START{ \
g_assert (((hash)->flags & 1) == 0); \
(hash)->hash_value = (*(hash)->done) (hash); \
(hash)->flags = 1; \
}G_STMT_END
#define GSK_HASH_DESTROY(hash) \
G_STMT_START{ \
(*(hash)->destroy) (hash); \
}G_STMT_END
#define GSK_HASH_GET_SIZE(hash) \
((hash)->size)
/**
* gsk_hash_feed:
* @hash: the hash to feed data.
* @data: binary data to accumulate in the hash.
* @length: length of the binary data.
*
* Affect the hash incrementally;
* hash the given binary data.
*
* You may call this function on little bits of data
* and it must have exactly the same effect
* is if you called it once with a larger
* slab of data.
*/
void
gsk_hash_feed (GskHash *hash,
gconstpointer data,
guint length)
{
GSK_HASH_FEED (hash, data, length);
}
/**
* gsk_hash_feed_str:
* @hash: the hash to feed data.
* @str: a NUL-terminated string to feed to the hash.
*
* Hash the given binary data (incrementally).
*
* You may mix calls to gsk_hash_feed() and gsk_hash_feed_str().
*/
void
gsk_hash_feed_str (GskHash *hash,
const char *str)
{
GSK_HASH_FEED (hash, str, strlen (str));
}
/**
* gsk_hash_done:
* @hash: the hash to finish.
*
* Finish processing loose data for the hash.
* This may only be called once in
* the lifetime of the hash.
*/
void
gsk_hash_done (GskHash *hash)
{
g_return_if_fail ((hash->flags & 1) == 0);
GSK_HASH_DONE (hash);
}
/**
* gsk_hash_get_size:
* @hash: the hash to query.
*
* Get the number of binary bytes that this
* function maps to.
*
* returns: the number of bytes of binary data in this hash.
*/
guint
gsk_hash_get_size (GskHash *hash)
{
return GSK_HASH_GET_SIZE (hash);
}
/**
* gsk_hash_get:
* @hash: the hash to query.
* @data_out: binary buffer to fill with the hash value.
*
* Get a binary hash value. This should be of the
* size returned by gsk_hash_get_size().
*/
void
gsk_hash_get (GskHash *hash,
guint8 *data_out)
{
g_return_if_fail ((hash->flags & 1) == 1);
memcpy (data_out, hash->hash_value, hash->size);
}
/**
* gsk_hash_get_hex:
* @hash: the hash to query.
* @hex_out: buffer to fill with a NUL-terminated hex hash value.
*
* Get a hex hash value. This should be of the
* size returned by (gsk_hash_get_size() * 2 + 1).
*/
void
gsk_hash_get_hex (GskHash *hash,
gchar *hex_out)
{
static const char hex_digits[] = "0123456789abcdef";
guint i;
g_return_if_fail ((hash->flags & 1) == 1);
for (i = 0; i < hash->size; i++)
{
guint8 h = ((guint8 *) hash->hash_value)[i];
*hex_out++ = hex_digits[h >> 4];
*hex_out++ = hex_digits[h & 15];
}
*hex_out = 0;
}
/**
* gsk_hash_destroy:
* @hash: the hash function.
*
* Free memory used by the hash object.
*/
void
gsk_hash_destroy (GskHash *hash)
{
GSK_HASH_DESTROY (hash);
}
/*
* __ __ ____ ____
* | \/ | _ \| ___|
* | |\/| | | | |___ \
* | | | | |_| |___) |
* |_| |_|____/|____/
*
*/
/* FreeBSD: src/sys/crypto/md5.h,v 1.1.2.1 2000/07/15 07:14:18 kris Exp */
/* KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define MD5_BUFLEN 64
typedef struct {
union {
guint32 md5_state32[4];
guint8 md5_state8[16];
} md5_st;
#define md5_sta md5_st.md5_state32[0]
#define md5_stb md5_st.md5_state32[1]
#define md5_stc md5_st.md5_state32[2]
#define md5_std md5_st.md5_state32[3]
#define md5_st8 md5_st.md5_state8
union {
guint64 md5_count64;
guint8 md5_count8[8];
} md5_count;
#define md5_n md5_count.md5_count64
#define md5_n8 md5_count.md5_count8
guint md5_i;
guint8 md5_buf[MD5_BUFLEN];
} md5_ctxt;
static void md5_init (md5_ctxt *);
static void md5_loop (md5_ctxt *, guint8 *, guint);
static void md5_pad (md5_ctxt *);
static void md5_result (guint8 *, md5_ctxt *);
/* compatibility */
#define MD5_CTX md5_ctxt
#define MD5Init(x) md5_init((x))
#define MD5Update(x, y, z) md5_loop((x), (y), (z))
#define MD5Final(x, y) \
do { \
md5_pad((y)); \
md5_result((x), (y)); \
} while (0)
/* FreeBSD: src/sys/crypto/md5.c,v 1.1.2.2 2001/07/03 11:01:27 ume Exp */
/* KAME: md5.c,v 1.5 2000/11/08 06:13:08 itojun Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#include <sys/time.h>
#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
#define ROUND1(a, b, c, d, k, s, i) { \
(a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
(a) = SHIFT((a), (s)); \
(a) = (b) + (a); \
}
#define ROUND2(a, b, c, d, k, s, i) { \
(a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
(a) = SHIFT((a), (s)); \
(a) = (b) + (a); \
}
#define ROUND3(a, b, c, d, k, s, i) { \
(a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
(a) = SHIFT((a), (s)); \
(a) = (b) + (a); \
}
#define ROUND4(a, b, c, d, k, s, i) { \
(a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
(a) = SHIFT((a), (s)); \
(a) = (b) + (a); \
}
#define Sa 7
#define Sb 12
#define Sc 17
#define Sd 22
#define Se 5
#define Sf 9
#define Sg 14
#define Sh 20
#define Si 4
#define Sj 11
#define Sk 16
#define Sl 23
#define Sm 6
#define Sn 10
#define So 15
#define Sp 21
#define MD5_A0 0x67452301
#define MD5_B0 0xefcdab89
#define MD5_C0 0x98badcfe
#define MD5_D0 0x10325476
/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
static const guint32 T[65] = {
0,
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
};
static const guint8 md5_paddat[MD5_BUFLEN] = {
0x80, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
static void md5_calc (guint8 *, md5_ctxt *);
static inline void md5_init(ctxt)
md5_ctxt *ctxt;
{
ctxt->md5_n = 0;
ctxt->md5_i = 0;
ctxt->md5_sta = MD5_A0;
ctxt->md5_stb = MD5_B0;
ctxt->md5_stc = MD5_C0;
ctxt->md5_std = MD5_D0;
bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
}
static inline void md5_loop(ctxt, input, len)
md5_ctxt *ctxt;
guint8 *input;
u_int len; /* number of bytes */
{
u_int gap, i;
ctxt->md5_n += len * 8; /* byte to bit */
gap = MD5_BUFLEN - ctxt->md5_i;
if (len >= gap) {
bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
gap);
md5_calc(ctxt->md5_buf, ctxt);
for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
md5_calc((guint8 *)(input + i), ctxt);
}
ctxt->md5_i = len - i;
bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i);
} else {
bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
len);
ctxt->md5_i += len;
}
}
static void md5_pad(ctxt)
md5_ctxt *ctxt;
{
u_int gap;
/* Don't count up padding. Keep md5_n. */
gap = MD5_BUFLEN - ctxt->md5_i;
if (gap > 8) {
bcopy((void *)md5_paddat,
(void *)(ctxt->md5_buf + ctxt->md5_i),
gap - sizeof(ctxt->md5_n));
} else {
/* including gap == 8 */
bcopy((void *)md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i),
gap);
md5_calc(ctxt->md5_buf, ctxt);
bcopy((void *)(md5_paddat + gap),
(void *)ctxt->md5_buf,
MD5_BUFLEN - sizeof(ctxt->md5_n));
}
/* 8 byte word */
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8);
#elif (G_BYTE_ORDER == G_BIG_ENDIAN)
ctxt->md5_buf[56] = ctxt->md5_n8[7];
ctxt->md5_buf[57] = ctxt->md5_n8[6];
ctxt->md5_buf[58] = ctxt->md5_n8[5];
ctxt->md5_buf[59] = ctxt->md5_n8[4];
ctxt->md5_buf[60] = ctxt->md5_n8[3];
ctxt->md5_buf[61] = ctxt->md5_n8[2];
ctxt->md5_buf[62] = ctxt->md5_n8[1];
ctxt->md5_buf[63] = ctxt->md5_n8[0];
#else
must be either BIG or LITTLE endian
#endif
md5_calc(ctxt->md5_buf, ctxt);
}
static void md5_result(digest, ctxt)
guint8 *digest;
md5_ctxt *ctxt;
{
/* 4 byte words */
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
bcopy(&ctxt->md5_st8[0], digest, 16);
#endif
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
#endif
}
static void md5_calc(b64, ctxt)
guint8 *b64;
md5_ctxt *ctxt;
{
guint32 A = ctxt->md5_sta;
guint32 B = ctxt->md5_stb;
guint32 C = ctxt->md5_stc;
guint32 D = ctxt->md5_std;
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
guint32 *X = (guint32 *)b64;
#elif (G_BYTE_ORDER == G_BIG_ENDIAN)
/* 4 byte words */
/* what a brute force but fast! */
guint32 X[16];
guint8 *y = (guint8 *)X;
y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
#else
Must be either BIG or LITTLE endian.
#endif
ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2);
ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4);
ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6);
ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8);
ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10);
ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18);
ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20);
ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24);
ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28);
ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30);
ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34);
ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38);
ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42);
ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44);
ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48);
ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50);
ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52);
ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54);
ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56);
ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);
ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);
ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);
ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64);
ctxt->md5_sta += A;
ctxt->md5_stb += B;
ctxt->md5_stc += C;
ctxt->md5_std += D;
}
#undef SHIFT
#undef F
#undef G
#undef H
#undef I
#undef ROUND1
#undef ROUND2
#undef ROUND3
#undef ROUND4
#undef Sa
#undef Sb
#undef Sc
#undef Sd
#undef Se
#undef Sf
#undef Sg
#undef Sh
#undef Si
#undef Sj
#undef Sk
#undef Sl
#undef Sm
#undef Sn
#undef So
#undef Sp
#undef MD5_A0
#undef MD5_B0
#undef MD5_C0
#undef MD5_D0
/* --- gskmd5 code --- */
typedef struct _HashMD5 HashMD5;
struct _HashMD5
{
GskHash hash;
guint8 md5value[16];
MD5_CTX context;
};
GSK_DECLARE_POOL_ALLOCATORS(HashMD5, hash_md5, 4)
static void
gsk_hash_md5_feed (GskHash *hash,
gconstpointer data,
guint len)
{
HashMD5 *hash_md5 = (HashMD5 *) hash;
MD5Update (&hash_md5->context, (gpointer) data, len);
}
static gpointer
gsk_hash_md5_done (GskHash *hash)
{
HashMD5 *hash_md5 = (HashMD5 *) hash;
MD5Final (hash_md5->md5value, &hash_md5->context);
return hash_md5->md5value;
}
static void
gsk_hash_md5_destroy (GskHash *hash)
{
hash_md5_free ((HashMD5 *) hash);
}
/**
* gsk_hash_new_md5:
*
* Create a new MD5 hasher.
*
* returns: the newly allocated hash object.
*/
GskHash *
gsk_hash_new_md5 ()
{
HashMD5 *hash_md5 = hash_md5_alloc ();
GskHash *hash = (GskHash *) hash_md5;
hash->size = 16;
hash->feed = gsk_hash_md5_feed;
hash->done = gsk_hash_md5_done;
hash->destroy = gsk_hash_md5_destroy;
hash->flags = 0;
hash->hash_value = NULL;
MD5Init (&hash_md5->context);
return hash;
}
/*
* ____ _ _ _ _
* / ___|| | | | / \ / |
* \___ \| |_| | / _ \ | |
* ___) | _ |/ ___ \| |
* |____/|_| |_/_/ \_\_|
*
*/
/* FreeBSD: src/sys/crypto/sha1.h,v 1.3.2.3 2000/10/12 18:59:31 archie Exp */
/* KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
* based on: http://csrc.nist.gov/fips/fip180-1.txt
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
*/
#ifndef _NETINET6_SHA1_H_
#define _NETINET6_SHA1_H_
struct sha1_ctxt {
union {
guint8 b8[20];
guint32 b32[5];
} h;
union {
guint8 b8[8];
guint64 b64[1];
} c;
union {
guint8 b8[64];
guint32 b32[16];
} m;
guint8 count;
};
static void sha1_init (struct sha1_ctxt *);
static void sha1_pad (struct sha1_ctxt *);
static void sha1_loop (struct sha1_ctxt *, const guint8 *, size_t);
static void sha1_result (struct sha1_ctxt *, guint8 *);
/* compatibilty with other SHA1 source codes */
typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Init(x) sha1_init((x))
#define SHA1Update(x, y, z) sha1_loop((x), (y), (z))
#define SHA1Final(x, y) sha1_result((y), (x))
#define SHA1_RESULTLEN (160/8)
#endif /*_NETINET6_SHA1_H_*/
/* FreeBSD: src/sys/crypto/sha1.c,v 1.2.2.4 2001/07/03 11:01:27 ume Exp */
/* KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
* based on: http://csrc.nist.gov/fips/fip180-1.txt
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
*/
#include <sys/types.h>
#include <sys/time.h>
/* constant table */
static guint32 _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
#define K(t) _K[(t) / 20]
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
#define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
#define H(n) (ctxt->h.b32[(n)])
#define COUNT (ctxt->count)
#define BCOUNT (ctxt->c.b64[0] / 8)
#define W(n) (ctxt->m.b32[(n)])
#define PUTBYTE(x) { \
ctxt->m.b8[(COUNT % 64)] = (x); \
COUNT++; \
COUNT %= 64; \
ctxt->c.b64[0] += 8; \
if (COUNT % 64 == 0) \
sha1_step(ctxt); \
}
#define PUTPAD(x) { \
ctxt->m.b8[(COUNT % 64)] = (x); \
COUNT++; \
COUNT %= 64; \
if (COUNT % 64 == 0) \
sha1_step(ctxt); \
}
static void sha1_step (struct sha1_ctxt *);
static void
sha1_step(ctxt)
struct sha1_ctxt *ctxt;
{
guint32 a, b, c, d, e;
size_t t, s;
guint32 tmp;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
struct sha1_ctxt tctxt;
bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
#endif
a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
for (t = 0; t < 20; t++) {
s = t & 0x0f;
if (t >= 16) {
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
}
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp;
}
for (t = 20; t < 40; t++) {
s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp;
}
for (t = 40; t < 60; t++) {
s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp;
}
for (t = 60; t < 80; t++) {
s = t & 0x0f;
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
e = d; d = c; c = S(30, b); b = a; a = tmp;
}
H(0) = H(0) + a;
H(1) = H(1) + b;
H(2) = H(2) + c;
H(3) = H(3) + d;
H(4) = H(4) + e;
bzero(&ctxt->m.b8[0], 64);
}
/*------------------------------------------------------------*/
static void
sha1_init(ctxt)
struct sha1_ctxt *ctxt;
{
bzero(ctxt, sizeof(struct sha1_ctxt));
H(0) = 0x67452301;
H(1) = 0xefcdab89;
H(2) = 0x98badcfe;
H(3) = 0x10325476;
H(4) = 0xc3d2e1f0;
}
static void
sha1_pad(ctxt)
struct sha1_ctxt *ctxt;
{
size_t padlen; /*pad length in bytes*/
size_t padstart;
PUTPAD(0x80);
padstart = COUNT % 64;
padlen = 64 - padstart;
if (padlen < 8) {
bzero(&ctxt->m.b8[padstart], padlen);
COUNT += padlen;
COUNT %= 64;
sha1_step(ctxt);
padstart = COUNT % 64; /* should be 0 */
padlen = 64 - padstart; /* should be 64 */
}
bzero(&ctxt->m.b8[padstart], padlen - 8);
COUNT += (padlen - 8);
COUNT %= 64;
#if G_BYTE_ORDER == G_BIG_ENDIAN
PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
#else
PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
#endif
}
static void
sha1_loop(ctxt, input, len)
struct sha1_ctxt *ctxt;
const guint8 *input;
size_t len;
{
size_t gaplen;
size_t gapstart;
size_t off;
size_t copysiz;
off = 0;
while (off < len) {
gapstart = COUNT % 64;
gaplen = 64 - gapstart;
copysiz = (gaplen < len - off) ? gaplen : len - off;
bcopy(&input[off], &ctxt->m.b8[gapstart], copysiz);
COUNT += copysiz;
COUNT %= 64;
ctxt->c.b64[0] += copysiz * 8;
if (COUNT % 64 == 0)
sha1_step(ctxt);
off += copysiz;
}
}
static void
sha1_result(ctxt, digest)
struct sha1_ctxt *ctxt;
guint8 *digest;
{
sha1_pad(ctxt);
#if G_BYTE_ORDER == G_BIG_ENDIAN
bcopy(&ctxt->h.b8[0], digest, 20);
#else
digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
#endif
}
#undef F0
#undef F1
#undef F2
#undef F3
#undef S
#undef H
#undef COUNT
#undef BCOUNT
#undef W
#undef PUTBYTE
#undef PUTPAD
/* --- gsk sha1 code --- */
typedef struct _HashSHA1 HashSHA1;
struct _HashSHA1
{
GskHash hash;
guint8 sha1value[16];
SHA1_CTX context;
};
GSK_DECLARE_POOL_ALLOCATORS(HashSHA1, hash_sha1, 4);
static void
gsk_hash_sha1_feed (GskHash *hash,
gconstpointer data,
guint len)
{
HashSHA1 *hash_sha1 = (HashSHA1 *) hash;
SHA1Update (&hash_sha1->context, (gpointer) data, len);
}
static gpointer
gsk_hash_sha1_done (GskHash *hash)
{
HashSHA1 *hash_sha1 = (HashSHA1 *) hash;
SHA1Final (hash_sha1->sha1value, &hash_sha1->context);
return hash_sha1->sha1value;
}
static void
gsk_hash_sha1_destroy (GskHash *hash)
{
hash_sha1_free ((HashSHA1 *) hash);
}
/**
* gsk_hash_new_sha1:
*
* Create a new SHA1 hasher.
*
* returns: the newly allocated hash object.
*/
GskHash *
gsk_hash_new_sha1 ()
{
HashSHA1 *hash_sha1 = hash_sha1_alloc ();
GskHash *hash = (GskHash *) hash_sha1;
hash->size = 20;
hash->feed = gsk_hash_sha1_feed;
hash->done = gsk_hash_sha1_done;
hash->destroy = gsk_hash_sha1_destroy;
hash->flags = 0;
hash->hash_value = NULL;
SHA1Init (&hash_sha1->context);
return hash;
}
/*
* ____ _ _ _ ____ ____ __
* / ___|| | | | / \ |___ \| ___| / /_
* \___ \| |_| | / _ \ _____ __) |___ \| '_ \
* ___) | _ |/ ___ \_____/ __/ ___) | (_) |
* |____/|_| |_/_/ \_\ |_____|____/ \___/
*/
typedef struct _HashSHA256 HashSHA256;
struct _HashSHA256
{
GskHash hash;
guint32 total[2];
guint32 state[8];
guint8 buffer[64];
guint8 digest[32]; /* if done */
};
#define GET_UINT32(n,b,i) \
G_STMT_START{ \
(n) = ((guint32) (b)[(i) ] << 24) \
| ((guint32) (b)[(i) + 1] << 16) \
| ((guint32) (b)[(i) + 2] << 8) \
| ((guint32) (b)[(i) + 3] ); \
}G_STMT_END
#define PUT_UINT32(n,b,i) \
G_STMT_START{ \
(b)[(i) ] = (guint8) ((n) >> 24); \
(b)[(i) + 1] = (guint8) ((n) >> 16); \
(b)[(i) + 2] = (guint8) ((n) >> 8); \
(b)[(i) + 3] = (guint8) ((n) ); \
}G_STMT_END
static inline void
sha256_process_64 (HashSHA256 *ctx,
const guint8 data[64])
{
guint32 temp1, temp2, W[64];
guint32 A, B, C, D, E, F, G, H;
GET_UINT32 (W[0], data, 0);
GET_UINT32 (W[1], data, 4);
GET_UINT32 (W[2], data, 8);
GET_UINT32 (W[3], data, 12);
GET_UINT32 (W[4], data, 16);
GET_UINT32 (W[5], data, 20);
GET_UINT32 (W[6], data, 24);
GET_UINT32 (W[7], data, 28);
GET_UINT32 (W[8], data, 32);
GET_UINT32 (W[9], data, 36);
GET_UINT32 (W[10], data, 40);
GET_UINT32 (W[11], data, 44);
GET_UINT32 (W[12], data, 48);
GET_UINT32 (W[13], data, 52);
GET_UINT32 (W[14], data, 56);
GET_UINT32 (W[15], data, 60);
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
G_STMT_START{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}G_STMT_END
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
P (A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
P (H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
P (G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
P (F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
P (E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
P (D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
P (C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
P (B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
P (A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
P (H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
P (G, H, A, B, C, D, E, F, W[10], 0x243185BE);
P (F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
P (E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
P (D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
P (C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
P (B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
P (A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
P (H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
P (G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
P (F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
P (E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
P (D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
P (C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
P (B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
P (A, B, C, D, E, F, G, H, R(24), 0x983E5152);
P (H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
P (G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
P (F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
P (E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
P (D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
P (C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
P (B, C, D, E, F, G, H, A, R(31), 0x14292967);
P (A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
P (H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
P (G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
P (F, G, H, A, B, C, D, E, R(35), 0x53380D13);
P (E, F, G, H, A, B, C, D, R(36), 0x650A7354);
P (D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
P (C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
P (B, C, D, E, F, G, H, A, R(39), 0x92722C85);
P (A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
P (H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
P (G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
P (F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
P (E, F, G, H, A, B, C, D, R(44), 0xD192E819);
P (D, E, F, G, H, A, B, C, R(45), 0xD6990624);
P (C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
P (B, C, D, E, F, G, H, A, R(47), 0x106AA070);
P (A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
P (H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
P (G, H, A, B, C, D, E, F, R(50), 0x2748774C);
P (F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
P (E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
P (D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
P (C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
P (B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
P (A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
P (H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
P (G, H, A, B, C, D, E, F, R(58), 0x84C87814);
P (F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
P (E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
P (D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
P (C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
P (B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
#undef SHR
#undef ROTR
#undef S0
#undef S1
#undef S2
#undef S3
#undef F0
#undef F1
#undef R
#undef P
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
static void
sha256_feed (GskHash *hash, gconstpointer buffer, guint length)
{
HashSHA256 *ctx = (HashSHA256 *) hash;
guint32 left, fill;
const guint8 *input = buffer;
if (length == 0)
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += length;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < length)
ctx->total[1]++;
if (left > 0 && length >= fill)
{
memcpy ((ctx->buffer + left), input, fill);
sha256_process_64 (ctx, ctx->buffer);
length -= fill;
input += fill;
left = 0;
}
while (length >= 64)
{
sha256_process_64 (ctx, input);
length -= 64;
input += 64;
}
if (length)
memcpy (ctx->buffer + left, input, length);
}
static guint8 sha256_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static gpointer
sha256_done (GskHash *hash)
{
HashSHA256 *ctx = (HashSHA256 *) hash;
guint32 last, padn;
guint32 high, low;
guint8 msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
PUT_UINT32 (high, msglen, 0);
PUT_UINT32 (low, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
sha256_feed (hash, sha256_padding, padn);
sha256_feed (hash, msglen, 8 );
PUT_UINT32 (ctx->state[0], ctx->digest, 0);
PUT_UINT32 (ctx->state[1], ctx->digest, 4);
PUT_UINT32 (ctx->state[2], ctx->digest, 8);
PUT_UINT32 (ctx->state[3], ctx->digest, 12);
PUT_UINT32 (ctx->state[4], ctx->digest, 16);
PUT_UINT32 (ctx->state[5], ctx->digest, 20);
PUT_UINT32 (ctx->state[6], ctx->digest, 24);
PUT_UINT32 (ctx->state[7], ctx->digest, 28);
return ctx->digest;
}
#undef PUT_UINT32
#undef GET_UINT32
GskHash *
gsk_hash_new_sha256 (void)
{
HashSHA256 *rv = g_new (HashSHA256, 1);
GskHash *h;
rv->total[0] = 0;
rv->total[1] = 0;
rv->state[0] = 0x6A09E667;
rv->state[1] = 0xBB67AE85;
rv->state[2] = 0x3C6EF372;
rv->state[3] = 0xA54FF53A;
rv->state[4] = 0x510E527F;
rv->state[5] = 0x9B05688C;
rv->state[6] = 0x1F83D9AB;
rv->state[7] = 0x5BE0CD19;
h = (GskHash *) rv;
h->size = 32;
h->feed = sha256_feed;
h->done = sha256_done;
h->destroy = (void (*)(GskHash*)) g_free;
return h;
}
/*
* ____ ____ ____ _________
* / ___| _ \ / ___|___ /___ \
* | | | |_) | | |_ \ __) |
* | |___| _ <| |___ ___) / __/
* \____|_| \_\\____|____/_____|
*
*/
/*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera
* tions for all combinations of data and CRC register values
*
* The values must be right-shifted by eight bits by the "updcrc
* logic; the shift must be unsigned (bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions
* polynomial $edb88320
*/
/* $Id: gskhash.c,v 1.1.2.3 2005/08/23 23:54:44 davebenson Exp $ */
static const guint32 crc32_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
static inline guint32
crc32(guint32 val, const void *ss, int len)
{
const unsigned char *s = ss;
while (--len >= 0)
val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
return val;
}
/* --- gsk crc32 interface --- */
typedef struct _HashCRC32 HashCRC32;
struct _HashCRC32
{
GskHash base;
guint32 cur_value;
};
GSK_DECLARE_POOL_ALLOCATORS (HashCRC32, hash_crc32, 4)
static void
gsk_hash_crc32_feed (GskHash *hash,
gconstpointer data,
guint len)
{
HashCRC32 *hash_crc32 = (HashCRC32 *) hash;
hash_crc32->cur_value = crc32 (hash_crc32->cur_value, data, len);
}
static gpointer
gsk_hash_crc32_done (GskHash *hash)
{
HashCRC32 *hash_crc32 = (HashCRC32 *) hash;
return &hash_crc32->cur_value;
}
static gpointer
gsk_hash_crc32_done_swap (GskHash *hash)
{
HashCRC32 *hash_crc32 = (HashCRC32 *) hash;
hash_crc32->cur_value = GUINT32_SWAP_LE_BE (hash_crc32->cur_value);
return &hash_crc32->cur_value;
}
static void
gsk_hash_crc32_destroy (GskHash *hash)
{
hash_crc32_free ((HashCRC32 *) hash);
}
/**
* gsk_hash_new_crc32:
* @big_endian: whether to compute a big-endian crc32 hash.
* (As opposed to a little endian hash).
*
* Typically called as gsk_hash_new_crc32(G_BYTE_ORDER == G_BIG_ENDIAN).
*
* returns: the newly allocated hash object.
*/
GskHash *
gsk_hash_new_crc32 (gboolean big_endian)
{
HashCRC32 *hash_crc32 = hash_crc32_alloc ();
GskHash *hash = (GskHash *) hash_crc32;
hash->size = 4;
hash->feed = gsk_hash_crc32_feed;
if (big_endian == (G_BYTE_ORDER == G_BIG_ENDIAN))
hash->done = gsk_hash_crc32_done;
else
hash->done = gsk_hash_crc32_done_swap;
hash->destroy = gsk_hash_crc32_destroy;
hash->flags = 0;
hash->hash_value = NULL;
hash_crc32->cur_value = 0;
return hash;
}
syntax highlighted by Code2HTML, v. 0.9.1