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