• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2021 Google LLC
2 Licensed under the Apache License, Version 2.0 (the "License");
3 you may not use this file except in compliance with the License.
4 You may obtain a copy of the License at
5       http://www.apache.org/licenses/LICENSE-2.0
6 Unless required by applicable law or agreed to in writing, software
7 distributed under the License is distributed on an "AS IS" BASIS,
8 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 See the License for the specific language governing permissions and
10 limitations under the License.
11 */
12 
13 
14 #include "config.h"
15 #include "syshead.h"
16 
17 #include <openssl/x509.h>
18 #include <openssl/x509v3.h>
19 #include <openssl/ssl.h>
20 #include <openssl/err.h>
21 
22 #include "fuzz_verify_cert.h"
23 #include "misc.h"
24 #include "manage.h"
25 #include "otime.h"
26 #include "base64.h"
27 #include "ssl_verify.h"
28 #include "ssl_verify_backend.h"
29 
30 #include "fuzz_randomizer.h"
31 
key_ctx_update_implicit_iv(struct key_ctx * ctx,uint8_t * key,size_t key_len)32 static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
33                                        size_t key_len) {
34   const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
35 
36   /* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
37   if (cipher_kt_mode_aead(cipher_kt)) {
38     size_t impl_iv_len = 0;
39     ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN);
40     impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type);
41     ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
42     ASSERT(impl_iv_len <= key_len);
43     memcpy(ctx->implicit_iv, key, impl_iv_len);
44     ctx->implicit_iv_len = impl_iv_len;
45   }
46 }
47 
init_frame(struct frame * frame)48 static int init_frame(struct frame *frame) {
49   frame->link_mtu = fuzz_randomizer_get_int(100, 1000);
50   frame->extra_buffer = fuzz_randomizer_get_int(100, 1000);
51   frame->link_mtu_dynamic = fuzz_randomizer_get_int(100, 1000);
52   frame->extra_frame = fuzz_randomizer_get_int(100, 1000);
53   frame->extra_tun = fuzz_randomizer_get_int(100, 1000);
54   frame->extra_link = fuzz_randomizer_get_int(100, 1000);
55   frame->align_flags = 0;
56   frame->align_adjust = 0;
57   if (TUN_MTU_SIZE(frame) <= 0) {
58     return -1;
59   }
60   return 0;
61 }
62 
LLVMFuzzerInitialize(int * argc,char *** argv)63 int LLVMFuzzerInitialize(int *argc, char ***argv) {
64   OPENSSL_malloc_init();
65   SSL_library_init();
66   ERR_load_crypto_strings();
67 
68   OpenSSL_add_all_algorithms();
69   OpenSSL_add_ssl_algorithms();
70 
71   SSL_load_error_strings();
72   return 0;
73 }
74 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)75 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
76   fuzz_random_init(data, size);
77   fuzz_success = 1;
78   bool key_ctx_dec_initialized = false;
79   bool key_ctx_enc_initialized = false;
80   struct key_ctx key_ctx_dec;
81   memset(&key_ctx_dec, 0, sizeof(struct key_ctx));
82   struct key_ctx key_ctx_enc;
83   memset(&key_ctx_enc, 0, sizeof(struct key_ctx));
84 
85   struct gc_arena gc;
86   struct tls_session *session = NULL;
87   X509 *x509 = NULL;
88   gc = gc_new();
89 
90   gb_init();
91 
92   // Read key file
93   struct key2 key2;
94   char *keydata = gb_get_random_string();
95   read_key_file(&key2, keydata, RKF_INLINE);
96 
97   // init key type
98   struct key_type kt;
99   memset(&kt, 0, sizeof(struct key_type));
100 
101   char *ciphername = gb_get_random_string();
102   char *authname = gb_get_random_string();
103   bool key_type_initialized = false;
104 
105   if (strcmp(ciphername, "AES-256-GCM") == 0 ||
106       strcmp(ciphername, "AES-128-GCM") == 0 ||
107       strcmp(ciphername, "AES-192-GCM") == 0 ||
108       strcmp(ciphername, "CAMELLIA-128-CFB128") == 0) {
109 
110     int v = fuzz_randomizer_get_int(0, 1);
111     if (v == 0) {
112       init_key_type(&kt, ciphername, authname, true, 0);
113     } else {
114       init_key_type(&kt, ciphername, authname, false, 0);
115     }
116     key_type_initialized = true;
117   }
118 
119   if (fuzz_success == 0) {
120     goto cleanup;
121   }
122 
123   // Generate key.
124   // Identify which one we should do, read or generate a random key.
125   int c = fuzz_randomizer_get_int(0, 1);
126   const uint8_t d[1024];
127   int key_read = 0;
128   struct key key;
129   if (c == 0) {
130     if (fuzz_get_random_data(d, 1024) != 1024) {
131       struct buffer buf = alloc_buf(1024);
132       buf_write(&buf, d, 1024);
133       if (read_key(&key, &kt, &buf) == 1) {
134         key_read = 1;
135       }
136       free_buf(&buf);
137     }
138   }
139   else {
140     if (key_type_initialized == true) {
141       generate_key_random(&key, &kt);
142     }
143   }
144 
145   if (fuzz_success == 0) {
146     goto cleanup;
147   }
148   key_read = 1;
149 
150   // init decryption context
151   if (key_type_initialized && key_read) {
152     init_key_ctx(&key_ctx_dec, &key, &kt, OPENVPN_OP_DECRYPT, "x");
153     key_ctx_update_implicit_iv(&key_ctx_dec, &(key.hmac), MAX_HMAC_KEY_LENGTH);
154     key_ctx_dec_initialized = true;
155   }
156 
157   // init encryption context
158   if (key_type_initialized && key_read) {
159     init_key_ctx(&key_ctx_enc, &key, &kt, OPENVPN_OP_DECRYPT, "x");
160     key_ctx_update_implicit_iv(&key_ctx_enc, &(key.hmac), MAX_HMAC_KEY_LENGTH);
161     key_ctx_enc_initialized = true;
162   }
163 
164   // perform encryption
165   struct frame frame;
166   memset(&frame, 0, sizeof(struct frame));
167   if (key_ctx_enc_initialized == true && key_ctx_dec_initialized == true &&
168       init_frame(&frame) == 0) {
169     struct crypto_options opt;
170     memset(&opt, 0, sizeof(opt));
171     opt.pid_persist = NULL;
172     opt.key_ctx_bi.encrypt = key_ctx_enc;
173     opt.key_ctx_bi.decrypt = key_ctx_dec;
174     opt.key_ctx_bi.initialized = true;
175     opt.packet_id.rec.initialized = true;
176     opt.packet_id.rec.seq_list = NULL;
177     opt.packet_id.rec.name = NULL;
178 
179     void *buf_p;
180 
181     struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
182     struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
183     struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
184     struct buffer buf = clear_buf();
185 
186     int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
187 
188     ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
189     ASSERT(buf_init(&src, 0));
190     src.len = x;
191     ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
192 
193     buf = work;
194     buf_p = buf_write_alloc(&buf, BLEN(&src));
195     ASSERT(buf_p);
196     memcpy(buf_p, BPTR(&src), BLEN(&src));
197 
198     ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(&(frame))));
199 
200     openvpn_encrypt(&buf, encrypt_workspace, &opt);
201   }
202 
203   // perform decryption
204   memset(&frame, 0, sizeof(struct frame));
205   if (key_ctx_dec_initialized == true && key_ctx_enc_initialized == true &&
206       init_frame(&frame) == 0) {
207     struct crypto_options opt;
208     memset(&opt, 0, sizeof(opt));
209     opt.pid_persist = NULL;
210     opt.key_ctx_bi.encrypt = key_ctx_enc;
211     opt.key_ctx_bi.decrypt = key_ctx_dec;
212     opt.key_ctx_bi.initialized = true;
213     opt.packet_id.rec.initialized = true;
214     opt.packet_id.rec.seq_list = NULL;
215     opt.packet_id.rec.name = NULL;
216 
217     void *buf_p;
218 
219     struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
220     struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
221     struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
222     struct buffer buf = clear_buf();
223 
224     int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
225 
226     ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
227     ASSERT(buf_init(&src, 0));
228     src.len = x;
229     ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
230 
231     buf = work;
232     buf_p = buf_write_alloc(&buf, BLEN(&src));
233     ASSERT(buf_p);
234     memcpy(buf_p, BPTR(&src), BLEN(&src));
235 
236     ASSERT(buf_init(&decrypt_workspace, FRAME_HEADROOM(&(frame))));
237 
238     openvpn_decrypt(&buf, decrypt_workspace, &opt, &frame, BPTR(&buf));
239   }
240 
241 cleanup:
242   // cleanup
243   gc_free(&gc);
244 
245   if (key_ctx_dec_initialized == true) {
246     free_key_ctx(&key_ctx_dec);
247   }
248 
249   if (key_ctx_enc_initialized == true) {
250     free_key_ctx(&key_ctx_enc);
251   }
252   fuzz_random_destroy();
253 
254   gb_cleanup();
255 
256   return 0;
257 }
258