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