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