Use SPTPS when ExperimentalProtocol is enabled.
[tinc] / src / sptps.c
1 /*
2     sptps.c -- Simple Peer-to-Peer Security
3     Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>,
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 "digest.h"
25 #include "ecdh.h"
26 #include "ecdsa.h"
27 #include "prf.h"
28 #include "sptps.h"
29
30 /*
31    Nonce MUST be exchanged first (done)
32    Signatures MUST be done over both nonces, to guarantee the signature is fresh
33    Otherwise: if ECDHE key of one side is compromised, it can be reused!
34
35    Add explicit tag to beginning of structure to distinguish the client and server when signing. (done)
36
37    Sign all handshake messages up to ECDHE kex with long-term public keys. (done)
38
39    HMACed KEX finished message to prevent downgrade attacks and prove you have the right key material (done by virtue of ECDSA over the whole ECDHE exchange?)
40
41    Explicit close message needs to be added.
42
43    Maybe do add some alert messages to give helpful error messages? Not more than TLS sends.
44
45    Use counter mode instead of OFB. (done)
46
47    Make sure ECC operations are fixed time (aka prevent side-channel attacks).
48 */
49
50 // Log an error message.
51 static bool error(sptps_t *s, int s_errno, const char *msg) {
52         fprintf(stderr, "SPTPS error: %s\n", msg);
53         errno = s_errno;
54         return false;
55 }
56
57 // Send a record (private version, accepts all record types, handles encryption and authentication).
58 static bool send_record_priv(sptps_t *s, uint8_t type, const char *data, uint16_t len) {
59         char buffer[len + 23UL];
60
61         // Create header with sequence number, length and record type
62         uint32_t seqno = htonl(s->outseqno++);
63         uint16_t netlen = htons(len);
64
65         memcpy(buffer, &seqno, 4);
66         memcpy(buffer + 4, &netlen, 2);
67         buffer[6] = type;
68
69         // Add plaintext (TODO: avoid unnecessary copy)
70         memcpy(buffer + 7, data, len);
71
72         if(s->outstate) {
73                 // If first handshake has finished, encrypt and HMAC
74                 if(!cipher_counter_xor(&s->outcipher, buffer + 4, len + 3UL, buffer + 4))
75                         return false;
76
77                 if(!digest_create(&s->outdigest, buffer, len + 7UL, buffer + 7UL + len))
78                         return false;
79
80                 return s->send_data(s->handle, buffer + 4, len + 19UL);
81         } else {
82                 // Otherwise send as plaintext
83                 return s->send_data(s->handle, buffer + 4, len + 3UL);
84         }
85 }
86
87 // Send an application record.
88 bool send_record(sptps_t *s, uint8_t type, const char *data, uint16_t len) {
89         // Sanity checks: application cannot send data before handshake is finished,
90         // and only record types 0..127 are allowed.
91         if(!s->outstate)
92                 return error(s, EINVAL, "Handshake phase not finished yet");
93
94         if(type >= SPTPS_HANDSHAKE)
95                 return error(s, EINVAL, "Invalid application record type");
96
97         return send_record_priv(s, type, data, len);
98 }
99
100 // Send a Key EXchange record, containing a random nonce and an ECDHE public key.
101 static bool send_kex(sptps_t *s) {
102         size_t keylen = ECDH_SIZE;
103
104         // Make room for our KEX message, which we will keep around since send_sig() needs it.
105         s->mykex = realloc(s->mykex, 1 + 32 + keylen);
106         if(!s->mykex)
107                 return error(s, errno, strerror(errno));
108
109         // Set version byte to zero.
110         s->mykex[0] = SPTPS_VERSION;
111
112         // Create a random nonce.
113         randomize(s->mykex + 1, 32);
114
115         // Create a new ECDH public key.
116         if(!ecdh_generate_public(&s->ecdh, s->mykex + 1 + 32))
117                 return false;
118
119         return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen);
120 }
121
122 // Send a SIGnature record, containing an ECDSA signature over both KEX records.
123 static bool send_sig(sptps_t *s) {
124         size_t keylen = ECDH_SIZE;
125         size_t siglen = ecdsa_size(&s->mykey);
126
127         // Concatenate both KEX messages, plus tag indicating if it is from the connection originator
128         char msg[(1 + 32 + keylen) * 2 + 1];
129         char sig[siglen];
130
131         msg[0] = s->initiator;
132         memcpy(msg + 1, s->mykex, 1 + 32 + keylen);
133         memcpy(msg + 2 + 32 + keylen, s->hiskex, 1 + 32 + keylen);
134
135         // Sign the result.
136         if(!ecdsa_sign(&s->mykey, msg, sizeof msg, sig))
137                 return false;
138
139         // Send the SIG exchange record.
140         return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof sig);
141 }
142
143 // Generate key material from the shared secret created from the ECDHE key exchange.
144 static bool generate_key_material(sptps_t *s, const char *shared, size_t len) {
145         // Initialise cipher and digest structures if necessary
146         if(!s->outstate) {
147                 bool result
148                         =  cipher_open_by_name(&s->incipher, "aes-256-ecb")
149                         && cipher_open_by_name(&s->outcipher, "aes-256-ecb")
150                         && digest_open_by_name(&s->indigest, "sha256", 16)
151                         && digest_open_by_name(&s->outdigest, "sha256", 16);
152                 if(!result)
153                         return false;
154         }
155
156         // Allocate memory for key material
157         size_t keylen = digest_keylength(&s->indigest) + digest_keylength(&s->outdigest) + cipher_keylength(&s->incipher) + cipher_keylength(&s->outcipher);
158
159         s->key = realloc(s->key, keylen);
160         if(!s->key)
161                 return error(s, errno, strerror(errno));
162
163         // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
164         char seed[s->labellen + 64 + 13];
165         strcpy(seed, "key expansion");
166         if(s->initiator) {
167                 memcpy(seed + 13, s->mykex + 1, 32);
168                 memcpy(seed + 45, s->hiskex + 1, 32);
169         } else {
170                 memcpy(seed + 13, s->hiskex + 1, 32);
171                 memcpy(seed + 45, s->mykex + 1, 32);
172         }
173         memcpy(seed + 78, s->label, s->labellen);
174
175         // Use PRF to generate the key material
176         if(!prf(shared, len, seed, s->labellen + 64 + 13, s->key, keylen))
177                 return false;
178
179         return true;
180 }
181
182 // Send an ACKnowledgement record.
183 static bool send_ack(sptps_t *s) {
184         return send_record_priv(s, SPTPS_HANDSHAKE, "", 0);
185 }
186
187 // Receive an ACKnowledgement record.
188 static bool receive_ack(sptps_t *s, const char *data, uint16_t len) {
189         if(len)
190                 return error(s, EIO, "Invalid ACK record length");
191
192         if(s->initiator) {
193                 bool result
194                         = cipher_set_counter_key(&s->incipher, s->key)
195                         && digest_set_key(&s->indigest, s->key + cipher_keylength(&s->incipher), digest_keylength(&s->indigest));
196                 if(!result)
197                         return false;
198         } else {
199                 bool result
200                         = cipher_set_counter_key(&s->incipher, s->key + cipher_keylength(&s->outcipher) + digest_keylength(&s->outdigest))
201                         && digest_set_key(&s->indigest, s->key + cipher_keylength(&s->outcipher) + digest_keylength(&s->outdigest) + cipher_keylength(&s->incipher), digest_keylength(&s->indigest));
202                 if(!result)
203                         return false;
204         }
205
206         free(s->key);
207         s->key = NULL;
208         s->instate = true;
209
210         return true;
211 }
212
213 // Receive a Key EXchange record, respond by sending a SIG record.
214 static bool receive_kex(sptps_t *s, const char *data, uint16_t len) {
215         // Verify length of the HELLO record
216         if(len != 1 + 32 + ECDH_SIZE)
217                 return error(s, EIO, "Invalid KEX record length");
218
219         // Ignore version number for now.
220
221         // Make a copy of the KEX message, send_sig() and receive_sig() need it
222         s->hiskex = realloc(s->hiskex, len);
223         if(!s->hiskex)
224                 return error(s, errno, strerror(errno));
225
226         memcpy(s->hiskex, data, len);
227
228         return send_sig(s);
229 }
230
231 // Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
232 static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
233         size_t keylen = ECDH_SIZE;
234         size_t siglen = ecdsa_size(&s->hiskey);
235
236         // Verify length of KEX record.
237         if(len != siglen)
238                 return error(s, EIO, "Invalid KEX record length");
239
240         // Concatenate both KEX messages, plus tag indicating if it is from the connection originator
241         char msg[(1 + 32 + keylen) * 2 + 1];
242
243         msg[0] = !s->initiator;
244         memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
245         memcpy(msg + 2 + 32 + keylen, s->mykex, 1 + 32 + keylen);
246
247         // Verify signature.
248         if(!ecdsa_verify(&s->hiskey, msg, sizeof msg, data))
249                 return false;
250
251         // Compute shared secret.
252         char shared[ECDH_SHARED_SIZE];
253         if(!ecdh_compute_shared(&s->ecdh, s->hiskex + 1 + 32, shared))
254                 return false;
255
256         // Generate key material from shared secret.
257         if(!generate_key_material(s, shared, sizeof shared))
258                 return false;
259
260         free(s->mykex);
261         free(s->hiskex);
262
263         s->mykex = NULL;
264         s->hiskex = NULL;
265
266         // Send cipher change record
267         if(!send_ack(s))
268                 return false;
269
270         // TODO: only set new keys after ACK has been set/received
271         if(s->initiator) {
272                 bool result
273                         = cipher_set_counter_key(&s->outcipher, s->key + cipher_keylength(&s->incipher) + digest_keylength(&s->indigest))
274                         && digest_set_key(&s->outdigest, s->key + cipher_keylength(&s->incipher) + digest_keylength(&s->indigest) + cipher_keylength(&s->outcipher), digest_keylength(&s->outdigest));
275                 if(!result)
276                         return false;
277         } else {
278                 bool result
279                         =  cipher_set_counter_key(&s->outcipher, s->key)
280                         && digest_set_key(&s->outdigest, s->key + cipher_keylength(&s->outcipher), digest_keylength(&s->outdigest));
281                 if(!result)
282                         return false;
283         }
284
285         s->outstate = true;
286
287         return true;
288 }
289
290 // Force another Key EXchange (for testing purposes).
291 bool force_kex(sptps_t *s) {
292         if(!s->outstate || s->state != SPTPS_SECONDARY_KEX)
293                 return error(s, EINVAL, "Cannot force KEX in current state");
294
295         s->state = SPTPS_KEX;
296         return send_kex(s);
297 }
298
299 // Receive a handshake record.
300 static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) {
301         // Only a few states to deal with handshaking.
302         fprintf(stderr, "Received handshake message, current state %d\n", s->state);
303         switch(s->state) {
304                 case SPTPS_SECONDARY_KEX:
305                         // We receive a secondary KEX request, first respond by sending our own.
306                         if(!send_kex(s))
307                                 return false;
308                 case SPTPS_KEX:
309                         // We have sent our KEX request, we expect our peer to sent one as well.
310                         if(!receive_kex(s, data, len))
311                                 return false;
312                         s->state = SPTPS_SIG;
313                         return true;
314                 case SPTPS_SIG:
315                         // If we already sent our secondary public ECDH key, we expect the peer to send his.
316                         if(!receive_sig(s, data, len))
317                                 return false;
318                         // s->state = SPTPS_ACK;
319                         s->state = SPTPS_ACK;
320                         return true;
321                 case SPTPS_ACK:
322                         // We expect a handshake message to indicate transition to the new keys.
323                         if(!receive_ack(s, data, len))
324                                 return false;
325                         s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0);
326                         s->state = SPTPS_SECONDARY_KEX;
327                         return true;
328                 // TODO: split ACK into a VERify and ACK?
329                 default:
330                         return error(s, EIO, "Invalid session state");
331         }
332 }
333
334 // Receive incoming data. Check if it contains a complete record, if so, handle it.
335 bool receive_data(sptps_t *s, const char *data, size_t len) {
336         while(len) {
337                 // First read the 2 length bytes.
338                 if(s->buflen < 6) {
339                         size_t toread = 6 - s->buflen;
340                         if(toread > len)
341                                 toread = len;
342
343                         memcpy(s->inbuf + s->buflen, data, toread);
344
345                         s->buflen += toread;
346                         len -= toread;
347                         data += toread;
348                 
349                         // Exit early if we don't have the full length.
350                         if(s->buflen < 6)
351                                 return true;
352
353                         // Decrypt the length bytes
354
355                         if(s->instate) {
356                                 if(!cipher_counter_xor(&s->incipher, s->inbuf + 4, 2, &s->reclen))
357                                         return false;
358                         } else {
359                                 memcpy(&s->reclen, s->inbuf + 4, 2);
360                         }
361
362                         s->reclen = ntohs(s->reclen);
363
364                         // If we have the length bytes, ensure our buffer can hold the whole request.
365                         s->inbuf = realloc(s->inbuf, s->reclen + 23UL);
366                         if(!s->inbuf)
367                                 return error(s, errno, strerror(errno));
368
369                         // Add sequence number.
370                         uint32_t seqno = htonl(s->inseqno++);
371                         memcpy(s->inbuf, &seqno, 4);
372
373                         // Exit early if we have no more data to process.
374                         if(!len)
375                                 return true;
376                 }
377
378                 // Read up to the end of the record.
379                 size_t toread = s->reclen + (s->instate ? 23UL : 7UL) - s->buflen;
380                 if(toread > len)
381                         toread = len;
382
383                 memcpy(s->inbuf + s->buflen, data, toread);
384                 s->buflen += toread;
385                 len -= toread;
386                 data += toread;
387
388                 // If we don't have a whole record, exit.
389                 if(s->buflen < s->reclen + (s->instate ? 23UL : 7UL))
390                         return true;
391
392                 // Check HMAC and decrypt.
393                 if(s->instate) {
394                         if(!digest_verify(&s->indigest, s->inbuf, s->reclen + 7UL, s->inbuf + s->reclen + 7UL))
395                                 return error(s, EIO, "Invalid HMAC");
396
397                         if(!cipher_counter_xor(&s->incipher, s->inbuf + 6UL, s->reclen + 1UL, s->inbuf + 6UL))
398                                 return false;
399                 }
400
401                 // Append a NULL byte for safety.
402                 s->inbuf[s->reclen + 7UL] = 0;
403
404                 uint8_t type = s->inbuf[6];
405
406                 if(type < SPTPS_HANDSHAKE) {
407                         if(!s->instate)
408                                 return error(s, EIO, "Application record received before handshake finished");
409                         if(!s->receive_record(s->handle, type, s->inbuf + 7, s->reclen))
410                                 return false;
411                 } else if(type == SPTPS_HANDSHAKE) {
412                         if(!receive_handshake(s, s->inbuf + 7, s->reclen))
413                                 return false;
414                 } else {
415                         return error(s, EIO, "Invalid record type");
416                 }
417
418                 s->buflen = 4;
419         }
420
421         return true;
422 }
423
424 // Start a SPTPS session.
425 bool start_sptps(sptps_t *s, void *handle, bool initiator, ecdsa_t mykey, ecdsa_t hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
426         // Initialise struct sptps
427         memset(s, 0, sizeof *s);
428
429         s->handle = handle;
430         s->initiator = initiator;
431         s->mykey = mykey;
432         s->hiskey = hiskey;
433
434         s->label = malloc(labellen);
435         if(!s->label)
436                 return error(s, errno, strerror(errno));
437
438         s->inbuf = malloc(7);
439         if(!s->inbuf)
440                 return error(s, errno, strerror(errno));
441         s->buflen = 4;
442         memset(s->inbuf, 0, 4);
443
444         memcpy(s->label, label, labellen);
445         s->labellen = labellen;
446
447         s->send_data = send_data;
448         s->receive_record = receive_record;
449
450         // Do first KEX immediately
451         s->state = SPTPS_KEX;
452         return send_kex(s);
453 }
454
455 // Stop a SPTPS session.
456 bool stop_sptps(sptps_t *s) {
457         // Clean up any resources.
458         ecdh_free(&s->ecdh);
459         free(s->inbuf);
460         free(s->mykex);
461         free(s->hiskex);
462         free(s->key);
463         free(s->label);
464         return true;
465 }