1 #include <stdint.h>
2 #include <stddef.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <stdbool.h>
6 #include <ftw.h>
7
8 #include "config.h"
9 #include "gpg.h"
10 #include "../common/types.h"
11 #include "../common/iobuf.h"
12 #include "keydb.h"
13 #include "keyedit.h"
14 #include "../common/util.h"
15 #include "main.h"
16 #include "call-dirmngr.h"
17 #include "trustdb.h"
18
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <sys/mount.h>
24
25 static bool initialized = false;
26 ctrl_t ctrlGlobal;
27 int fd;
28 char *filename;
29
30 //hack not to include gpg.c which has main function
31 int g10_errors_seen = 0;
32
33 void
g10_exit(int rc)34 g10_exit( int rc )
35 {
36 gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
37 gcry_control (GCRYCTL_TERM_SECMEM );
38 exit (rc);
39 }
40
41 static void
gpg_deinit_default_ctrl(ctrl_t ctrl)42 gpg_deinit_default_ctrl (ctrl_t ctrl)
43 {
44 #ifdef USE_TOFU
45 tofu_closedbs (ctrl);
46 #endif
47 gpg_dirmngr_deinit_session_data (ctrl);
48
49 keydb_release (ctrl->cached_getkey_kdb);
50 }
51
52 static void
my_gcry_logger(void * dummy,int level,const char * format,va_list arg_ptr)53 my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr)
54 {
55 return;
56 }
57
unlink_cb(const char * fpath,const struct stat * sb,int typeflag)58 static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag)
59 {
60 if (typeflag == FTW_F){
61 unlink(fpath);
62 }
63 return 0;
64 }
65
rmrfdir(char * path)66 static void rmrfdir(char *path)
67 {
68 ftw(path, unlink_cb, 16);
69 if (rmdir(path) != 0) {
70 printf("failed rmdir, errno=%d\n", errno);
71 }
72 }
73
74 // 65kb should be enough ;-)
75 #define MAX_LEN 0x10000
76
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)77 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
78 IOBUF a;
79 armor_filter_context_t *afx = NULL;
80
81 if (! initialized) {
82 ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal));
83 if (!ctrlGlobal) {
84 exit(1);
85 }
86 //deletes previous tmp dir and (re)create it as a ramfs
87 //system("umount /tmp/fuzzdirlist");
88 rmrfdir("/tmp/fuzzdirlist");
89 if (mkdir("/tmp/fuzzdirlist", 0700) < 0) {
90 printf("failed mkdir, errno=%d\n", errno);
91 if (errno != EEXIST) {
92 return 0;
93 }
94 }
95 //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirlist");
96 filename=strdup("/tmp/fuzzdirlist/fuzz.gpg");
97 if (!filename) {
98 free(ctrlGlobal);
99 return 0;
100 }
101 fd = open(filename, O_RDWR | O_CREAT, 0666);
102 if (fd == -1) {
103 free(filename);
104 free(ctrlGlobal);
105 printf("failed open, errno=%d\n", errno);
106 return 0;
107 }
108 gnupg_set_homedir("/tmp/fuzzdirlist/");
109 gpg_error_t gpgerr = keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT);
110 if (gpgerr != GPG_ERR_NO_ERROR) {
111 free(filename);
112 free(ctrlGlobal);
113 close(fd);
114 printf("failed keydb_add_resource, errno=%d\n", gpgerr);
115 return 0;
116 }
117 gpgerr = setup_trustdb (1, NULL);
118 if (gpgerr != GPG_ERR_NO_ERROR) {
119 free(filename);
120 free(ctrlGlobal);
121 close(fd);
122 printf("failed setup_trustdb, errno=%d\n", gpgerr);
123 return 0;
124 }
125 //populate /tmp/fuzzdirlist/ as homedir ~/.gnupg
126 strlist_t sl = NULL;
127 public_key_list (ctrlGlobal, sl, 0, 0);
128 free_strlist(sl);
129 //no output for stderr
130 log_set_file("/dev/null");
131 gcry_set_log_handler (my_gcry_logger, NULL);
132 gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
133 opt.list_packets=1;
134 set_packet_list_mode(1);
135 initialized = true;
136 }
137
138 if (Size > MAX_LEN) {
139 // limit maximum size to avoid long computing times
140 return 0;
141 }
142
143 memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
144 ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
145
146 if (ftruncate(fd, Size) == -1) {
147 return 0;
148 }
149 if (lseek (fd, 0, SEEK_SET) < 0) {
150 return 0;
151 }
152 if (write (fd, Data, Size) != Size) {
153 return 0;
154 }
155
156 a = iobuf_open(filename);
157 if( !a ) {
158 printf("failed iobuf_open\n");
159 return 0;
160 }
161 if( use_armor_filter( a ) ) {
162 afx = new_armor_context ();
163 push_armor_filter (afx, a);
164 }
165 proc_packets (ctrlGlobal, NULL, a );
166 iobuf_close(a);
167 release_armor_context (afx);
168 gpg_deinit_default_ctrl (ctrlGlobal);
169
170 return 0;
171 }
172