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