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