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
95 if (! initialized) {
96 ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal));
97 if (!ctrlGlobal) {
98 exit(1);
99 }
100 //deletes previous tmp dir and (re)create it as a ramfs
101 //system("umount /tmp/fuzzdirdecrypt");
102 rmrfdir("/tmp/fuzzdirdecrypt");
103 mkdir("/tmp/fuzzdirdecrypt", 0700);
104 //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirdecrypt");
105 filename=strdup("/tmp/fuzzdirdecrypt/fuzz.gpg");
106 if (!filename) {
107 free(ctrlGlobal);
108 return 0;
109 }
110 fd = open("/tmp/fuzzdirdecrypt/fuzz.gpg", O_RDWR | O_CREAT, 0600);
111 if (fd == -1) {
112 free(ctrlGlobal);
113 free(filename);
114 return 0;
115 }
116 gnupg_set_homedir("/tmp/fuzzdirdecrypt/");
117 if (keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG,
118 KEYDB_RESOURCE_FLAG_DEFAULT) != GPG_ERR_NO_ERROR) {
119 free(filename);
120 free(ctrlGlobal);
121 close(fd);
122 return 0;
123 }
124 if (setup_trustdb (1, NULL) != GPG_ERR_NO_ERROR) {
125 free(filename);
126 free(ctrlGlobal);
127 close(fd);
128 return 0;
129 }
130 //populate /tmp/fuzzdirdecrypt/ as homedir ~/.gnupg
131 strlist_t sl = NULL;
132 public_key_list (ctrlGlobal, sl, 0, 0);
133 free_strlist(sl);
134 //no output for stderr
135 log_set_file("/dev/null");
136 gcry_set_log_handler (my_gcry_logger, NULL);
137 gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
138 //overwrite output file
139 opt.batch = 1;
140 opt.answer_yes = 1;
141 initialized = true;
142 }
143
144 memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
145 ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
146 if (Size > MAX_LEN) {
147 // limit maximum size to avoid long computing times
148 Size = MAX_LEN;
149 }
150
151 if (ftruncate(fd, Size) == -1) {
152 return 0;
153 }
154 if (lseek (fd, 0, SEEK_SET) < 0) {
155 return 0;
156 }
157 if (write (fd, Data, Size) != Size) {
158 return 0;
159 }
160
161 decrypt_messages(ctrlGlobal, 1, &filename);
162 gpg_deinit_default_ctrl (ctrlGlobal);
163 memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
164 ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
165 decrypt_message(ctrlGlobal, filename);
166 gpg_deinit_default_ctrl (ctrlGlobal);
167
168 return 0;
169 }
170