ec.c 5.6 KB

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