tor

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

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 }