/src/libcoap/tests/oss-fuzz/dtls_define_target.c
Line | Count | Source |
1 | | /* libFuzzer harness for libcoap's (D)TLS key-type / define mapping |
2 | | * (coap_dtls.c). |
3 | | * |
4 | | * coap_dtls_map_key_type_to_define() is reached when the application hands |
5 | | * libcoap a coap_dtls_pki_t setup blob and walks every key_type variant |
6 | | * (PEM / ASN1 / PEM_BUF / PKCS11 / DEFINE), each with their own subfields. |
7 | | * coap_dtls_define_issue() then formats a diagnostic for every |
8 | | * type+fail+role combination. None of the existing harnesses drive this |
9 | | * matrix. |
10 | | */ |
11 | | |
12 | | #include "coap3/coap_internal.h" |
13 | | #include "coap3/coap.h" |
14 | | |
15 | | #include <stdint.h> |
16 | | #include <stdio.h> |
17 | | #include <string.h> |
18 | | |
19 | | extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
20 | | |
21 | | static const coap_pki_key_t k_key_types[] = { |
22 | | COAP_PKI_KEY_PEM, |
23 | | COAP_PKI_KEY_ASN1, |
24 | | COAP_PKI_KEY_PEM_BUF, |
25 | | COAP_PKI_KEY_PKCS11, |
26 | | COAP_PKI_KEY_DEFINE, |
27 | | }; |
28 | 342 | #define K_KEY_TYPE_N (sizeof(k_key_types) / sizeof(k_key_types[0])) |
29 | | |
30 | | static const coap_define_issue_key_t k_issue_keys[] = { |
31 | | COAP_DEFINE_KEY_CA, |
32 | | COAP_DEFINE_KEY_ROOT_CA, |
33 | | COAP_DEFINE_KEY_PUBLIC, |
34 | | COAP_DEFINE_KEY_PRIVATE, |
35 | | }; |
36 | | |
37 | | static const coap_define_issue_fail_t k_issue_fails[] = { |
38 | | COAP_DEFINE_FAIL_BAD, |
39 | | COAP_DEFINE_FAIL_NOT_SUPPORTED, |
40 | | COAP_DEFINE_FAIL_NONE, |
41 | | }; |
42 | | |
43 | | int |
44 | 82 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
45 | 82 | if (size < 4 || size > 1024) |
46 | 25 | return 0; |
47 | | |
48 | | /* Build a NUL-terminated string copy of the fuzz buffer so we can use it |
49 | | * as PEM/PKCS11 path strings without overrunning. */ |
50 | 57 | char strbuf[256]; |
51 | 57 | size_t slen = size < sizeof(strbuf) - 1 ? size : sizeof(strbuf) - 1; |
52 | 57 | memcpy(strbuf, data, slen); |
53 | 57 | strbuf[slen] = '\0'; |
54 | | |
55 | | /* Stop unnecessary logging output */ |
56 | 57 | coap_set_log_level(COAP_LOG_EMERG); |
57 | | |
58 | | /* The PKCS11 branch does strncasecmp(name, "pkcs11:", 7); about a quarter |
59 | | * of the time we want that string to actually match. */ |
60 | 57 | char pkcs11_str[sizeof(strbuf) + 8]; |
61 | 57 | snprintf(pkcs11_str, sizeof(pkcs11_str), "pkcs11:%s", strbuf); |
62 | | |
63 | 342 | for (size_t i = 0; i < K_KEY_TYPE_N; i++) { |
64 | 285 | coap_dtls_pki_t setup; |
65 | 285 | memset(&setup, 0, sizeof(setup)); |
66 | 285 | setup.version = COAP_DTLS_PKI_SETUP_VERSION; |
67 | 285 | setup.is_rpk_not_cert = (data[0] >> i) & 1; |
68 | 285 | setup.pki_key.key_type = k_key_types[i]; |
69 | | |
70 | 285 | switch (k_key_types[i]) { |
71 | 57 | case COAP_PKI_KEY_PEM: |
72 | 57 | setup.pki_key.key.pem.ca_file = strbuf; |
73 | 57 | setup.pki_key.key.pem.public_cert = strbuf; |
74 | 57 | setup.pki_key.key.pem.private_key = strbuf; |
75 | 57 | break; |
76 | 57 | case COAP_PKI_KEY_ASN1: |
77 | 57 | setup.pki_key.key.asn1.ca_cert = data; |
78 | 57 | setup.pki_key.key.asn1.public_cert = data; |
79 | 57 | setup.pki_key.key.asn1.private_key = data; |
80 | 57 | setup.pki_key.key.asn1.ca_cert_len = size; |
81 | 57 | setup.pki_key.key.asn1.public_cert_len = size; |
82 | 57 | setup.pki_key.key.asn1.private_key_len = size; |
83 | 57 | setup.pki_key.key.asn1.private_key_type = |
84 | 57 | (coap_asn1_privatekey_type_t)(data[1] & 0x0f); |
85 | 57 | break; |
86 | 57 | case COAP_PKI_KEY_PEM_BUF: |
87 | 57 | setup.pki_key.key.pem_buf.ca_cert = data; |
88 | 57 | setup.pki_key.key.pem_buf.public_cert = data; |
89 | 57 | setup.pki_key.key.pem_buf.private_key = data; |
90 | 57 | setup.pki_key.key.pem_buf.ca_cert_len = size; |
91 | 57 | setup.pki_key.key.pem_buf.public_cert_len = size; |
92 | 57 | setup.pki_key.key.pem_buf.private_key_len = size; |
93 | 57 | break; |
94 | 57 | case COAP_PKI_KEY_PKCS11: { |
95 | 57 | const char *which = (data[1] & 1) ? pkcs11_str : strbuf; |
96 | 57 | setup.pki_key.key.pkcs11.ca = which; |
97 | 57 | setup.pki_key.key.pkcs11.public_cert = which; |
98 | 57 | setup.pki_key.key.pkcs11.private_key = which; |
99 | 57 | setup.pki_key.key.pkcs11.user_pin = strbuf; |
100 | 57 | break; |
101 | 0 | } |
102 | 57 | case COAP_PKI_KEY_DEFINE: |
103 | 57 | setup.pki_key.key.define.ca.s_byte = strbuf; |
104 | 57 | setup.pki_key.key.define.public_cert.s_byte = strbuf; |
105 | 57 | setup.pki_key.key.define.private_key.s_byte = strbuf; |
106 | 57 | setup.pki_key.key.define.ca_def = (coap_pki_define_t)(data[2] & 0x0f); |
107 | 57 | setup.pki_key.key.define.public_cert_def = |
108 | 57 | (coap_pki_define_t)(data[2] & 0x0f); |
109 | 57 | setup.pki_key.key.define.private_key_def = |
110 | 57 | (coap_pki_define_t)(data[2] & 0x0f); |
111 | 57 | break; |
112 | 0 | default: |
113 | 0 | break; |
114 | 285 | } |
115 | | |
116 | 285 | coap_dtls_key_t mapped; |
117 | 285 | memset(&mapped, 0, sizeof(mapped)); |
118 | 285 | coap_dtls_map_key_type_to_define(&setup, &mapped); |
119 | | |
120 | | /* Now exercise the diagnostic formatter over the full type x fail x |
121 | | * role matrix using the mapped key. */ |
122 | 1.42k | for (size_t t = 0; t < sizeof(k_issue_keys) / sizeof(k_issue_keys[0]); |
123 | 1.14k | t++) { |
124 | 1.14k | for (size_t f = 0; |
125 | 4.56k | f < sizeof(k_issue_fails) / sizeof(k_issue_fails[0]); f++) { |
126 | 3.42k | coap_dtls_define_issue(k_issue_keys[t], k_issue_fails[f], &mapped, |
127 | 3.42k | COAP_DTLS_ROLE_SERVER, 0); |
128 | 3.42k | coap_dtls_define_issue(k_issue_keys[t], k_issue_fails[f], &mapped, |
129 | 3.42k | COAP_DTLS_ROLE_CLIENT, 0); |
130 | 3.42k | } |
131 | 1.14k | } |
132 | 285 | } |
133 | 57 | return 0; |
134 | 57 | } |