2 sptps.c -- Simple Peer-to-Peer Security
3 Copyright (C) 2011-2021 Guus Sliepen <guus@tinc-vpn.org>,
4 2010 Brandon L. Black <blblack@gmail.com>
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.
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.
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.
23 #include "chacha-poly1305/chachapoly.h"
32 #include <openssl/evp.h>
35 #define CIPHER_KEYLEN 64
37 unsigned int sptps_replaywin = 16;
40 Nonce MUST be exchanged first (done)
41 Signatures MUST be done over both nonces, to guarantee the signature is fresh
42 Otherwise: if ECDHE key of one side is compromised, it can be reused!
44 Add explicit tag to beginning of structure to distinguish the client and server when signing. (done)
46 Sign all handshake messages up to ECDHE kex with long-term public keys. (done)
48 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?)
50 Explicit close message needs to be added.
52 Maybe do add some alert messages to give helpful error messages? Not more than TLS sends.
54 Use counter mode instead of OFB. (done)
56 Make sure ECC operations are fixed time (aka prevent side-channel attacks).
59 void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap) {
66 void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap) {
70 vfprintf(stderr, format, ap);
74 void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap) = sptps_log_stderr;
76 // Log an error message.
77 static bool error(sptps_t *s, int s_errno, const char *format, ...) ATTR_FORMAT(printf, 3, 4);
78 static bool error(sptps_t *s, int s_errno, const char *format, ...) {
85 sptps_log(s, s_errno, format, ap);
93 static void warning(sptps_t *s, const char *format, ...) ATTR_FORMAT(printf, 2, 3);
94 static void warning(sptps_t *s, const char *format, ...) {
97 sptps_log(s, 0, format, ap);
101 static sptps_kex_t *new_sptps_kex(void) {
102 return xzalloc(sizeof(sptps_kex_t));
105 static void free_sptps_kex(sptps_kex_t *kex) {
106 xzfree(kex, sizeof(sptps_kex_t));
109 static sptps_key_t *new_sptps_key(void) {
110 return xzalloc(sizeof(sptps_key_t));
113 static void free_sptps_key(sptps_key_t *key) {
114 xzfree(key, sizeof(sptps_key_t));
117 static bool cipher_init(uint8_t suite, void **ctx, const sptps_key_t *keys, bool key_half) {
118 const uint8_t *key = key_half ? keys->key1 : keys->key0;
123 case SPTPS_CHACHA_POLY1305:
124 *ctx = malloc(sizeof(struct chachapoly_ctx));
125 return *ctx && chachapoly_init(*ctx, key, 256) == CHACHAPOLY_OK;
129 case SPTPS_CHACHA_POLY1305:
130 *ctx = EVP_CIPHER_CTX_new();
136 return EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
137 && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
138 && EVP_EncryptInit_ex(*ctx, NULL, NULL, key, key + 32);
140 case SPTPS_AES256_GCM:
141 *ctx = EVP_CIPHER_CTX_new();
147 return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
148 && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
149 && EVP_EncryptInit_ex(*ctx, NULL, NULL, key, key + 32);
157 static void cipher_exit(uint8_t suite, void *ctx) {
161 case SPTPS_CHACHA_POLY1305:
167 case SPTPS_CHACHA_POLY1305:
168 case SPTPS_AES256_GCM:
169 EVP_CIPHER_CTX_free(ctx);
178 static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
182 case SPTPS_CHACHA_POLY1305: {
183 if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) {
188 *outlen = inlen + 16;
196 case SPTPS_CHACHA_POLY1305:
197 case SPTPS_AES256_GCM: {
198 uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
200 if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
204 int outlen1 = 0, outlen2 = 0;
206 if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
210 if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
216 if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
236 static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
246 case SPTPS_CHACHA_POLY1305:
247 if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) {
259 case SPTPS_CHACHA_POLY1305:
260 case SPTPS_AES256_GCM: {
261 uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
263 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
267 int outlen1 = 0, outlen2 = 0;
269 if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
273 if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
277 if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
282 *outlen = outlen1 + outlen2;
295 // Send a record (datagram version, accepts all record types, handles encryption and authentication).
296 static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
297 uint8_t *buffer = alloca(len + SPTPS_DATAGRAM_OVERHEAD);
298 // Create header with sequence number, length and record type
299 uint32_t seqno = s->outseqno++;
301 memcpy(buffer, &seqno, 4);
303 memcpy(buffer + 5, data, len);
306 // If first handshake has finished, encrypt and HMAC
307 if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL)) {
308 return error(s, EINVAL, "Failed to encrypt message");
311 return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_OVERHEAD);
313 // Otherwise send as plaintext
314 return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_HEADER);
317 // Send a record (private version, accepts all record types, handles encryption and authentication).
318 static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
320 return send_record_priv_datagram(s, type, data, len);
323 uint8_t *buffer = alloca(len + SPTPS_OVERHEAD);
325 // Create header with sequence number, length and record type
326 uint32_t seqno = s->outseqno++;
327 uint16_t netlen = len;
329 memcpy(buffer, &netlen, 2);
331 memcpy(buffer + 3, data, len);
334 // If first handshake has finished, encrypt and HMAC
335 if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL)) {
336 return error(s, EINVAL, "Failed to encrypt message");
339 return s->send_data(s->handle, type, buffer, len + SPTPS_OVERHEAD);
341 // Otherwise send as plaintext
342 return s->send_data(s->handle, type, buffer, len + SPTPS_HEADER);
346 // Send an application record.
347 bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
348 // Sanity checks: application cannot send data before handshake is finished,
349 // and only record types 0..127 are allowed.
351 return error(s, EINVAL, "Handshake phase not finished yet");
354 if(type >= SPTPS_HANDSHAKE) {
355 return error(s, EINVAL, "Invalid application record type");
358 return send_record_priv(s, type, data, len);
361 // Send a Key EXchange record, containing a random nonce and an ECDHE public key.
362 static bool send_kex(sptps_t *s) {
363 // Make room for our KEX message, which we will keep around since send_sig() needs it.
368 s->mykex = new_sptps_kex();
370 // Set version byte to zero.
371 s->mykex->version = SPTPS_VERSION;
372 s->mykex->preferred_suite = s->preferred_suite;
373 s->mykex->cipher_suites = s->cipher_suites;
375 // Create a random nonce.
376 randomize(s->mykex->nonce, ECDH_SIZE);
378 // Create a new ECDH public key.
379 if(!(s->ecdh = ecdh_generate_public(s->mykex->pubkey))) {
380 return error(s, EINVAL, "Failed to generate ECDH public key");
383 return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, sizeof(sptps_kex_t));
386 static size_t sigmsg_len(size_t labellen) {
387 return 1 + 2 * sizeof(sptps_kex_t) + labellen;
390 static void fill_msg(uint8_t *msg, bool initiator, const sptps_kex_t *kex0, const sptps_kex_t *kex1, const sptps_t *s) {
391 *msg = initiator, msg++;
392 memcpy(msg, kex0, sizeof(*kex0)), msg += sizeof(*kex0);
393 memcpy(msg, kex1, sizeof(*kex1)), msg += sizeof(*kex1);
394 memcpy(msg, s->label, s->labellen);
397 // Send a SIGnature record, containing an Ed25519 signature over both KEX records.
398 static bool send_sig(sptps_t *s) {
399 // Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label
400 size_t msglen = sigmsg_len(s->labellen);
401 uint8_t *msg = alloca(msglen);
402 fill_msg(msg, s->initiator, s->mykex, s->hiskex, s);
405 size_t siglen = ecdsa_size(s->mykey);
406 uint8_t *sig = alloca(siglen);
408 if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
409 return error(s, EINVAL, "Failed to sign SIG record");
412 // Send the SIG exchange record.
413 return send_record_priv(s, SPTPS_HANDSHAKE, sig, siglen);
416 // Generate key material from the shared secret created from the ECDHE key exchange.
417 static bool generate_key_material(sptps_t *s, const uint8_t *shared, size_t len) {
418 // Allocate memory for key material
419 s->key = new_sptps_key();
421 // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
422 const size_t msglen = sizeof("key expansion") - 1;
423 const size_t seedlen = msglen + s->labellen + ECDH_SIZE * 2;
424 uint8_t *seed = alloca(seedlen);
427 memcpy(ptr, "key expansion", msglen);
430 memcpy(ptr, (s->initiator ? s->mykex : s->hiskex)->nonce, ECDH_SIZE);
433 memcpy(ptr, (s->initiator ? s->hiskex : s->mykex)->nonce, ECDH_SIZE);
436 memcpy(ptr, s->label, s->labellen);
438 // Use PRF to generate the key material
439 if(!prf(shared, len, seed, seedlen, s->key->both, sizeof(sptps_key_t))) {
440 return error(s, EINVAL, "Failed to generate key material");
446 // Send an ACKnowledgement record.
447 static bool send_ack(sptps_t *s) {
448 return send_record_priv(s, SPTPS_HANDSHAKE, "", 0);
451 // Receive an ACKnowledgement record.
452 static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
456 return error(s, EIO, "Invalid ACK record length");
459 if(!cipher_init(s->cipher_suite, &s->incipher, s->key, s->initiator)) {
460 return error(s, EINVAL, "Failed to initialize cipher");
463 free_sptps_key(s->key);
470 static uint8_t select_cipher_suite(uint16_t mask, uint8_t pref1, uint8_t pref2) {
471 // Check if there is a viable preference, if so select the lowest one
472 uint8_t selection = 255;
474 if(mask & (1U << pref1)) {
478 if(pref2 < selection && (mask & (1U << pref2))) {
482 // Otherwise, select the lowest cipher suite both sides support
483 if(selection == 255) {
486 while(!(mask & 1U)) {
495 // Receive a Key EXchange record, respond by sending a SIG record.
496 static bool receive_kex(sptps_t *s, const uint8_t *data, uint16_t len) {
497 // Verify length of the HELLO record
499 if(len != sizeof(sptps_kex_t)) {
500 return error(s, EIO, "Invalid KEX record length");
503 if(*data != SPTPS_VERSION) {
504 return error(s, EINVAL, "Received incorrect version %d", *data);
508 memcpy(&suites, data + 2, 2);
509 suites &= s->cipher_suites;
512 return error(s, EIO, "No matching cipher suites");
515 s->cipher_suite = select_cipher_suite(suites, s->preferred_suite, data[1] & 0xf);
517 // Make a copy of the KEX message, send_sig() and receive_sig() need it
519 return error(s, EINVAL, "Received a second KEX message before first has been processed");
522 s->hiskex = new_sptps_kex();
523 memcpy(s->hiskex, data, sizeof(sptps_kex_t));
532 // Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
533 static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
534 // Verify length of KEX record.
535 if(len != ecdsa_size(s->hiskey)) {
536 return error(s, EIO, "Invalid KEX record length");
539 // Concatenate both KEX messages, plus tag indicating if it is from the connection originator
540 const size_t msglen = sigmsg_len(s->labellen);
541 uint8_t *msg = alloca(msglen);
542 fill_msg(msg, !s->initiator, s->hiskex, s->mykex, s);
545 if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
546 return error(s, EIO, "Failed to verify SIG record");
549 // Compute shared secret.
550 uint8_t shared[ECDH_SHARED_SIZE];
552 if(!ecdh_compute_shared(s->ecdh, s->hiskex->pubkey, shared)) {
553 memzero(shared, sizeof(shared));
554 return error(s, EINVAL, "Failed to compute ECDH shared secret");
559 // Generate key material from shared secret.
560 bool generated = generate_key_material(s, shared, sizeof(shared));
561 memzero(shared, sizeof(shared));
567 if(!s->initiator && !send_sig(s)) {
571 free_sptps_kex(s->mykex);
574 free_sptps_kex(s->hiskex);
577 // Send cipher change record
578 if(s->outstate && !send_ack(s)) {
582 if(!cipher_init(s->cipher_suite, &s->outcipher, s->key, !s->initiator)) {
583 return error(s, EINVAL, "Failed to initialize cipher");
589 // Force another Key EXchange (for testing purposes).
590 bool sptps_force_kex(sptps_t *s) {
591 if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) {
592 return error(s, EINVAL, "Cannot force KEX in current state");
595 s->state = SPTPS_KEX;
599 // Receive a handshake record.
600 static bool receive_handshake(sptps_t *s, const uint8_t *data, uint16_t len) {
601 // Only a few states to deal with handshaking.
603 case SPTPS_SECONDARY_KEX:
605 // We receive a secondary KEX request, first respond by sending our own.
613 // We have sent our KEX request, we expect our peer to sent one as well.
614 if(!receive_kex(s, data, len)) {
618 s->state = SPTPS_SIG;
623 // If we already sent our secondary public ECDH key, we expect the peer to send his.
624 if(!receive_sig(s, data, len)) {
629 s->state = SPTPS_ACK;
633 if(!receive_ack(s, NULL, 0)) {
637 s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
638 s->state = SPTPS_SECONDARY_KEX;
645 // We expect a handshake message to indicate transition to the new keys.
646 if(!receive_ack(s, data, len)) {
650 s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
651 s->state = SPTPS_SECONDARY_KEX;
654 // TODO: split ACK into a VERify and ACK?
656 return error(s, EIO, "Invalid session state %d", s->state);
660 static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
661 // Replay protection using a sliding window of configurable size.
662 // s->inseqno is expected sequence number
663 // seqno is received sequence number
664 // s->late[] is a circular buffer, a 1 bit means a packet has not been received yet
665 // The circular buffer contains bits for sequence numbers from s->inseqno - s->replaywin * 8 to (but excluding) s->inseqno.
667 if(seqno != s->inseqno) {
668 if(seqno >= s->inseqno + s->replaywin * 8) {
669 // Prevent packets that jump far ahead of the queue from causing many others to be dropped.
670 bool farfuture = s->farfuture < s->replaywin >> 2;
677 return update_state ? error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture) : false;
680 // Unless we have seen lots of them, in which case we consider the others lost.
682 warning(s, "Lost %d packets\n", seqno - s->inseqno);
686 // Mark all packets in the replay window as being late.
687 memset(s->late, 255, s->replaywin);
689 } else if(seqno < s->inseqno) {
690 // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it.
691 if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) {
692 return update_state ? error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno) : false;
694 } else if(update_state) {
695 // We missed some packets. Mark them in the bitmap as being late.
696 for(uint32_t i = s->inseqno; i < seqno; i++) {
697 s->late[(i / 8) % s->replaywin] |= 1 << i % 8;
703 // Mark the current packet as not being late.
704 s->late[(seqno / 8) % s->replaywin] &= ~(1 << seqno % 8);
710 if(seqno >= s->inseqno) {
711 s->inseqno = seqno + 1;
724 // Check datagram for valid HMAC
725 bool sptps_verify_datagram(sptps_t *s, const void *vdata, size_t len) {
726 if(!s->instate || len < 21) {
727 return error(s, EIO, "Received short packet");
730 const uint8_t *data = vdata;
732 memcpy(&seqno, data, 4);
734 if(!sptps_check_seqno(s, seqno, false)) {
738 uint8_t *buffer = alloca(len);
739 return cipher_decrypt(s->cipher_suite, s->incipher, seqno, data + 4, len - 4, buffer, NULL);
742 // Receive incoming data, datagram version.
743 static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t len) {
744 if(len < (s->instate ? 21 : 5)) {
745 return error(s, EIO, "Received short packet");
749 memcpy(&seqno, data, 4);
754 if(seqno != s->inseqno) {
755 return error(s, EIO, "Invalid packet seqno: %d != %d", seqno, s->inseqno);
758 s->inseqno = seqno + 1;
760 uint8_t type = *(data++);
763 if(type != SPTPS_HANDSHAKE) {
764 return error(s, EIO, "Application record received before handshake finished");
767 return receive_handshake(s, data, len);
772 uint8_t *buffer = alloca(len);
775 if(!cipher_decrypt(s->cipher_suite, s->incipher, seqno, data, len, buffer, &outlen)) {
776 return error(s, EIO, "Failed to decrypt and verify packet");
779 if(!sptps_check_seqno(s, seqno, true)) {
783 // Append a NULL byte for safety.
789 uint8_t type = *(data++);
792 if(type < SPTPS_HANDSHAKE) {
794 return error(s, EIO, "Application record received before handshake finished");
797 if(!s->receive_record(s->handle, type, data, len)) {
800 } else if(type == SPTPS_HANDSHAKE) {
801 if(!receive_handshake(s, data, len)) {
805 return error(s, EIO, "Invalid record type %d", type);
811 // Receive incoming data. Check if it contains a complete record, if so, handle it.
812 size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
813 const uint8_t *data = vdata;
814 size_t total_read = 0;
817 return error(s, EIO, "Invalid session state zero");
821 return sptps_receive_data_datagram(s, data, len) ? len : false;
824 // First read the 2 length bytes.
826 size_t toread = 2 - s->buflen;
832 memcpy(s->inbuf + s->buflen, data, toread);
834 total_read += toread;
839 // Exit early if we don't have the full length.
844 // Get the length bytes
846 memcpy(&s->reclen, s->inbuf, 2);
848 // If we have the length bytes, ensure our buffer can hold the whole request.
849 s->inbuf = realloc(s->inbuf, s->reclen + SPTPS_OVERHEAD);
852 return error(s, errno, "%s", strerror(errno));
855 // Exit early if we have no more data to process.
861 // Read up to the end of the record.
862 size_t toread = s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER) - s->buflen;
868 memcpy(s->inbuf + s->buflen, data, toread);
869 total_read += toread;
872 // If we don't have a whole record, exit.
873 if(s->buflen < s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER)) {
877 // Update sequence number.
879 uint32_t seqno = s->inseqno++;
881 // Check HMAC and decrypt.
883 if(!cipher_decrypt(s->cipher_suite, s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
884 return error(s, EINVAL, "Failed to decrypt and verify record");
888 // Append a NULL byte for safety.
889 s->inbuf[s->reclen + SPTPS_HEADER] = 0;
891 uint8_t type = s->inbuf[2];
893 if(type < SPTPS_HANDSHAKE) {
895 return error(s, EIO, "Application record received before handshake finished");
898 if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen)) {
901 } else if(type == SPTPS_HANDSHAKE) {
902 if(!receive_handshake(s, s->inbuf + 3, s->reclen)) {
906 return error(s, EIO, "Invalid record type %d", type);
914 // Start a SPTPS session.
915 bool sptps_start(sptps_t *s, const sptps_params_t *params) {
916 // Initialise struct sptps
917 memset(s, 0, sizeof(*s));
919 s->handle = params->handle;
920 s->initiator = params->initiator;
921 s->datagram = params->datagram;
922 s->mykey = params->mykey;
923 s->hiskey = params->hiskey;
924 s->replaywin = sptps_replaywin;
925 s->cipher_suites = params->cipher_suites ? params->cipher_suites & SPTPS_ALL_CIPHER_SUITES : SPTPS_ALL_CIPHER_SUITES;
926 s->preferred_suite = params->preferred_suite;
929 s->late = malloc(s->replaywin);
932 return error(s, errno, "%s", strerror(errno));
935 memset(s->late, 0, s->replaywin);
938 s->labellen = params->labellen ? params->labellen : strlen(params->label);
939 s->label = malloc(s->labellen);
942 return error(s, errno, "%s", strerror(errno));
945 memcpy(s->label, params->label, s->labellen);
948 s->inbuf = malloc(7);
951 return error(s, errno, "%s", strerror(errno));
958 s->send_data = params->send_data;
959 s->receive_record = params->receive_record;
961 // Do first KEX immediately
962 s->state = SPTPS_KEX;
966 // Stop a SPTPS session.
967 bool sptps_stop(sptps_t *s) {
968 // Clean up any resources.
969 cipher_exit(s->cipher_suite, s->incipher);
970 cipher_exit(s->cipher_suite, s->outcipher);
973 free_sptps_kex(s->mykex);
974 free_sptps_kex(s->hiskex);
975 free_sptps_key(s->key);
978 memset(s, 0, sizeof(*s));