Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
/*
2
This code is based on the code found from 7-Zip, which has a modified
3
version of the SHA-256 found from Crypto++ .
4
The code was modified a little to fit into liblzma and fitz.
5
 
6
This file has been put into the public domain.
7
You can do whatever you want with this file.
8
*/
9
 
10
#include "fitz.h"
11
 
12
static inline int isbigendian(void)
13
{
14
	static const int one = 1;
15
	return *(char*)&one == 0;
16
}
17
 
18
static inline unsigned int bswap32(unsigned int num)
19
{
20
	if (!isbigendian())
21
	{
22
		return	( (((num) << 24))
23
			| (((num) << 8) & 0x00FF0000)
24
			| (((num) >> 8) & 0x0000FF00)
25
			| (((num) >> 24)) );
26
	}
27
	return num;
28
}
29
 
30
/* At least on x86, GCC is able to optimize this to a rotate instruction. */
31
#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
32
 
33
#define blk0(i) (W[i] = data[i])
34
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
35
		+ s0(W[(i - 15) & 15]))
36
 
37
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
38
#define Maj(x, y, z) ((x & y) | (z & (x | y)))
39
 
40
#define a(i) T[(0 - i) & 7]
41
#define b(i) T[(1 - i) & 7]
42
#define c(i) T[(2 - i) & 7]
43
#define d(i) T[(3 - i) & 7]
44
#define e(i) T[(4 - i) & 7]
45
#define f(i) T[(5 - i) & 7]
46
#define g(i) T[(6 - i) & 7]
47
#define h(i) T[(7 - i) & 7]
48
 
49
#define R(i) \
50
	h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
51
		+ (j ? blk2(i) : blk0(i)); \
52
	d(i) += h(i); \
53
	h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
54
 
55
#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
56
#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
57
#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
58
#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
59
 
60
static const unsigned int SHA256_K[64] = {
61
	0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
62
	0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
63
	0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
64
	0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
65
	0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
66
	0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
67
	0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
68
	0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
69
	0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
70
	0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
71
	0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
72
	0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
73
	0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
74
	0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
75
	0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
76
	0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
77
};
78
 
79
static void
80
transform(unsigned int state[8], const unsigned int data_xe[16])
81
{
82
	unsigned int data[16];
83
	unsigned int W[16];
84
	unsigned int T[8];
85
	unsigned int j;
86
 
87
	/* ensure big-endian integers */
88
	for (j = 0; j < 16; j++)
89
		data[j] = bswap32(data_xe[j]);
90
 
91
	/* Copy state[] to working vars. */
92
	memcpy(T, state, sizeof(T));
93
 
94
	/* 64 operations, partially loop unrolled */
95
	for (j = 0; j < 64; j += 16) {
96
		R( 0); R( 1); R( 2); R( 3);
97
		R( 4); R( 5); R( 6); R( 7);
98
		R( 8); R( 9); R(10); R(11);
99
		R(12); R(13); R(14); R(15);
100
	}
101
 
102
	/* Add the working vars back into state[]. */
103
	state[0] += a(0);
104
	state[1] += b(0);
105
	state[2] += c(0);
106
	state[3] += d(0);
107
	state[4] += e(0);
108
	state[5] += f(0);
109
	state[6] += g(0);
110
	state[7] += h(0);
111
}
112
 
113
void fz_sha256_init(fz_sha256 *context)
114
{
115
	context->count[0] = context->count[1] = 0;
116
 
117
	context->state[0] = 0x6A09E667;
118
	context->state[1] = 0xBB67AE85;
119
	context->state[2] = 0x3C6EF372;
120
	context->state[3] = 0xA54FF53A;
121
	context->state[4] = 0x510E527F;
122
	context->state[5] = 0x9B05688C;
123
	context->state[6] = 0x1F83D9AB;
124
	context->state[7] = 0x5BE0CD19;
125
}
126
 
127
void fz_sha256_update(fz_sha256 *context, const unsigned char *input, unsigned int inlen)
128
{
129
	/* Copy the input data into a properly aligned temporary buffer.
130
	 * This way we can be called with arbitrarily sized buffers
131
	 * (no need to be multiple of 64 bytes), and the code works also
132
	 * on architectures that don't allow unaligned memory access. */
133
	while (inlen > 0)
134
	{
135
		const unsigned int copy_start = context->count[0] & 0x3F;
136
		unsigned int copy_size = 64 - copy_start;
137
		if (copy_size > inlen)
138
			copy_size = inlen;
139
 
140
		memcpy(context->buffer.u8 + copy_start, input, copy_size);
141
 
142
		input += copy_size;
143
		inlen -= copy_size;
144
		context->count[0] += copy_size;
145
		/* carry overflow from low to high */
146
		if (context->count[0] < copy_size)
147
			context->count[1]++;
148
 
149
		if ((context->count[0] & 0x3F) == 0)
150
			transform(context->state, context->buffer.u32);
151
	}
152
}
153
 
154
void fz_sha256_final(fz_sha256 *context, unsigned char digest[32])
155
{
156
	/* Add padding as described in RFC 3174 (it describes SHA-1 but
157
	 * the same padding style is used for SHA-256 too). */
158
	unsigned int j = context->count[0] & 0x3F;
159
	context->buffer.u8[j++] = 0x80;
160
 
161
	while (j != 56)
162
	{
163
		if (j == 64)
164
		{
165
			transform(context->state, context->buffer.u32);
166
			j = 0;
167
		}
168
		context->buffer.u8[j++] = 0x00;
169
	}
170
 
171
	/* Convert the message size from bytes to bits. */
172
	context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
173
	context->count[0] = context->count[0] << 3;
174
 
175
	context->buffer.u32[14] = bswap32(context->count[1]);
176
	context->buffer.u32[15] = bswap32(context->count[0]);
177
	transform(context->state, context->buffer.u32);
178
 
179
	for (j = 0; j < 8; j++)
180
		((unsigned int *)digest)[j] = bswap32(context->state[j]);
181
	memset(context, 0, sizeof(fz_sha256));
182
}