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 // 8kb should be enough ;-)
42 #define MAX_LEN 0x2000
43
44 static bool initialized = false;
45 ctrl_t ctrlGlobal;
46 int fd;
47 char *filename;
48
49 //hack not to include gpg.c which has main function
50 int g10_errors_seen = 0;
51
52 void
g10_exit(int rc)53 g10_exit( int rc )
54 {
55 gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
56 gcry_control (GCRYCTL_TERM_SECMEM );
57 exit (rc);
58 }
59
60 static void
gpg_deinit_default_ctrl(ctrl_t ctrl)61 gpg_deinit_default_ctrl (ctrl_t ctrl)
62 {
63 #ifdef USE_TOFU
64 tofu_closedbs (ctrl);
65 #endif
66 gpg_dirmngr_deinit_session_data (ctrl);
67
68 keydb_release (ctrl->cached_getkey_kdb);
69 }
70
71 static void
my_gcry_logger(void * dummy,int level,const char * format,va_list arg_ptr)72 my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr)
73 {
74 return;
75 }
76
unlink_cb(const char * fpath,const struct stat * sb,int typeflag)77 static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag)
78 {
79 if (typeflag == FTW_F){
80 unlink(fpath);
81 }
82 return 0;
83 }
84
rmrfdir(char * path)85 static void rmrfdir(char *path)
86 {
87 ftw(path, unlink_cb, 16);
88 if (rmdir(path) != 0) {
89 printf("failed rmdir, errno=%d\n", errno);
90 }
91 }
92
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)93 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
94 if (! initialized) {
95 ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal));
96 if (!ctrlGlobal) {
97 exit(1);
98 }
99 //deletes previous tmp dir and (re)create it as a ramfs
100 //system("umount /tmp/fuzzdirimport");
101 rmrfdir("/tmp/fuzzdirimport");
102 if (mkdir("/tmp/fuzzdirimport", 0700) < 0) {
103 printf("failed mkdir, errno=%d\n", errno);
104 if (errno != EEXIST) {
105 return 0;
106 }
107 }
108 //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirimport");
109 filename=strdup("/tmp/fuzzdirimport/fuzz.gpg");
110 if (!filename) {
111 free(ctrlGlobal);
112 return 0;
113 }
114 fd = open(filename, O_RDWR | O_CREAT, 0666);
115 if (fd == -1) {
116 free(filename);
117 free(ctrlGlobal);
118 printf("failed open, errno=%d\n", errno);
119 return 0;
120 }
121 gnupg_set_homedir("/tmp/fuzzdirimport/");
122 gpg_error_t gpgerr = keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT);
123 if (gpgerr != GPG_ERR_NO_ERROR) {
124 free(filename);
125 free(ctrlGlobal);
126 close(fd);
127 printf("failed keydb_add_resource, errno=%d\n", gpgerr);
128 return 0;
129 }
130 gpgerr = setup_trustdb (1, NULL);
131 if (gpgerr != GPG_ERR_NO_ERROR) {
132 free(filename);
133 free(ctrlGlobal);
134 close(fd);
135 printf("failed setup_trustdb, errno=%d\n", gpgerr);
136 return 0;
137 }
138 //populate /tmp/fuzzdirimport/ as homedir ~/.gnupg
139 strlist_t sl = NULL;
140 public_key_list (ctrlGlobal, sl, 0, 0);
141 free_strlist(sl);
142 //no output for stderr
143 log_set_file("/dev/null");
144 gcry_set_log_handler (my_gcry_logger, NULL);
145 gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
146 initialized = true;
147 }
148
149 memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
150 ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
151 if (Size > MAX_LEN) {
152 // limit maximum size to avoid long computing times
153 Size = MAX_LEN;
154 }
155
156 if (ftruncate(fd, Size) == -1) {
157 return 0;
158 }
159 if (lseek (fd, 0, SEEK_SET) < 0) {
160 return 0;
161 }
162 if (write (fd, Data, Size) != Size) {
163 return 0;
164 }
165
166 import_keys (ctrlGlobal, &filename, 1, NULL, IMPORT_REPAIR_KEYS, 0, NULL);
167 gpg_deinit_default_ctrl (ctrlGlobal);
168 /*memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
169 ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
170 PKT_public_key pk;
171 get_pubkey_fromfile (ctrlGlobal, &pk, filename);
172 release_public_key_parts (&pk);
173 gpg_deinit_default_ctrl (ctrlGlobal);*/
174
175 return 0;
176 }
177