From 3ac8a363f0b51dc9474b01d0396fe3e8b9f6955e Mon Sep 17 00:00:00 2001 From: dlg Date: Sun, 19 Apr 2015 12:56:42 +0000 Subject: [PATCH] by default fill the ping payload with a chacha stream instead of an unvarying payload. each ping process generates a random key, and each packet then uses the timestamps mac as the IV for the stream. this allows us to have a different payload per packet that we can recalculate and compare in the same was as the static payload was checked before. by aggressively varying the payload we hope to generate more opportunities for dodgy network equipment to show errors. note that we do siphash before chacha because we want to be strict about the timestamp payload, but we want to be able to recognise errors in the rest of the payload and where those errors were. doing chacha before siphash would have us than fail the whole packet if a checksum doesnt match. discussed with jp aumasson ok florian@ --- sbin/ping/ping.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index 7485cfafddf..7ce9b4bbb07 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ping.c,v 1.119 2015/04/19 12:45:37 dlg Exp $ */ +/* $OpenBSD: ping.c,v 1.120 2015/04/19 12:56:42 dlg Exp $ */ /* $NetBSD: ping.c,v 1.20 1995/08/11 22:37:58 cgd Exp $ */ /* @@ -72,7 +72,10 @@ #include #include #include + #include +#define KEYSTREAM_ONLY +#include struct tv64 { u_int64_t tv64_sec; @@ -162,6 +165,7 @@ int bufspace = IP_MAXPACKET; struct tv64 tv64_offset; SIPHASH_KEY mac_key; +chacha_ctx fill_stream; void fill(char *, char *); void catcher(int signo); @@ -188,7 +192,7 @@ main(int argc, char *argv[]) struct hostent *hp; struct sockaddr_in *to; struct in_addr saddr; - int ch, i, optval = 1, packlen, preload, maxsize, df = 0, tos = 0; + int ch, optval = 1, packlen, preload, maxsize, df = 0, tos = 0; u_char *datap, *packet, ttl = MAXTTL, loop = 1; char *target, hnamebuf[HOST_NAME_MAX+1]; char rspace[3 + 4 * NROUTES + 1]; /* record route space */ @@ -385,9 +389,11 @@ main(int argc, char *argv[]) packlen = datalen + MAXIPLEN + MAXICMPLEN; if (!(packet = malloc((size_t)packlen))) err(1, "malloc"); - if (!(options & F_PINGFILLED)) - for (i = sizeof(struct payload); i < datalen; ++i) - *datap++ = i; + if (!(options & F_PINGFILLED) && datalen > sizeof(struct payload)) { + u_int8_t key[32]; + arc4random_buf(key, sizeof(key)); + chacha_keysetup(&fill_stream, key, sizeof(key) * 8, 0); + } ident = getpid() & 0xFFFF; @@ -647,6 +653,14 @@ pinger(void) SipHash24_Final(&payload.mac, &ctx); memcpy(&outpack[8], &payload, sizeof(payload)); + + if (!(options & F_PINGFILLED) && datalen > sizeof(payload)) { + u_int8_t *dp = &outpack[8 + sizeof(payload)]; + + chacha_ivsetup(&fill_stream, payload.mac); + chacha_encrypt_bytes(&fill_stream, dp, dp, + datalen - sizeof(payload)); + } } cc = datalen + 8; /* skips ICMP portion */ @@ -700,6 +714,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from) char *pkttime; quad_t triptime = 0; int hlen, hlen2, dupflag; + struct payload payload; if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) err(1, "clock_gettime(CLOCK_MONOTONIC)"); @@ -723,7 +738,6 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from) ++nreceived; if (cc >= 8 + sizeof(struct payload)) { SIPHASH_CTX ctx; - struct payload payload; struct tv64 *tv64 = &payload.tv64; u_int8_t mac[SIPHASH_DIGEST_LENGTH]; @@ -790,6 +804,11 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from) (void)printf(" (TRUNC!)"); cp = (u_char *)&icp->icmp_data[sizeof(struct payload)]; dp = &outpack[8 + sizeof(struct payload)]; + if (!(options & F_PINGFILLED)) { + chacha_ivsetup(&fill_stream, payload.mac); + chacha_encrypt_bytes(&fill_stream, dp, dp, + datalen - sizeof(payload)); + } for (i = 8 + sizeof(struct payload); i < cc && i < datalen; ++i, ++cp, ++dp) { -- 2.20.1