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