blob: dc8b0705cd4e6b9ce87cbafb421aa265521c2bfb [file] [log] [blame]
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include "picotls.h"
#include "picotls/asn1.h"
#include "picotls/minicrypto.h"
static struct feeder {
const uint8_t *data;
size_t size;
} feeder;
static void feeder_init(const uint8_t *orig_data, size_t orig_size)
{
feeder.data = orig_data;
feeder.size = orig_size;
}
static uint8_t feeder_next_byte(void)
{
if (feeder.size == 0) {
return 0;
}
uint8_t byte = *feeder.data;
--feeder.size;
++feeder.data;
return byte;
}
void count_printf(void *ctx, const char *format, ...)
{
int *c = ctx;
c++;
return;
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
int i, counter, indefinite_length, decode_error;
ptls_minicrypto_log_ctx_t ctx = {&counter, count_printf};
uint8_t *bytes, expected_type;
size_t last_byte, bytes_max, byte_index;
uint32_t length;
uint8_t ret;
feeder_init(Data, Size);
bytes_max = (feeder_next_byte() << 8) + feeder_next_byte();
if (bytes_max == 0)
return 0;
/* fill the test buffer */
bytes = malloc(bytes_max);
for (i = 0; i < bytes_max; i++) {
bytes[i] = feeder_next_byte();
}
ret = feeder_next_byte() % 4;
/* fuzz either ptls_asn1_validation or ptls_asn1_get_expected_type_and_length */
if (ret == 0) {
ptls_asn1_validation(bytes, bytes_max, &ctx);
} else if (ret == 1) {
byte_index = (feeder_next_byte() << 8) + feeder_next_byte();
byte_index = byte_index % bytes_max;
expected_type = feeder_next_byte();
ptls_asn1_get_expected_type_and_length(bytes, bytes_max, byte_index, expected_type, &length, &indefinite_length, &last_byte,
&decode_error, &ctx);
} else if (ret == 2 || ret == 3) {
ptls_context_t ctx = {};
char fname[] = "/tmp/XXXXXXXX";
int fd, ret;
fd = mkstemp(fname);
if (fd < 0) {
goto out;
}
ret = write(fd, bytes, bytes_max);
if (ret != bytes_max) {
goto out2;
}
ctx.random_bytes = ptls_minicrypto_random_bytes;
ctx.get_time = &ptls_get_time;
ctx.key_exchanges = ptls_minicrypto_key_exchanges;
ctx.cipher_suites = ptls_minicrypto_cipher_suites;
if (ret == 2) {
ptls_load_certificates(&ctx, fname);
if (ctx.certificates.list) {
for (i = 0; i < ctx.certificates.count; i++) {
if (ctx.certificates.list[i].base)
free(ctx.certificates.list[i].base);
}
free(ctx.certificates.list);
}
} else {
ptls_minicrypto_load_private_key(&ctx, fname);
}
out2:
close(fd);
unlink(fname);
}
out:
free(bytes);
return 0;
}