Remove preOptimize step from hphpc
[hiphop-php.git] / hphp / zend / zend-sha1.cpp
blob264a528b78551cd27cc7f7d555a1f704272bc4e6
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 2.00 of the Zend license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.zend.com/license/2_00.txt. |
12 | If you did not receive a copy of the Zend license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@zend.com so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #include "hphp/zend/zend-string.h"
20 #include <cinttypes>
22 namespace HPHP {
23 ///////////////////////////////////////////////////////////////////////////////
25 static unsigned char PADDING[64] = {
26 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
31 // F, G, H and I are basic SHA1 functions.
32 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
33 #define G(x, y, z) ((x) ^ (y) ^ (z))
34 #define H(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
35 #define I(x, y, z) ((x) ^ (y) ^ (z))
37 // ROTATE_LEFT rotates x left n bits.
38 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
40 // W[i]
41 #define W(i) ( tmp=x[(i-3)&15]^x[(i-8)&15]^x[(i-14)&15]^x[i&15], \
42 (x[i&15]=ROTATE_LEFT(tmp, 1)) )
44 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
45 #define FF(a, b, c, d, e, w) { \
46 (e) += F ((b), (c), (d)) + (w) + (uint32_t)(0x5A827999); \
47 (e) += ROTATE_LEFT ((a), 5); \
48 (b) = ROTATE_LEFT((b), 30); \
50 #define GG(a, b, c, d, e, w) { \
51 (e) += G ((b), (c), (d)) + (w) + (uint32_t)(0x6ED9EBA1); \
52 (e) += ROTATE_LEFT ((a), 5); \
53 (b) = ROTATE_LEFT((b), 30); \
55 #define HH(a, b, c, d, e, w) { \
56 (e) += H ((b), (c), (d)) + (w) + (uint32_t)(0x8F1BBCDC); \
57 (e) += ROTATE_LEFT ((a), 5); \
58 (b) = ROTATE_LEFT((b), 30); \
60 #define II(a, b, c, d, e, w) { \
61 (e) += I ((b), (c), (d)) + (w) + (uint32_t)(0xCA62C1D6); \
62 (e) += ROTATE_LEFT ((a), 5); \
63 (b) = ROTATE_LEFT((b), 30); \
66 static void SHA1Transform(uint32_t state[5], const unsigned char block[64]);
68 /**
69 * Encodes input (uint32_t) into output (unsigned char). Assumes len is
70 * a multiple of 4.
72 static void SHA1Encode(unsigned char *output, uint32_t *input,
73 unsigned int len) {
74 unsigned int i, j;
76 for (i = 0, j = 0; j < len; i++, j += 4) {
77 output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
78 output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
79 output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
80 output[j + 3] = (unsigned char) (input[i] & 0xff);
84 /**
85 * Decodes input (unsigned char) into output (uint32_t). Assumes len is
86 * a multiple of 4.
88 static void SHA1Decode(uint32_t *output, const unsigned char *input,
89 unsigned int len) {
90 unsigned int i, j;
92 for (i = 0, j = 0; j < len; i++, j += 4) {
93 output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) |
94 (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24);
98 /* SHA1 context. */
99 typedef struct {
100 uint32_t state[5]; /* state (ABCD) */
101 uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
102 unsigned char buffer[64]; /* input buffer */
103 } PHP_SHA1_CTX;
106 * SHA1 initialization. Begins an SHA1 operation, writing a new context.
108 void PHP_SHA1Init(PHP_SHA1_CTX * context) {
109 context->count[0] = context->count[1] = 0;
110 // Load magic initialization constants.
111 context->state[0] = 0x67452301;
112 context->state[1] = 0xefcdab89;
113 context->state[2] = 0x98badcfe;
114 context->state[3] = 0x10325476;
115 context->state[4] = 0xc3d2e1f0;
119 * SHA1 block update operation. Continues an SHA1 message-digest
120 * operation, processing another message block, and updating the context.
122 void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *input,
123 unsigned int inputLen) {
124 unsigned int i, index, partLen;
126 /* Compute number of bytes mod 64 */
127 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
129 /* Update number of bits */
130 if ((context->count[0] += ((uint32_t) inputLen << 3))
131 < ((uint32_t) inputLen << 3)) {
132 context->count[1]++;
134 context->count[1] += ((uint32_t) inputLen >> 29);
136 partLen = 64 - index;
138 // Transform as many times as possible.
139 if (inputLen >= partLen) {
140 memcpy((unsigned char*) & context->buffer[index],
141 (unsigned char*) input, partLen);
142 SHA1Transform(context->state, context->buffer);
144 for (i = partLen; i + 63 < inputLen; i += 64) {
145 SHA1Transform(context->state, &input[i]);
148 index = 0;
149 } else
150 i = 0;
152 /* Buffer remaining input */
153 memcpy((unsigned char*) & context->buffer[index],
154 (unsigned char*) & input[i], inputLen - i);
158 * SHA1 finalization. Ends an SHA1 message-digest operation, writing the
159 * the message digest and zeroizing the context.
161 void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX * context) {
162 unsigned char bits[8];
163 unsigned int index, padLen;
165 /* Save number of bits */
166 bits[7] = context->count[0] & 0xFF;
167 bits[6] = (context->count[0] >> 8) & 0xFF;
168 bits[5] = (context->count[0] >> 16) & 0xFF;
169 bits[4] = (context->count[0] >> 24) & 0xFF;
170 bits[3] = context->count[1] & 0xFF;
171 bits[2] = (context->count[1] >> 8) & 0xFF;
172 bits[1] = (context->count[1] >> 16) & 0xFF;
173 bits[0] = (context->count[1] >> 24) & 0xFF;
175 // Pad out to 56 mod 64.
176 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
177 padLen = (index < 56) ? (56 - index) : (120 - index);
178 PHP_SHA1Update(context, PADDING, padLen);
180 /* Append length (before padding) */
181 PHP_SHA1Update(context, bits, 8);
183 /* Store state in digest */
184 SHA1Encode(digest, context->state, 20);
186 // Zeroize sensitive information.
187 memset((unsigned char*) context, 0, sizeof(*context));
191 * SHA1 basic transformation. Transforms state based on block.
193 static void SHA1Transform(uint32_t state[5], const unsigned char block[64]) {
194 uint32_t a = state[0], b = state[1], c = state[2];
195 uint32_t d = state[3], e = state[4], x[16], tmp;
197 SHA1Decode(x, block, 64);
199 /* Round 1 */
200 FF(a, b, c, d, e, x[0]); /* 1 */
201 FF(e, a, b, c, d, x[1]); /* 2 */
202 FF(d, e, a, b, c, x[2]); /* 3 */
203 FF(c, d, e, a, b, x[3]); /* 4 */
204 FF(b, c, d, e, a, x[4]); /* 5 */
205 FF(a, b, c, d, e, x[5]); /* 6 */
206 FF(e, a, b, c, d, x[6]); /* 7 */
207 FF(d, e, a, b, c, x[7]); /* 8 */
208 FF(c, d, e, a, b, x[8]); /* 9 */
209 FF(b, c, d, e, a, x[9]); /* 10 */
210 FF(a, b, c, d, e, x[10]); /* 11 */
211 FF(e, a, b, c, d, x[11]); /* 12 */
212 FF(d, e, a, b, c, x[12]); /* 13 */
213 FF(c, d, e, a, b, x[13]); /* 14 */
214 FF(b, c, d, e, a, x[14]); /* 15 */
215 FF(a, b, c, d, e, x[15]); /* 16 */
216 FF(e, a, b, c, d, W(16)); /* 17 */
217 FF(d, e, a, b, c, W(17)); /* 18 */
218 FF(c, d, e, a, b, W(18)); /* 19 */
219 FF(b, c, d, e, a, W(19)); /* 20 */
221 /* Round 2 */
222 GG(a, b, c, d, e, W(20)); /* 21 */
223 GG(e, a, b, c, d, W(21)); /* 22 */
224 GG(d, e, a, b, c, W(22)); /* 23 */
225 GG(c, d, e, a, b, W(23)); /* 24 */
226 GG(b, c, d, e, a, W(24)); /* 25 */
227 GG(a, b, c, d, e, W(25)); /* 26 */
228 GG(e, a, b, c, d, W(26)); /* 27 */
229 GG(d, e, a, b, c, W(27)); /* 28 */
230 GG(c, d, e, a, b, W(28)); /* 29 */
231 GG(b, c, d, e, a, W(29)); /* 30 */
232 GG(a, b, c, d, e, W(30)); /* 31 */
233 GG(e, a, b, c, d, W(31)); /* 32 */
234 GG(d, e, a, b, c, W(32)); /* 33 */
235 GG(c, d, e, a, b, W(33)); /* 34 */
236 GG(b, c, d, e, a, W(34)); /* 35 */
237 GG(a, b, c, d, e, W(35)); /* 36 */
238 GG(e, a, b, c, d, W(36)); /* 37 */
239 GG(d, e, a, b, c, W(37)); /* 38 */
240 GG(c, d, e, a, b, W(38)); /* 39 */
241 GG(b, c, d, e, a, W(39)); /* 40 */
243 /* Round 3 */
244 HH(a, b, c, d, e, W(40)); /* 41 */
245 HH(e, a, b, c, d, W(41)); /* 42 */
246 HH(d, e, a, b, c, W(42)); /* 43 */
247 HH(c, d, e, a, b, W(43)); /* 44 */
248 HH(b, c, d, e, a, W(44)); /* 45 */
249 HH(a, b, c, d, e, W(45)); /* 46 */
250 HH(e, a, b, c, d, W(46)); /* 47 */
251 HH(d, e, a, b, c, W(47)); /* 48 */
252 HH(c, d, e, a, b, W(48)); /* 49 */
253 HH(b, c, d, e, a, W(49)); /* 50 */
254 HH(a, b, c, d, e, W(50)); /* 51 */
255 HH(e, a, b, c, d, W(51)); /* 52 */
256 HH(d, e, a, b, c, W(52)); /* 53 */
257 HH(c, d, e, a, b, W(53)); /* 54 */
258 HH(b, c, d, e, a, W(54)); /* 55 */
259 HH(a, b, c, d, e, W(55)); /* 56 */
260 HH(e, a, b, c, d, W(56)); /* 57 */
261 HH(d, e, a, b, c, W(57)); /* 58 */
262 HH(c, d, e, a, b, W(58)); /* 59 */
263 HH(b, c, d, e, a, W(59)); /* 60 */
265 /* Round 4 */
266 II(a, b, c, d, e, W(60)); /* 61 */
267 II(e, a, b, c, d, W(61)); /* 62 */
268 II(d, e, a, b, c, W(62)); /* 63 */
269 II(c, d, e, a, b, W(63)); /* 64 */
270 II(b, c, d, e, a, W(64)); /* 65 */
271 II(a, b, c, d, e, W(65)); /* 66 */
272 II(e, a, b, c, d, W(66)); /* 67 */
273 II(d, e, a, b, c, W(67)); /* 68 */
274 II(c, d, e, a, b, W(68)); /* 69 */
275 II(b, c, d, e, a, W(69)); /* 70 */
276 II(a, b, c, d, e, W(70)); /* 71 */
277 II(e, a, b, c, d, W(71)); /* 72 */
278 II(d, e, a, b, c, W(72)); /* 73 */
279 II(c, d, e, a, b, W(73)); /* 74 */
280 II(b, c, d, e, a, W(74)); /* 75 */
281 II(a, b, c, d, e, W(75)); /* 76 */
282 II(e, a, b, c, d, W(76)); /* 77 */
283 II(d, e, a, b, c, W(77)); /* 78 */
284 II(c, d, e, a, b, W(78)); /* 79 */
285 II(b, c, d, e, a, W(79)); /* 80 */
287 state[0] += a;
288 state[1] += b;
289 state[2] += c;
290 state[3] += d;
291 state[4] += e;
293 /* Zeroize sensitive information. */
294 memset((unsigned char*) x, 0, sizeof(x));
297 ///////////////////////////////////////////////////////////////////////////////
299 char *string_sha1(const char *arg, int arg_len, bool raw, int &out_len) {
300 PHP_SHA1_CTX context;
301 unsigned char digest[20];
303 PHP_SHA1Init(&context);
304 PHP_SHA1Update(&context, (const unsigned char *)arg, arg_len);
305 PHP_SHA1Final(digest, &context);
306 if (raw) {
307 out_len = 20;
308 return string_duplicate((const char *)digest, 20);
311 out_len = 20;
312 return string_bin2hex((const char*)digest, out_len);
315 ///////////////////////////////////////////////////////////////////////////////