netpkt.c (3828B)
1 #include <errno.h> 2 #include <stdint.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 6 #if defined(__linux__) 7 #include <bsd/stdlib.h> 8 #endif 9 10 #include "warp.h" 11 12 /* the various states the input handler can be in */ 13 enum { 14 RXINITIAL, 15 RXNONCE, 16 RXHDR, 17 RXPAYLOAD, 18 RXTAG, 19 RXDECRYPT, 20 RXDISCARD 21 }; 22 23 /* output buffer for writing data to the network */ 24 static unsigned char *wbuf; 25 /* input buffer for reading data from the network */ 26 static unsigned char *rbuf; 27 28 /* total number of bytes read into input buffer */ 29 static size_t rbuftotal; 30 /* number of bytes remaining to read into buffer for current state */ 31 static size_t rbufrem; 32 33 /* maximum input/output buffer size */ 34 static size_t maxbuflen; 35 36 /* nonce size in bytes */ 37 static size_t noncelen; 38 /* tag size in bytes */ 39 static size_t taglen; 40 41 /* state tracking for input handling */ 42 static int rxstate; 43 44 int 45 netwrite(int fd, unsigned char *pt, unsigned long long ptlen, 46 unsigned long long *outlen) 47 { 48 unsigned char *p = wbuf; 49 unsigned long long buflen = noncelen + HDRLEN + ptlen + taglen; 50 int n, total = 0; 51 52 if (buflen > maxbuflen) { 53 logwarnx("packet is too large"); 54 return PKTFAILED; 55 } 56 57 arc4random_buf(wbuf, noncelen); 58 pack16(&wbuf[noncelen], ptlen); 59 if (cryptoseal(&wbuf[noncelen + HDRLEN], outlen, 60 pt, ptlen, &wbuf[noncelen], HDRLEN, wbuf) != 0) { 61 logwarnx("cryptoseal failed"); 62 return -1; 63 } 64 65 /* spin until all data is written */ 66 while (buflen > 0) { 67 n = write(fd, p + total, buflen); 68 if (n == 0) { 69 return PKTFAILED; 70 } else if (n < 0) { 71 if (errno == EWOULDBLOCK) 72 continue; 73 return PKTFAILED; 74 } 75 total += n; 76 buflen -= n; 77 } 78 return PKTCOMPLETE; 79 } 80 81 int 82 netread(int fd, unsigned char *pt, unsigned long long ptlen, 83 unsigned long long *outlen) 84 { 85 unsigned long long buflen = noncelen + HDRLEN + ptlen + taglen; 86 int n, ctlen; 87 88 if (buflen > maxbuflen) { 89 logwarnx("packet is too large"); 90 return PKTFAILED; 91 } 92 93 for (;;) { 94 switch (rxstate) { 95 case RXINITIAL: 96 rbuftotal = 0; 97 rbufrem = noncelen; 98 rxstate = RXNONCE; 99 break; 100 case RXNONCE: 101 if ((n = read(fd, rbuf + rbuftotal, rbufrem)) <= 0) 102 goto out; 103 rbuftotal += n; 104 rbufrem -= n; 105 if (rbufrem == 0) { 106 rbufrem = HDRLEN; 107 rxstate = RXHDR; 108 } 109 break; 110 case RXHDR: 111 if ((n = read(fd, rbuf + rbuftotal, rbufrem)) <= 0) 112 goto out; 113 rbuftotal += n; 114 rbufrem -= n; 115 if (rbufrem == 0) { 116 ctlen = unpack16(&rbuf[noncelen]); 117 if (ctlen > ptlen) { 118 rxstate = RXDISCARD; 119 } else { 120 rbufrem = ctlen; 121 rxstate = RXPAYLOAD; 122 } 123 } 124 break; 125 case RXPAYLOAD: 126 if ((n = read(fd, rbuf + rbuftotal, rbufrem)) <= 0) 127 goto out; 128 rbuftotal += n; 129 rbufrem -= n; 130 if (rbufrem == 0) { 131 rbufrem = taglen; 132 rxstate = RXTAG; 133 } 134 break; 135 case RXTAG: 136 if ((n = read(fd, rbuf + rbuftotal, rbufrem)) <= 0) 137 goto out; 138 rbuftotal += n; 139 rbufrem -= n; 140 if (rbufrem == 0) 141 rxstate = RXDECRYPT; 142 break; 143 case RXDECRYPT: 144 rxstate = RXINITIAL; 145 if (cryptoopen(pt, outlen, &rbuf[noncelen + HDRLEN], 146 rbuftotal - noncelen - HDRLEN, 147 &rbuf[noncelen], HDRLEN, rbuf) != 0) { 148 logwarnx("cryptoopen failed"); 149 return PKTPARTIAL; 150 } 151 return PKTCOMPLETE; 152 case RXDISCARD: 153 rxstate = RXINITIAL; 154 for (;;) 155 if ((n = read(fd, rbuf, maxbuflen)) <= 0) 156 goto out; 157 break; 158 } 159 } 160 out: 161 if (n < 0 && errno == EWOULDBLOCK) 162 return PKTPARTIAL; 163 return PKTFAILED; 164 } 165 166 /* Reset state machine. This is required when a fatal error occurs. */ 167 void 168 netreset(void) 169 { 170 rxstate = RXINITIAL; 171 } 172 173 void 174 netinit(void) 175 { 176 noncelen = cryptononcelen(); 177 taglen = cryptotaglen(); 178 maxbuflen = noncelen + HDRLEN + MAXPAYLOADLEN + taglen; 179 if (!(wbuf = malloc(maxbuflen))) 180 fatal("malloc"); 181 if (!(rbuf = malloc(maxbuflen))) 182 fatal("malloc"); 183 netreset(); 184 }