PageRenderTime 22ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/sha256.c

https://github.com/Tyrael/suhosin
C | 432 lines | 273 code | 68 blank | 91 comment | 22 complexity | 888f8633e179f8238e82e33b23c3e08f MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Suhosin Version 1 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2006-2007 The Hardened-PHP Project |
  6. | Copyright (c) 2007-2010 SektionEins GmbH |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. | Author: Stefan Esser <sesser@sektioneins.de> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id: sha256.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */
  20. #include <stdio.h>
  21. #include "php.h"
  22. /* This code is heavily based on the PHP md5/sha1 implementations */
  23. #include "sha256.h"
  24. static void make_sha256_digest(char *sha256str, unsigned char *digest)
  25. {
  26. int i;
  27. for (i = 0; i < 32; i++) {
  28. sprintf(sha256str, "%02x", digest[i]);
  29. sha256str += 2;
  30. }
  31. *sha256str = '\0';
  32. }
  33. /* {{{ proto string sha256(string str [, bool raw_output])
  34. Calculate the sha256 hash of a string */
  35. static PHP_FUNCTION(suhosin_sha256)
  36. {
  37. char *arg;
  38. int arg_len;
  39. zend_bool raw_output = 0;
  40. char sha256str[65];
  41. suhosin_SHA256_CTX context;
  42. unsigned char digest[32];
  43. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
  44. return;
  45. }
  46. sha256str[0] = '\0';
  47. suhosin_SHA256Init(&context);
  48. suhosin_SHA256Update(&context, (unsigned char *)arg, (unsigned int)arg_len);
  49. suhosin_SHA256Final(digest, &context);
  50. if (raw_output) {
  51. RETURN_STRINGL((char *)digest, 32, 1);
  52. } else {
  53. make_sha256_digest(sha256str, digest);
  54. RETVAL_STRING(sha256str, 1);
  55. }
  56. }
  57. /* }}} */
  58. /* {{{ proto string sha256_file(string filename [, bool raw_output])
  59. Calculate the sha256 hash of given filename */
  60. static PHP_FUNCTION(suhosin_sha256_file)
  61. {
  62. char *arg;
  63. int arg_len;
  64. zend_bool raw_output = 0;
  65. char sha256str[65];
  66. unsigned char buf[1024];
  67. unsigned char digest[32];
  68. suhosin_SHA256_CTX context;
  69. int n;
  70. FILE *fp;
  71. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
  72. return;
  73. }
  74. if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
  75. RETURN_FALSE;
  76. }
  77. if (php_check_open_basedir(arg TSRMLS_CC)) {
  78. RETURN_FALSE;
  79. }
  80. if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) {
  81. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file");
  82. RETURN_FALSE;
  83. }
  84. suhosin_SHA256Init(&context);
  85. while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
  86. suhosin_SHA256Update(&context, buf, n);
  87. }
  88. suhosin_SHA256Final(digest, &context);
  89. if (ferror(fp)) {
  90. fclose(fp);
  91. RETURN_FALSE;
  92. }
  93. fclose(fp);
  94. if (raw_output) {
  95. RETURN_STRINGL((char *)digest, 32, 1);
  96. } else {
  97. make_sha256_digest(sha256str, digest);
  98. RETVAL_STRING(sha256str, 1);
  99. }
  100. }
  101. /* }}} */
  102. static void SHA256Transform(php_uint32[8], const unsigned char[64]);
  103. static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
  104. static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
  105. static unsigned char PADDING[64] =
  106. {
  107. 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  109. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  110. };
  111. /* F, G, H and I are basic SHA256 functions.
  112. */
  113. #define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
  114. #define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
  115. #define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
  116. #define I(x, y, z) (((x) & (y)) | ((~x) & z))
  117. /* ROTATE_RIGHT rotates x right n bits.
  118. */
  119. #define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
  120. /* W[i]
  121. */
  122. #define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
  123. tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
  124. (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
  125. /* ROUND function of sha256
  126. */
  127. #define ROUND(a,b,c,d,e,f,g,h,w,k) { \
  128. t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
  129. (h) = F((a)) + G((a), (b), (c)) + t1; \
  130. (d) += t1; \
  131. }
  132. /* {{{ suhosin_SHA256Init
  133. * SHA256 initialization. Begins an SHA256 operation, writing a new context.
  134. */
  135. void suhosin_SHA256Init(suhosin_SHA256_CTX * context)
  136. {
  137. context->count[0] = context->count[1] = 0;
  138. /* Load magic initialization constants.
  139. */
  140. context->state[0] = 0x6a09e667;
  141. context->state[1] = 0xbb67ae85;
  142. context->state[2] = 0x3c6ef372;
  143. context->state[3] = 0xa54ff53a;
  144. context->state[4] = 0x510e527f;
  145. context->state[5] = 0x9b05688c;
  146. context->state[6] = 0x1f83d9ab;
  147. context->state[7] = 0x5be0cd19;
  148. }
  149. /* }}} */
  150. /* {{{ suhosin_SHA256Update
  151. SHA256 block update operation. Continues an SHA256 message-digest
  152. operation, processing another message block, and updating the
  153. context.
  154. */
  155. void suhosin_SHA256Update(suhosin_SHA256_CTX * context, const unsigned char *input,
  156. unsigned int inputLen)
  157. {
  158. unsigned int i, index, partLen;
  159. /* Compute number of bytes mod 64 */
  160. index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
  161. /* Update number of bits */
  162. if ((context->count[0] += ((php_uint32) inputLen << 3))
  163. < ((php_uint32) inputLen << 3))
  164. context->count[1]++;
  165. context->count[1] += ((php_uint32) inputLen >> 29);
  166. partLen = 64 - index;
  167. /* Transform as many times as possible.
  168. */
  169. if (inputLen >= partLen) {
  170. memcpy
  171. ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
  172. SHA256Transform(context->state, context->buffer);
  173. for (i = partLen; i + 63 < inputLen; i += 64)
  174. SHA256Transform(context->state, &input[i]);
  175. index = 0;
  176. } else
  177. i = 0;
  178. /* Buffer remaining input */
  179. memcpy
  180. ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
  181. inputLen - i);
  182. }
  183. /* }}} */
  184. /* {{{ suhosin_SHA256Final
  185. SHA256 finalization. Ends an SHA256 message-digest operation, writing the
  186. the message digest and zeroizing the context.
  187. */
  188. void suhosin_SHA256Final(unsigned char digest[32], suhosin_SHA256_CTX * context)
  189. {
  190. unsigned char bits[8];
  191. unsigned int index, padLen;
  192. /* Save number of bits */
  193. bits[7] = context->count[0] & 0xFF;
  194. bits[6] = (context->count[0] >> 8) & 0xFF;
  195. bits[5] = (context->count[0] >> 16) & 0xFF;
  196. bits[4] = (context->count[0] >> 24) & 0xFF;
  197. bits[3] = context->count[1] & 0xFF;
  198. bits[2] = (context->count[1] >> 8) & 0xFF;
  199. bits[1] = (context->count[1] >> 16) & 0xFF;
  200. bits[0] = (context->count[1] >> 24) & 0xFF;
  201. /* Pad out to 56 mod 64.
  202. */
  203. index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
  204. padLen = (index < 56) ? (56 - index) : (120 - index);
  205. suhosin_SHA256Update(context, PADDING, padLen);
  206. /* Append length (before padding) */
  207. suhosin_SHA256Update(context, bits, 8);
  208. /* Store state in digest */
  209. SHA256Encode(digest, context->state, 32);
  210. /* Zeroize sensitive information.
  211. */
  212. memset((unsigned char*) context, 0, sizeof(*context));
  213. }
  214. /* }}} */
  215. /* {{{ SHA256Transform
  216. * SHA256 basic transformation. Transforms state based on block.
  217. */
  218. static void SHA256Transform(state, block)
  219. php_uint32 state[8];
  220. const unsigned char block[64];
  221. {
  222. php_uint32 a = state[0], b = state[1], c = state[2];
  223. php_uint32 d = state[3], e = state[4], f = state[5];
  224. php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
  225. SHA256Decode(x, block, 64);
  226. ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
  227. ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
  228. ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
  229. ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
  230. ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
  231. ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
  232. ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
  233. ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
  234. ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
  235. ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
  236. ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
  237. ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
  238. ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
  239. ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
  240. ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
  241. ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
  242. ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
  243. ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
  244. ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
  245. ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
  246. ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
  247. ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
  248. ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
  249. ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
  250. ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
  251. ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
  252. ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
  253. ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
  254. ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
  255. ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
  256. ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
  257. ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
  258. ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
  259. ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
  260. ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
  261. ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
  262. ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
  263. ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
  264. ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
  265. ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
  266. ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
  267. ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
  268. ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
  269. ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
  270. ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
  271. ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
  272. ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
  273. ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
  274. ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
  275. ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
  276. ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
  277. ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
  278. ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
  279. ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
  280. ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
  281. ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
  282. ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
  283. ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
  284. ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
  285. ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
  286. ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
  287. ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
  288. ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
  289. ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
  290. state[0] += a;
  291. state[1] += b;
  292. state[2] += c;
  293. state[3] += d;
  294. state[4] += e;
  295. state[5] += f;
  296. state[6] += g;
  297. state[7] += h;
  298. /* Zeroize sensitive information. */
  299. memset((unsigned char*) x, 0, sizeof(x));
  300. }
  301. /* }}} */
  302. /* {{{ SHA256Encode
  303. Encodes input (php_uint32) into output (unsigned char). Assumes len is
  304. a multiple of 4.
  305. */
  306. static void SHA256Encode(output, input, len)
  307. unsigned char *output;
  308. php_uint32 *input;
  309. unsigned int len;
  310. {
  311. unsigned int i, j;
  312. for (i = 0, j = 0; j < len; i++, j += 4) {
  313. output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
  314. output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
  315. output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
  316. output[j + 3] = (unsigned char) (input[i] & 0xff);
  317. }
  318. }
  319. /* }}} */
  320. /* {{{ SHA256Decode
  321. Decodes input (unsigned char) into output (php_uint32). Assumes len is
  322. a multiple of 4.
  323. */
  324. static void SHA256Decode(output, input, len)
  325. php_uint32 *output;
  326. const unsigned char *input;
  327. unsigned int len;
  328. {
  329. unsigned int i, j;
  330. for (i = 0, j = 0; j < len; i++, j += 4)
  331. output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
  332. (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
  333. }
  334. /* }}} */
  335. /* {{{ suhosin_sha256_functions[]
  336. */
  337. static function_entry suhosin_sha256_functions[] = {
  338. PHP_NAMED_FE(sha256, PHP_FN(suhosin_sha256), NULL)
  339. PHP_NAMED_FE(sha256_file, PHP_FN(suhosin_sha256_file), NULL)
  340. {NULL, NULL, NULL}
  341. };
  342. /* }}} */
  343. void suhosin_hook_sha256()
  344. {
  345. TSRMLS_FETCH();
  346. /* check if we already have sha256 support */
  347. if (zend_hash_exists(CG(function_table), "sha256", sizeof("sha256"))) {
  348. return;
  349. }
  350. /* add the sha256 functions */
  351. #ifndef ZEND_ENGINE_2
  352. zend_register_functions(suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
  353. #else
  354. zend_register_functions(NULL, suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
  355. #endif
  356. }
  357. /*
  358. * Local variables:
  359. * tab-width: 4
  360. * c-basic-offset: 4
  361. * End:
  362. * vim600: sw=4 ts=4 fdm=marker
  363. * vim<600: sw=4 ts=4
  364. */