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