utils_sha1.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * Tencent is pleased to support the open source community by making IoT Hub
  3. available.
  4. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  5. * Licensed under the MIT License (the "License"); you may not use this file
  6. except in
  7. * compliance with the License. You may obtain a copy of the License at
  8. * http://opensource.org/licenses/MIT
  9. * Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is
  11. * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. KIND,
  13. * either express or implied. See the License for the specific language
  14. governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "utils_sha1.h"
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "qcloud_iot_export_log.h"
  22. #include "qcloud_iot_import.h"
  23. /* Implementation that should never be optimized out by the compiler */
  24. static void utils_sha1_zeroize(void *v, size_t n)
  25. {
  26. volatile unsigned char *p = v;
  27. while (n--) {
  28. *p++ = 0;
  29. }
  30. }
  31. /*
  32. * 32-bit integer manipulation macros (big endian)
  33. */
  34. #ifndef IOT_SHA1_GET_UINT32_BE
  35. #define IOT_SHA1_GET_UINT32_BE(n, b, i) \
  36. { \
  37. (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | \
  38. ((uint32_t)(b)[(i) + 3]); \
  39. }
  40. #endif
  41. #ifndef IOT_SHA1_PUT_UINT32_BE
  42. #define IOT_SHA1_PUT_UINT32_BE(n, b, i) \
  43. { \
  44. (b)[(i)] = (unsigned char)((n) >> 24); \
  45. (b)[(i) + 1] = (unsigned char)((n) >> 16); \
  46. (b)[(i) + 2] = (unsigned char)((n) >> 8); \
  47. (b)[(i) + 3] = (unsigned char)((n)); \
  48. }
  49. #endif
  50. void utils_sha1_init(iot_sha1_context *ctx)
  51. {
  52. memset(ctx, 0, sizeof(iot_sha1_context));
  53. }
  54. void utils_sha1_free(iot_sha1_context *ctx)
  55. {
  56. if (ctx == NULL) {
  57. return;
  58. }
  59. utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
  60. }
  61. void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src)
  62. {
  63. *dst = *src;
  64. }
  65. /*
  66. * SHA-1 context setup
  67. */
  68. void utils_sha1_starts(iot_sha1_context *ctx)
  69. {
  70. ctx->total[0] = 0;
  71. ctx->total[1] = 0;
  72. ctx->state[0] = 0x67452301;
  73. ctx->state[1] = 0xEFCDAB89;
  74. ctx->state[2] = 0x98BADCFE;
  75. ctx->state[3] = 0x10325476;
  76. ctx->state[4] = 0xC3D2E1F0;
  77. }
  78. void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
  79. {
  80. uint32_t temp, W[16], A, B, C, D, E;
  81. IOT_SHA1_GET_UINT32_BE(W[0], data, 0);
  82. IOT_SHA1_GET_UINT32_BE(W[1], data, 4);
  83. IOT_SHA1_GET_UINT32_BE(W[2], data, 8);
  84. IOT_SHA1_GET_UINT32_BE(W[3], data, 12);
  85. IOT_SHA1_GET_UINT32_BE(W[4], data, 16);
  86. IOT_SHA1_GET_UINT32_BE(W[5], data, 20);
  87. IOT_SHA1_GET_UINT32_BE(W[6], data, 24);
  88. IOT_SHA1_GET_UINT32_BE(W[7], data, 28);
  89. IOT_SHA1_GET_UINT32_BE(W[8], data, 32);
  90. IOT_SHA1_GET_UINT32_BE(W[9], data, 36);
  91. IOT_SHA1_GET_UINT32_BE(W[10], data, 40);
  92. IOT_SHA1_GET_UINT32_BE(W[11], data, 44);
  93. IOT_SHA1_GET_UINT32_BE(W[12], data, 48);
  94. IOT_SHA1_GET_UINT32_BE(W[13], data, 52);
  95. IOT_SHA1_GET_UINT32_BE(W[14], data, 56);
  96. IOT_SHA1_GET_UINT32_BE(W[15], data, 60);
  97. #define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
  98. #define R(t) \
  99. (temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ W[t & 0x0F], (W[t & 0x0F] = S(temp, 1)))
  100. #define P(a, b, c, d, e, x) \
  101. { \
  102. e += S(a, 5) + F(b, c, d) + K + x; \
  103. b = S(b, 30); \
  104. }
  105. A = ctx->state[0];
  106. B = ctx->state[1];
  107. C = ctx->state[2];
  108. D = ctx->state[3];
  109. E = ctx->state[4];
  110. #define F(x, y, z) (z ^ (x & (y ^ z)))
  111. #define K 0x5A827999
  112. P(A, B, C, D, E, W[0]);
  113. P(E, A, B, C, D, W[1]);
  114. P(D, E, A, B, C, W[2]);
  115. P(C, D, E, A, B, W[3]);
  116. P(B, C, D, E, A, W[4]);
  117. P(A, B, C, D, E, W[5]);
  118. P(E, A, B, C, D, W[6]);
  119. P(D, E, A, B, C, W[7]);
  120. P(C, D, E, A, B, W[8]);
  121. P(B, C, D, E, A, W[9]);
  122. P(A, B, C, D, E, W[10]);
  123. P(E, A, B, C, D, W[11]);
  124. P(D, E, A, B, C, W[12]);
  125. P(C, D, E, A, B, W[13]);
  126. P(B, C, D, E, A, W[14]);
  127. P(A, B, C, D, E, W[15]);
  128. P(E, A, B, C, D, R(16));
  129. P(D, E, A, B, C, R(17));
  130. P(C, D, E, A, B, R(18));
  131. P(B, C, D, E, A, R(19));
  132. #undef K
  133. #undef F
  134. #define F(x, y, z) (x ^ y ^ z)
  135. #define K 0x6ED9EBA1
  136. P(A, B, C, D, E, R(20));
  137. P(E, A, B, C, D, R(21));
  138. P(D, E, A, B, C, R(22));
  139. P(C, D, E, A, B, R(23));
  140. P(B, C, D, E, A, R(24));
  141. P(A, B, C, D, E, R(25));
  142. P(E, A, B, C, D, R(26));
  143. P(D, E, A, B, C, R(27));
  144. P(C, D, E, A, B, R(28));
  145. P(B, C, D, E, A, R(29));
  146. P(A, B, C, D, E, R(30));
  147. P(E, A, B, C, D, R(31));
  148. P(D, E, A, B, C, R(32));
  149. P(C, D, E, A, B, R(33));
  150. P(B, C, D, E, A, R(34));
  151. P(A, B, C, D, E, R(35));
  152. P(E, A, B, C, D, R(36));
  153. P(D, E, A, B, C, R(37));
  154. P(C, D, E, A, B, R(38));
  155. P(B, C, D, E, A, R(39));
  156. #undef K
  157. #undef F
  158. #define F(x, y, z) ((x & y) | (z & (x | y)))
  159. #define K 0x8F1BBCDC
  160. P(A, B, C, D, E, R(40));
  161. P(E, A, B, C, D, R(41));
  162. P(D, E, A, B, C, R(42));
  163. P(C, D, E, A, B, R(43));
  164. P(B, C, D, E, A, R(44));
  165. P(A, B, C, D, E, R(45));
  166. P(E, A, B, C, D, R(46));
  167. P(D, E, A, B, C, R(47));
  168. P(C, D, E, A, B, R(48));
  169. P(B, C, D, E, A, R(49));
  170. P(A, B, C, D, E, R(50));
  171. P(E, A, B, C, D, R(51));
  172. P(D, E, A, B, C, R(52));
  173. P(C, D, E, A, B, R(53));
  174. P(B, C, D, E, A, R(54));
  175. P(A, B, C, D, E, R(55));
  176. P(E, A, B, C, D, R(56));
  177. P(D, E, A, B, C, R(57));
  178. P(C, D, E, A, B, R(58));
  179. P(B, C, D, E, A, R(59));
  180. #undef K
  181. #undef F
  182. #define F(x, y, z) (x ^ y ^ z)
  183. #define K 0xCA62C1D6
  184. P(A, B, C, D, E, R(60));
  185. P(E, A, B, C, D, R(61));
  186. P(D, E, A, B, C, R(62));
  187. P(C, D, E, A, B, R(63));
  188. P(B, C, D, E, A, R(64));
  189. P(A, B, C, D, E, R(65));
  190. P(E, A, B, C, D, R(66));
  191. P(D, E, A, B, C, R(67));
  192. P(C, D, E, A, B, R(68));
  193. P(B, C, D, E, A, R(69));
  194. P(A, B, C, D, E, R(70));
  195. P(E, A, B, C, D, R(71));
  196. P(D, E, A, B, C, R(72));
  197. P(C, D, E, A, B, R(73));
  198. P(B, C, D, E, A, R(74));
  199. P(A, B, C, D, E, R(75));
  200. P(E, A, B, C, D, R(76));
  201. P(D, E, A, B, C, R(77));
  202. P(C, D, E, A, B, R(78));
  203. P(B, C, D, E, A, R(79));
  204. #undef K
  205. #undef F
  206. ctx->state[0] += A;
  207. ctx->state[1] += B;
  208. ctx->state[2] += C;
  209. ctx->state[3] += D;
  210. ctx->state[4] += E;
  211. }
  212. /*
  213. * SHA-1 process buffer
  214. */
  215. void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen)
  216. {
  217. size_t fill;
  218. uint32_t left;
  219. if (ilen == 0) {
  220. return;
  221. }
  222. left = ctx->total[0] & 0x3F;
  223. fill = 64 - left;
  224. ctx->total[0] += (uint32_t)ilen;
  225. ctx->total[0] &= 0xFFFFFFFF;
  226. if (ctx->total[0] < (uint32_t)ilen) {
  227. ctx->total[1]++;
  228. }
  229. if (left && ilen >= fill) {
  230. memcpy((void *)(ctx->buffer + left), input, fill);
  231. utils_sha1_process(ctx, ctx->buffer);
  232. input += fill;
  233. ilen -= fill;
  234. left = 0;
  235. }
  236. while (ilen >= 64) {
  237. utils_sha1_process(ctx, input);
  238. input += 64;
  239. ilen -= 64;
  240. }
  241. if (ilen > 0) {
  242. memcpy((void *)(ctx->buffer + left), input, ilen);
  243. }
  244. }
  245. static const unsigned char iot_sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  246. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  247. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  248. /*
  249. * SHA-1 final digest
  250. */
  251. void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
  252. {
  253. uint32_t last, padn;
  254. uint32_t high, low;
  255. unsigned char msglen[8];
  256. high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
  257. low = (ctx->total[0] << 3);
  258. IOT_SHA1_PUT_UINT32_BE(high, msglen, 0);
  259. IOT_SHA1_PUT_UINT32_BE(low, msglen, 4);
  260. last = ctx->total[0] & 0x3F;
  261. padn = (last < 56) ? (56 - last) : (120 - last);
  262. utils_sha1_update(ctx, iot_sha1_padding, padn);
  263. utils_sha1_update(ctx, msglen, 8);
  264. IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0);
  265. IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4);
  266. IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8);
  267. IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12);
  268. IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16);
  269. }
  270. /*
  271. * output = SHA-1( input buffer )
  272. */
  273. void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20])
  274. {
  275. iot_sha1_context ctx;
  276. utils_sha1_init(&ctx);
  277. utils_sha1_starts(&ctx);
  278. utils_sha1_update(&ctx, input, ilen);
  279. utils_sha1_finish(&ctx, output);
  280. utils_sha1_free(&ctx);
  281. }