fuzz-curve25519.c (3686B)
1 #if defined(_WIN32) 2 #include <windows.h> 3 #include <wincrypt.h> 4 typedef unsigned int uint32_t; 5 typedef unsigned __int64 uint64_t; 6 #else 7 #include <stdint.h> 8 #endif 9 10 #include <string.h> 11 #include <stdio.h> 12 13 #include "ed25519-donna.h" 14 #include "curve25519-ref10.h" 15 16 static void 17 print_diff(const char *desc, const unsigned char *a, const unsigned char *b, size_t len) { 18 size_t p = 0; 19 unsigned char diff; 20 printf("%s diff:\n", desc); 21 while (len--) { 22 diff = *a++ ^ *b++; 23 if (!diff) 24 printf("____,"); 25 else 26 printf("0x%02x,", diff); 27 if ((++p & 15) == 0) 28 printf("\n"); 29 } 30 printf("\n\n"); 31 } 32 33 static void 34 print_bytes(const char *desc, const unsigned char *bytes, size_t len) { 35 size_t p = 0; 36 printf("%s:\n", desc); 37 while (len--) { 38 printf("0x%02x,", *bytes++); 39 if ((++p & 15) == 0) 40 printf("\n"); 41 } 42 printf("\n\n"); 43 } 44 45 46 /* chacha20/12 prng */ 47 void 48 prng(unsigned char *out, size_t bytes) { 49 static uint32_t state[16]; 50 static int init = 0; 51 uint32_t x[16], t; 52 size_t i; 53 54 if (!init) { 55 #if defined(_WIN32) 56 HCRYPTPROV csp; 57 if (!CryptAcquireContext(&csp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 58 printf("CryptAcquireContext failed\n"); 59 exit(1); 60 } 61 if (!CryptGenRandom(csp, (DWORD)sizeof(state), (BYTE*)state)) { 62 printf("CryptGenRandom failed\n"); 63 exit(1); 64 } 65 CryptReleaseContext(csp, 0); 66 #else 67 FILE *f = NULL; 68 f = fopen("/dev/urandom", "rb"); 69 if (!f) { 70 printf("failed to open /dev/urandom\n"); 71 exit(1); 72 } 73 if (fread(state, sizeof(state), 1, f) != 1) { 74 printf("read error on /dev/urandom\n"); 75 exit(1); 76 } 77 #endif 78 init = 1; 79 } 80 81 while (bytes) { 82 for (i = 0; i < 16; i++) x[i] = state[i]; 83 84 #define rotl32(x,k) ((x << k) | (x >> (32 - k))) 85 #define quarter(a,b,c,d) \ 86 x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t,16); \ 87 x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t,12); \ 88 x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t, 8); \ 89 x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t, 7); 90 91 for (i = 0; i < 12; i += 2) { 92 quarter( 0, 4, 8,12) 93 quarter( 1, 5, 9,13) 94 quarter( 2, 6,10,14) 95 quarter( 3, 7,11,15) 96 quarter( 0, 5,10,15) 97 quarter( 1, 6,11,12) 98 quarter( 2, 7, 8,13) 99 quarter( 3, 4, 9,14) 100 }; 101 102 if (bytes <= 64) { 103 memcpy(out, x, bytes); 104 bytes = 0; 105 } else { 106 memcpy(out, x, 64); 107 bytes -= 64; 108 out += 64; 109 } 110 111 /* don't need a nonce, so last 4 words are the counter. 2^136 bytes can be generated */ 112 if (!++state[12]) if (!++state[13]) if (!++state[14]) ++state[15]; 113 } 114 } 115 116 117 118 int main() { 119 const size_t skmax = 1024; 120 static unsigned char sk[1024][32]; 121 unsigned char pk[3][32]; 122 unsigned char *skp; 123 size_t ski, pki, i; 124 uint64_t ctr; 125 126 printf("fuzzing: "); 127 printf(" ref10"); 128 printf(" curved25519"); 129 #if defined(ED25519_SSE2) 130 printf(" curved25519-sse2"); 131 #endif 132 printf("\n\n"); 133 134 for (ctr = 0, ski = skmax;;ctr++) { 135 if (ski == skmax) { 136 prng((unsigned char *)sk, sizeof(sk)); 137 ski = 0; 138 } 139 skp = sk[ski++]; 140 141 pki = 0; 142 crypto_scalarmult_base_ref10(pk[pki++], skp); 143 curved25519_scalarmult_basepoint(pk[pki++], skp); 144 #if defined(ED25519_SSE2) 145 curved25519_scalarmult_basepoint_sse2(pk[pki++], skp); 146 #endif 147 148 for (i = 1; i < pki; i++) { 149 if (memcmp(pk[0], pk[i], 32) != 0) { 150 printf("\n\n"); 151 print_bytes("sk", skp, 32); 152 print_bytes("ref10", pk[0], 32); 153 print_diff("curved25519", pk[0], pk[1], 32); 154 #if defined(ED25519_SSE2) 155 print_diff("curved25519-sse2", pk[0], pk[2], 32); 156 #endif 157 exit(1); 158 } 159 } 160 161 if (ctr && (ctr % 0x1000 == 0)) { 162 printf("."); 163 if ((ctr % 0x20000) == 0) { 164 printf(" ["); 165 for (i = 0; i < 8; i++) 166 printf("%02x", (unsigned char)(ctr >> ((7 - i) * 8))); 167 printf("]\n"); 168 } 169 } 170 } 171 }