From: markus Date: Mon, 29 May 2017 20:59:28 +0000 (+0000) Subject: fuzz the iked payload parser using the openssh unit-test framework X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a230c5a5ceb1ac11489695fd7cf6d70bd582abb3;p=openbsd fuzz the iked payload parser using the openssh unit-test framework from hshoexer --- diff --git a/regress/sbin/iked/parser/Makefile b/regress/sbin/iked/parser/Makefile new file mode 100644 index 00000000000..7bd3b966b63 --- /dev/null +++ b/regress/sbin/iked/parser/Makefile @@ -0,0 +1,37 @@ +# $OpenBSD: Makefile,v 1.1 2017/05/29 20:59:28 markus Exp $ + +WARNINGS=Yes + +.include +.include + +.PATH: ${.CURDIR}/../../../../sbin/iked \ + ${.CURDIR}/../../../../sbin/iked/${__objdir} + +PROG= test_parser +SRCS= tests.c common.c test_parser_fuzz.c ikev2_pld.c \ + imsg_util.c log.c util.c +SRCS+= ikev2_map.c eap_map.c + +LDADD= -lutil -lcrypto +DPADD+= ${LIBUTIL} ${LIBCRYPTO} +CFLAGS+= -I${.CURDIR}/../../../../sbin/iked +CFLAGS+= -I${.CURDIR}/../../../../sbin/iked/${__objdir} +CFLAGS+= -Wno-missing-field-initializers + +CFLAGS+= -I${.CURDIR}/../test_helper + +.if exists(${.CURDIR}/../test_helper/${__objdir}) +LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper +DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a +.else +LDADD+=-L${.CURDIR}/../test_helper -ltest_helper +DPADD+=${.CURDIR}/../test_helper/libtest_helper.a +.endif + +REGRESS_TARGETS=stamp-regress-${PROG} + +stamp-regress-${PROG}: ${PROG} + ./${PROG} && touch stamp-regress-${PROG} + +.include diff --git a/regress/sbin/iked/parser/common.c b/regress/sbin/iked/parser/common.c new file mode 100644 index 00000000000..904af476b3f --- /dev/null +++ b/regress/sbin/iked/parser/common.c @@ -0,0 +1,187 @@ +/* $OpenBSD: common.c,v 1.1 2017/05/29 20:59:28 markus Exp $ */ +/* + * A bunch of stub functions so we can compile and link ikev2_pld.c + * in a standalone program for testing purposes. + * + * Placed in the public domain + */ + +#include +#include +#include +#include + +#include +#include + +#include "iked.h" +#include "types.h" +#include "test_helper.h" + +int eap_parse(struct iked *, struct iked_sa *, void *, int); +int ikev2_msg_frompeer(struct iked_message *); +int ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *, + u_int8_t, u_int8_t, int); +void ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *); +struct iked_childsa * + childsa_lookup(struct iked_sa *, u_int64_t, u_int8_t); +int ikev2_childsa_delete(struct iked *, struct iked_sa *, + u_int8_t, u_int64_t, u_int64_t *, int); +int sa_stateok(struct iked_sa *, int); +void sa_state(struct iked *, struct iked_sa *, int); +void ikev2_disable_rekeying(struct iked *, struct iked_sa *); +void ikev2_init_ike_sa(struct iked *, void *); +struct group * + group_get(u_int32_t); +void timer_set(struct iked *, struct iked_timer *, + void (*)(struct iked *, void *), void *); +void timer_add(struct iked *, struct iked_timer *, int); +void timer_del(struct iked *, struct iked_timer *); +ssize_t ikev2_nat_detection(struct iked *, struct iked_message *, + void *, size_t, u_int); +int ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *, + u_int8_t, u_int8_t *, size_t, enum privsep_procid); +int ikev2_print_id(struct iked_id *, char *, size_t); +struct iked_transform * + config_add_transform(struct iked_proposal *, u_int, u_int, u_int, + u_int); +struct iked_proposal * + config_add_proposal(struct iked_proposals *, u_int, u_int); +int ikev2_send_informational(struct iked *, struct iked_message *); +struct ibuf * + ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *, + struct ibuf *); + +int +eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) +{ + return (0); +} + +int +ikev2_msg_frompeer(struct iked_message *msg) +{ + return (0); +} + +int +ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf, + u_int8_t firstpayload, u_int8_t exchange, int response) +{ + return (0); +} + +void +ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa) +{ +} + +struct iked_childsa * +childsa_lookup(struct iked_sa *a, u_int64_t b, u_int8_t c) +{ + return (NULL); +} + +int +ikev2_childsa_delete(struct iked *a, struct iked_sa *b, u_int8_t c, + u_int64_t d, u_int64_t *e , int f) +{ + return (0); +} + +int +sa_stateok(struct iked_sa *a, int b) +{ + return (0); +} + +void +sa_state(struct iked * a, struct iked_sa *b, int c) +{ +} + +void +ikev2_disable_rekeying(struct iked *a, struct iked_sa *b) +{ +} + +void +ikev2_init_ike_sa(struct iked *a, void *b) +{ +} + +const struct group_id * +group_getid(u_int32_t id) +{ + return (NULL); +} + +void +timer_set(struct iked *env, struct iked_timer *tmr, + void (*cb)(struct iked *, void *), void *arg) +{ +} + +void +timer_add(struct iked *env, struct iked_timer *tmr, int timeout) +{ +} + +void +timer_del(struct iked *env, struct iked_timer *tmr) +{ +} + +ssize_t +ikev2_nat_detection(struct iked *env, struct iked_message *msg, + void *ptr, size_t len, u_int type) +{ + return (0); +} + +int +ca_setreq(struct iked *env, struct iked_sa *sh, + struct iked_static_id *localid, u_int8_t type, u_int8_t *data, + size_t len, enum privsep_procid procid) +{ + return (0); +} + +int +ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen) +{ + return (0); +} + +struct iked_transform * +config_add_transform(struct iked_proposal *prop, u_int type, + u_int id, u_int length, u_int keylength) +{ + return (NULL); +} + +struct iked_proposal * +config_add_proposal(struct iked_proposals *head, u_int id, u_int proto) +{ + return (NULL); +} + +int +ikev2_send_informational(struct iked *env, struct iked_message *msg) +{ + return (0); +} + +struct ibuf * +ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa, + struct ibuf *msg, struct ibuf *src) +{ + ASSERT_PTR_NE(src, NULL); + + /* + * Free src as caller uses ikev2_msg_decrypt() like this: + * src = ikev2_msg_decrypt(..., src); + */ + ibuf_free(src); + return (NULL); +} diff --git a/regress/sbin/iked/parser/test_parser_fuzz.c b/regress/sbin/iked/parser/test_parser_fuzz.c new file mode 100644 index 00000000000..52c3729c6eb --- /dev/null +++ b/regress/sbin/iked/parser/test_parser_fuzz.c @@ -0,0 +1,748 @@ +/* $OpenBSD: test_parser_fuzz.c,v 1.1 2017/05/29 20:59:28 markus Exp $ */ +/* + * Fuzz tests for payload parsing + * + * Placed in the public domain + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "iked.h" +#include "ikev2.h" +#include "test_helper.h" + +extern int ikev2_pld_payloads(struct iked *, struct iked_message *, + size_t, size_t, u_int); + +void parser_fuzz_tests(void); + +u_int8_t cookies[] = { + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, /* initator cookie */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* responder cookie */ +}; + +u_int8_t genhdr[] = { + 0x00, 0x20, 0x22, 0x08, /* next, major/minor, exchange type, flags */ + 0x00, 0x00, 0x00, 0x00, /* message ID */ + 0x00, 0x00, 0x00, 0x00 /* total length */ +}; + +u_int8_t sa_pld[] = { + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00 +}; + +u_int8_t saxform_pld[] = { + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3c, + 0x01, 0x01, 0x00, 0x06, 0x03, 0x00, 0x00, 0x08, + 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x0c, + 0x01, 0x00, 0x00, 0x0c, 0x80, 0x0e, 0x00, 0xc0, + 0x03, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x0e, + 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, + 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x01 +}; + +u_int8_t ke_pld[] = { + 0x00, 0x00, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x16, 0xcb, + 0x68, 0xaf, 0x63, 0xfe, 0xb0, 0x58, 0x49, 0x0e, 0x7f, 0x85, + 0x60, 0x53, 0x80, 0xae, 0x3f, 0x82, 0xf3, 0x35, 0x21, 0xd5, + 0xae, 0x09, 0x1c, 0xfa, 0x68, 0xc2, 0xfb, 0x4b, 0xb3, 0x84, + 0xda, 0xaf, 0x6e, 0xe2, 0x5e, 0xc5, 0xb6, 0x8c, 0x35, 0x3c, + 0xec, 0x58, 0x7f, 0xa9, 0xf8, 0xa4, 0x24, 0xf3, 0xf8, 0xf4, + 0x65, 0x59, 0x8c, 0x15, 0x4d, 0x2c, 0xf1, 0x5d, 0xeb, 0x57, + 0x68, 0xfe, 0x75, 0x61, 0x5a, 0x80, 0x96, 0xa4, 0x0a, 0xad, + 0x75, 0x71, 0xd8, 0xe0, 0x06, 0xbc, 0xde, 0x16, 0x6d, 0x1e, + 0xd9, 0x5d, 0x2c, 0x00, 0x66, 0x43, 0x82, 0xe4, 0x6f, 0x5f, + 0x95, 0xe7, 0x9b, 0xfd, 0xf2, 0xe2, 0xcb, 0xc5, 0xf1, 0x52, + 0xdd, 0x3b, 0xed, 0x88, 0xd4, 0xa9, 0x13, 0x4e, 0x42, 0xe8, + 0x60, 0x2d, 0x3c, 0xf6, 0xc8, 0xf0, 0x70, 0x42, 0xfa, 0x33, + 0x7f, 0x28, 0xdf, 0x6b, 0x79, 0x2c, 0x79, 0x8f, 0xc0, 0x5d, + 0x81, 0x7a, 0x62, 0xdb, 0xd4, 0x44, 0x3a, 0x3c, 0x21, 0xbf, + 0x85, 0xc8, 0x0b, 0x8c, 0x77, 0x72, 0xe9, 0xfb, 0x50, 0x5c, + 0x03, 0xa6, 0xb2, 0x3f, 0x17, 0x4a, 0xd1, 0xb3, 0x01, 0x30, + 0xad, 0xe4, 0xfa, 0xe2, 0xba, 0x6f, 0x22, 0x83, 0xf4, 0xde, + 0x38, 0x43, 0xe8, 0x27, 0x00, 0xb8, 0x95, 0xbe, 0x03, 0x8f, + 0xcd, 0xd3, 0x72, 0xed, 0xa5, 0xed, 0x8d, 0xf4, 0x68, 0x98, + 0xef, 0x59, 0xcc, 0xfb, 0x54, 0x89, 0xde, 0xa9, 0xd4, 0x88, + 0xcd, 0xb9, 0xca, 0x09, 0xd3, 0xd5, 0x25, 0xb1, 0x8c, 0x58, + 0x12, 0x9c, 0x69, 0x03, 0x72, 0x00, 0xc9, 0xca, 0x95, 0x8a, + 0xce, 0x0d, 0xd2, 0xc8, 0x25, 0xe7, 0x7c, 0xed, 0x5e, 0xee, + 0x35, 0x01, 0xfc, 0x00, 0x56, 0xed, 0xf3, 0x8d, 0x81, 0x6c, + 0x3e, 0x86, 0x6a, 0x40, 0xac, 0xc7, 0x9c, 0x7a, 0xbf, 0x9f, + 0x8e, 0x1f, 0xd8, 0x60 +}; + +u_int8_t nonce_pld[] = { + 0x00, 0x00, 0x00, 0x24, 0x5f, 0x61, 0x42, 0x72, 0x7d, 0xb2, + 0xa8, 0xc1, 0xfe, 0xb1, 0x38, 0x2e, 0xb8, 0x75, 0xa7, 0xc1, + 0x1d, 0x8a, 0xa7, 0xb7, 0x9b, 0x92, 0xe2, 0x0e, 0x3a, 0x18, + 0x20, 0xb6, 0x16, 0xf3, 0x35, 0x67, +}; + +u_int8_t notify_pld[] = { + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x04, 0xc7, 0xa0, + 0x68, 0x68, 0x09, 0x0a, 0x7f, 0x12, 0x0b, 0x13, 0xd3, 0x2f, + 0xde, 0x64, 0x8b, 0xf1, 0xc3, 0x3c, 0x79, 0x8f, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x40, 0x05, 0x9f, 0xbc, 0x8c, 0xd0, + 0x91, 0x5e, 0xa0, 0x87, 0x81, 0xab, 0x4f, 0xa1, 0x8a, 0xa7, + 0xa8, 0xf9, 0xeb, 0xdf, 0x9f, 0x2c +}; + +u_int8_t id_pld[] = { + 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, + 0xac, 0x12, 0x7d, 0x01 +}; + +u_int8_t cert_pld[] = { + 0x00, 0x00, 0x01, 0x10, 0x0b, 0x00, 0x00, 0x00, + 0x30, 0x82, 0x01, 0x0c, 0x02, 0x82, 0x01, 0x01, 0x00, 0x8a, + 0x26, 0xf8, 0x9e, 0xe8, 0x09, 0x11, 0x6b, 0x3d, 0x00, 0xd3, + 0x25, 0xf8, 0x9f, 0xe8, 0x09, 0x11, 0x6b, 0x3d, 0x10, 0xd3, + 0x0b, 0x9a, 0xb0, 0xb7, 0xe4, 0x3e, 0x40, 0x59, 0xd7, 0x51, + 0x03, 0xaf, 0x09, 0x79, 0x1b, 0x0d, 0x63, 0x66, 0x28, 0xaa, + 0x97, 0xc8, 0x20, 0x4b, 0x28, 0x9b, 0x5e, 0x8c, 0xa9, 0x8f, + 0x73, 0x81, 0xb4, 0xfa, 0xf4, 0xdd, 0x05, 0x69, 0x0b, 0x71, + 0x72, 0xd8, 0xbb, 0xac, 0x4b, 0x6d, 0x67, 0x5a, 0xa2, 0x63, + 0x5d, 0x6d, 0x27, 0xc5, 0xf4, 0xe6, 0x0a, 0xbd, 0x2b, 0x0a, + 0x64, 0xb2, 0xcf, 0x59, 0x63, 0x9b, 0x5c, 0x4f, 0x26, 0x36, + 0xe3, 0x10, 0x70, 0x3c, 0x39, 0x77, 0x55, 0x07, 0x1c, 0x12, + 0xde, 0x60, 0x53, 0xa1, 0x70, 0xf4, 0xda, 0xfc, 0xcc, 0xec, + 0xad, 0x6d, 0x34, 0xad, 0xe2, 0x36, 0x10, 0x93, 0x59, 0x0c, + 0x81, 0x8d, 0x22, 0x7e, 0x57, 0xeb, 0x89, 0x26, 0xdb, 0x6e, + 0x99, 0x9a, 0xde, 0xbe, 0xad, 0xef, 0xca, 0xaf, 0xfe, 0xfe, + 0x99, 0x9a, 0xde, 0xbe, 0xad, 0xef, 0xca, 0xaf, 0xfe, 0xfe, + 0x6f, 0xd4, 0xe4, 0x63, 0x6c, 0x3e, 0x83, 0x09, 0xf4, 0x32, + 0x78, 0x3b, 0x71, 0xe9, 0x36, 0xb6, 0x92, 0xf6, 0xa8, 0x31, + 0x4d, 0x7c, 0xd0, 0xa1, 0x30, 0x55, 0xb6, 0x6b, 0x9e, 0xb7, + 0x41, 0xa8, 0x77, 0x6c, 0x96, 0xb8, 0xa2, 0x0c, 0x7d, 0x70, + 0xca, 0x51, 0xb9, 0xad, 0xc5, 0x75, 0xa7, 0xf1, 0x1e, 0x0e, + 0xca, 0x51, 0xb9, 0xad, 0xc5, 0x75, 0xa7, 0xf1, 0x1e, 0x0e, + 0xf2, 0xcf, 0x69, 0xbf, 0x20, 0xe9, 0x97, 0x05, 0xdd, 0xf3, + 0xf2, 0xcf, 0x69, 0xbf, 0x20, 0xe9, 0x97, 0x05, 0xdd, 0xf3, + 0x32, 0x58, 0x37, 0x8c, 0x5d, 0x02, 0x05, 0x00, 0xd1, 0x76, + 0x67, 0x01, 0x67, 0x75, 0x3b, 0xba, 0x45, 0xc2, 0xa2, 0x77, + 0x3b, 0x7e, 0xb4, 0x03, 0x88, 0x08, 0x93, 0xfe, 0x07, 0x51, + 0x8e, 0xcf +}; + +u_int8_t certreq_pld[] = { + 0x00, 0x00, 0x00, 0x05, 0x0b +}; + +u_int8_t auth_pld[] = { + 0x00, 0x00, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x34, 0x80, 0x52, 0x3c, 0x86, 0x1c, 0xfa, 0x9a, 0x2b, + 0x8b, 0xff, 0xbb, 0xb5, 0x0d, 0x6b, 0xa1, 0x62, 0x58, 0xd8, + 0x16, 0xaa, 0x15, 0xe4, 0x34, 0x24, 0xca, 0xc3, 0x09, 0x08, + 0x51, 0x69, 0x69, 0xef, 0xbd, 0xb7, 0xd4, 0xc5, 0x4f, 0x6c, + 0x12, 0xd5, 0xd0, 0x0b, 0xc7, 0x66, 0x0d, 0xcb, 0x6d, 0x01, + 0x7b, 0x8c, 0xec, 0x3d, 0x98, 0xe5, 0x2a, 0xac, 0x11, 0xde, + 0x88, 0x2e, 0xf2, 0x22, 0x98, 0x13, 0x73, 0xa3, 0x38, 0xd0, + 0x43, 0xf4, 0xc6, 0xf0, 0xc1, 0x24, 0x1a, 0x7a, 0x9f, 0xba, + 0x03, 0x25, 0x49, 0xe5, 0x8e, 0xb7, 0x5d, 0x79, 0x76, 0xfd, + 0x22, 0x5c, 0xba, 0x82, 0xb8, 0x75, 0x81, 0xc6, 0x79, 0xb3, + 0x56, 0x44, 0x82, 0x80, 0x5a, 0x3c, 0xe8, 0x21, 0xe4, 0xdb, + 0xfd, 0x1c, 0xd3, 0x18, 0xbd, 0x74, 0x22, 0x25, 0x44, 0xde, + 0x0b, 0x7e, 0x6e, 0xdb, 0xe3, 0x3b, 0x17, 0xc1, 0x4d, 0x5e, + 0x51, 0x87, 0xb0, 0x5a, 0xce, 0x5f, 0x23, 0xce, 0x18, 0x61, + 0x03, 0x02, 0x7e, 0x4b, 0x36, 0xb0, 0x7c, 0x90, 0xcf, 0xac, + 0x81, 0xc4, 0x45, 0xa3, 0x50, 0x01, 0x2e, 0x0a, 0xce, 0x62, + 0x7a, 0xe0, 0xa7, 0xc0, 0x45, 0x5e, 0x90, 0xe2, 0x2e, 0xc6, + 0x90, 0xe9, 0xbe, 0x8f, 0xe9, 0x31, 0xa9, 0xc9, 0x44, 0x62, + 0x31, 0xb6, 0x13, 0xaf, 0xd5, 0x9a, 0x55, 0x9b, 0x14, 0xf9, + 0x80, 0xcc, 0x73, 0xe3, 0x51, 0xdf, 0x2a, 0x04, 0x79, 0x0d, + 0x04, 0xee, 0x4c, 0xa8, 0x9d, 0xaa, 0x67, 0x2f, 0x77, 0x87, + 0x5e, 0x2d, 0x05, 0x95, 0xbe, 0x53, 0x45, 0x96, 0x8b, 0x89, + 0x79, 0x5b, 0x48, 0xe2, 0x6f, 0x3a, 0xc9, 0xef, 0x83, 0x81, + 0xcc, 0x4c, 0xfe, 0xb7, 0x40, 0x2d, 0xa5, 0xa5, 0x51, 0xb7, + 0xad, 0x2f, 0x29, 0xd8, 0xc8, 0x02, 0xbe, 0x18, 0x09, 0xd0, + 0xba, 0x71, 0x77, 0xfe, 0x2c, 0x6d +}; + +u_int8_t delete_pld[] = { + 0x2a, 0x00, 0x00, 0x10, 0x01, 0x08, 0x00, 0x01, /* IKE SA */ + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xaf, 0xfe, + 0x00, 0x00, 0x00, 0x10, 0x03, 0x04, 0x00, 0x02, /* ESP SA */ + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11 +}; + +u_int8_t vendor_pld[] = { + 0x00, 0x00, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44 +}; + +u_int8_t ts_pld[] = { + 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x10, 0x00, 0x00, 0xff, 0xff, + 0xac, 0x28, 0x7d, 0x00, 0xac, 0x28, 0x7d, 0xff +}; + +u_int8_t sk_pld[] = { + 0x21, 0x00, 0x01, 0x94, 0x14, 0x77, 0x25, 0x7b, 0x82, 0xc0, + 0xdb, 0x0b, 0x24, 0x36, 0x36, 0x13, 0x36, 0xe4, 0x99, 0xad, + 0xf5, 0xaf, 0x26, 0x6f, 0x47, 0xd2, 0x0d, 0x65, 0xe1, 0xa8, + 0xcb, 0x35, 0x1e, 0x53, 0xce, 0x6d, 0x8e, 0xf9, 0xe4, 0x51, + 0xe3, 0x27, 0x10, 0x43, 0x38, 0x84, 0x54, 0x1d, 0x7a, 0x1a, + 0x89, 0x34, 0x06, 0xb3, 0x62, 0x86, 0x98, 0x3b, 0x39, 0x91, + 0x6e, 0xe8, 0x65, 0x3e, 0x31, 0xa8, 0x08, 0xfe, 0x83, 0x56, + 0x30, 0xd3, 0xe0, 0xfd, 0x73, 0x92, 0x85, 0x2d, 0xae, 0x1d, + 0x7d, 0xdb, 0x47, 0x05, 0x57, 0xe7, 0x8e, 0xc5, 0xa5, 0x1b, + 0x0e, 0x85, 0x1f, 0x12, 0x6d, 0xe6, 0xdb, 0x3a, 0x3e, 0x99, + 0xd1, 0x23, 0x41, 0xa4, 0x1c, 0x46, 0x38, 0xd1, 0xa8, 0x84, + 0x96, 0x13, 0xdb, 0x2a, 0x1d, 0x3b, 0xb8, 0xd2, 0x04, 0xb3, + 0x0d, 0xb4, 0x71, 0x90, 0xdb, 0xf6, 0x2d, 0x60, 0x01, 0xc2, + 0xb2, 0x89, 0xbd, 0xe9, 0x95, 0x7b, 0x53, 0xa4, 0x94, 0x7e, + 0x12, 0xe9, 0x5f, 0xfc, 0x51, 0x17, 0x94, 0x3e, 0xba, 0xc2, + 0xa5, 0x4d, 0x3a, 0x4d, 0x4b, 0x95, 0x6d, 0x91, 0xc2, 0xb0, + 0x2d, 0xb7, 0x24, 0xe8, 0x3b, 0xbd, 0xe0, 0xcc, 0x09, 0x50, + 0x11, 0x83, 0xc0, 0xcd, 0x29, 0x33, 0xd5, 0x8f, 0x8a, 0xd1, + 0xe3, 0xe8, 0x4f, 0x6a, 0x10, 0x4a, 0x64, 0x97, 0x0f, 0x38, + 0x58, 0x8d, 0x7f, 0x5d, 0xb4, 0x6b, 0xa0, 0x42, 0x5e, 0x95, + 0xe6, 0x08, 0x3e, 0x01, 0xf8, 0x82, 0x90, 0x81, 0xd4, 0x70, + 0xb5, 0xb2, 0x8c, 0x64, 0xa9, 0x56, 0xdd, 0xc2, 0xda, 0xe1, + 0xd3, 0xad, 0xf8, 0x5b, 0x99, 0x0b, 0x19, 0x5e, 0x88, 0x0d, + 0x81, 0x04, 0x4d, 0xc1, 0x43, 0x41, 0xf1, 0xd3, 0x45, 0x65, + 0x62, 0x70, 0x2f, 0xfa, 0x62, 0xbe, 0x7d, 0xf4, 0x94, 0x91, + 0xe0, 0xbb, 0xb1, 0xbc, 0xe5, 0x27, 0xc8, 0x15, 0xd4, 0xcb, + 0x82, 0x97, 0x15, 0x46, 0x82, 0xbb, 0x48, 0xbb, 0x16, 0x25, + 0xbe, 0x82, 0xe4, 0x27, 0x80, 0xf3, 0xc2, 0x92, 0x3b, 0xd6, + 0xc3, 0x65, 0x20, 0xec, 0x50, 0xdb, 0x6a, 0xcb, 0x47, 0x73, + 0xf7, 0x98, 0xf1, 0x66, 0x5e, 0xc4, 0xe9, 0x87, 0xf8, 0xcb, + 0x1e, 0x06, 0xa7, 0x67, 0xf5, 0xec, 0x73, 0xe5, 0xc7, 0x4d, + 0xc2, 0x90, 0xe4, 0xdf, 0x9d, 0x1f, 0x05, 0x67, 0x99, 0xd6, + 0xf0, 0xc4, 0x20, 0xbc, 0xf8, 0xf5, 0x3e, 0x19, 0xe9, 0x3a, + 0x12, 0xe1, 0xcc, 0x9f, 0x81, 0x55, 0x1e, 0xad, 0xc8, 0xa3, + 0xe5, 0x98, 0xbe, 0xe0, 0x4d, 0xb7, 0x6b, 0xd5, 0xbe, 0x6a, + 0x3d, 0x76, 0xb6, 0xe2, 0xa5, 0xa7, 0x96, 0x68, 0xeb, 0x91, + 0xee, 0x02, 0xfc, 0xe4, 0x01, 0xc3, 0x24, 0xda, 0x4c, 0xff, + 0x10, 0x27, 0x78, 0xb0, 0x0b, 0x55, 0x5c, 0xce, 0x62, 0x7d, + 0x33, 0x2b, 0x25, 0x99, 0xaa, 0x99, 0xea, 0xa3, 0x1d, 0xd8, + 0x2b, 0x57, 0xb5, 0xe4, 0x04, 0x21, 0x75, 0xd9, 0xc4, 0xd0, + 0x3d, 0xa1, 0xa5, 0x8f +}; + +u_int8_t cp_pld[] = { + 0x2f, 0x00, 0x00, 0x0c, + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x2f, 0x00, 0x00, 0x10, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, + 0xaa, 0xbb, 0xcc, 0xdd, + 0x2f, 0x00, 0x00, 0x08, + 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, + 0x04, 0x00, 0x00, 0x00, +}; + +u_int8_t eap_pld[] = { + 0x30, 0x00, 0x00, 0x09, + 0x01, 0x00, 0x00, 0x05, 0x01, + 0x30, 0x00, 0x00, 0x0c, + 0x02, 0x00, 0x00, 0x05, 0x01, 0xfa, 0xfb, 0xfc, + 0x30, 0x00, 0x00, 0x08, + 0x03, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x08, + 0x04, 0x00, 0x00, 0x04 +}; + +/* Valid initator packet */ +u_int8_t valid_packet[] = { + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x22, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x22, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x01, 0x00, 0x06, + 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, + 0x00, 0x0c, 0x01, 0x00, 0x00, 0x0c, 0x80, 0x0e, 0x00, 0xc0, + 0x03, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, + 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x08, + 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, + 0x00, 0x01, 0x28, 0x00, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x00, + 0x16, 0xcb, 0x68, 0xaf, 0x63, 0xfe, 0xb0, 0x58, 0x49, 0x0e, + 0x7f, 0x85, 0x60, 0x53, 0x80, 0xae, 0x3f, 0x82, 0xf3, 0x35, + 0x21, 0xd5, 0xae, 0x09, 0x1c, 0xfa, 0x68, 0xc2, 0xfb, 0x4b, + 0xb3, 0x84, 0xda, 0xaf, 0x6e, 0xe2, 0x5e, 0xc5, 0xb6, 0x8c, + 0x35, 0x3c, 0xec, 0x58, 0x7f, 0xa9, 0xf8, 0xa4, 0x24, 0xf3, + 0xf8, 0xf4, 0x65, 0x59, 0x8c, 0x15, 0x4d, 0x2c, 0xf1, 0x5d, + 0xeb, 0x57, 0x68, 0xfe, 0x75, 0x61, 0x5a, 0x80, 0x96, 0xa4, + 0x0a, 0xad, 0x75, 0x71, 0xd8, 0xe0, 0x06, 0xbc, 0xde, 0x16, + 0x6d, 0x1e, 0xd9, 0x5d, 0x2c, 0x00, 0x66, 0x43, 0x82, 0xe4, + 0x6f, 0x5f, 0x95, 0xe7, 0x9b, 0xfd, 0xf2, 0xe2, 0xcb, 0xc5, + 0xf1, 0x52, 0xdd, 0x3b, 0xed, 0x88, 0xd4, 0xa9, 0x13, 0x4e, + 0x42, 0xe8, 0x60, 0x2d, 0x3c, 0xf6, 0xc8, 0xf0, 0x70, 0x42, + 0xfa, 0x33, 0x7f, 0x28, 0xdf, 0x6b, 0x79, 0x2c, 0x79, 0x8f, + 0xc0, 0x5d, 0x81, 0x7a, 0x62, 0xdb, 0xd4, 0x44, 0x3a, 0x3c, + 0x21, 0xbf, 0x85, 0xc8, 0x0b, 0x8c, 0x77, 0x72, 0xe9, 0xfb, + 0x50, 0x5c, 0x03, 0xa6, 0xb2, 0x3f, 0x17, 0x4a, 0xd1, 0xb3, + 0x01, 0x30, 0xad, 0xe4, 0xfa, 0xe2, 0xba, 0x6f, 0x22, 0x83, + 0xf4, 0xde, 0x38, 0x43, 0xe8, 0x27, 0x00, 0xb8, 0x95, 0xbe, + 0x03, 0x8f, 0xcd, 0xd3, 0x72, 0xed, 0xa5, 0xed, 0x8d, 0xf4, + 0x68, 0x98, 0xef, 0x59, 0xcc, 0xfb, 0x54, 0x89, 0xde, 0xa9, + 0xd4, 0x88, 0xcd, 0xb9, 0xca, 0x09, 0xd3, 0xd5, 0x25, 0xb1, + 0x8c, 0x58, 0x12, 0x9c, 0x69, 0x03, 0x72, 0x00, 0xc9, 0xca, + 0x95, 0x8a, 0xce, 0x0d, 0xd2, 0xc8, 0x25, 0xe7, 0x7c, 0xed, + 0x5e, 0xee, 0x35, 0x01, 0xfc, 0x00, 0x56, 0xed, 0xf3, 0x8d, + 0x81, 0x6c, 0x3e, 0x86, 0x6a, 0x40, 0xac, 0xc7, 0x9c, 0x7a, + 0xbf, 0x9f, 0x8e, 0x1f, 0xd8, 0x60, 0x29, 0x00, 0x00, 0x24, + 0x5f, 0x61, 0x42, 0x72, 0x7d, 0xb2, 0xa8, 0xc1, 0xfe, 0xb1, + 0x38, 0x2e, 0xb8, 0x75, 0xa7, 0xc1, 0x1d, 0x8a, 0xa7, 0xb7, + 0x9b, 0x92, 0xe2, 0x0e, 0x3a, 0x18, 0x20, 0xb6, 0x16, 0xf3, + 0x35, 0x67, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x04, + 0xc7, 0xa0, 0x68, 0x68, 0x09, 0x0a, 0x7f, 0x12, 0x0b, 0x13, + 0xd3, 0x2f, 0xde, 0x64, 0x8b, 0xf1, 0xc3, 0x3c, 0x79, 0x8f, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x05, 0x9f, 0xbc, + 0x8c, 0xd0, 0x91, 0x5e, 0xa0, 0x87, 0x81, 0xab, 0x4f, 0xa1, + 0x8a, 0xa7, 0xa8, 0xf9, 0xeb, 0xdf, 0x9f, 0x2c +}; + +#define OFFSET_ICOOKIE 0 +#define OFFSET_RCOOKIE 8 +#define OFFSET_NEXTPAYLOAD (0 + sizeof(cookies)) +#define OFFSET_VERSION (1 + sizeof(cookies)) +#define OFFSET_EXCHANGE (2 + sizeof(cookies)) +#define OFFSET_LENGTH (8 + sizeof(cookies)) + +static u_int8_t * +get_icookie(u_int8_t *data) +{ + return &data[OFFSET_ICOOKIE]; +} + +static u_int8_t * +get_rcookie(u_int8_t *data) +{ + return &data[OFFSET_RCOOKIE]; +} + +static u_int8_t +get_nextpayload(u_int8_t *data) +{ + return data[OFFSET_NEXTPAYLOAD]; +} + +static u_int8_t +get_version(u_int8_t *data) +{ + return data[OFFSET_VERSION]; +} + +static u_int8_t +get_exchange(u_int8_t *data) +{ + return data[OFFSET_EXCHANGE]; +} + +static u_int32_t +get_length(u_int8_t *data) +{ + return *(u_int32_t *)&data[OFFSET_LENGTH]; +} + +static void +set_length(u_int8_t *data, u_int32_t length) +{ + u_int32_t *p; + + p = (u_int32_t *)&data[OFFSET_LENGTH]; + *p = htobe32(length); +} + +static void +set_nextpayload(u_int8_t *data, u_int8_t next) +{ + data[OFFSET_NEXTPAYLOAD] = next; +} + +static void +prepare_header(struct ike_header *hdr, struct ibuf *data) +{ + bzero(hdr, sizeof(*hdr)); + bcopy(get_icookie(ibuf_data(data)), &hdr->ike_ispi, + sizeof(hdr->ike_ispi)); + bcopy(get_rcookie(ibuf_data(data)), &hdr->ike_rspi, + sizeof(hdr->ike_rspi)); + hdr->ike_nextpayload = get_nextpayload(ibuf_data(data)); + hdr->ike_version = get_version(ibuf_data(data)); + hdr->ike_exchange = get_exchange(ibuf_data(data)); + hdr->ike_length = get_length(ibuf_data(data)); +} + +static void +prepare_message(struct iked_message *msg, struct ibuf *data) +{ + static struct iked_sa sa; + + bzero(&sa, sizeof(sa)); + bzero(msg, sizeof(*msg)); + + msg->msg_sa = &sa; + msg->msg_data = data; +} + +static void +perform_test(struct fuzz *fuzz) +{ + struct ibuf *fuzzed; + struct ike_header hdr; + struct iked_message msg; + + bzero(&hdr, sizeof(hdr)); + bzero(&msg, sizeof(msg)); + + for (; !fuzz_done(fuzz); fuzz_next(fuzz)) { + ASSERT_PTR_NE(fuzzed = ibuf_new(fuzz_ptr(fuzz), fuzz_len(fuzz)), + NULL); + print_hex(ibuf_data(fuzzed), 0, ibuf_size(fuzzed)); + + /* We need at least cookies and generic header. */ + if (ibuf_size(fuzzed) < sizeof(cookies) + sizeof(genhdr)) { + ibuf_free(fuzzed); + continue; + } + + prepare_header(&hdr, fuzzed); + prepare_message(&msg, fuzzed); + + ikev2_pld_parse(NULL, &hdr, &msg, 0); + + ibuf_free(fuzzed); + } +} + +void +parser_fuzz_tests(void) +{ + struct fuzz *fuzz; + struct ike_header hdr; + struct iked_message msg; + struct ibuf *data; + +#if 0 + log_init(3); +#endif + + TEST_START("fuzz generic header"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz sa payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, sa_pld, sizeof(sa_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_SA); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz sa and xform payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, saxform_pld, sizeof(saxform_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_SA); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz ke payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, ke_pld, sizeof(ke_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_KE); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz nonce payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, nonce_pld, sizeof(nonce_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_NONCE); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz notify payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, notify_pld, sizeof(notify_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_NOTIFY); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz id payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, id_pld, sizeof(id_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_IDi); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz cert payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, cert_pld, sizeof(cert_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_CERT); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz certreq payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, certreq_pld, sizeof(certreq_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_CERTREQ); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz auth payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, auth_pld, sizeof(auth_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_AUTH); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz delete notify payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, delete_pld, sizeof(delete_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_DELETE); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz vendor id payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, vendor_pld, sizeof(vendor_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_VENDOR); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz traffic selector initiator payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, ts_pld, sizeof(ts_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_TSi); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz traffic selector responder payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, ts_pld, sizeof(ts_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_TSr); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz configuration payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, cp_pld, sizeof(cp_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_CP); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz eap payload"); + ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL); + ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0); + ASSERT_INT_EQ(ibuf_add(data, eap_pld, sizeof(eap_pld)), 0); + set_length(ibuf_data(data), ibuf_size(data)); + set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_EAP); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); + + TEST_START("fuzz full valid packet"); + ASSERT_PTR_NE(data = ibuf_new(valid_packet, sizeof(valid_packet)), + NULL); + set_length(ibuf_data(data), ibuf_size(data)); + print_hex(ibuf_data(data), 0, ibuf_size(data)); + prepare_header(&hdr, data); + prepare_message(&msg, data); + ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END | + FUZZ_BASE64, + ibuf_data(data), ibuf_size(data)); + ibuf_free(data); + perform_test(fuzz); + TEST_DONE(); +} diff --git a/regress/sbin/iked/parser/tests.c b/regress/sbin/iked/parser/tests.c new file mode 100644 index 00000000000..691f3e2ec8f --- /dev/null +++ b/regress/sbin/iked/parser/tests.c @@ -0,0 +1,16 @@ +/* $OpenBSD: tests.c,v 1.1 2017/05/29 20:59:28 markus Exp $ */ +/* + * Regress test for iked payload parser + * + * Placed in the public domain + */ + +#include "test_helper.h" + +void parser_fuzz_tests(void); + +void +tests(void) +{ + parser_fuzz_tests(); +} diff --git a/regress/sbin/iked/test_helper/Makefile b/regress/sbin/iked/test_helper/Makefile new file mode 100644 index 00000000000..4029f94fd63 --- /dev/null +++ b/regress/sbin/iked/test_helper/Makefile @@ -0,0 +1,13 @@ +# $OpenBSD: Makefile,v 1.1 2017/05/29 20:59:32 markus Exp $ + +LIB= test_helper +SRCS= test_helper.c fuzz.c + +DEBUGLIBS= no +NOPROFILE= yes +NOPIC= yes + +install: + @echo -n + +.include diff --git a/regress/sbin/iked/test_helper/fuzz.c b/regress/sbin/iked/test_helper/fuzz.c new file mode 100644 index 00000000000..4f14217d559 --- /dev/null +++ b/regress/sbin/iked/test_helper/fuzz.c @@ -0,0 +1,374 @@ +/* $OpenBSD */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for fuzz tests */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "test_helper.h" + +/* #define FUZZ_DEBUG */ + +#ifdef FUZZ_DEBUG +# define FUZZ_DBG(x) do { \ + printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ + printf x; \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +# define FUZZ_DBG(x) +#endif + +/* For brevity later */ +typedef unsigned long long fuzz_ullong; + +/* For base-64 fuzzing */ +static const char fuzz_b64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct fuzz { + /* Fuzz method currently in use */ + int strategy; + + /* Fuzz methods remaining */ + int strategies; + + /* Original seed data blob */ + void *seed; + size_t slen; + + /* Current working copy of seed with fuzz mutations applied */ + u_char *fuzzed; + + /* Used by fuzz methods */ + size_t o1, o2; +}; + +static const char * +fuzz_ntop(u_int n) +{ + switch (n) { + case 0: + return "NONE"; + case FUZZ_1_BIT_FLIP: + return "FUZZ_1_BIT_FLIP"; + case FUZZ_2_BIT_FLIP: + return "FUZZ_2_BIT_FLIP"; + case FUZZ_1_BYTE_FLIP: + return "FUZZ_1_BYTE_FLIP"; + case FUZZ_2_BYTE_FLIP: + return "FUZZ_2_BYTE_FLIP"; + case FUZZ_TRUNCATE_START: + return "FUZZ_TRUNCATE_START"; + case FUZZ_TRUNCATE_END: + return "FUZZ_TRUNCATE_END"; + case FUZZ_BASE64: + return "FUZZ_BASE64"; + default: + abort(); + } +} + +void +fuzz_dump(struct fuzz *fuzz) +{ + u_char *p = fuzz_ptr(fuzz); + size_t i, j, len = fuzz_len(fuzz); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen * 8, fuzz->o1); + break; + case FUZZ_2_BIT_FLIP: + fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, + ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, + fuzz->o1, fuzz->o2); + break; + case FUZZ_1_BYTE_FLIP: + fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + break; + case FUZZ_2_BYTE_FLIP: + fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, + ((fuzz_ullong)fuzz->slen) * fuzz->slen, + fuzz->o1, fuzz->o2); + break; + case FUZZ_TRUNCATE_START: + fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + break; + case FUZZ_TRUNCATE_END: + fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + break; + case FUZZ_BASE64: + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n", + fuzz_ntop(fuzz->strategy), + (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, + fuzz->slen * (fuzz_ullong)64, fuzz->o1, + fuzz_b64chars[fuzz->o2]); + break; + default: + abort(); + } + + fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len); + for (i = 0; i < len; i += 16) { + fprintf(stderr, "%.4zd: ", i); + for (j = i; j < i + 16; j++) { + if (j < len) + fprintf(stderr, "%02x ", p[j]); + else + fprintf(stderr, " "); + } + fprintf(stderr, " "); + for (j = i; j < i + 16; j++) { + if (j < len) { + if (isascii(p[j]) && isprint(p[j])) + fprintf(stderr, "%c", p[j]); + else + fprintf(stderr, "."); + } + } + fprintf(stderr, "\n"); + } +} + +struct fuzz * +fuzz_begin(u_int strategies, void *p, size_t l) +{ + struct fuzz *ret = calloc(sizeof(*ret), 1); + + assert(p != NULL); + assert(ret != NULL); + ret->seed = malloc(l); + assert(ret->seed != NULL); + memcpy(ret->seed, p, l); + ret->slen = l; + ret->strategies = strategies; + + assert(ret->slen < SIZE_MAX / 8); + assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); + + FUZZ_DBG(("begin, ret = %p", ret)); + + fuzz_next(ret); + return ret; +} + +void +fuzz_cleanup(struct fuzz *fuzz) +{ + FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); + assert(fuzz != NULL); + assert(fuzz->seed != NULL); + assert(fuzz->fuzzed != NULL); + free(fuzz->seed); + free(fuzz->fuzzed); + free(fuzz); +} + +static int +fuzz_strategy_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", + fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + return fuzz->o1 >= fuzz->slen * 8; + case FUZZ_2_BIT_FLIP: + return fuzz->o2 >= fuzz->slen * 8; + case FUZZ_2_BYTE_FLIP: + return fuzz->o2 >= fuzz->slen; + case FUZZ_1_BYTE_FLIP: + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + case FUZZ_BASE64: + return fuzz->o1 >= fuzz->slen; + default: + abort(); + } +} + +void +fuzz_next(struct fuzz *fuzz) +{ + u_int i; + + FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); + + if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { + /* If we are just starting out, we need to allocate too */ + if (fuzz->fuzzed == NULL) { + FUZZ_DBG(("alloc")); + fuzz->fuzzed = calloc(fuzz->slen, 1); + } + /* Pick next strategy */ + FUZZ_DBG(("advance")); + for (i = 1; i <= FUZZ_MAX; i <<= 1) { + if ((fuzz->strategies & i) != 0) { + fuzz->strategy = i; + break; + } + } + FUZZ_DBG(("selected = %u", fuzz->strategy)); + if (fuzz->strategy == 0) { + FUZZ_DBG(("done, no more strategies")); + return; + } + fuzz->strategies &= ~(fuzz->strategy); + fuzz->o1 = fuzz->o2 = 0; + } + + assert(fuzz->fuzzed != NULL); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->o1++; + break; + case FUZZ_2_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + assert(fuzz->o2 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen * 8) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_1_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->o1++; + break; + case FUZZ_2_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->fuzzed[fuzz->o2] ^= 0xff; + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->o1++; + break; + case FUZZ_BASE64: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; + fuzz->o2++; + if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { + fuzz->o2 = 0; + fuzz->o1++; + } + break; + default: + abort(); + } + + FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); +} + +int +fuzz_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, + (u_long)fuzz->strategies)); + + return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; +} + +size_t +fuzz_len(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->slen; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->slen - fuzz->o1; + default: + abort(); + } +} + +u_char * +fuzz_ptr(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->fuzzed; + case FUZZ_TRUNCATE_START: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed + fuzz->o1; + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed; + default: + abort(); + } +} + diff --git a/regress/sbin/iked/test_helper/test_helper.c b/regress/sbin/iked/test_helper/test_helper.c new file mode 100644 index 00000000000..cc642cae9da --- /dev/null +++ b/regress/sbin/iked/test_helper/test_helper.c @@ -0,0 +1,426 @@ +/* $OpenBSD */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "test_helper.h" + +#define TEST_CHECK_INT(r, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (r == 0) \ + return; \ + break; \ + case TEST_NE: \ + if (r != 0) \ + return; \ + break; \ + case TEST_LT: \ + if (r < 0) \ + return; \ + break; \ + case TEST_LE: \ + if (r <= 0) \ + return; \ + break; \ + case TEST_GT: \ + if (r > 0) \ + return; \ + break; \ + case TEST_GE: \ + if (r >= 0) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +#define TEST_CHECK(x1, x2, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (x1 == x2) \ + return; \ + break; \ + case TEST_NE: \ + if (x1 != x2) \ + return; \ + break; \ + case TEST_LT: \ + if (x1 < x2) \ + return; \ + break; \ + case TEST_LE: \ + if (x1 <= x2) \ + return; \ + break; \ + case TEST_GT: \ + if (x1 > x2) \ + return; \ + break; \ + case TEST_GE: \ + if (x1 >= x2) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +extern char *__progname; + +static int verbose_mode = 0; +static int quiet_mode = 0; +static char *active_test_name = NULL; +static u_int test_number = 0; +static test_onerror_func_t *test_onerror = NULL; +static void *onerror_ctx = NULL; +static const char *data_dir = NULL; + +int +main(int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "vqd:")) != -1) { + switch (ch) { + case 'd': + data_dir = optarg; + break; + case 'q': + verbose_mode = 0; + quiet_mode = 1; + break; + case 'v': + verbose_mode = 1; + quiet_mode = 0; + break; + default: + fprintf(stderr, "Unrecognised command line option\n"); + fprintf(stderr, "Usage: %s [-v]\n", __progname); + exit(1); + } + } + setvbuf(stdout, NULL, _IONBF, 0); + if (!quiet_mode) + printf("%s: ", __progname); + if (verbose_mode) + printf("\n"); + + tests(); + + if (!quiet_mode) + printf(" %u tests ok\n", test_number); + return 0; +} + +const char * +test_data_file(const char *name) +{ + static char ret[PATH_MAX]; + + if (data_dir != NULL) + snprintf(ret, sizeof(ret), "%s/%s", data_dir, name); + else + strlcpy(ret, name, sizeof(ret)); + if (access(ret, F_OK) != 0) { + fprintf(stderr, "Cannot access data file %s: %s\n", + ret, strerror(errno)); + exit(1); + } + return ret; +} + +void +test_start(const char *n) +{ + assert(active_test_name == NULL); + assert((active_test_name = strdup(n)) != NULL); + if (verbose_mode) + printf("test %u - \"%s\": ", test_number, active_test_name); + test_number++; +} + +void +set_onerror_func(test_onerror_func_t *f, void *ctx) +{ + test_onerror = f; + onerror_ctx = ctx; +} + +void +test_done(void) +{ + assert(active_test_name != NULL); + free(active_test_name); + active_test_name = NULL; + if (verbose_mode) + printf("OK\n"); + else if (!quiet_mode) { + printf("."); + fflush(stdout); + } +} + +static const char * +pred_name(enum test_predicate p) +{ + switch (p) { + case TEST_EQ: + return "EQ"; + case TEST_NE: + return "NE"; + case TEST_LT: + return "LT"; + case TEST_LE: + return "LE"; + case TEST_GT: + return "GT"; + case TEST_GE: + return "GE"; + default: + return "UNKNOWN"; + } +} + +static void +test_die(void) +{ + if (test_onerror != NULL) + test_onerror(onerror_ctx); + abort(); +} + +static void +test_header(const char *file, int line, const char *a1, const char *a2, + const char *name, enum test_predicate pred) +{ + fprintf(stderr, "\n%s:%d test #%u \"%s\"\n", + file, line, test_number, active_test_name); + fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", + name, pred_name(pred), a1, + a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); +} + +void +assert_string(const char *file, int line, const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred) +{ + int r = strcmp(aa1, aa2); + + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2)); + test_die(); +} + +static char * +tohex(const void *_s, size_t l) +{ + u_int8_t *s = (u_int8_t *)_s; + size_t i, j; + const char *hex = "0123456789abcdef"; + char *r = malloc((l * 2) + 1); + + assert(r != NULL); + for (i = j = 0; i < l; i++) { + r[j++] = hex[(s[i] >> 4) & 0xf]; + r[j++] = hex[s[i] & 0xf]; + } + r[j] = '\0'; + return r; +} + +void +assert_mem(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred) +{ + int r = memcmp(aa1, aa2, l); + + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, tohex(aa2, MIN(l, 256)), l); + test_die(); +} + +static int +memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where) +{ + size_t i; + + for (i = 0; i < l; i++) { + if (s[i] != v) { + *where = i; + return 1; + } + } + return 0; +} + +void +assert_mem_filled(const char *file, int line, const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred) +{ + size_t where = -1; + int r = memvalcmp(aa1, v, l, &where); + char tmp[64]; + + if (l == 0) + return; + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, NULL, "MEM_ZERO", pred); + fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, + tohex(aa1, MIN(l, 20)), l > 20 ? "..." : "", l); + snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where); + fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp, + ((u_char *)aa1)[where], v); + test_die(); +} + +void +assert_int(const char *file, int line, const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "INT", pred); + fprintf(stderr, "%12s = %d\n", a1, aa1); + fprintf(stderr, "%12s = %d\n", a2, aa2); + test_die(); +} + +void +assert_size_t(const char *file, int line, const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "SIZE_T", pred); + fprintf(stderr, "%12s = %zu\n", a1, aa1); + fprintf(stderr, "%12s = %zu\n", a2, aa2); + test_die(); +} + +void +assert_u_int(const char *file, int line, const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U_INT", pred); + fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2); + test_die(); +} + +void +assert_long_long(const char *file, int line, const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG LONG", pred); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2); + test_die(); +} + +void +assert_char(const char *file, int line, const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred) +{ + char buf[8]; + + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "CHAR", pred); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2); + test_die(); +} + +void +assert_u8(const char *file, int line, const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U8", pred); + fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u16(const char *file, int line, const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U16", pred); + fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u32(const char *file, int line, const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U32", pred); + fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u64(const char *file, int line, const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U64", pred); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a1, + (unsigned long long)aa1, (unsigned long long)aa1); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a2, + (unsigned long long)aa2, (unsigned long long)aa2); + test_die(); +} + +void +assert_ptr(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "PTR", pred); + fprintf(stderr, "%12s = %p\n", a1, aa1); + fprintf(stderr, "%12s = %p\n", a2, aa2); + test_die(); +} + diff --git a/regress/sbin/iked/test_helper/test_helper.h b/regress/sbin/iked/test_helper/test_helper.h new file mode 100644 index 00000000000..f6fd518c39a --- /dev/null +++ b/regress/sbin/iked/test_helper/test_helper.h @@ -0,0 +1,271 @@ +/* $OpenBSD */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#ifndef _TEST_HELPER_H +#define _TEST_HELPER_H + +#include +#include + +#include +#include + +enum test_predicate { + TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE +}; +typedef void (test_onerror_func_t)(void *); + +/* Supplied by test suite */ +void tests(void); + +const char *test_data_file(const char *name); +void test_start(const char *n); +void set_onerror_func(test_onerror_func_t *f, void *ctx); +void test_done(void); +void assert_string(const char *file, int line, + const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred); +void assert_mem(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred); +void assert_mem_filled(const char *file, int line, + const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred); +void assert_int(const char *file, int line, + const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred); +void assert_size_t(const char *file, int line, + const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred); +void assert_u_int(const char *file, int line, + const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred); +void assert_long_long(const char *file, int line, + const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred); +void assert_char(const char *file, int line, + const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred); +void assert_ptr(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred); +void assert_u8(const char *file, int line, + const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred); +void assert_u16(const char *file, int line, + const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred); +void assert_u32(const char *file, int line, + const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred); +void assert_u64(const char *file, int line, + const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred); + +#define TEST_START(n) test_start(n) +#define TEST_DONE() test_done() +#define TEST_ONERROR(f, c) set_onerror_func(f, c) + +#define ASSERT_STRING_EQ(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_MEM_EQ(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ) +#define ASSERT_MEM_FILLED_EQ(a1, c, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ) +#define ASSERT_MEM_ZERO_EQ(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ) +#define ASSERT_INT_EQ(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_SIZE_T_EQ(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U_INT_EQ(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_LONG_EQ(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_CHAR_EQ(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_PTR_EQ(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U8_EQ(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U16_EQ(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U32_EQ(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U64_EQ(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) + +#define ASSERT_STRING_NE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_MEM_NE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE) +#define ASSERT_MEM_ZERO_NE(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE) +#define ASSERT_INT_NE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_SIZE_T_NE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U_INT_NE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_LONG_NE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_CHAR_NE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_PTR_NE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U8_NE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U16_NE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U32_NE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U64_NE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) + +#define ASSERT_STRING_LT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_MEM_LT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT) +#define ASSERT_INT_LT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_SIZE_T_LT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U_INT_LT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LONG_LT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_CHAR_LT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_PTR_LT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U8_LT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U16_LT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U32_LT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U64_LT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) + +#define ASSERT_STRING_LE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_MEM_LE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE) +#define ASSERT_INT_LE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_SIZE_T_LE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U_INT_LE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LONG_LE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_CHAR_LE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_PTR_LE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U8_LE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U16_LE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U32_LE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U64_LE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) + +#define ASSERT_STRING_GT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_MEM_GT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT) +#define ASSERT_INT_GT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_SIZE_T_GT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U_INT_GT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_LONG_GT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_CHAR_GT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_PTR_GT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U8_GT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U16_GT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U32_GT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U64_GT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) + +#define ASSERT_STRING_GE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_MEM_GE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE) +#define ASSERT_INT_GE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_SIZE_T_GE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U_INT_GE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_LONG_GE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_CHAR_GE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_PTR_GE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U8_GE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U16_GE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U32_GE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U64_GE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) + +/* Fuzzing support */ + +struct fuzz; +#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */ +#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */ +#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */ +#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */ +#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */ +#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */ +#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */ +#define FUZZ_MAX FUZZ_BASE64 + +/* Start fuzzing a blob of data with selected strategies (bitmask) */ +struct fuzz *fuzz_begin(u_int strategies, void *p, size_t l); + +/* Free a fuzz context */ +void fuzz_cleanup(struct fuzz *fuzz); + +/* Prepare the next fuzz case in the series */ +void fuzz_next(struct fuzz *fuzz); + +/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ +int fuzz_done(struct fuzz *fuzz); + +/* Return the length and a pointer to the current fuzzed case */ +size_t fuzz_len(struct fuzz *fuzz); +u_char *fuzz_ptr(struct fuzz *fuzz); + +/* Dump the current fuzz case to stderr */ +void fuzz_dump(struct fuzz *fuzz); +#endif /* _TEST_HELPER_H */