/src/dropbear/fuzz/fuzzer-verify.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "fuzz.h" |
2 | | #include "session.h" |
3 | | #include "fuzz-wrapfd.h" |
4 | | #include "debug.h" |
5 | | #include "dss.h" |
6 | | #include "ed25519.h" |
7 | | |
8 | 1 | static void setup_fuzzer(void) { |
9 | 1 | fuzz_common_setup(); |
10 | 1 | } |
11 | | |
12 | | static buffer *verifydata; |
13 | | |
14 | | /* Tests reading a public key and verifying a signature */ |
15 | 2.83k | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
16 | 2.83k | static int once = 0; |
17 | 2.83k | if (!once) { |
18 | 1 | setup_fuzzer(); |
19 | 1 | verifydata = buf_new(30); |
20 | 1 | buf_putstring(verifydata, "x", 1); |
21 | 1 | once = 1; |
22 | 1 | } |
23 | | |
24 | 2.83k | if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { |
25 | 0 | return 0; |
26 | 0 | } |
27 | | |
28 | 2.83k | m_malloc_set_epoch(1); |
29 | | |
30 | 2.83k | if (setjmp(fuzz.jmp) == 0) { |
31 | 2.83k | sign_key *key = new_sign_key(); |
32 | 2.83k | enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY; |
33 | 2.83k | if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) { |
34 | 1.70k | enum signature_type sigtype; |
35 | 1.70k | if (keytype == DROPBEAR_SIGNKEY_RSA) { |
36 | | /* Flip a coin to decide rsa signature type */ |
37 | 889 | int flag = buf_getbyte(fuzz.input); |
38 | 889 | if (flag & 0x01) { |
39 | 13 | sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; |
40 | 876 | } else { |
41 | 876 | sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; |
42 | 876 | } |
43 | 889 | } else { |
44 | 814 | sigtype = signature_type_from_signkey(keytype); |
45 | 814 | } |
46 | 1.70k | if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) { |
47 | | /* The fuzzer is capable of generating keys with a signature to match. |
48 | | We don't want false positives if the key is bogus, since a client/server |
49 | | wouldn't be trusting a bogus key anyway */ |
50 | 111 | int boguskey = 0; |
51 | | |
52 | 111 | if (keytype == DROPBEAR_SIGNKEY_DSS) { |
53 | | /* So far have seen dss keys with bad p/q/g domain parameters */ |
54 | 109 | int pprime, qprime, trials; |
55 | 109 | trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p)); |
56 | 109 | assert(mp_prime_is_prime(key->dsskey->p, trials, &pprime) == MP_OKAY); |
57 | 109 | trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->q)); |
58 | 109 | assert(mp_prime_is_prime(key->dsskey->q, trials, &qprime) == MP_OKAY); |
59 | 109 | boguskey = !(pprime && qprime); |
60 | | /* Could also check g**q mod p == 1 */ |
61 | 109 | } |
62 | | |
63 | 111 | if (keytype == DROPBEAR_SIGNKEY_SK_ED25519 || keytype == DROPBEAR_SIGNKEY_ED25519) { |
64 | 2 | dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype); |
65 | 2 | if (eck && *eck) { |
66 | 2 | int i; |
67 | | /* we've seen all-zero keys validate */ |
68 | 2 | boguskey = 1; |
69 | 66 | for (i = 0; i < CURVE25519_LEN; i++) { |
70 | 64 | if ((*eck)->priv[i] != 0x00 || (*eck)->pub[i] != 0x00) { |
71 | 0 | boguskey = 0; |
72 | 0 | } |
73 | 64 | } |
74 | | |
75 | 2 | } |
76 | 2 | } |
77 | | |
78 | 111 | if (!boguskey) { |
79 | 0 | printf("Random key/signature managed to verify!\n"); |
80 | 0 | abort(); |
81 | 0 | } |
82 | | |
83 | | |
84 | 111 | } |
85 | 1.70k | } |
86 | 2.83k | sign_key_free(key); |
87 | 2.83k | m_malloc_free_epoch(1, 0); |
88 | 2.83k | } else { |
89 | 0 | m_malloc_free_epoch(1, 1); |
90 | 0 | TRACE(("dropbear_exit longjmped")) |
91 | | /* dropbear_exit jumped here */ |
92 | 0 | } |
93 | | |
94 | 2.83k | return 0; |
95 | 2.83k | } |