Line data Source code
1 : #if !FD_HAS_HOSTED
2 : #error "This target requires FD_HAS_HOSTED"
3 : #endif
4 :
5 : #include <assert.h>
6 : #include <dlfcn.h>
7 : #include <stdio.h>
8 : #include <stdlib.h>
9 :
10 : #include "../../util/fd_util.h"
11 : #include "../../util/sanitize/fd_fuzz.h"
12 : #include "fd_ed25519.h"
13 :
14 0 : #define DALEK_SO_DEFAULT "contrib/ed25519/dalek_target/target/x86_64-unknown-linux-gnu/release/libdalek_target.so"
15 :
16 : typedef int
17 : (* verify_fn_t)( uchar const * msg,
18 : ulong sz,
19 : uchar const * sig,
20 : uchar const * pub );
21 :
22 : static union {
23 : verify_fn_t fn;
24 : void * ptr;
25 : } verify_fn;
26 :
27 : typedef int
28 : (* sign_fn_t)( uchar * sig,
29 : uchar const * msg,
30 : ulong sz,
31 : uchar const * pub,
32 : uchar const * prv );
33 :
34 : static union {
35 : sign_fn_t fn;
36 : void * ptr;
37 : } sign_fn;
38 :
39 :
40 : int
41 : LLVMFuzzerInitialize( int * argc,
42 0 : char *** argv ) {
43 : /* Set up shell without signal handlers */
44 0 : putenv( "FD_LOG_BACKTRACE=0" );
45 0 : setenv( "FD_LOG_PATH", "", 0 );
46 0 : fd_boot( argc, argv );
47 0 : atexit( fd_halt );
48 0 : fd_log_level_core_set(3); /* crash on warning log */
49 :
50 0 : char const * dalek_path = getenv( "DALEK_TARGET_SO" );
51 0 : if( !dalek_path ) {
52 0 : dalek_path = DALEK_SO_DEFAULT;
53 0 : }
54 0 : void * dalek = dlopen( dalek_path, RTLD_LAZY );
55 0 : if( FD_UNLIKELY( !dalek ) )
56 0 : FD_LOG_CRIT(( "%s", dlerror() ));
57 :
58 0 : verify_fn.ptr = dlsym( dalek, "ed25519_dalek_verify" );
59 0 : if( FD_UNLIKELY( !verify_fn.ptr ) )
60 0 : FD_LOG_CRIT(( "%s", dlerror() ));
61 :
62 0 : sign_fn.ptr = dlsym( dalek, "ed25519_dalek_sign" );
63 0 : if( FD_UNLIKELY( !sign_fn.ptr ) )
64 0 : FD_LOG_CRIT(( "%s", dlerror() ));
65 :
66 0 : return 0;
67 0 : }
68 :
69 : struct verification_test {
70 : uchar prv[ 32 ];
71 : uchar sig[ 64 ];
72 : uchar msg[ ];
73 : };
74 : typedef struct verification_test verification_test_t;
75 :
76 : int
77 : LLVMFuzzerTestOneInput( uchar const * data,
78 : ulong size ) {
79 : if( FD_UNLIKELY( size<96UL ) ) return -1;
80 :
81 : verification_test_t * const test = ( verification_test_t * const ) data;
82 : ulong sz = size-96UL;
83 :
84 : fd_sha512_t _sha[1];
85 : fd_sha512_t *sha = fd_sha512_join( fd_sha512_new( _sha ) );
86 :
87 : uchar pub[ 32 ];
88 : fd_ed25519_public_from_private( pub, test->prv, sha );
89 :
90 : /* test that C and Rust create the same signature */
91 : uchar sigC[ 64 ];
92 : uchar sigR[ 64 ];
93 : uchar * sig_resultC = fd_ed25519_sign( sigC, test->msg, sz, pub, test->prv, sha );
94 : int sig_resultR = sign_fn.fn( sigR, test->msg, sz, pub, test->prv );
95 : assert( sig_resultC == sigC );
96 : assert( sig_resultR == 0 );
97 : assert( fd_memeq( sigC, sigR, 64UL ) );
98 :
99 : /* test that C and Rust successfully verify this signature */
100 : int ok0 = fd_ed25519_verify( test->msg, sz, sigC, pub, sha ) == FD_ED25519_SUCCESS;
101 : int ok1 = verify_fn.fn( test->msg, sz, sigC, pub ) == 0;
102 : assert( ok0 );
103 : assert( ok1 );
104 :
105 : /* test that C and Rust return the same result on a random sig */
106 : ok0 = fd_ed25519_verify( test->msg, sz, test->sig, pub, sha ) == FD_ED25519_SUCCESS;
107 : ok1 = verify_fn.fn( test->msg, sz, test->sig, pub ) == 0;
108 : assert( ok0==ok1 );
109 : return 0;
110 : }
|