9fe93cc7e7f0107d1251fee513244eab6668dbb3
[tinc] / src / sptps.c
1 /*
2     sptps.c -- Simple Peer-to-Peer Security
3     Copyright (C) 2011-2015 Guus Sliepen <guus@tinc-vpn.org>,
4                   2010      Brandon L. Black <blblack@gmail.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "system.h"
22
23 #include "chacha-poly1305/chacha-poly1305.h"
24 #include "crypto.h"
25 #include "ecdh.h"
26 #include "ecdsa.h"
27 #include "logger.h"
28 #include "prf.h"
29 #include "sptps.h"
30
31 unsigned int sptps_replaywin = 16;
32
33 /*
34    Nonce MUST be exchanged first (done)
35    Signatures MUST be done over both nonces, to guarantee the signature is fresh
36    Otherwise: if ECDHE key of one side is compromised, it can be reused!
37
38    Add explicit tag to beginning of structure to distinguish the client and server when signing. (done)
39
40    Sign all handshake messages up to ECDHE kex with long-term public keys. (done)
41
42    HMACed KEX finished message to prevent downgrade attacks and prove you have the right key material (done by virtue of Ed25519 over the whole ECDHE exchange?)
43
44    Explicit close message needs to be added.
45
46    Maybe do add some alert messages to give helpful error messages? Not more than TLS sends.
47
48    Use counter mode instead of OFB. (done)
49
50    Make sure ECC operations are fixed time (aka prevent side-channel attacks).
51 */
52
53 void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap) {
54         (void)s;
55         (void)s_errno;
56         (void)format;
57         (void)ap;
58 }
59
60 void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap) {
61         (void)s;
62         (void)s_errno;
63
64         vfprintf(stderr, format, ap);
65         fputc('\n', stderr);
66 }
67
68 void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap) = sptps_log_stderr;
69
70 // Log an error message.
71 static bool error(sptps_t *s, int s_errno, const char *format, ...) {
72         (void)s;
73         (void)s_errno;
74
75         if(format) {
76                 va_list ap;
77                 va_start(ap, format);
78                 sptps_log(s, s_errno, format, ap);
79                 va_end(ap);
80         }
81
82         errno = s_errno;
83         return false;
84 }
85
86 static void warning(sptps_t *s, const char *format, ...) {
87         va_list ap;
88         va_start(ap, format);
89         sptps_log(s, 0, format, ap);
90         va_end(ap);
91 }
92
93 // Send a record (datagram version, accepts all record types, handles encryption and authentication).
94 static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
95         uint8_t *buffer = alloca(len + 21UL);
96
97         // Create header with sequence number, length and record type
98         uint32_t seqno = s->outseqno++;
99         uint32_t netseqno = ntohl(seqno);
100
101         memcpy(buffer, &netseqno, 4);
102         buffer[4] = type;
103         memcpy(buffer + 5, data, len);
104
105         if(s->outstate) {
106                 // If first handshake has finished, encrypt and HMAC
107                 chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL);
108                 return s->send_data(s->handle, type, buffer, len + 21UL);
109         } else {
110                 // Otherwise send as plaintext
111                 return s->send_data(s->handle, type, buffer, len + 5UL);
112         }
113 }
114 // Send a record (private version, accepts all record types, handles encryption and authentication).
115 static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
116         if(s->datagram) {
117                 return send_record_priv_datagram(s, type, data, len);
118         }
119
120         uint8_t *buffer = alloca(len + 19UL);
121
122         // Create header with sequence number, length and record type
123         uint32_t seqno = s->outseqno++;
124         uint16_t netlen = htons(len);
125
126         memcpy(buffer, &netlen, 2);
127         buffer[2] = type;
128         memcpy(buffer + 3, data, len);
129
130         if(s->outstate) {
131                 // If first handshake has finished, encrypt and HMAC
132                 chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL);
133                 return s->send_data(s->handle, type, buffer, len + 19UL);
134         } else {
135                 // Otherwise send as plaintext
136                 return s->send_data(s->handle, type, buffer, len + 3UL);
137         }
138 }
139
140 // Send an application record.
141 bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
142         // Sanity checks: application cannot send data before handshake is finished,
143         // and only record types 0..127 are allowed.
144         if(!s->outstate) {
145                 return error(s, EINVAL, "Handshake phase not finished yet");
146         }
147
148         if(type >= SPTPS_HANDSHAKE) {
149                 return error(s, EINVAL, "Invalid application record type");
150         }
151
152         return send_record_priv(s, type, data, len);
153 }
154
155 // Send a Key EXchange record, containing a random nonce and an ECDHE public key.
156 static bool send_kex(sptps_t *s) {
157         size_t keylen = ECDH_SIZE;
158
159         // Make room for our KEX message, which we will keep around since send_sig() needs it.
160         if(s->mykex) {
161                 return false;
162         }
163
164         s->mykex = realloc(s->mykex, 1 + 32 + keylen);
165
166         if(!s->mykex) {
167                 return error(s, errno, strerror(errno));
168         }
169
170         // Set version byte to zero.
171         s->mykex[0] = SPTPS_VERSION;
172
173         // Create a random nonce.
174         randomize(s->mykex + 1, 32);
175
176         // Create a new ECDH public key.
177         if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) {
178                 return error(s, EINVAL, "Failed to generate ECDH public key");
179         }
180
181         return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen);
182 }
183
184 // Send a SIGnature record, containing an Ed25519 signature over both KEX records.
185 static bool send_sig(sptps_t *s) {
186         size_t keylen = ECDH_SIZE;
187         size_t siglen = ecdsa_size(s->mykey);
188
189         // Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label
190         const size_t msglen = (1 + 32 + keylen) * 2 + 1 + s->labellen;
191         uint8_t *msg = alloca(msglen);
192         uint8_t *sig = alloca(siglen);
193
194         msg[0] = s->initiator;
195         memcpy(msg + 1, s->mykex, 1 + 32 + keylen);
196         memcpy(msg + 1 + 33 + keylen, s->hiskex, 1 + 32 + keylen);
197         memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
198
199         // Sign the result.
200         if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
201                 return error(s, EINVAL, "Failed to sign SIG record");
202         }
203
204         // Send the SIG exchange record.
205         return send_record_priv(s, SPTPS_HANDSHAKE, sig, siglen);
206 }
207
208 // Generate key material from the shared secret created from the ECDHE key exchange.
209 static bool generate_key_material(sptps_t *s, const uint8_t *shared, size_t len) {
210         // Initialise cipher and digest structures if necessary
211         if(!s->outstate) {
212                 s->incipher = chacha_poly1305_init();
213                 s->outcipher = chacha_poly1305_init();
214
215                 if(!s->incipher || !s->outcipher) {
216                         return error(s, EINVAL, "Failed to open cipher");
217                 }
218         }
219
220         // Allocate memory for key material
221         size_t keylen = 2 * CHACHA_POLY1305_KEYLEN;
222
223         s->key = realloc(s->key, keylen);
224
225         if(!s->key) {
226                 return error(s, errno, strerror(errno));
227         }
228
229         // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
230         uint8_t *seed = alloca(s->labellen + 64 + 13);
231         memcpy(seed, "key expansion", 13);
232
233         if(s->initiator) {
234                 memcpy(seed + 13, s->mykex + 1, 32);
235                 memcpy(seed + 45, s->hiskex + 1, 32);
236         } else {
237                 memcpy(seed + 13, s->hiskex + 1, 32);
238                 memcpy(seed + 45, s->mykex + 1, 32);
239         }
240
241         memcpy(seed + 77, s->label, s->labellen);
242
243         // Use PRF to generate the key material
244         if(!prf(shared, len, seed, s->labellen + 64 + 13, s->key, keylen)) {
245                 return error(s, EINVAL, "Failed to generate key material");
246         }
247
248         return true;
249 }
250
251 // Send an ACKnowledgement record.
252 static bool send_ack(sptps_t *s) {
253         return send_record_priv(s, SPTPS_HANDSHAKE, "", 0);
254 }
255
256 // Receive an ACKnowledgement record.
257 static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
258         (void)data;
259
260         if(len) {
261                 return error(s, EIO, "Invalid ACK record length");
262         }
263
264         if(s->initiator) {
265                 if(!chacha_poly1305_set_key(s->incipher, s->key)) {
266                         return error(s, EINVAL, "Failed to set counter");
267                 }
268         } else {
269                 if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) {
270                         return error(s, EINVAL, "Failed to set counter");
271                 }
272         }
273
274         free(s->key);
275         s->key = NULL;
276         s->instate = true;
277
278         return true;
279 }
280
281 // Receive a Key EXchange record, respond by sending a SIG record.
282 static bool receive_kex(sptps_t *s, const uint8_t *data, uint16_t len) {
283         // Verify length of the HELLO record
284         if(len != 1 + 32 + ECDH_SIZE) {
285                 return error(s, EIO, "Invalid KEX record length");
286         }
287
288         // Ignore version number for now.
289
290         // Make a copy of the KEX message, send_sig() and receive_sig() need it
291         if(s->hiskex) {
292                 return error(s, EINVAL, "Received a second KEX message before first has been processed");
293         }
294
295         s->hiskex = realloc(s->hiskex, len);
296
297         if(!s->hiskex) {
298                 return error(s, errno, strerror(errno));
299         }
300
301         memcpy(s->hiskex, data, len);
302
303         if(s->initiator) {
304                 return send_sig(s);
305         } else {
306                 return true;
307         }
308 }
309
310 // Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
311 static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
312         size_t keylen = ECDH_SIZE;
313         size_t siglen = ecdsa_size(s->hiskey);
314
315         // Verify length of KEX record.
316         if(len != siglen) {
317                 return error(s, EIO, "Invalid KEX record length");
318         }
319
320         // Concatenate both KEX messages, plus tag indicating if it is from the connection originator
321         const size_t msglen = (1 + 32 + keylen) * 2 + 1 + s->labellen;
322         uint8_t *msg = alloca(msglen);
323
324         msg[0] = !s->initiator;
325         memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
326         memcpy(msg + 1 + 33 + keylen, s->mykex, 1 + 32 + keylen);
327         memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
328
329         // Verify signature.
330         if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
331                 return error(s, EIO, "Failed to verify SIG record");
332         }
333
334         // Compute shared secret.
335         uint8_t shared[ECDH_SHARED_SIZE];
336
337         if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) {
338                 return error(s, EINVAL, "Failed to compute ECDH shared secret");
339         }
340
341         s->ecdh = NULL;
342
343         // Generate key material from shared secret.
344         if(!generate_key_material(s, shared, sizeof(shared))) {
345                 return false;
346         }
347
348         if(!s->initiator && !send_sig(s)) {
349                 return false;
350         }
351
352         free(s->mykex);
353         free(s->hiskex);
354
355         s->mykex = NULL;
356         s->hiskex = NULL;
357
358         // Send cipher change record
359         if(s->outstate && !send_ack(s)) {
360                 return false;
361         }
362
363         // TODO: only set new keys after ACK has been set/received
364         if(s->initiator) {
365                 if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) {
366                         return error(s, EINVAL, "Failed to set key");
367                 }
368         } else {
369                 if(!chacha_poly1305_set_key(s->outcipher, s->key)) {
370                         return error(s, EINVAL, "Failed to set key");
371                 }
372         }
373
374         return true;
375 }
376
377 // Force another Key EXchange (for testing purposes).
378 bool sptps_force_kex(sptps_t *s) {
379         if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) {
380                 return error(s, EINVAL, "Cannot force KEX in current state");
381         }
382
383         s->state = SPTPS_KEX;
384         return send_kex(s);
385 }
386
387 // Receive a handshake record.
388 static bool receive_handshake(sptps_t *s, const uint8_t *data, uint16_t len) {
389         // Only a few states to deal with handshaking.
390         switch(s->state) {
391         case SPTPS_SECONDARY_KEX:
392
393                 // We receive a secondary KEX request, first respond by sending our own.
394                 if(!send_kex(s)) {
395                         return false;
396                 }
397
398         // Fall through
399         case SPTPS_KEX:
400
401                 // We have sent our KEX request, we expect our peer to sent one as well.
402                 if(!receive_kex(s, data, len)) {
403                         return false;
404                 }
405
406                 s->state = SPTPS_SIG;
407                 return true;
408
409         case SPTPS_SIG:
410
411                 // If we already sent our secondary public ECDH key, we expect the peer to send his.
412                 if(!receive_sig(s, data, len)) {
413                         return false;
414                 }
415
416                 if(s->outstate) {
417                         s->state = SPTPS_ACK;
418                 } else {
419                         s->outstate = true;
420
421                         if(!receive_ack(s, NULL, 0)) {
422                                 return false;
423                         }
424
425                         s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
426                         s->state = SPTPS_SECONDARY_KEX;
427                 }
428
429                 return true;
430
431         case SPTPS_ACK:
432
433                 // We expect a handshake message to indicate transition to the new keys.
434                 if(!receive_ack(s, data, len)) {
435                         return false;
436                 }
437
438                 s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
439                 s->state = SPTPS_SECONDARY_KEX;
440                 return true;
441
442         // TODO: split ACK into a VERify and ACK?
443         default:
444                 return error(s, EIO, "Invalid session state %d", s->state);
445         }
446 }
447
448 static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
449         // Replay protection using a sliding window of configurable size.
450         // s->inseqno is expected sequence number
451         // seqno is received sequence number
452         // s->late[] is a circular buffer, a 1 bit means a packet has not been received yet
453         // The circular buffer contains bits for sequence numbers from s->inseqno - s->replaywin * 8 to (but excluding) s->inseqno.
454         if(s->replaywin) {
455                 if(seqno != s->inseqno) {
456                         if(seqno >= s->inseqno + s->replaywin * 8) {
457                                 // Prevent packets that jump far ahead of the queue from causing many others to be dropped.
458                                 bool farfuture = s->farfuture < s->replaywin >> 2;
459
460                                 if(update_state) {
461                                         s->farfuture++;
462                                 }
463
464                                 if(farfuture) {
465                                         return update_state ? error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture) : false;
466                                 }
467
468                                 // Unless we have seen lots of them, in which case we consider the others lost.
469                                 if(update_state) {
470                                         warning(s, "Lost %d packets\n", seqno - s->inseqno);
471                                 }
472
473                                 if(update_state) {
474                                         // Mark all packets in the replay window as being late.
475                                         memset(s->late, 255, s->replaywin);
476                                 }
477                         } else if(seqno < s->inseqno) {
478                                 // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it.
479                                 if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) {
480                                         return update_state ? error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno) : false;
481                                 }
482                         } else if(update_state) {
483                                 // We missed some packets. Mark them in the bitmap as being late.
484                                 for(uint32_t i = s->inseqno; i < seqno; i++) {
485                                         s->late[(i / 8) % s->replaywin] |= 1 << i % 8;
486                                 }
487                         }
488                 }
489
490                 if(update_state) {
491                         // Mark the current packet as not being late.
492                         s->late[(seqno / 8) % s->replaywin] &= ~(1 << seqno % 8);
493                         s->farfuture = 0;
494                 }
495         }
496
497         if(update_state) {
498                 if(seqno >= s->inseqno) {
499                         s->inseqno = seqno + 1;
500                 }
501
502                 if(!s->inseqno) {
503                         s->received = 0;
504                 } else {
505                         s->received++;
506                 }
507         }
508
509         return true;
510 }
511
512 // Check datagram for valid HMAC
513 bool sptps_verify_datagram(sptps_t *s, const void *vdata, size_t len) {
514         if(!s->instate || len < 21) {
515                 return error(s, EIO, "Received short packet");
516         }
517
518         const uint8_t *data = vdata;
519         uint32_t seqno;
520         memcpy(&seqno, data, 4);
521         seqno = ntohl(seqno);
522
523         if(!sptps_check_seqno(s, seqno, false)) {
524                 return false;
525         }
526
527         uint8_t *buffer = alloca(len);
528         size_t outlen;
529         return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
530 }
531
532 // Receive incoming data, datagram version.
533 static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t len) {
534         if(len < (s->instate ? 21 : 5)) {
535                 return error(s, EIO, "Received short packet");
536         }
537
538         uint32_t seqno;
539         memcpy(&seqno, data, 4);
540         seqno = ntohl(seqno);
541         data += 4;
542         len -= 4;
543
544         if(!s->instate) {
545                 if(seqno != s->inseqno) {
546                         return error(s, EIO, "Invalid packet seqno: %d != %d", seqno, s->inseqno);
547                 }
548
549                 s->inseqno = seqno + 1;
550
551                 uint8_t type = *(data++);
552                 len--;
553
554                 if(type != SPTPS_HANDSHAKE) {
555                         return error(s, EIO, "Application record received before handshake finished");
556                 }
557
558                 return receive_handshake(s, data, len);
559         }
560
561         // Decrypt
562
563         uint8_t *buffer = alloca(len);
564         size_t outlen;
565
566         if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen)) {
567                 return error(s, EIO, "Failed to decrypt and verify packet");
568         }
569
570         if(!sptps_check_seqno(s, seqno, true)) {
571                 return false;
572         }
573
574         // Append a NULL byte for safety.
575         buffer[outlen] = 0;
576
577         data = buffer;
578         len = outlen;
579
580         uint8_t type = *(data++);
581         len--;
582
583         if(type < SPTPS_HANDSHAKE) {
584                 if(!s->instate) {
585                         return error(s, EIO, "Application record received before handshake finished");
586                 }
587
588                 if(!s->receive_record(s->handle, type, data, len)) {
589                         return false;
590                 }
591         } else if(type == SPTPS_HANDSHAKE) {
592                 if(!receive_handshake(s, data, len)) {
593                         return false;
594                 }
595         } else {
596                 return error(s, EIO, "Invalid record type %d", type);
597         }
598
599         return true;
600 }
601
602 // Receive incoming data. Check if it contains a complete record, if so, handle it.
603 size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
604         const uint8_t *data = vdata;
605         size_t total_read = 0;
606
607         if(!s->state) {
608                 return error(s, EIO, "Invalid session state zero");
609         }
610
611         if(s->datagram) {
612                 return sptps_receive_data_datagram(s, data, len) ? len : false;
613         }
614
615         // First read the 2 length bytes.
616         if(s->buflen < 2) {
617                 size_t toread = 2 - s->buflen;
618
619                 if(toread > len) {
620                         toread = len;
621                 }
622
623                 memcpy(s->inbuf + s->buflen, data, toread);
624
625                 total_read += toread;
626                 s->buflen += toread;
627                 len -= toread;
628                 data += toread;
629
630                 // Exit early if we don't have the full length.
631                 if(s->buflen < 2) {
632                         return total_read;
633                 }
634
635                 // Get the length bytes
636
637                 memcpy(&s->reclen, s->inbuf, 2);
638                 s->reclen = ntohs(s->reclen);
639
640                 // If we have the length bytes, ensure our buffer can hold the whole request.
641                 s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
642
643                 if(!s->inbuf) {
644                         return error(s, errno, strerror(errno));
645                 }
646
647                 // Exit early if we have no more data to process.
648                 if(!len) {
649                         return total_read;
650                 }
651         }
652
653         // Read up to the end of the record.
654         size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
655
656         if(toread > len) {
657                 toread = len;
658         }
659
660         memcpy(s->inbuf + s->buflen, data, toread);
661         total_read += toread;
662         s->buflen += toread;
663
664         // If we don't have a whole record, exit.
665         if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {
666                 return total_read;
667         }
668
669         // Update sequence number.
670
671         uint32_t seqno = s->inseqno++;
672
673         // Check HMAC and decrypt.
674         if(s->instate) {
675                 if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
676                         return error(s, EINVAL, "Failed to decrypt and verify record");
677                 }
678         }
679
680         // Append a NULL byte for safety.
681         s->inbuf[s->reclen + 3UL] = 0;
682
683         uint8_t type = s->inbuf[2];
684
685         if(type < SPTPS_HANDSHAKE) {
686                 if(!s->instate) {
687                         return error(s, EIO, "Application record received before handshake finished");
688                 }
689
690                 if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen)) {
691                         return false;
692                 }
693         } else if(type == SPTPS_HANDSHAKE) {
694                 if(!receive_handshake(s, s->inbuf + 3, s->reclen)) {
695                         return false;
696                 }
697         } else {
698                 return error(s, EIO, "Invalid record type %d", type);
699         }
700
701         s->buflen = 0;
702
703         return total_read;
704 }
705
706 // Start a SPTPS session.
707 bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
708         // Initialise struct sptps
709         memset(s, 0, sizeof(*s));
710
711         s->handle = handle;
712         s->initiator = initiator;
713         s->datagram = datagram;
714         s->mykey = mykey;
715         s->hiskey = hiskey;
716         s->replaywin = sptps_replaywin;
717
718         if(s->replaywin) {
719                 s->late = malloc(s->replaywin);
720
721                 if(!s->late) {
722                         return error(s, errno, strerror(errno));
723                 }
724
725                 memset(s->late, 0, s->replaywin);
726         }
727
728         s->label = malloc(labellen);
729
730         if(!s->label) {
731                 return error(s, errno, strerror(errno));
732         }
733
734         if(!datagram) {
735                 s->inbuf = malloc(7);
736
737                 if(!s->inbuf) {
738                         return error(s, errno, strerror(errno));
739                 }
740
741                 s->buflen = 0;
742         }
743
744         memcpy(s->label, label, labellen);
745         s->labellen = labellen;
746
747         s->send_data = send_data;
748         s->receive_record = receive_record;
749
750         // Do first KEX immediately
751         s->state = SPTPS_KEX;
752         return send_kex(s);
753 }
754
755 // Stop a SPTPS session.
756 bool sptps_stop(sptps_t *s) {
757         // Clean up any resources.
758         chacha_poly1305_exit(s->incipher);
759         chacha_poly1305_exit(s->outcipher);
760         ecdh_free(s->ecdh);
761         free(s->inbuf);
762         free(s->mykex);
763         free(s->hiskex);
764         free(s->key);
765         free(s->label);
766         free(s->late);
767         memset(s, 0, sizeof(*s));
768         return true;
769 }