Support is and as
[hiphop-php.git] / hphp / zend / zend-sha1.cpp
blob2817390c7b8f7e3a4a3fd5803611b9452cb63946
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>
21 #include <cstdlib>
23 #include <folly/ScopeGuard.h>
25 namespace HPHP {
26 ///////////////////////////////////////////////////////////////////////////////
28 static unsigned char PADDING[64] = {
29 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
34 // F, G, H and I are basic SHA1 functions.
35 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
36 #define G(x, y, z) ((x) ^ (y) ^ (z))
37 #define H(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
38 #define I(x, y, z) ((x) ^ (y) ^ (z))
40 // ROTATE_LEFT rotates x left n bits.
41 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
43 // W[i]
44 #define W(i) ( tmp=x[(i-3)&15]^x[(i-8)&15]^x[(i-14)&15]^x[i&15], \
45 (x[i&15]=ROTATE_LEFT(tmp, 1)) )
47 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
48 #define FF(a, b, c, d, e, w) { \
49 (e) += F ((b), (c), (d)) + (w) + (uint32_t)(0x5A827999); \
50 (e) += ROTATE_LEFT ((a), 5); \
51 (b) = ROTATE_LEFT((b), 30); \
53 #define GG(a, b, c, d, e, w) { \
54 (e) += G ((b), (c), (d)) + (w) + (uint32_t)(0x6ED9EBA1); \
55 (e) += ROTATE_LEFT ((a), 5); \
56 (b) = ROTATE_LEFT((b), 30); \
58 #define HH(a, b, c, d, e, w) { \
59 (e) += H ((b), (c), (d)) + (w) + (uint32_t)(0x8F1BBCDC); \
60 (e) += ROTATE_LEFT ((a), 5); \
61 (b) = ROTATE_LEFT((b), 30); \
63 #define II(a, b, c, d, e, w) { \
64 (e) += I ((b), (c), (d)) + (w) + (uint32_t)(0xCA62C1D6); \
65 (e) += ROTATE_LEFT ((a), 5); \
66 (b) = ROTATE_LEFT((b), 30); \
69 static void SHA1Transform(uint32_t state[5], const unsigned char block[64]);
71 /**
72 * Encodes input (uint32_t) into output (unsigned char). Assumes len is
73 * a multiple of 4.
75 static void SHA1Encode(unsigned char *output, uint32_t *input,
76 unsigned int len) {
77 unsigned int i, j;
79 for (i = 0, j = 0; j < len; i++, j += 4) {
80 output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
81 output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
82 output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
83 output[j + 3] = (unsigned char) (input[i] & 0xff);
87 /**
88 * Decodes input (unsigned char) into output (uint32_t). Assumes len is
89 * a multiple of 4.
91 static void SHA1Decode(uint32_t *output, const unsigned char *input,
92 unsigned int len) {
93 unsigned int i, j;
95 for (i = 0, j = 0; j < len; i++, j += 4) {
96 output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) |
97 (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24);
101 /* SHA1 context. */
102 typedef struct {
103 uint32_t state[5]; /* state (ABCD) */
104 uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
105 unsigned char buffer[64]; /* input buffer */
106 } PHP_SHA1_CTX;
109 * SHA1 initialization. Begins an SHA1 operation, writing a new context.
111 void PHP_SHA1Init(PHP_SHA1_CTX * context) {
112 context->count[0] = context->count[1] = 0;
113 // Load magic initialization constants.
114 context->state[0] = 0x67452301;
115 context->state[1] = 0xefcdab89;
116 context->state[2] = 0x98badcfe;
117 context->state[3] = 0x10325476;
118 context->state[4] = 0xc3d2e1f0;
122 * SHA1 block update operation. Continues an SHA1 message-digest
123 * operation, processing another message block, and updating the context.
125 void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *input,
126 unsigned int inputLen) {
127 unsigned int i, index, partLen;
129 /* Compute number of bytes mod 64 */
130 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
132 /* Update number of bits */
133 if ((context->count[0] += ((uint32_t) inputLen << 3))
134 < ((uint32_t) inputLen << 3)) {
135 context->count[1]++;
137 context->count[1] += ((uint32_t) inputLen >> 29);
139 partLen = 64 - index;
141 // Transform as many times as possible.
142 if (inputLen >= partLen) {
143 memcpy((unsigned char*) & context->buffer[index],
144 (unsigned char*) input, partLen);
145 SHA1Transform(context->state, context->buffer);
147 for (i = partLen; i + 63 < inputLen; i += 64) {
148 SHA1Transform(context->state, &input[i]);
151 index = 0;
152 } else
153 i = 0;
155 /* Buffer remaining input */
156 memcpy((unsigned char*) & context->buffer[index],
157 (unsigned char*) & input[i], inputLen - i);
161 * SHA1 finalization. Ends an SHA1 message-digest operation, writing the
162 * the message digest and zeroizing the context.
164 void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX * context) {
165 unsigned char bits[8];
166 unsigned int index, padLen;
168 /* Save number of bits */
169 bits[7] = context->count[0] & 0xFF;
170 bits[6] = (context->count[0] >> 8) & 0xFF;
171 bits[5] = (context->count[0] >> 16) & 0xFF;
172 bits[4] = (context->count[0] >> 24) & 0xFF;
173 bits[3] = context->count[1] & 0xFF;
174 bits[2] = (context->count[1] >> 8) & 0xFF;
175 bits[1] = (context->count[1] >> 16) & 0xFF;
176 bits[0] = (context->count[1] >> 24) & 0xFF;
178 // Pad out to 56 mod 64.
179 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
180 padLen = (index < 56) ? (56 - index) : (120 - index);
181 PHP_SHA1Update(context, PADDING, padLen);
183 /* Append length (before padding) */
184 PHP_SHA1Update(context, bits, 8);
186 /* Store state in digest */
187 SHA1Encode(digest, context->state, 20);
189 // Zeroize sensitive information.
190 memset((unsigned char*) context, 0, sizeof(*context));
194 * SHA1 basic transformation. Transforms state based on block.
196 static void SHA1Transform(uint32_t state[5], const unsigned char block[64]) {
197 uint32_t a = state[0], b = state[1], c = state[2];
198 uint32_t d = state[3], e = state[4], x[16], tmp;
200 SHA1Decode(x, block, 64);
202 /* Round 1 */
203 FF(a, b, c, d, e, x[0]); /* 1 */
204 FF(e, a, b, c, d, x[1]); /* 2 */
205 FF(d, e, a, b, c, x[2]); /* 3 */
206 FF(c, d, e, a, b, x[3]); /* 4 */
207 FF(b, c, d, e, a, x[4]); /* 5 */
208 FF(a, b, c, d, e, x[5]); /* 6 */
209 FF(e, a, b, c, d, x[6]); /* 7 */
210 FF(d, e, a, b, c, x[7]); /* 8 */
211 FF(c, d, e, a, b, x[8]); /* 9 */
212 FF(b, c, d, e, a, x[9]); /* 10 */
213 FF(a, b, c, d, e, x[10]); /* 11 */
214 FF(e, a, b, c, d, x[11]); /* 12 */
215 FF(d, e, a, b, c, x[12]); /* 13 */
216 FF(c, d, e, a, b, x[13]); /* 14 */
217 FF(b, c, d, e, a, x[14]); /* 15 */
218 FF(a, b, c, d, e, x[15]); /* 16 */
219 FF(e, a, b, c, d, W(16)); /* 17 */
220 FF(d, e, a, b, c, W(17)); /* 18 */
221 FF(c, d, e, a, b, W(18)); /* 19 */
222 FF(b, c, d, e, a, W(19)); /* 20 */
224 /* Round 2 */
225 GG(a, b, c, d, e, W(20)); /* 21 */
226 GG(e, a, b, c, d, W(21)); /* 22 */
227 GG(d, e, a, b, c, W(22)); /* 23 */
228 GG(c, d, e, a, b, W(23)); /* 24 */
229 GG(b, c, d, e, a, W(24)); /* 25 */
230 GG(a, b, c, d, e, W(25)); /* 26 */
231 GG(e, a, b, c, d, W(26)); /* 27 */
232 GG(d, e, a, b, c, W(27)); /* 28 */
233 GG(c, d, e, a, b, W(28)); /* 29 */
234 GG(b, c, d, e, a, W(29)); /* 30 */
235 GG(a, b, c, d, e, W(30)); /* 31 */
236 GG(e, a, b, c, d, W(31)); /* 32 */
237 GG(d, e, a, b, c, W(32)); /* 33 */
238 GG(c, d, e, a, b, W(33)); /* 34 */
239 GG(b, c, d, e, a, W(34)); /* 35 */
240 GG(a, b, c, d, e, W(35)); /* 36 */
241 GG(e, a, b, c, d, W(36)); /* 37 */
242 GG(d, e, a, b, c, W(37)); /* 38 */
243 GG(c, d, e, a, b, W(38)); /* 39 */
244 GG(b, c, d, e, a, W(39)); /* 40 */
246 /* Round 3 */
247 HH(a, b, c, d, e, W(40)); /* 41 */
248 HH(e, a, b, c, d, W(41)); /* 42 */
249 HH(d, e, a, b, c, W(42)); /* 43 */
250 HH(c, d, e, a, b, W(43)); /* 44 */
251 HH(b, c, d, e, a, W(44)); /* 45 */
252 HH(a, b, c, d, e, W(45)); /* 46 */
253 HH(e, a, b, c, d, W(46)); /* 47 */
254 HH(d, e, a, b, c, W(47)); /* 48 */
255 HH(c, d, e, a, b, W(48)); /* 49 */
256 HH(b, c, d, e, a, W(49)); /* 50 */
257 HH(a, b, c, d, e, W(50)); /* 51 */
258 HH(e, a, b, c, d, W(51)); /* 52 */
259 HH(d, e, a, b, c, W(52)); /* 53 */
260 HH(c, d, e, a, b, W(53)); /* 54 */
261 HH(b, c, d, e, a, W(54)); /* 55 */
262 HH(a, b, c, d, e, W(55)); /* 56 */
263 HH(e, a, b, c, d, W(56)); /* 57 */
264 HH(d, e, a, b, c, W(57)); /* 58 */
265 HH(c, d, e, a, b, W(58)); /* 59 */
266 HH(b, c, d, e, a, W(59)); /* 60 */
268 /* Round 4 */
269 II(a, b, c, d, e, W(60)); /* 61 */
270 II(e, a, b, c, d, W(61)); /* 62 */
271 II(d, e, a, b, c, W(62)); /* 63 */
272 II(c, d, e, a, b, W(63)); /* 64 */
273 II(b, c, d, e, a, W(64)); /* 65 */
274 II(a, b, c, d, e, W(65)); /* 66 */
275 II(e, a, b, c, d, W(66)); /* 67 */
276 II(d, e, a, b, c, W(67)); /* 68 */
277 II(c, d, e, a, b, W(68)); /* 69 */
278 II(b, c, d, e, a, W(69)); /* 70 */
279 II(a, b, c, d, e, W(70)); /* 71 */
280 II(e, a, b, c, d, W(71)); /* 72 */
281 II(d, e, a, b, c, W(72)); /* 73 */
282 II(c, d, e, a, b, W(73)); /* 74 */
283 II(b, c, d, e, a, W(74)); /* 75 */
284 II(a, b, c, d, e, W(75)); /* 76 */
285 II(e, a, b, c, d, W(76)); /* 77 */
286 II(d, e, a, b, c, W(77)); /* 78 */
287 II(c, d, e, a, b, W(78)); /* 79 */
288 II(b, c, d, e, a, W(79)); /* 80 */
290 state[0] += a;
291 state[1] += b;
292 state[2] += c;
293 state[3] += d;
294 state[4] += e;
296 /* Zeroize sensitive information. */
297 memset((unsigned char*) x, 0, sizeof(x));
300 ///////////////////////////////////////////////////////////////////////////////
302 std::string string_sha1(folly::StringPiece s) {
303 int out_len;
304 auto const hex = string_sha1(s.data(), s.size(), false, out_len);
305 SCOPE_EXIT { free(hex); };
307 return std::string(hex, out_len);
310 char *string_sha1(const char *arg, int arg_len, bool raw, int &out_len) {
311 PHP_SHA1_CTX context;
312 unsigned char digest[20];
314 PHP_SHA1Init(&context);
315 PHP_SHA1Update(&context, (const unsigned char *)arg, arg_len);
316 PHP_SHA1Final(digest, &context);
317 if (raw) {
318 out_len = 20;
319 return string_duplicate((const char *)digest, 20);
322 out_len = 20;
323 return string_bin2hex((const char*)digest, out_len);
326 ///////////////////////////////////////////////////////////////////////////////