mirror of https://github.com/google/oss-fuzz.git
259 lines
7.4 KiB
C
259 lines
7.4 KiB
C
/* Copyright 2021 Google LLC
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
#include "syshead.h"
|
|
|
|
#include <openssl/x509.h>
|
|
#include <openssl/x509v3.h>
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/err.h>
|
|
|
|
#include "fuzz_verify_cert.h"
|
|
#include "misc.h"
|
|
#include "manage.h"
|
|
#include "otime.h"
|
|
#include "base64.h"
|
|
#include "ssl_verify.h"
|
|
#include "ssl_verify_backend.h"
|
|
|
|
#include "fuzz_randomizer.h"
|
|
|
|
static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
|
|
size_t key_len) {
|
|
//const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
|
|
|
|
cipher_ctx_t *cipher_kt = ctx->cipher;
|
|
/* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
|
|
if (cipher_ctx_mode_aead(cipher_kt)) {
|
|
size_t impl_iv_len = 0;
|
|
ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN);
|
|
impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type);
|
|
ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
|
|
ASSERT(impl_iv_len <= key_len);
|
|
memcpy(ctx->implicit_iv, key, impl_iv_len);
|
|
ctx->implicit_iv_len = impl_iv_len;
|
|
}
|
|
}
|
|
|
|
static int init_frame(struct frame *frame) {
|
|
frame->link_mtu = fuzz_randomizer_get_int(100, 1000);
|
|
frame->extra_buffer = fuzz_randomizer_get_int(100, 1000);
|
|
frame->link_mtu_dynamic = fuzz_randomizer_get_int(100, 1000);
|
|
frame->extra_frame = fuzz_randomizer_get_int(100, 1000);
|
|
frame->extra_tun = fuzz_randomizer_get_int(100, 1000);
|
|
frame->extra_link = fuzz_randomizer_get_int(100, 1000);
|
|
frame->align_flags = 0;
|
|
frame->align_adjust = 0;
|
|
if (TUN_MTU_SIZE(frame) <= 0) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
|
OPENSSL_malloc_init();
|
|
SSL_library_init();
|
|
ERR_load_crypto_strings();
|
|
|
|
OpenSSL_add_all_algorithms();
|
|
OpenSSL_add_ssl_algorithms();
|
|
|
|
SSL_load_error_strings();
|
|
return 0;
|
|
}
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
fuzz_random_init(data, size);
|
|
fuzz_success = 1;
|
|
bool key_ctx_dec_initialized = false;
|
|
bool key_ctx_enc_initialized = false;
|
|
struct key_ctx key_ctx_dec;
|
|
memset(&key_ctx_dec, 0, sizeof(struct key_ctx));
|
|
struct key_ctx key_ctx_enc;
|
|
memset(&key_ctx_enc, 0, sizeof(struct key_ctx));
|
|
|
|
struct gc_arena gc;
|
|
struct tls_session *session = NULL;
|
|
X509 *x509 = NULL;
|
|
gc = gc_new();
|
|
|
|
gb_init();
|
|
|
|
// Read key file
|
|
struct key2 key2;
|
|
char *keydata = gb_get_random_string();
|
|
read_key_file(&key2, keydata, RKF_INLINE);
|
|
|
|
// init key type
|
|
struct key_type kt;
|
|
memset(&kt, 0, sizeof(struct key_type));
|
|
|
|
char *ciphername = gb_get_random_string();
|
|
char *authname = gb_get_random_string();
|
|
bool key_type_initialized = false;
|
|
|
|
if (strcmp(ciphername, "AES-256-GCM") == 0 ||
|
|
strcmp(ciphername, "AES-128-GCM") == 0 ||
|
|
strcmp(ciphername, "AES-192-GCM") == 0 ||
|
|
strcmp(ciphername, "CAMELLIA-128-CFB128") == 0) {
|
|
|
|
int v = fuzz_randomizer_get_int(0, 1);
|
|
if (v == 0) {
|
|
init_key_type(&kt, ciphername, authname, true, 0);
|
|
} else {
|
|
init_key_type(&kt, ciphername, authname, false, 0);
|
|
}
|
|
key_type_initialized = true;
|
|
}
|
|
|
|
if (fuzz_success == 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
// Generate key.
|
|
// Identify which one we should do, read or generate a random key.
|
|
int c = fuzz_randomizer_get_int(0, 1);
|
|
const uint8_t d[1024];
|
|
int key_read = 0;
|
|
struct key key;
|
|
if (c == 0) {
|
|
if (fuzz_get_random_data(d, 1024) != 1024) {
|
|
struct buffer buf = alloc_buf(1024);
|
|
buf_write(&buf, d, 1024);
|
|
if (read_key(&key, &kt, &buf) == 1) {
|
|
key_read = 1;
|
|
}
|
|
free_buf(&buf);
|
|
}
|
|
}
|
|
else {
|
|
if (key_type_initialized == true) {
|
|
generate_key_random(&key, &kt);
|
|
}
|
|
}
|
|
|
|
if (fuzz_success == 0) {
|
|
goto cleanup;
|
|
}
|
|
key_read = 1;
|
|
|
|
// init decryption context
|
|
if (key_type_initialized && key_read) {
|
|
init_key_ctx(&key_ctx_dec, &key, &kt, OPENVPN_OP_DECRYPT, "x");
|
|
key_ctx_update_implicit_iv(&key_ctx_dec, &(key.hmac), MAX_HMAC_KEY_LENGTH);
|
|
key_ctx_dec_initialized = true;
|
|
}
|
|
|
|
// init encryption context
|
|
if (key_type_initialized && key_read) {
|
|
init_key_ctx(&key_ctx_enc, &key, &kt, OPENVPN_OP_DECRYPT, "x");
|
|
key_ctx_update_implicit_iv(&key_ctx_enc, &(key.hmac), MAX_HMAC_KEY_LENGTH);
|
|
key_ctx_enc_initialized = true;
|
|
}
|
|
|
|
// perform encryption
|
|
struct frame frame;
|
|
memset(&frame, 0, sizeof(struct frame));
|
|
if (key_ctx_enc_initialized == true && key_ctx_dec_initialized == true &&
|
|
init_frame(&frame) == 0) {
|
|
struct crypto_options opt;
|
|
memset(&opt, 0, sizeof(opt));
|
|
opt.pid_persist = NULL;
|
|
opt.key_ctx_bi.encrypt = key_ctx_enc;
|
|
opt.key_ctx_bi.decrypt = key_ctx_dec;
|
|
opt.key_ctx_bi.initialized = true;
|
|
opt.packet_id.rec.initialized = true;
|
|
opt.packet_id.rec.seq_list = NULL;
|
|
opt.packet_id.rec.name = NULL;
|
|
|
|
void *buf_p;
|
|
|
|
struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
|
struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
|
struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
|
|
struct buffer buf = clear_buf();
|
|
|
|
int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
|
|
|
|
ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
|
|
ASSERT(buf_init(&src, 0));
|
|
src.len = x;
|
|
ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
|
|
|
|
buf = work;
|
|
buf_p = buf_write_alloc(&buf, BLEN(&src));
|
|
ASSERT(buf_p);
|
|
memcpy(buf_p, BPTR(&src), BLEN(&src));
|
|
|
|
ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(&(frame))));
|
|
|
|
openvpn_encrypt(&buf, encrypt_workspace, &opt);
|
|
}
|
|
|
|
// perform decryption
|
|
memset(&frame, 0, sizeof(struct frame));
|
|
if (key_ctx_dec_initialized == true && key_ctx_enc_initialized == true &&
|
|
init_frame(&frame) == 0) {
|
|
struct crypto_options opt;
|
|
memset(&opt, 0, sizeof(opt));
|
|
opt.pid_persist = NULL;
|
|
opt.key_ctx_bi.encrypt = key_ctx_enc;
|
|
opt.key_ctx_bi.decrypt = key_ctx_dec;
|
|
opt.key_ctx_bi.initialized = true;
|
|
opt.packet_id.rec.initialized = true;
|
|
opt.packet_id.rec.seq_list = NULL;
|
|
opt.packet_id.rec.name = NULL;
|
|
|
|
void *buf_p;
|
|
|
|
struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
|
struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
|
struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
|
|
struct buffer buf = clear_buf();
|
|
|
|
int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
|
|
|
|
ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
|
|
ASSERT(buf_init(&src, 0));
|
|
src.len = x;
|
|
ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
|
|
|
|
buf = work;
|
|
buf_p = buf_write_alloc(&buf, BLEN(&src));
|
|
ASSERT(buf_p);
|
|
memcpy(buf_p, BPTR(&src), BLEN(&src));
|
|
|
|
ASSERT(buf_init(&decrypt_workspace, FRAME_HEADROOM(&(frame))));
|
|
|
|
openvpn_decrypt(&buf, decrypt_workspace, &opt, &frame, BPTR(&buf));
|
|
}
|
|
|
|
cleanup:
|
|
// cleanup
|
|
gc_free(&gc);
|
|
|
|
if (key_ctx_dec_initialized == true) {
|
|
free_key_ctx(&key_ctx_dec);
|
|
}
|
|
|
|
if (key_ctx_enc_initialized == true) {
|
|
free_key_ctx(&key_ctx_enc);
|
|
}
|
|
fuzz_random_destroy();
|
|
|
|
gb_cleanup();
|
|
|
|
return 0;
|
|
}
|