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