PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Core/Common/Crypto/ec.cpp

https://github.com/bunnei/dolphin
C++ | 394 lines | 288 code | 89 blank | 17 comment | 30 complexity | f37dfc94ccd03befc74d0e3e090c4e5c MD5 | raw file
Possible License(s): GPL-2.0
  1. // Copyright 2013 Dolphin Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. // Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
  5. // Licensed under the terms of the GNU GPL, version 2
  6. // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
  7. #include <cstdio>
  8. #include <cstdlib>
  9. #include <ctime>
  10. #include <string.h>
  11. #include "Common/Common.h"
  12. #include "Common/Crypto/bn.h"
  13. #include "Common/Crypto/ec.h"
  14. // y**2 + x*y = x**3 + x + b
  15. UNUSED static const u8 ec_b[30] =
  16. {0x00,0x66,0x64,0x7e,0xde,0x6c,0x33,0x2c,0x7f,0x8c,0x09,0x23,0xbb,0x58,0x21
  17. ,0x3b,0x33,0x3b,0x20,0xe9,0xce,0x42,0x81,0xfe,0x11,0x5f,0x7d,0x8f,0x90,0xad};
  18. // order of the addition group of points
  19. static const u8 ec_N[30] =
  20. {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  21. ,0x13,0xe9,0x74,0xe7,0x2f,0x8a,0x69,0x22,0x03,0x1d,0x26,0x03,0xcf,0xe0,0xd7};
  22. // base point
  23. static const u8 ec_G[60] =
  24. {0x00,0xfa,0xc9,0xdf,0xcb,0xac,0x83,0x13,0xbb,0x21,0x39,0xf1,0xbb,0x75,0x5f
  25. ,0xef,0x65,0xbc,0x39,0x1f,0x8b,0x36,0xf8,0xf8,0xeb,0x73,0x71,0xfd,0x55,0x8b
  26. ,0x01,0x00,0x6a,0x08,0xa4,0x19,0x03,0x35,0x06,0x78,0xe5,0x85,0x28,0xbe,0xbf
  27. ,0x8a,0x0b,0xef,0xf8,0x67,0xa7,0xca,0x36,0x71,0x6f,0x7e,0x01,0xf8,0x10,0x52};
  28. static void elt_copy(u8 *d, const u8 *a)
  29. {
  30. memcpy(d, a, 30);
  31. }
  32. static void elt_zero(u8 *d)
  33. {
  34. memset(d, 0, 30);
  35. }
  36. static int elt_is_zero(const u8 *d)
  37. {
  38. u32 i;
  39. for (i = 0; i < 30; i++)
  40. if (d[i] != 0)
  41. return 0;
  42. return 1;
  43. }
  44. static void elt_add(u8 *d, const u8 *a, const u8 *b)
  45. {
  46. u32 i;
  47. for (i = 0; i < 30; i++)
  48. d[i] = a[i] ^ b[i];
  49. }
  50. static void elt_mul_x(u8 *d, const u8 *a)
  51. {
  52. u8 carry, x, y;
  53. u32 i;
  54. carry = a[0] & 1;
  55. x = 0;
  56. for (i = 0; i < 29; i++) {
  57. y = a[i + 1];
  58. d[i] = x ^ (y >> 7);
  59. x = y << 1;
  60. }
  61. d[29] = x ^ carry;
  62. d[20] ^= carry << 2;
  63. }
  64. static void elt_mul(u8 *d, const u8 *a, const u8 *b)
  65. {
  66. u32 i, n;
  67. u8 mask;
  68. elt_zero(d);
  69. i = 0;
  70. mask = 1;
  71. for (n = 0; n < 233; n++) {
  72. elt_mul_x(d, d);
  73. if ((a[i] & mask) != 0)
  74. elt_add(d, d, b);
  75. mask >>= 1;
  76. if (mask == 0) {
  77. mask = 0x80;
  78. i++;
  79. }
  80. }
  81. }
  82. static const u8 square[16] =
  83. {0x00,0x01,0x04,0x05,0x10,0x11,0x14,0x15,0x40,0x41,0x44,0x45,0x50,0x51,0x54,0x55};
  84. static void elt_square_to_wide(u8 *d, const u8 *a)
  85. {
  86. u32 i;
  87. for (i = 0; i < 30; i++) {
  88. d[2*i] = square[a[i] >> 4];
  89. d[2*i + 1] = square[a[i] & 15];
  90. }
  91. }
  92. static void wide_reduce(u8 *d)
  93. {
  94. u32 i;
  95. u8 x;
  96. for (i = 0; i < 30; i++) {
  97. x = d[i];
  98. d[i + 19] ^= x >> 7;
  99. d[i + 20] ^= x << 1;
  100. d[i + 29] ^= x >> 1;
  101. d[i + 30] ^= x << 7;
  102. }
  103. x = d[30] & ~1;
  104. d[49] ^= x >> 7;
  105. d[50] ^= x << 1;
  106. d[59] ^= x >> 1;
  107. d[30] &= 1;
  108. }
  109. static void elt_square(u8 *d, const u8 *a)
  110. {
  111. u8 wide[60];
  112. elt_square_to_wide(wide, a);
  113. wide_reduce(wide);
  114. elt_copy(d, wide + 30);
  115. }
  116. static void itoh_tsujii(u8 *d, const u8 *a, const u8 *b, u32 j)
  117. {
  118. u8 t[30];
  119. elt_copy(t, a);
  120. while (j--) {
  121. elt_square(d, t);
  122. elt_copy(t, d);
  123. }
  124. elt_mul(d, t, b);
  125. }
  126. static void elt_inv(u8 *d, const u8 *a)
  127. {
  128. u8 t[30];
  129. u8 s[30];
  130. itoh_tsujii(t, a, a, 1);
  131. itoh_tsujii(s, t, a, 1);
  132. itoh_tsujii(t, s, s, 3);
  133. itoh_tsujii(s, t, a, 1);
  134. itoh_tsujii(t, s, s, 7);
  135. itoh_tsujii(s, t, t, 14);
  136. itoh_tsujii(t, s, a, 1);
  137. itoh_tsujii(s, t, t, 29);
  138. itoh_tsujii(t, s, s, 58);
  139. itoh_tsujii(s, t, t, 116);
  140. elt_square(d, s);
  141. }
  142. UNUSED static int point_is_on_curve(u8 *p)
  143. {
  144. u8 s[30], t[30];
  145. u8 *x, *y;
  146. x = p;
  147. y = p + 30;
  148. elt_square(t, x);
  149. elt_mul(s, t, x);
  150. elt_add(s, s, t);
  151. elt_square(t, y);
  152. elt_add(s, s, t);
  153. elt_mul(t, x, y);
  154. elt_add(s, s, t);
  155. elt_add(s, s, ec_b);
  156. return elt_is_zero(s);
  157. }
  158. static int point_is_zero(const u8 *p)
  159. {
  160. return elt_is_zero(p) && elt_is_zero(p + 30);
  161. }
  162. static void point_double(u8 *r, const u8 *p)
  163. {
  164. u8 s[30], t[30];
  165. const u8 *px, *py;
  166. u8 *rx, *ry;
  167. px = p;
  168. py = p + 30;
  169. rx = r;
  170. ry = r + 30;
  171. if (elt_is_zero(px)) {
  172. elt_zero(rx);
  173. elt_zero(ry);
  174. return;
  175. }
  176. elt_inv(t, px);
  177. elt_mul(s, py, t);
  178. elt_add(s, s, px);
  179. elt_square(t, px);
  180. elt_square(rx, s);
  181. elt_add(rx, rx, s);
  182. rx[29] ^= 1;
  183. elt_mul(ry, s, rx);
  184. elt_add(ry, ry, rx);
  185. elt_add(ry, ry, t);
  186. }
  187. static void point_add(u8 *r, const u8 *p, const u8 *q)
  188. {
  189. u8 s[30], t[30], u[30];
  190. const u8 *px, *py, *qx, *qy;
  191. u8 *rx, *ry;
  192. px = p;
  193. py = p + 30;
  194. qx = q;
  195. qy = q + 30;
  196. rx = r;
  197. ry = r + 30;
  198. if (point_is_zero(p)) {
  199. elt_copy(rx, qx);
  200. elt_copy(ry, qy);
  201. return;
  202. }
  203. if (point_is_zero(q)) {
  204. elt_copy(rx, px);
  205. elt_copy(ry, py);
  206. return;
  207. }
  208. elt_add(u, px, qx);
  209. if (elt_is_zero(u)) {
  210. elt_add(u, py, qy);
  211. if (elt_is_zero(u))
  212. point_double(r, p);
  213. else {
  214. elt_zero(rx);
  215. elt_zero(ry);
  216. }
  217. return;
  218. }
  219. elt_inv(t, u);
  220. elt_add(u, py, qy);
  221. elt_mul(s, t, u);
  222. elt_square(t, s);
  223. elt_add(t, t, s);
  224. elt_add(t, t, qx);
  225. t[29] ^= 1;
  226. elt_mul(u, s, t);
  227. elt_add(s, u, py);
  228. elt_add(rx, t, px);
  229. elt_add(ry, s, rx);
  230. }
  231. void point_mul(u8 *d, const u8 *a, const u8 *b) // a is bignum
  232. {
  233. u32 i;
  234. u8 mask;
  235. elt_zero(d);
  236. elt_zero(d + 30);
  237. for (i = 0; i < 30; i++)
  238. for (mask = 0x80; mask != 0; mask >>= 1) {
  239. point_double(d, d);
  240. if ((a[i] & mask) != 0)
  241. point_add(d, d, b);
  242. }
  243. }
  244. static void silly_random(u8 * rndArea, u8 count)
  245. {
  246. u16 i;
  247. srand((unsigned) (time(nullptr)));
  248. for (i=0;i<count;i++)
  249. {
  250. rndArea[i]=rand();
  251. }
  252. }
  253. void generate_ecdsa(u8 *R, u8 *S, const u8 *k, const u8 *hash)
  254. {
  255. u8 e[30];
  256. u8 kk[30];
  257. u8 m[30];
  258. u8 minv[30];
  259. u8 mG[60];
  260. //FILE *fp;
  261. elt_zero(e);
  262. memcpy(e + 10, hash, 20);
  263. //Changing random number generator to a lame one...
  264. silly_random(m, sizeof(m));
  265. //fp = fopen("/dev/random", "rb");
  266. //if (fread(m, sizeof m, 1, fp) != 1)
  267. // fatal("reading random");
  268. //fclose(fp);
  269. m[0] = 0;
  270. // R = (mG).x
  271. point_mul(mG, m, ec_G);
  272. elt_copy(R, mG);
  273. if (bn_compare(R, ec_N, 30) >= 0)
  274. bn_sub_modulus(R, ec_N, 30);
  275. // S = m**-1*(e + Rk) (mod N)
  276. elt_copy(kk, k);
  277. if (bn_compare(kk, ec_N, 30) >= 0)
  278. bn_sub_modulus(kk, ec_N, 30);
  279. bn_mul(S, R, kk, ec_N, 30);
  280. bn_add(kk, S, e, ec_N, 30);
  281. bn_inv(minv, m, ec_N, 30);
  282. bn_mul(S, minv, kk, ec_N, 30);
  283. }
  284. UNUSED static int check_ecdsa(u8 *Q, u8 *R, u8 *S, const u8 *hash)
  285. {
  286. u8 Sinv[30];
  287. u8 e[30];
  288. u8 w1[30], w2[30];
  289. u8 r1[60], r2[60];
  290. bn_inv(Sinv, S, ec_N, 30);
  291. elt_zero(e);
  292. memcpy(e + 10, hash, 20);
  293. bn_mul(w1, e, Sinv, ec_N, 30);
  294. bn_mul(w2, R, Sinv, ec_N, 30);
  295. point_mul(r1, w1, ec_G);
  296. point_mul(r2, w2, Q);
  297. point_add(r1, r1, r2);
  298. if (bn_compare(r1, ec_N, 30) >= 0)
  299. bn_sub_modulus(r1, ec_N, 30);
  300. return (bn_compare(r1, R, 30) == 0);
  301. }
  302. void ec_priv_to_pub(const u8 *k, u8 *Q)
  303. {
  304. point_mul(Q, k, ec_G);
  305. }