tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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 }