fuzz-ed25519.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #if defined(_WIN32)
  2. #include <windows.h>
  3. #include <wincrypt.h>
  4. typedef unsigned int uint32_t;
  5. #else
  6. #include <stdint.h>
  7. #endif
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include "ed25519-donna.h"
  11. #include "ed25519-ref10.h"
  12. static void
  13. print_diff(const char *desc, const unsigned char *a, const unsigned char *b, size_t len) {
  14. size_t p = 0;
  15. unsigned char diff;
  16. printf("%s diff:\n", desc);
  17. while (len--) {
  18. diff = *a++ ^ *b++;
  19. if (!diff)
  20. printf("____,");
  21. else
  22. printf("0x%02x,", diff);
  23. if ((++p & 15) == 0)
  24. printf("\n");
  25. }
  26. printf("\n");
  27. }
  28. static void
  29. print_bytes(const char *desc, const unsigned char *bytes, size_t len) {
  30. size_t p = 0;
  31. printf("%s:\n", desc);
  32. while (len--) {
  33. printf("0x%02x,", *bytes++);
  34. if ((++p & 15) == 0)
  35. printf("\n");
  36. }
  37. printf("\n");
  38. }
  39. /* chacha20/12 prng */
  40. void
  41. prng(unsigned char *out, size_t bytes) {
  42. static uint32_t state[16];
  43. static int init = 0;
  44. uint32_t x[16], t;
  45. size_t i;
  46. if (!init) {
  47. #if defined(_WIN32)
  48. HCRYPTPROV csp = NULL;
  49. if (!CryptAcquireContext(&csp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
  50. printf("CryptAcquireContext failed\n");
  51. exit(1);
  52. }
  53. if (!CryptGenRandom(csp, (DWORD)sizeof(state), (BYTE*)state)) {
  54. printf("CryptGenRandom failed\n");
  55. exit(1);
  56. }
  57. CryptReleaseContext(csp, 0);
  58. #else
  59. FILE *f = NULL;
  60. f = fopen("/dev/urandom", "rb");
  61. if (!f) {
  62. printf("failed to open /dev/urandom\n");
  63. exit(1);
  64. }
  65. if (fread(state, sizeof(state), 1, f) != 1) {
  66. printf("read error on /dev/urandom\n");
  67. exit(1);
  68. }
  69. #endif
  70. init = 1;
  71. }
  72. while (bytes) {
  73. for (i = 0; i < 16; i++) x[i] = state[i];
  74. #define rotl32(x,k) ((x << k) | (x >> (32 - k)))
  75. #define quarter(a,b,c,d) \
  76. x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t,16); \
  77. x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t,12); \
  78. x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t, 8); \
  79. x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t, 7);
  80. for (i = 0; i < 12; i += 2) {
  81. quarter( 0, 4, 8,12)
  82. quarter( 1, 5, 9,13)
  83. quarter( 2, 6,10,14)
  84. quarter( 3, 7,11,15)
  85. quarter( 0, 5,10,15)
  86. quarter( 1, 6,11,12)
  87. quarter( 2, 7, 8,13)
  88. quarter( 3, 4, 9,14)
  89. };
  90. if (bytes <= 64) {
  91. memcpy(out, x, bytes);
  92. bytes = 0;
  93. } else {
  94. memcpy(out, x, 64);
  95. bytes -= 64;
  96. out += 64;
  97. }
  98. /* don't need a nonce, so last 4 words are the counter. 2^136 bytes can be generated */
  99. if (!++state[12]) if (!++state[13]) if (!++state[14]) ++state[15];
  100. }
  101. }
  102. typedef struct random_data_t {
  103. unsigned char sk[32];
  104. unsigned char m[128];
  105. } random_data;
  106. typedef struct generated_data_t {
  107. unsigned char pk[32];
  108. unsigned char sig[64];
  109. int valid;
  110. } generated_data;
  111. static void
  112. print_generated(const char *desc, generated_data *g) {
  113. printf("%s:\n", desc);
  114. print_bytes("pk", g->pk, 32);
  115. print_bytes("sig", g->sig, 64);
  116. printf("valid: %s\n\n", g->valid ? "no" : "yes");
  117. }
  118. static void
  119. print_generated_diff(const char *desc, const generated_data *base, generated_data *g) {
  120. printf("%s:\n", desc);
  121. print_diff("pk", base->pk, g->pk, 32);
  122. print_diff("sig", base->sig, g->sig, 64);
  123. printf("valid: %s\n\n", (base->valid == g->valid) ? "___" : (g->valid ? "no" : "yes"));
  124. }
  125. int main() {
  126. const size_t rndmax = 128;
  127. static random_data rnd[128];
  128. static generated_data gen[3];
  129. random_data *r;
  130. generated_data *g;
  131. unsigned long long dummylen;
  132. unsigned char dummysk[64];
  133. unsigned char dummymsg[2][128+64];
  134. size_t rndi, geni, i, j;
  135. uint64_t ctr;
  136. printf("fuzzing: ");
  137. printf(" ref10");
  138. printf(" ed25519-donna");
  139. #if defined(ED25519_SSE2)
  140. printf(" ed25519-donna-sse2");
  141. #endif
  142. printf("\n\n");
  143. for (ctr = 0, rndi = rndmax;;ctr++) {
  144. if (rndi == rndmax) {
  145. prng((unsigned char *)rnd, sizeof(rnd));
  146. rndi = 0;
  147. }
  148. r = &rnd[rndi++];
  149. /* ref10, lots of horrible gymnastics to work around the wonky api */
  150. geni = 0;
  151. g = &gen[geni++];
  152. memcpy(dummysk, r->sk, 32); /* pk is appended to the sk, need to copy the sk to a larger buffer */
  153. crypto_sign_pk_ref10(dummysk + 32, dummysk);
  154. memcpy(g->pk, dummysk + 32, 32);
  155. crypto_sign_ref10(dummymsg[0], &dummylen, r->m, 128, dummysk);
  156. memcpy(g->sig, dummymsg[0], 64); /* sig is placed in front of the signed message */
  157. g->valid = crypto_sign_open_ref10(dummymsg[1], &dummylen, dummymsg[0], 128 + 64, g->pk);
  158. /* ed25519-donna */
  159. g = &gen[geni++];
  160. ed25519_publickey(r->sk, g->pk);
  161. ed25519_sign(r->m, 128, r->sk, g->pk, g->sig);
  162. g->valid = ed25519_sign_open(r->m, 128, g->pk, g->sig);
  163. #if defined(ED25519_SSE2)
  164. /* ed25519-donna-sse2 */
  165. g = &gen[geni++];
  166. ed25519_publickey_sse2(r->sk, g->pk);
  167. ed25519_sign_sse2(r->m, 128, r->sk, g->pk, g->sig);
  168. g->valid = ed25519_sign_open_sse2(r->m, 128, g->pk, g->sig);
  169. #endif
  170. /* compare implementations 1..geni against the reference */
  171. for (i = 1; i < geni; i++) {
  172. if (memcmp(&gen[0], &gen[i], sizeof(generated_data)) != 0) {
  173. printf("\n\n");
  174. print_bytes("sk", r->sk, 32);
  175. print_bytes("m", r->m, 128);
  176. print_generated("ref10", &gen[0]);
  177. print_generated_diff("ed25519-donna", &gen[0], &gen[1]);
  178. #if defined(ED25519_SSE2)
  179. print_generated_diff("ed25519-donna-sse2", &gen[0], &gen[2]);
  180. #endif
  181. exit(1);
  182. }
  183. }
  184. /* print out status */
  185. if (ctr && (ctr % 0x1000 == 0)) {
  186. printf(".");
  187. if ((ctr % 0x20000) == 0) {
  188. printf(" [");
  189. for (i = 0; i < 8; i++)
  190. printf("%02x", (unsigned char)(ctr >> ((7 - i) * 8)));
  191. printf("]\n");
  192. }
  193. }
  194. }
  195. }