fuzz the iked payload parser using the openssh unit-test framework
authormarkus <markus@openbsd.org>
Mon, 29 May 2017 20:59:28 +0000 (20:59 +0000)
committermarkus <markus@openbsd.org>
Mon, 29 May 2017 20:59:28 +0000 (20:59 +0000)
from hshoexer

regress/sbin/iked/parser/Makefile [new file with mode: 0644]
regress/sbin/iked/parser/common.c [new file with mode: 0644]
regress/sbin/iked/parser/test_parser_fuzz.c [new file with mode: 0644]
regress/sbin/iked/parser/tests.c [new file with mode: 0644]
regress/sbin/iked/test_helper/Makefile [new file with mode: 0644]
regress/sbin/iked/test_helper/fuzz.c [new file with mode: 0644]
regress/sbin/iked/test_helper/test_helper.c [new file with mode: 0644]
regress/sbin/iked/test_helper/test_helper.h [new file with mode: 0644]

diff --git a/regress/sbin/iked/parser/Makefile b/regress/sbin/iked/parser/Makefile
new file mode 100644 (file)
index 0000000..7bd3b96
--- /dev/null
@@ -0,0 +1,37 @@
+#      $OpenBSD: Makefile,v 1.1 2017/05/29 20:59:28 markus Exp $
+
+WARNINGS=Yes
+
+.include <bsd.own.mk>
+.include <bsd.obj.mk>
+
+.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 <bsd.regress.mk>
diff --git a/regress/sbin/iked/parser/common.c b/regress/sbin/iked/parser/common.c
new file mode 100644 (file)
index 0000000..904af47
--- /dev/null
@@ -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 <sys/socket.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <event.h>
+#include <limits.h>
+
+#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 (file)
index 0000000..52c3729
--- /dev/null
@@ -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 <sys/socket.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+
+#include <event.h>
+#include <imsg.h>
+#include <string.h>
+
+#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 (file)
index 0000000..691f3e2
--- /dev/null
@@ -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 (file)
index 0000000..4029f94
--- /dev/null
@@ -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 <bsd.lib.mk>
diff --git a/regress/sbin/iked/test_helper/fuzz.c b/regress/sbin/iked/test_helper/fuzz.c
new file mode 100644 (file)
index 0000000..4f14217
--- /dev/null
@@ -0,0 +1,374 @@
+/*     $OpenBSD        */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * 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 <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#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 (file)
index 0000000..cc642ca
--- /dev/null
@@ -0,0 +1,426 @@
+/*     $OpenBSD        */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/param.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+
+#include <vis.h>
+
+#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 (file)
index 0000000..f6fd518
--- /dev/null
@@ -0,0 +1,271 @@
+/*     $OpenBSD        */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * 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 <sys/types.h>
+#include <stdint.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+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 */