PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/LibOrange/hmac-sha256.c

http://github.com/unixpickle/LibOrange
C | 388 lines | 187 code | 16 blank | 185 comment | 39 complexity | 810664c3dc0de54366a15cf96e34bce2 MD5 | raw file
  1. /*
  2. * Copyright 2006 Apple Computer, Inc. All rights reserved.
  3. *
  4. * iTunes U Sample Code License
  5. * IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple")
  6. * in consideration of your agreement to the following terms, and your use,
  7. * installation, modification or distribution of this Apple software constitutes
  8. * acceptance of these terms. If you do not agree with these terms, please do not use,
  9. * install, modify or distribute this Apple software.
  10. *
  11. * In consideration of your agreement to abide by the following terms and subject to
  12. * these terms, Apple grants you a personal, non-exclusive, non-transferable license,
  13. * under Apple's copyrights in this original Apple software (the "Apple Software"):
  14. *
  15. * (a) to internally use, reproduce, modify and internally distribute the Apple
  16. * Software, with or without modifications, in source and binary forms, within your
  17. * educational organization or internal campus network for the sole purpose of
  18. * integrating Apple's iTunes U software with your internal campus network systems; and
  19. *
  20. * (b) to redistribute the Apple Software to other universities or educational
  21. * organizations, with or without modifications, in source and binary forms, for the
  22. * sole purpose of integrating Apple's iTunes U software with their internal campus
  23. * network systems; provided that the following conditions are met:
  24. *
  25. * - If you redistribute the Apple Software in its entirety and without
  26. * modifications, you must retain the above copyright notice, this entire license
  27. * and the disclaimer provisions in all such redistributions of the Apple Software.
  28. * - If you modify and redistribute the Apple Software, you must indicate that you
  29. * have made changes to the Apple Software, and you must retain the above
  30. * copyright notice, this entire license and the disclaimer provisions in all
  31. * such redistributions of the Apple Software and/or derivatives thereof created
  32. * by you.
  33. * - Neither the name, trademarks, service marks or logos of Apple may be used to
  34. * endorse or promote products derived from the Apple Software without specific
  35. * prior written permission from Apple.
  36. *
  37. * Except as expressly stated above, no other rights or licenses, express or implied,
  38. * are granted by Apple herein, including but not limited to any patent rights that may
  39. * be infringed by your derivative works or by other works in which the Apple Software
  40. * may be incorporated. THE APPLE SOFTWARE IS PROVIDED BY APPLE ON AN "AS IS" BASIS.
  41. * APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, AND HEREBY DISCLAIMS ALL WARRANTIES,
  42. * INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
  43. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE
  44. * OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS OR SYSTEMS.
  45. * APPLE IS NOT OBLIGATED TO PROVIDE ANY MAINTENANCE, TECHNICAL OR OTHER SUPPORT FOR
  46. * THE APPLE SOFTWARE, OR TO PROVIDE ANY UPDATES TO THE APPLE SOFTWARE. IN NO EVENT
  47. * SHALL APPLE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL OR
  48. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  49. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  50. * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
  51. * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
  52. * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
  53. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  54. *
  55. * Rev. 120806
  56. *
  57. * This source code file contains a self-contained ANSI C program with no
  58. * external dependencies except for standard ANSI C libraries. On Mac OS X, it
  59. * can be compiled and run by executing the following commands in a terminal
  60. * window:
  61. * gcc -o seconds seconds.c
  62. * ./seconds
  63. */
  64. // Compile note added by RKW
  65. // gcc -o hmac-sha256 hmac-sha256.c
  66. // should work on latter-day gcc installs, but c99 can be made explicit this way:
  67. // gcc -std=c99 -o hmac-sha256 hmac-sha256.c
  68. #include <ctype.h>
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. /* #include <string.h> */
  72. #include <stdint.h> // Added by RKW, needed for types uint8_t, uint32_t; requires C99 compiler
  73. /******************************************************************************
  74. * SHA-256.
  75. */
  76. typedef struct {
  77. uint8_t hash[32]; // Changed by RKW, unsigned char becomes uint8_t
  78. uint32_t buffer[16]; // Changed by RKW, unsigned long becomes uint32_t
  79. uint32_t state[8]; // Changed by RKW, unsinged long becomes uint32_t
  80. uint8_t length[8]; // Changed by RKW, unsigned char becomes uint8_t
  81. } sha256;
  82. void sha256_initialize(sha256 *sha) {
  83. int i;
  84. for (i = 0; i < 17; ++i) sha->buffer[i] = 0;
  85. sha->state[0] = 0x6a09e667;
  86. sha->state[1] = 0xbb67ae85;
  87. sha->state[2] = 0x3c6ef372;
  88. sha->state[3] = 0xa54ff53a;
  89. sha->state[4] = 0x510e527f;
  90. sha->state[5] = 0x9b05688c;
  91. sha->state[6] = 0x1f83d9ab;
  92. sha->state[7] = 0x5be0cd19;
  93. for (i = 0; i < 8; ++i) sha->length[i] = 0;
  94. }
  95. // Changed by RKW, formal args are now const uint8_t, uint_32
  96. // from const unsigned char, unsigned long respectively
  97. void sha256_update(sha256 *sha,
  98. const uint8_t *message,
  99. uint32_t length) {
  100. int i, j;
  101. /* Add the length of the received message, counted in
  102. * bytes, to the total length of the messages hashed to
  103. * date, counted in bits and stored in 8 separate bytes. */
  104. for (i = 7; i >= 0; --i) {
  105. int bits;
  106. if (i == 7)
  107. bits = length << 3;
  108. else if (i == 0 || i == 1 || i == 2)
  109. bits = 0;
  110. else
  111. bits = length >> (53 - 8 * i);
  112. bits &= 0xff;
  113. if (sha->length[i] + bits > 0xff) {
  114. for (j = i - 1; j >= 0 && sha->length[j]++ == 0xff; --j);
  115. }
  116. sha->length[i] += bits;
  117. }
  118. /* Add the received message to the SHA buffer, updating the
  119. * hash at each block (each time the buffer is filled). */
  120. while (length > 0) {
  121. /* Find the index in the SHA buffer at which to
  122. * append what's left of the received message. */
  123. int index = sha->length[6] % 2 * 32 + sha->length[7] / 8;
  124. index = (index + 64 - length % 64) % 64;
  125. /* Append the received message bytes to the SHA buffer until
  126. * we run out of message bytes or until the buffer is filled. */
  127. for (;length > 0 && index < 64; ++message, ++index, --length) {
  128. sha->buffer[index / 4] |= *message << (24 - index % 4 * 8);
  129. }
  130. /* Update the hash with the buffer contents if the buffer is full. */
  131. if (index == 64) {
  132. /* Update the hash with a block of message content. See FIPS 180-2
  133. * (<csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf>)
  134. * for a description of and details on the algorithm used here. */
  135. // Changed by RKW, const unsigned long becomes const uint32_t
  136. const uint32_t k[64] = {
  137. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  138. 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  139. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  140. 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  141. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  142. 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  143. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  144. 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  145. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  146. 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  147. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  148. 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  149. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  150. 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  151. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  152. 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  153. };
  154. // Changed by RKW, unsigned long becomes uint32_t
  155. uint32_t w[64], a, b, c, d, e, f, g, h;
  156. int t;
  157. for (t = 0; t < 16; ++t) {
  158. w[t] = sha->buffer[t];
  159. sha->buffer[t] = 0;
  160. }
  161. for (t = 16; t < 64; ++t) {
  162. // Changed by RKW, unsigned long becomes uint32_t
  163. uint32_t s0, s1;
  164. s0 = (w[t - 15] >> 7 | w[t - 15] << 25);
  165. s0 ^= (w[t - 15] >> 18 | w[t - 15] << 14);
  166. s0 ^= (w[t - 15] >> 3);
  167. s1 = (w[t - 2] >> 17 | w[t - 2] << 15);
  168. s1 ^= (w[t - 2] >> 19 | w[t - 2] << 13);
  169. s1 ^= (w[t - 2] >> 10);
  170. w[t] = (s1 + w[t - 7] + s0 + w[t - 16]) & 0xffffffffU;
  171. }
  172. a = sha->state[0];
  173. b = sha->state[1];
  174. c = sha->state[2];
  175. d = sha->state[3];
  176. e = sha->state[4];
  177. f = sha->state[5];
  178. g = sha->state[6];
  179. h = sha->state[7];
  180. for (t = 0; t < 64; ++t) {
  181. // Changed by RKW, unsigned long becomes uint32_t
  182. uint32_t e0, e1, t1, t2;
  183. e0 = (a >> 2 | a << 30);
  184. e0 ^= (a >> 13 | a << 19);
  185. e0 ^= (a >> 22 | a << 10);
  186. e1 = (e >> 6 | e << 26);
  187. e1 ^= (e >> 11 | e << 21);
  188. e1 ^= (e >> 25 | e << 7);
  189. t1 = h + e1 + ((e & f) ^ (~e & g)) + k[t] + w[t];
  190. t2 = e0 + ((a & b) ^ (a & c) ^ (b & c));
  191. h = g;
  192. g = f;
  193. f = e;
  194. e = d + t1;
  195. d = c;
  196. c = b;
  197. b = a;
  198. a = t1 + t2;
  199. }
  200. sha->state[0] = (sha->state[0] + a) & 0xffffffffU;
  201. sha->state[1] = (sha->state[1] + b) & 0xffffffffU;
  202. sha->state[2] = (sha->state[2] + c) & 0xffffffffU;
  203. sha->state[3] = (sha->state[3] + d) & 0xffffffffU;
  204. sha->state[4] = (sha->state[4] + e) & 0xffffffffU;
  205. sha->state[5] = (sha->state[5] + f) & 0xffffffffU;
  206. sha->state[6] = (sha->state[6] + g) & 0xffffffffU;
  207. sha->state[7] = (sha->state[7] + h) & 0xffffffffU;
  208. }
  209. }
  210. }
  211. // Changed by RKW, formal args are now const uint8_t, uint_32
  212. // from const unsigned char, unsigned long respectively
  213. void sha256_finalize(sha256 *sha,
  214. const uint8_t *message,
  215. uint32_t length) {
  216. int i;
  217. // Changed by RKW, unsigned char becomes uint8_t
  218. uint8_t terminator[64 + 8] = { 0x80 };
  219. /* Hash the final message bytes if necessary. */
  220. if (length > 0) sha256_update(sha, message, length);
  221. /* Create a terminator that includes a stop bit, padding, and
  222. * the the total message length. See FIPS 180-2 for details. */
  223. length = 64 - sha->length[6] % 2 * 32 - sha->length[7] / 8;
  224. if (length < 9) length += 64;
  225. for (i = 0; i < 8; ++i) terminator[length - 8 + i] = sha->length[i];
  226. /* Hash the terminator to finalize the message digest. */
  227. sha256_update(sha, terminator, length);
  228. /* Extract the message digest. */
  229. for (i = 0; i < 32; ++i) {
  230. sha->hash[i] = (sha->state[i / 4] >> (24 - 8 * (i % 4))) & 0xff;
  231. }
  232. }
  233. // Changed by RKW, formal args are now uint8_t, const uint_8
  234. // from unsigned char, const unsigned char respectively
  235. void sha256_get(uint8_t hash[32],
  236. const uint8_t *message,
  237. int length) {
  238. int i;
  239. sha256 sha;
  240. sha256_initialize(&sha);
  241. sha256_finalize(&sha, message, length);
  242. for (i = 0; i < 32; ++i) hash[i] = sha.hash[i];
  243. }
  244. /******************************************************************************
  245. * HMAC-SHA256.
  246. */
  247. typedef struct _hmac_sha256 {
  248. uint8_t digest[32]; // Changed by RKW, unsigned char becomes uint_8
  249. uint8_t key[64]; // Changed by RKW, unsigned char becomes uint_8
  250. sha256 sha;
  251. } hmac_sha256;
  252. // Changed by RKW, formal arg is now const uint8_t
  253. // from const unsigned char
  254. void hmac_sha256_initialize(hmac_sha256 *hmac,
  255. const uint8_t *key, int length) {
  256. int i;
  257. /* Prepare the inner hash key block, hashing the key if it's too long. */
  258. if (length <= 64) {
  259. for (i = 0; i < length; ++i) hmac->key[i] = key[i] ^ 0x36;
  260. for (; i < 64; ++i) hmac->key[i] = 0x36;
  261. } else {
  262. sha256_initialize(&(hmac->sha));
  263. sha256_finalize(&(hmac->sha), key, length);
  264. for (i = 0; i < 32; ++i) hmac->key[i] = hmac->sha.hash[i] ^ 0x36;
  265. for (; i < 64; ++i) hmac->key[i] = 0x36;
  266. }
  267. /* Initialize the inner hash with the key block. */
  268. sha256_initialize(&(hmac->sha));
  269. sha256_update(&(hmac->sha), hmac->key, 64);
  270. }
  271. // Changed by RKW, formal arg is now const uint8_t
  272. // from const unsigned char
  273. void hmac_sha256_update(hmac_sha256 *hmac,
  274. const uint8_t *message, int length) {
  275. /* Update the inner hash. */
  276. sha256_update(&(hmac->sha), message, length);
  277. }
  278. // Changed by RKW, formal arg is now const uint8_t
  279. // from const unsigned char
  280. void hmac_sha256_finalize(hmac_sha256 *hmac,
  281. const uint8_t *message, int length) {
  282. int i;
  283. /* Finalize the inner hash and store its value in the digest array. */
  284. sha256_finalize(&(hmac->sha), message, length);
  285. for (i = 0; i < 32; ++i) hmac->digest[i] = hmac->sha.hash[i];
  286. /* Convert the inner hash key block to the outer hash key block. */
  287. for (i = 0; i < 64; ++i) hmac->key[i] ^= (0x36 ^ 0x5c);
  288. /* Calculate the outer hash. */
  289. sha256_initialize(&(hmac->sha));
  290. sha256_update(&(hmac->sha), hmac->key, 64);
  291. sha256_finalize(&(hmac->sha), hmac->digest, 32);
  292. /* Use the outer hash value as the HMAC digest. */
  293. for (i = 0; i < 32; ++i) hmac->digest[i] = hmac->sha.hash[i];
  294. }
  295. // Changed by RKW, formal args are now uint8_t, const uint8_t
  296. // from unsinged char, const unsigned char respectively
  297. void hmac_sha256_get(uint8_t digest[32],
  298. const uint8_t *message, int message_length,
  299. const uint8_t *key, int key_length) {
  300. int i;
  301. hmac_sha256 hmac;
  302. hmac_sha256_initialize(&hmac, key, key_length);
  303. hmac_sha256_finalize(&hmac, message, message_length);
  304. for (i = 0; i < 32; ++i) digest[i] = hmac.digest[i];
  305. }
  306. /******************************************************************************
  307. * Input/output.
  308. */
  309. //int main(int argc, const char *const *argv) {
  310. // hmac_sha256 hmac;
  311. // sha256 sha;
  312. // unsigned char key[64];
  313. // unsigned char block[1024];
  314. // int i, c, d;
  315. // /* Parse and verify arguments. */
  316. // int hexadecimals = (argc == 2 && strcmp(argv[1], "-x") == 0);
  317. // if (argc > 2 || argc > 1 && !hexadecimals) {
  318. // fprintf(stderr, "%s -- %s\n%s\n%s\n%s\n%s\n",
  319. // "hmac-sha256: illegal option", argv[1],
  320. // "usage: hmac-sha256 [ -x ]",
  321. // " -x interpret the key line as a hexadecimal value",
  322. // " the first line of input should be the key",
  323. // " the rest of the input should be the message to sign");
  324. // exit(1);
  325. // }
  326. // /* Read the key, hashing it if necessary. */
  327. // sha256_initialize(&sha);
  328. // for (i = 0; (c = getchar()) > 31 && c < 127; ++i) {
  329. // if (i > 0 && i % 64 == 0) sha256_update(&sha, key, 64);
  330. // if (!hexadecimals) {
  331. // key[i % 64] = c;
  332. // } else if (isxdigit(c) && isxdigit(d = getchar())) {
  333. // key[i % 64] = (c % 32 + 9) % 25 * 16 + (d % 32 + 9) % 25;
  334. // } else {
  335. // c = '?';
  336. // break;
  337. // }
  338. // }
  339. // /* Handle "\r\n" and "\r" like "\n". */
  340. // if (i > 0 && c == '\r' && (c = getchar()) != '\n' && c != EOF) {
  341. // ungetc(c, stdin);
  342. // c = '\n';
  343. // }
  344. // /* Display an error and exit if the key is invalid. */
  345. // if (i == 0 || c != '\n' && c != EOF) {
  346. // fprintf(stderr, "hmac-sha256: invalid key\n");
  347. // exit(1);
  348. // }
  349. // /* Initialize the HMAC-SHA256 digest with the key or its hash. */
  350. // if (i <= 64) {
  351. // hmac_sha256_initialize(&hmac, key, i);
  352. // } else {
  353. // sha256_finalize(&sha, key, i % 64);
  354. // hmac_sha256_initialize(&hmac, sha.hash, 64);
  355. // }
  356. // /* Read the message, updating the HMAC-SHA256 digest accordingly. */
  357. // if (c != EOF) {
  358. // while (!feof(stdin) && !ferror(stdin)) {
  359. // i = fread(block, 1, sizeof(block), stdin);
  360. // hmac_sha256_update(&hmac, block, i);
  361. // }
  362. // }
  363. // /* Finalize the HMAC-SHA256 digest and output its value. */
  364. // hmac_sha256_finalize(&hmac, NULL, 0);
  365. // for (i = 0; i < 32; ++i) {
  366. // // Cast added by RKW to get format specifier to work as expected
  367. // printf("%02lx", (unsigned long)hmac.digest[i]);
  368. // }
  369. // putchar('\n');
  370. // /* That's all folks! */
  371. // return 0;
  372. //}