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>
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/chacha-poly1305.h"
31 unsigned int sptps_replaywin = 16;
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!
38 Add explicit tag to beginning of structure to distinguish the client and server when signing. (done)
40 Sign all handshake messages up to ECDHE kex with long-term public keys. (done)
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?)
44 Explicit close message needs to be added.
46 Maybe do add some alert messages to give helpful error messages? Not more than TLS sends.
48 Use counter mode instead of OFB. (done)
50 Make sure ECC operations are fixed time (aka prevent side-channel attacks).
53 void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap) {
60 void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap) {
64 vfprintf(stderr, format, ap);
68 void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap) = sptps_log_stderr;
70 // Log an error message.
71 static bool error(sptps_t *s, int s_errno, const char *format, ...) {
78 sptps_log(s, s_errno, format, ap);
86 static void warning(sptps_t *s, const char *format, ...) {
89 sptps_log(s, 0, format, ap);
93 static sptps_kex_t *new_sptps_kex(void) {
94 return xzalloc(sizeof(sptps_kex_t));
97 static void free_sptps_kex(sptps_kex_t *kex) {
98 xzfree(kex, sizeof(sptps_kex_t));
101 static sptps_key_t *new_sptps_key(void) {
102 return xzalloc(sizeof(sptps_key_t));
105 static void free_sptps_key(sptps_key_t *key) {
106 xzfree(key, sizeof(sptps_key_t));
109 // Send a record (datagram version, accepts all record types, handles encryption and authentication).
110 static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
111 uint8_t *buffer = alloca(len + 21UL);
113 // Create header with sequence number, length and record type
114 uint32_t seqno = s->outseqno++;
115 uint32_t netseqno = ntohl(seqno);
117 memcpy(buffer, &netseqno, 4);
119 memcpy(buffer + 5, data, len);
122 // If first handshake has finished, encrypt and HMAC
123 chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL);
124 return s->send_data(s->handle, type, buffer, len + 21UL);
126 // Otherwise send as plaintext
127 return s->send_data(s->handle, type, buffer, len + 5UL);
130 // Send a record (private version, accepts all record types, handles encryption and authentication).
131 static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
133 return send_record_priv_datagram(s, type, data, len);
136 uint8_t *buffer = alloca(len + 19UL);
138 // Create header with sequence number, length and record type
139 uint32_t seqno = s->outseqno++;
140 uint16_t netlen = htons(len);
142 memcpy(buffer, &netlen, 2);
144 memcpy(buffer + 3, data, len);
147 // If first handshake has finished, encrypt and HMAC
148 chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL);
149 return s->send_data(s->handle, type, buffer, len + 19UL);
151 // Otherwise send as plaintext
152 return s->send_data(s->handle, type, buffer, len + 3UL);
156 // Send an application record.
157 bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
158 // Sanity checks: application cannot send data before handshake is finished,
159 // and only record types 0..127 are allowed.
161 return error(s, EINVAL, "Handshake phase not finished yet");
164 if(type >= SPTPS_HANDSHAKE) {
165 return error(s, EINVAL, "Invalid application record type");
168 return send_record_priv(s, type, data, len);
171 // Send a Key EXchange record, containing a random nonce and an ECDHE public key.
172 static bool send_kex(sptps_t *s) {
173 // Make room for our KEX message, which we will keep around since send_sig() needs it.
178 s->mykex = new_sptps_kex();
180 // Set version byte to zero.
181 s->mykex->version = SPTPS_VERSION;
183 // Create a random nonce.
184 randomize(s->mykex->nonce, ECDH_SIZE);
186 // Create a new ECDH public key.
187 if(!(s->ecdh = ecdh_generate_public(s->mykex->pubkey))) {
188 return error(s, EINVAL, "Failed to generate ECDH public key");
191 return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, sizeof(sptps_kex_t));
194 static size_t sigmsg_len(size_t labellen) {
195 return 1 + 2 * sizeof(sptps_kex_t) + labellen;
198 static void fill_msg(uint8_t *msg, bool initiator, const sptps_kex_t *kex0, const sptps_kex_t *kex1, const sptps_t *s) {
199 *msg = initiator, msg++;
200 memcpy(msg, kex0, sizeof(*kex0)), msg += sizeof(*kex0);
201 memcpy(msg, kex1, sizeof(*kex1)), msg += sizeof(*kex1);
202 memcpy(msg, s->label, s->labellen);
205 // Send a SIGnature record, containing an Ed25519 signature over both KEX records.
206 static bool send_sig(sptps_t *s) {
207 // Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label
208 size_t msglen = sigmsg_len(s->labellen);
209 uint8_t *msg = alloca(msglen);
210 fill_msg(msg, s->initiator, s->mykex, s->hiskex, s);
213 size_t siglen = ecdsa_size(s->mykey);
214 uint8_t *sig = alloca(siglen);
216 if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
217 return error(s, EINVAL, "Failed to sign SIG record");
220 // Send the SIG exchange record.
221 return send_record_priv(s, SPTPS_HANDSHAKE, sig, siglen);
224 // Generate key material from the shared secret created from the ECDHE key exchange.
225 static bool generate_key_material(sptps_t *s, const uint8_t *shared, size_t len) {
226 // Initialise cipher and digest structures if necessary
228 s->incipher = chacha_poly1305_init();
229 s->outcipher = chacha_poly1305_init();
231 if(!s->incipher || !s->outcipher) {
232 return error(s, EINVAL, "Failed to open cipher");
236 // Allocate memory for key material
237 s->key = new_sptps_key();
239 // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
240 const size_t msglen = sizeof("key expansion") - 1;
241 const size_t seedlen = msglen + s->labellen + ECDH_SIZE * 2;
242 uint8_t *seed = alloca(seedlen);
245 memcpy(ptr, "key expansion", msglen);
248 memcpy(ptr, (s->initiator ? s->mykex : s->hiskex)->nonce, ECDH_SIZE);
251 memcpy(ptr, (s->initiator ? s->hiskex : s->mykex)->nonce, ECDH_SIZE);
254 memcpy(ptr, s->label, s->labellen);
256 // Use PRF to generate the key material
257 if(!prf(shared, len, seed, seedlen, s->key->both, sizeof(sptps_key_t))) {
258 return error(s, EINVAL, "Failed to generate key material");
264 // Send an ACKnowledgement record.
265 static bool send_ack(sptps_t *s) {
266 return send_record_priv(s, SPTPS_HANDSHAKE, "", 0);
269 // Receive an ACKnowledgement record.
270 static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
274 return error(s, EIO, "Invalid ACK record length");
277 uint8_t *key = s->initiator ? s->key->key0 : s->key->key1;
279 if(!chacha_poly1305_set_key(s->incipher, key)) {
280 return error(s, EINVAL, "Failed to set counter");
283 free_sptps_key(s->key);
290 // Receive a Key EXchange record, respond by sending a SIG record.
291 static bool receive_kex(sptps_t *s, const uint8_t *data, uint16_t len) {
292 // Verify length of the HELLO record
293 if(len != sizeof(sptps_kex_t)) {
294 return error(s, EIO, "Invalid KEX record length");
297 if(*data != SPTPS_VERSION) {
298 return error(s, EINVAL, "Received incorrect version %d", *data);
301 // Make a copy of the KEX message, send_sig() and receive_sig() need it
303 return error(s, EINVAL, "Received a second KEX message before first has been processed");
306 s->hiskex = new_sptps_kex();
307 memcpy(s->hiskex, data, sizeof(sptps_kex_t));
316 // Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
317 static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
318 // Verify length of KEX record.
319 if(len != ecdsa_size(s->hiskey)) {
320 return error(s, EIO, "Invalid KEX record length");
323 // Concatenate both KEX messages, plus tag indicating if it is from the connection originator
324 const size_t msglen = sigmsg_len(s->labellen);
325 uint8_t *msg = alloca(msglen);
326 fill_msg(msg, !s->initiator, s->hiskex, s->mykex, s);
329 if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
330 return error(s, EIO, "Failed to verify SIG record");
333 // Compute shared secret.
334 uint8_t shared[ECDH_SHARED_SIZE];
336 if(!ecdh_compute_shared(s->ecdh, s->hiskex->pubkey, shared)) {
337 memzero(shared, sizeof(shared));
338 return error(s, EINVAL, "Failed to compute ECDH shared secret");
343 // Generate key material from shared secret.
344 bool generated = generate_key_material(s, shared, sizeof(shared));
345 memzero(shared, sizeof(shared));
351 if(!s->initiator && !send_sig(s)) {
355 free_sptps_kex(s->mykex);
358 free_sptps_kex(s->hiskex);
361 // Send cipher change record
362 if(s->outstate && !send_ack(s)) {
366 // TODO: only set new keys after ACK has been set/received
367 uint8_t *key = s->initiator ? s->key->key1 : s->key->key0;
369 if(!chacha_poly1305_set_key(s->outcipher, key)) {
370 return error(s, EINVAL, "Failed to set key");
376 // Force another Key EXchange (for testing purposes).
377 bool sptps_force_kex(sptps_t *s) {
378 if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) {
379 return error(s, EINVAL, "Cannot force KEX in current state");
382 s->state = SPTPS_KEX;
386 // Receive a handshake record.
387 static bool receive_handshake(sptps_t *s, const uint8_t *data, uint16_t len) {
388 // Only a few states to deal with handshaking.
390 case SPTPS_SECONDARY_KEX:
392 // We receive a secondary KEX request, first respond by sending our own.
400 // We have sent our KEX request, we expect our peer to sent one as well.
401 if(!receive_kex(s, data, len)) {
405 s->state = SPTPS_SIG;
410 // If we already sent our secondary public ECDH key, we expect the peer to send his.
411 if(!receive_sig(s, data, len)) {
416 s->state = SPTPS_ACK;
420 if(!receive_ack(s, NULL, 0)) {
424 s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
425 s->state = SPTPS_SECONDARY_KEX;
432 // We expect a handshake message to indicate transition to the new keys.
433 if(!receive_ack(s, data, len)) {
437 s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
438 s->state = SPTPS_SECONDARY_KEX;
441 // TODO: split ACK into a VERify and ACK?
443 return error(s, EIO, "Invalid session state %d", s->state);
447 static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
448 // Replay protection using a sliding window of configurable size.
449 // s->inseqno is expected sequence number
450 // seqno is received sequence number
451 // s->late[] is a circular buffer, a 1 bit means a packet has not been received yet
452 // The circular buffer contains bits for sequence numbers from s->inseqno - s->replaywin * 8 to (but excluding) s->inseqno.
454 if(seqno != s->inseqno) {
455 if(seqno >= s->inseqno + s->replaywin * 8) {
456 // Prevent packets that jump far ahead of the queue from causing many others to be dropped.
457 bool farfuture = s->farfuture < s->replaywin >> 2;
464 return update_state ? error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture) : false;
467 // Unless we have seen lots of them, in which case we consider the others lost.
469 warning(s, "Lost %d packets\n", seqno - s->inseqno);
473 // Mark all packets in the replay window as being late.
474 memset(s->late, 255, s->replaywin);
476 } else if(seqno < s->inseqno) {
477 // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it.
478 if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) {
479 return update_state ? error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno) : false;
481 } else if(update_state) {
482 // We missed some packets. Mark them in the bitmap as being late.
483 for(uint32_t i = s->inseqno; i < seqno; i++) {
484 s->late[(i / 8) % s->replaywin] |= 1 << i % 8;
490 // Mark the current packet as not being late.
491 s->late[(seqno / 8) % s->replaywin] &= ~(1 << seqno % 8);
497 if(seqno >= s->inseqno) {
498 s->inseqno = seqno + 1;
511 // Check datagram for valid HMAC
512 bool sptps_verify_datagram(sptps_t *s, const void *vdata, size_t len) {
513 if(!s->instate || len < 21) {
514 return error(s, EIO, "Received short packet");
517 const uint8_t *data = vdata;
519 memcpy(&seqno, data, 4);
520 seqno = ntohl(seqno);
522 if(!sptps_check_seqno(s, seqno, false)) {
526 uint8_t *buffer = alloca(len);
528 return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
531 // Receive incoming data, datagram version.
532 static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t len) {
533 if(len < (s->instate ? 21 : 5)) {
534 return error(s, EIO, "Received short packet");
538 memcpy(&seqno, data, 4);
539 seqno = ntohl(seqno);
544 if(seqno != s->inseqno) {
545 return error(s, EIO, "Invalid packet seqno: %d != %d", seqno, s->inseqno);
548 s->inseqno = seqno + 1;
550 uint8_t type = *(data++);
553 if(type != SPTPS_HANDSHAKE) {
554 return error(s, EIO, "Application record received before handshake finished");
557 return receive_handshake(s, data, len);
562 uint8_t *buffer = alloca(len);
565 if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen)) {
566 return error(s, EIO, "Failed to decrypt and verify packet");
569 if(!sptps_check_seqno(s, seqno, true)) {
573 // Append a NULL byte for safety.
579 uint8_t type = *(data++);
582 if(type < SPTPS_HANDSHAKE) {
584 return error(s, EIO, "Application record received before handshake finished");
587 if(!s->receive_record(s->handle, type, data, len)) {
590 } else if(type == SPTPS_HANDSHAKE) {
591 if(!receive_handshake(s, data, len)) {
595 return error(s, EIO, "Invalid record type %d", type);
601 // Receive incoming data. Check if it contains a complete record, if so, handle it.
602 size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
603 const uint8_t *data = vdata;
604 size_t total_read = 0;
607 return error(s, EIO, "Invalid session state zero");
611 return sptps_receive_data_datagram(s, data, len) ? len : false;
614 // First read the 2 length bytes.
616 size_t toread = 2 - s->buflen;
622 memcpy(s->inbuf + s->buflen, data, toread);
624 total_read += toread;
629 // Exit early if we don't have the full length.
634 // Get the length bytes
636 memcpy(&s->reclen, s->inbuf, 2);
637 s->reclen = ntohs(s->reclen);
639 // If we have the length bytes, ensure our buffer can hold the whole request.
640 s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
643 return error(s, errno, strerror(errno));
646 // Exit early if we have no more data to process.
652 // Read up to the end of the record.
653 size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
659 memcpy(s->inbuf + s->buflen, data, toread);
660 total_read += toread;
663 // If we don't have a whole record, exit.
664 if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {
668 // Update sequence number.
670 uint32_t seqno = s->inseqno++;
672 // Check HMAC and decrypt.
674 if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
675 return error(s, EINVAL, "Failed to decrypt and verify record");
679 // Append a NULL byte for safety.
680 s->inbuf[s->reclen + 3UL] = 0;
682 uint8_t type = s->inbuf[2];
684 if(type < SPTPS_HANDSHAKE) {
686 return error(s, EIO, "Application record received before handshake finished");
689 if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen)) {
692 } else if(type == SPTPS_HANDSHAKE) {
693 if(!receive_handshake(s, s->inbuf + 3, s->reclen)) {
697 return error(s, EIO, "Invalid record type %d", type);
705 // Start a SPTPS session.
706 bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
707 // Initialise struct sptps
708 memset(s, 0, sizeof(*s));
711 s->initiator = initiator;
712 s->datagram = datagram;
715 s->replaywin = sptps_replaywin;
718 s->late = malloc(s->replaywin);
721 return error(s, errno, strerror(errno));
724 memset(s->late, 0, s->replaywin);
727 s->label = malloc(labellen);
730 return error(s, errno, strerror(errno));
734 s->inbuf = malloc(7);
737 return error(s, errno, strerror(errno));
743 memcpy(s->label, label, labellen);
744 s->labellen = labellen;
746 s->send_data = send_data;
747 s->receive_record = receive_record;
749 // Do first KEX immediately
750 s->state = SPTPS_KEX;
754 // Stop a SPTPS session.
755 bool sptps_stop(sptps_t *s) {
756 // Clean up any resources.
757 chacha_poly1305_exit(s->incipher);
758 chacha_poly1305_exit(s->outcipher);
761 free_sptps_kex(s->mykex);
762 free_sptps_kex(s->hiskex);
763 free_sptps_key(s->key);
766 memset(s, 0, sizeof(*s));