lsquic_handshake.c revision 90fe3b25
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2
3#include <assert.h>
4#include <errno.h>
5#include <time.h>
6#include <string.h>
7#include <sys/queue.h>
8#ifndef WIN32
9#include <sys/socket.h>
10#endif
11
12#include <openssl/ssl.h>
13#include <openssl/crypto.h>
14#include <openssl/stack.h>
15#include <openssl/x509.h>
16#include <openssl/rand.h>
17#include <openssl/nid.h>
18#include <zlib.h>
19
20#include "lsquic.h"
21#include "lsquic_types.h"
22#include "lsquic_crypto.h"
23#include "lsquic_str.h"
24#include "lsquic_handshake.h"
25#include "lsquic_parse.h"
26#include "lsquic_crt_compress.h"
27#include "lsquic_util.h"
28#include "lsquic_version.h"
29#include "lsquic_mm.h"
30#include "lsquic_engine_public.h"
31#include "lsquic_hash.h"
32#include "lsquic_buf.h"
33#include "lsquic_qtags.h"
34
35#include "fiu-local.h"
36
37#include "lsquic_ev_log.h"
38
39#define MIN_CHLO_SIZE 1024
40
41#define LSQUIC_LOGGER_MODULE LSQLM_HANDSHAKE
42#include "lsquic_logger.h"
43
44enum handshake_state
45{
46    HSK_CHLO_REJ = 0,
47    HSK_SHLO,
48    HSK_COMPLETED,
49    N_HSK_STATES
50};
51
52#if LSQUIC_KEEP_ENC_SESS_HISTORY
53typedef unsigned char eshist_idx_t;
54
55enum enc_sess_history_event
56{
57    ESHE_EMPTY              =  '\0',
58    ESHE_SET_SNI            =  'I',
59    ESHE_SET_SNO            =  'O',
60    ESHE_SET_STK            =  'K',
61    ESHE_SET_SCID           =  'D',
62    ESHE_SET_PROF           =  'P',
63    ESHE_SET_SRST           =  'S',
64};
65#endif
66
67
68typedef struct hs_ctx_st
69{
70    enum {
71        HSET_TCID     =   (1 << 0),     /* tcid is set */
72        HSET_SMHL     =   (1 << 1),     /* smhl is set */
73        HSET_SCID     =   (1 << 2),
74        HSET_IRTT     =   (1 << 3),
75        HSET_SRST     =   (1 << 4),
76    }           set;
77    enum {
78        HOPT_NSTP     =   (1 << 0),     /* NSTP option present in COPT */
79        HOPT_SREJ     =   (1 << 1),     /* SREJ option present in COPT */
80    }           opts;
81    uint32_t    pdmd;
82    uint32_t    aead;
83    uint32_t    kexs;
84
85    uint32_t    mids;
86    uint32_t    scls;
87    uint32_t    cfcw;
88    uint32_t    sfcw;
89    uint32_t    icsl;
90
91    uint32_t    irtt;
92    uint64_t    rcid;
93    uint32_t    tcid;
94    uint32_t    smhl;
95    uint64_t    sttl;
96    unsigned char scid[SCID_LENGTH];
97    //unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
98    unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
99    unsigned char  pubs[32];
100    unsigned char srst[SRST_LENGTH];
101
102    uint32_t    rrej;
103    struct lsquic_str ccs;
104    struct lsquic_str sni;   /* 0 rtt */
105    struct lsquic_str ccrt;
106    struct lsquic_str stk;
107    struct lsquic_str sno;
108    struct lsquic_str prof;
109
110    struct lsquic_str csct;
111    struct lsquic_str crt; /* compressed certs buffer */
112} hs_ctx_t;
113
114
115struct lsquic_enc_session
116{
117    enum handshake_state hsk_state;
118    enum {
119        ES_RECV_REJ =   1 << 2,
120    }                    es_flags;
121
122    uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
123    uint8_t peer_have_final_key;
124    uint8_t server_start_use_final_key;
125
126    lsquic_cid_t cid;
127    unsigned char priv_key[32];
128    EVP_AEAD_CTX *enc_ctx_i;
129    EVP_AEAD_CTX *dec_ctx_i;
130
131    /* Have to save the initial key for diversification need */
132    unsigned char enc_key_i[aes128_key_len];
133    unsigned char dec_key_i[aes128_key_len];
134    unsigned char enc_key_nonce_i[aes128_iv_len];
135    unsigned char dec_key_nonce_i[aes128_iv_len];
136
137    EVP_AEAD_CTX *enc_ctx_f;
138    EVP_AEAD_CTX *dec_ctx_f;
139    unsigned char enc_key_nonce_f[aes128_iv_len];
140    unsigned char dec_key_nonce_f[aes128_iv_len];
141
142    hs_ctx_t hs_ctx;
143    lsquic_session_cache_info_t *info;
144    c_cert_item_t *cert_item;
145    SSL_CTX *  ssl_ctx;
146    const struct lsquic_engine_public *enpub;
147    struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
148    struct lsquic_str   chlo; /* real copy of CHLO message */
149    struct lsquic_str   sstk;
150    struct lsquic_str   ssno;
151
152#if LSQUIC_KEEP_ENC_SESS_HISTORY
153    eshist_idx_t        es_hist_idx;
154    unsigned char       es_hist_buf[1 << ESHIST_BITS];
155#endif
156};
157
158
159
160/* client */
161static c_cert_item_t *make_c_cert_item(struct lsquic_str **certs, int count);
162static void free_c_cert_item(c_cert_item_t *item);
163
164static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val);
165static int init_hs_hash_tables(int flags);
166static uint32_t get_tag_value_i32(unsigned char *, int);
167static uint64_t get_tag_value_i64(unsigned char *, int);
168
169static int determine_keys(lsquic_enc_session_t *enc_session);
170
171
172#if LSQUIC_KEEP_ENC_SESS_HISTORY
173static void
174eshist_append (lsquic_enc_session_t *enc_session,
175                                        enum enc_sess_history_event eh_event)
176{
177    enc_session->es_hist_buf[
178                    ESHIST_MASK & enc_session->es_hist_idx++ ] = eh_event;
179}
180
181
182#   define ESHIST_APPEND(sess, event) eshist_append(sess, event)
183#else
184#   define ESHIST_APPEND(sess, event) do { } while (0)
185#endif
186
187static int
188lsquic_handshake_init(int flags)
189{
190    crypto_init();
191    return init_hs_hash_tables(flags);
192}
193
194
195static void
196lsquic_handshake_cleanup (void)
197{
198    lsquic_crt_cleanup();
199}
200
201
202/* return -1 for fail, 0 OK*/
203static int init_hs_hash_tables(int flags)
204{
205
206    return 0;
207}
208
209
210/* client */
211static c_cert_item_t *
212make_c_cert_item (lsquic_str_t **certs, int count)
213{
214    int i;
215    uint64_t hash;
216    c_cert_item_t *item = (c_cert_item_t *)malloc(sizeof(c_cert_item_t));
217    item->crts = (lsquic_str_t *)malloc(count * sizeof(lsquic_str_t));
218    item->hashs = lsquic_str_new(NULL, 0);
219    item->count = count;
220    for (i = 0; i < count; ++i)
221    {
222        lsquic_str_copy(&item->crts[i], certs[i]);
223        hash = fnv1a_64((const uint8_t *)lsquic_str_cstr(certs[i]),
224                        lsquic_str_len(certs[i]));
225        lsquic_str_append(item->hashs, (char *)&hash, 8);
226    }
227    return item;
228}
229
230
231/* client */
232static void
233free_c_cert_item (c_cert_item_t *item)
234{
235    int i;
236    if (item)
237    {
238        lsquic_str_delete(item->hashs);
239        for(i=0; i<item->count; ++i)
240            lsquic_str_d(&item->crts[i]);
241        free(item->crts);
242        free(item);
243    }
244}
245
246
247enum rtt_deserialize_return_type
248{
249    RTT_DESERIALIZE_OK              = 0,
250    RTT_DESERIALIZE_BAD_QUIC_VER    = 1,
251    RTT_DESERIALIZE_BAD_SERIAL_VER  = 2,
252    RTT_DESERIALIZE_BAD_CERT_SIZE   = 3,
253};
254
255#define RTT_SERIALIZER_VERSION  (1 << 0)
256
257static void
258lsquic_enc_session_serialize_zero_rtt(struct lsquic_zero_rtt_storage *storage,
259                                        enum lsquic_version version,
260                                        const lsquic_session_cache_info_t *info,
261                                                const c_cert_item_t *cert_item)
262{
263    uint32_t i;
264    uint32_t *cert_len;
265    uint8_t *cert_data;
266    /*
267     * assign versions
268     */
269    storage->quic_version_tag = lsquic_ver2tag(version);
270    storage->serializer_version = RTT_SERIALIZER_VERSION;
271    /*
272     * server config
273     */
274    storage->ver = info->ver;
275    storage->aead = info->aead;
276    storage->kexs = info->kexs;
277    storage->pdmd = info->pdmd;
278    storage->orbt = info->orbt;
279    storage->expy = info->expy;
280    storage->sstk_len = lsquic_str_len(&info->sstk);
281    storage->scfg_len = lsquic_str_len(&info->scfg);
282    storage->scfg_flag = info->scfg_flag;
283    memcpy(storage->sstk, lsquic_str_buf(&info->sstk), storage->sstk_len);
284    memcpy(storage->scfg, lsquic_str_buf(&info->scfg), storage->scfg_len);
285    memcpy(storage->sscid, &info->sscid, SCID_LENGTH);
286    memcpy(storage->spubs, &info->spubs, MAX_SPUBS_LENGTH);
287    /*
288     * certificate chain
289     */
290    storage->cert_count = (uint32_t)cert_item->count;
291    cert_len = (uint32_t *)(storage + 1);
292    cert_data = (uint8_t *)(cert_len + 1);
293    for (i = 0; i < storage->cert_count; i++)
294    {
295        *cert_len = lsquic_str_len(&cert_item->crts[i]);
296        memcpy(cert_data, lsquic_str_buf(&cert_item->crts[i]), *cert_len);
297        cert_len = (uint32_t *)(cert_data + *cert_len);
298        cert_data = (uint8_t *)(cert_len + 1);
299    }
300}
301
302
303#define CHECK_SPACE(need, start, end) \
304    do { if ((intptr_t) (need) > ((intptr_t) (end) - (intptr_t) (start))) \
305        { return RTT_DESERIALIZE_BAD_CERT_SIZE; } \
306    } while (0) \
307
308static enum rtt_deserialize_return_type
309lsquic_enc_session_deserialize_zero_rtt(
310                                const struct lsquic_zero_rtt_storage *storage,
311                                                        size_t storage_size,
312                                const struct lsquic_engine_settings *settings,
313                                            lsquic_session_cache_info_t *info,
314                                                    c_cert_item_t *cert_item)
315{
316    enum lsquic_version ver;
317    uint32_t i, len;
318    uint64_t hash;
319    uint32_t *cert_len;
320    uint8_t *cert_data;
321    void *storage_end = (uint8_t *)storage + storage_size;
322    /*
323     * check versions
324     */
325    ver = lsquic_tag2ver(storage->quic_version_tag);
326    if ((int)ver == -1 || !((1 << ver) & settings->es_versions))
327        return RTT_DESERIALIZE_BAD_QUIC_VER;
328    if (storage->serializer_version != RTT_SERIALIZER_VERSION)
329        return RTT_DESERIALIZE_BAD_SERIAL_VER;
330    /*
331     * server config
332     */
333    info->ver = storage->ver;
334    info->aead = storage->aead;
335    info->kexs = storage->kexs;
336    info->pdmd = storage->pdmd;
337    info->orbt = storage->orbt;
338    info->expy = storage->expy;
339    info->scfg_flag = storage->scfg_flag;
340    lsquic_str_setto(&info->sstk, storage->sstk, storage->sstk_len);
341    lsquic_str_setto(&info->scfg, storage->scfg, storage->scfg_len);
342    memcpy(&info->sscid, storage->sscid, SCID_LENGTH);
343    memcpy(&info->spubs, storage->spubs, MAX_SPUBS_LENGTH);
344    /*
345     * certificate chain
346     */
347    cert_item->count = storage->cert_count;
348    cert_item->crts = malloc(cert_item->count * sizeof(lsquic_str_t));
349    cert_item->hashs = lsquic_str_new(NULL, 0);
350    cert_len = (uint32_t *)(storage + 1);
351    for (i = 0; i < storage->cert_count; i++)
352    {
353        CHECK_SPACE(sizeof(uint32_t), cert_len, storage_end);
354        cert_data = (uint8_t *)(cert_len + 1);
355        memcpy(&len, cert_len, sizeof(len));
356        CHECK_SPACE(len, cert_data, storage_end);
357        lsquic_str_prealloc(&cert_item->crts[i], len);
358        lsquic_str_setlen(&cert_item->crts[i], len);
359        memcpy(lsquic_str_buf(&cert_item->crts[i]), cert_data, len);
360        hash = fnv1a_64((const uint8_t *)cert_data, len);
361        lsquic_str_append(cert_item->hashs, (char *)&hash, 8);
362        cert_len = (uint32_t *)(cert_data + len);
363    }
364    return RTT_DESERIALIZE_OK;
365}
366
367
368static lsquic_enc_session_t *
369lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
370                                    const struct lsquic_engine_public *enpub,
371                                    const unsigned char *zero_rtt, size_t zero_rtt_len)
372{
373    lsquic_session_cache_info_t *info;
374    lsquic_enc_session_t *enc_session;
375    c_cert_item_t *item;
376    const struct lsquic_zero_rtt_storage *zero_rtt_storage;
377
378    if (!domain)
379    {
380        errno = EINVAL;
381        return NULL;
382    }
383
384    enc_session = calloc(1, sizeof(*enc_session));
385    if (!enc_session)
386        return NULL;
387
388    /* have to allocate every time */
389    info = calloc(1, sizeof(*info));
390    if (!info)
391    {
392        free(enc_session);
393        return NULL;
394    }
395
396    if (zero_rtt && zero_rtt_len > sizeof(struct lsquic_zero_rtt_storage))
397    {
398        item = calloc(1, sizeof(*item));
399        if (!item)
400        {
401            free(enc_session);
402            free(info);
403            return NULL;
404        }
405        zero_rtt_storage = (const struct lsquic_zero_rtt_storage *)zero_rtt;
406        switch (lsquic_enc_session_deserialize_zero_rtt(zero_rtt_storage,
407                                                        zero_rtt_len,
408                                                        &enpub->enp_settings,
409                                                        info, item))
410        {
411            case RTT_DESERIALIZE_BAD_QUIC_VER:
412                LSQ_ERROR("provided zero_rtt has unsupported QUIC version");
413                free(item);
414                break;
415            case RTT_DESERIALIZE_BAD_SERIAL_VER:
416                LSQ_ERROR("provided zero_rtt has bad serializer version");
417                free(item);
418                break;
419            case RTT_DESERIALIZE_BAD_CERT_SIZE:
420                LSQ_ERROR("provided zero_rtt has bad cert size");
421                free(item);
422                break;
423            case RTT_DESERIALIZE_OK:
424                memcpy(enc_session->hs_ctx.pubs, info->spubs, 32);
425                enc_session->cert_item = item;
426                break;
427        }
428    }
429    enc_session->enpub = enpub;
430    enc_session->cid   = cid;
431    enc_session->info  = info;
432    /* FIXME: allocation may fail */
433    lsquic_str_append(&enc_session->hs_ctx.sni, domain, strlen(domain));
434    return enc_session;
435}
436
437
438static void
439lsquic_enc_session_destroy (lsquic_enc_session_t *enc_session)
440{
441    if (!enc_session)
442        return ;
443
444    hs_ctx_t *hs_ctx = &enc_session->hs_ctx;
445    lsquic_str_d(&hs_ctx->sni);
446    lsquic_str_d(&hs_ctx->ccs);
447    lsquic_str_d(&hs_ctx->ccrt);
448    lsquic_str_d(&hs_ctx->stk);
449    lsquic_str_d(&hs_ctx->sno);
450    lsquic_str_d(&hs_ctx->prof);
451    lsquic_str_d(&hs_ctx->csct);
452    lsquic_str_d(&hs_ctx->crt);
453    lsquic_str_d(&enc_session->chlo);
454    lsquic_str_d(&enc_session->sstk);
455    lsquic_str_d(&enc_session->ssno);
456    if (enc_session->dec_ctx_i)
457    {
458        EVP_AEAD_CTX_cleanup(enc_session->dec_ctx_i);
459        free(enc_session->dec_ctx_i);
460    }
461    if (enc_session->enc_ctx_i)
462    {
463        EVP_AEAD_CTX_cleanup(enc_session->enc_ctx_i);
464        free(enc_session->enc_ctx_i);
465    }
466    if (enc_session->dec_ctx_f)
467    {
468        EVP_AEAD_CTX_cleanup(enc_session->dec_ctx_f);
469        free(enc_session->dec_ctx_f);
470    }
471    if (enc_session->enc_ctx_f)
472    {
473        EVP_AEAD_CTX_cleanup(enc_session->enc_ctx_f);
474        free(enc_session->enc_ctx_f);
475    }
476    if (enc_session->info)
477    {
478        lsquic_str_d(&enc_session->info->sstk);
479        lsquic_str_d(&enc_session->info->scfg);
480        lsquic_str_d(&enc_session->info->sni_key);
481        free(enc_session->info);
482    }
483    if (enc_session->cert_item)
484    {
485        free_c_cert_item(enc_session->cert_item);
486        enc_session->cert_item = NULL;
487    }
488    free(enc_session);
489
490}
491
492
493static int get_hs_state(lsquic_enc_session_t *enc_session)
494{
495    return enc_session->hsk_state;
496}
497
498
499/* make sure have more room for encrypt */
500static int
501lsquic_enc_session_is_hsk_done (lsquic_enc_session_t *enc_session)
502{
503    return (get_hs_state(enc_session) == HSK_COMPLETED);
504}
505
506
507static void
508process_copt (lsquic_enc_session_t *enc_session, const uint32_t *const opts,
509                unsigned n_opts)
510{
511    unsigned i;
512    for (i = 0; i < n_opts; ++i)
513        switch (opts[i])
514        {
515        case QTAG_NSTP:
516            enc_session->hs_ctx.opts |= HOPT_NSTP;
517            break;
518        case QTAG_SREJ:
519            enc_session->hs_ctx.opts |= HOPT_SREJ;
520            break;
521        }
522}
523
524
525static int parse_hs_data (lsquic_enc_session_t *enc_session, uint32_t tag,
526                          unsigned char *val, int len, uint32_t head_tag)
527{
528    hs_ctx_t * hs_ctx = &enc_session->hs_ctx;
529
530    switch(tag)
531    {
532    case QTAG_PDMD:
533        hs_ctx->pdmd = get_tag_value_i32(val, len);
534        break;
535
536    case QTAG_MIDS:
537        if (0 != get_tag_val_u32(val, len, &hs_ctx->mids))
538            return -1;
539        break;
540
541    case QTAG_SCLS:
542        hs_ctx->scls = get_tag_value_i32(val, len);
543        break;
544
545    case QTAG_CFCW:
546        if (0 != get_tag_val_u32(val, len, &hs_ctx->cfcw))
547            return -1;
548        break;
549
550    case QTAG_SFCW:
551        if (0 != get_tag_val_u32(val, len, &hs_ctx->sfcw))
552            return -1;
553        break;
554
555    case QTAG_ICSL:
556        hs_ctx->icsl = get_tag_value_i32(val, len);
557        break;
558
559    case QTAG_IRTT:
560        if (0 != get_tag_val_u32(val, len, &hs_ctx->irtt))
561            return -1;
562        hs_ctx->set |= HSET_IRTT;
563        break;
564
565    case QTAG_COPT:
566        if (0 == len % sizeof(uint32_t))
567            process_copt(enc_session, (uint32_t *) val, len / sizeof(uint32_t));
568        /* else ignore, following the reference implementation */
569        break;
570
571    case QTAG_SNI:
572        lsquic_str_setto(&hs_ctx->sni, val, len);
573        ESHIST_APPEND(enc_session, ESHE_SET_SNI);
574        break;
575
576    case QTAG_CCS:
577        lsquic_str_setto(&hs_ctx->ccs, val, len);
578        break;
579
580    case QTAG_CCRT:
581        lsquic_str_setto(&hs_ctx->ccrt, val, len);
582        break;
583
584    case QTAG_CRT:
585        lsquic_str_setto(&hs_ctx->crt, val, len);
586        break;
587
588    case QTAG_PUBS:
589        /* FIXME:Server side may send a list of pubs,
590         * we support only ONE kenx now.
591         * REJ is 35 bytes, SHLO is 32 bytes
592         * Only save other peer's pubs to hs_ctx
593         */
594        if( len < 32)
595            break;
596        memcpy(hs_ctx->pubs, val + (len - 32), 32);
597        if (head_tag == QTAG_SCFG)
598        {
599            memcpy(enc_session->info->spubs, hs_ctx->pubs, 32);
600        }
601        break;
602
603    case QTAG_RCID:
604        hs_ctx->rcid = get_tag_value_i64(val, len);
605        break;
606
607
608    case QTAG_SMHL:
609        if (0 != get_tag_val_u32(val, len, &hs_ctx->smhl))
610            return -1;
611        hs_ctx->set |= HSET_SMHL;
612        break;
613
614    case QTAG_TCID:
615        if (0 != get_tag_val_u32(val, len, &hs_ctx->tcid))
616            return -1;
617        hs_ctx->set |= HSET_TCID;
618        break;
619
620    case QTAG_EXPY:
621        enc_session->info->expy = get_tag_value_i64(val, len);
622        break;
623
624    case QTAG_ORBT:
625        enc_session->info->orbt = get_tag_value_i64(val, len);
626        break;
627
628    case QTAG_SNO:
629        lsquic_str_setto(&enc_session->ssno, val, len);
630        ESHIST_APPEND(enc_session, ESHE_SET_SNO);
631        break;
632
633    case QTAG_STK:
634        lsquic_str_setto(&enc_session->info->sstk, val, len);
635    ESHIST_APPEND(enc_session, ESHE_SET_STK);
636    break;
637
638    case QTAG_SCID:
639        if (len != SCID_LENGTH)
640            return -1;
641        memcpy(enc_session->info->sscid, val, len);
642        ESHIST_APPEND(enc_session, ESHE_SET_SCID);
643        break;
644
645    case QTAG_AEAD:
646        enc_session->info->aead = get_tag_value_i32(val, len);
647        break;
648
649    case QTAG_KEXS:
650        enc_session->info->kexs = get_tag_value_i32(val, len);
651        break;
652
653    case QTAG_NONC:
654        if (len != sizeof(hs_ctx->nonc))
655            return -1;
656        memcpy(hs_ctx->nonc, val, len);
657        break;
658
659    case QTAG_SCFG:
660        lsquic_str_setto(&enc_session->info->scfg, val, len);
661        enc_session->info->scfg_flag = 1;
662        break;
663
664    case QTAG_PROF:
665        lsquic_str_setto(&hs_ctx->prof, val, len);
666        ESHIST_APPEND(enc_session, ESHE_SET_PROF);
667        break;
668
669    case QTAG_STTL:
670        hs_ctx->sttl = get_tag_value_i64(val, len);
671        break;
672
673    case QTAG_SRST:
674        if (len != sizeof(hs_ctx->srst))
675        {
676            LSQ_INFO("Unexpected size of SRST: %u instead of %zu bytes",
677                len, sizeof(hs_ctx->srst));
678            return -1;
679        }
680        memcpy(hs_ctx->srst, val, len);
681        hs_ctx->set |= HSET_SRST;
682        ESHIST_APPEND(enc_session, ESHE_SET_SRST);
683        break;
684
685    default:
686        LSQ_DEBUG("Ignored tag '%.*s'", 4, (char *)&tag);
687        break;
688    }
689
690    return 0;
691}
692
693
694/* only for the hs stream-frame data, NOT with the packet header or frame header*/
695static enum handshake_error parse_hs (lsquic_enc_session_t *enc_session,
696                                      const unsigned char *buf, int buf_len,
697                                      uint32_t *head_tag)
698{
699    uint16_t i;
700    const unsigned char *p = buf;
701    const unsigned char *pend = buf + buf_len;
702
703    unsigned char *data;
704    uint32_t len = 0, offset = 0;
705    uint16_t num;
706    uint32_t tag;
707    if (buf_len < 6)
708        return DATA_FORMAT_ERROR;
709
710    memcpy(&tag, p, 4);
711    p += 4;
712
713    {
714        if (tag != QTAG_SREJ && tag != QTAG_REJ && tag != QTAG_SHLO &&
715                                                        tag != QTAG_SCFG)
716            return DATA_FORMAT_ERROR;
717    }
718
719    *head_tag = tag;
720
721    memcpy((char *)&num, p, 2);
722    p += 2 + 2;  /* the 2 bytes padding 0x0000 need to be bypassed */
723
724    if (num < 1)
725        return DATA_FORMAT_ERROR;
726
727    data = (uint8_t *)(buf + 4 * 2 * (1 + num));
728    if ((const char *)data > (const char *)pend)
729    {
730        LSQ_DEBUG("parse_hs tag '%.*s' error: data not enough", 4, (char *)head_tag);
731        return DATA_NOT_ENOUGH;
732    }
733
734    /* check last offset */
735    memcpy((char *)&len, data - 4, 4);
736    if ((const char *)data + len > (const char *)pend)
737    {
738        LSQ_DEBUG("parse_hs tag '%.*s' error: data not enough!!!", 4, (char *)head_tag);
739        return DATA_NOT_ENOUGH;
740    }
741
742    for (i=0; i<num; ++i)
743    {
744        memcpy((char *)&tag, p, 4);
745        p += 4;
746        memcpy((char *)&len, p, 4);
747        len -= offset;
748        p += 4;
749
750        if ((const char *)data + offset + len > (const char *)pend)
751            return DATA_FORMAT_ERROR;
752
753        if (0 != parse_hs_data(enc_session, tag, data + offset, len,
754                                                                *head_tag))
755            return DATA_FORMAT_ERROR;
756        offset += len;
757    }
758
759    LSQ_DEBUG("parse_hs tag '%.*s' no error.", 4, (char *)head_tag);
760    return DATA_NO_ERROR;
761}
762
763
764static uint32_t get_tag_value_i32(unsigned char *val, int len)
765{
766    uint32_t v;
767    if (len < 4)
768        return 0;
769    memcpy(&v, val, 4);
770    return v;
771}
772
773
774static uint64_t get_tag_value_i64(unsigned char *val, int len)
775{
776    uint64_t v;
777    if (len < 8)
778        return 0;
779    memcpy(&v, val, 8);
780    return v;
781}
782
783
784static int
785get_tag_val_u32 (unsigned char *v, int len, uint32_t *val)
786{
787    if (len != 4)
788        return -1;
789    memcpy(val, v, 4);
790    return 0;
791}
792
793
794static void
795generate_cid_buf (void *buf, size_t bufsz)
796{
797    RAND_bytes(buf, bufsz);
798}
799
800
801static lsquic_cid_t
802lsquic_generate_cid (void)
803{
804    lsquic_cid_t cid;
805    generate_cid_buf(&cid, sizeof(cid));
806    return cid;
807}
808
809
810/*  From "QUIC Crypto" for easy reference:
811 *
812 *  A handshake message consists of:
813 *    - The tag of the message.
814 *    - A uint16 containing the number of tag-value pairs.
815 *    - Two bytes of padding which should be zero when sent but ignored when
816 *          received.
817 *    - A series of uint32 tags and uint32 end offsets, one for each
818 *          tag-value pair. The tags must be strictly monotonically
819 *          increasing, and the end-offsets must be monotonic non-decreasing.
820 *          The end offset gives the offset, from the start of the value
821 *          data, to a byte one beyond the end of the data for that tag.
822 *          (Thus the end offset of the last tag contains the length of the
823 *          value data).
824 *    - The value data, concatenated without padding.
825 */
826
827struct table_entry { uint32_t tag, off; };
828
829struct message_writer
830{
831    unsigned char       *mw_p;
832    struct table_entry   mw_first_dummy_entry;
833    struct table_entry  *mw_entry,
834                        *mw_prev_entry,
835                        *mw_end;
836};
837
838/* MW_ family of macros is used to write entries to handshake message
839 * (MW stands for "message writer").
840 */
841#define MW_BEGIN(mw, msg_tag, n_entries, data_ptr) do {             \
842    uint32_t t_ = msg_tag;                                          \
843    uint16_t n_ = n_entries;                                        \
844    memcpy(data_ptr, &t_, 4);                                       \
845    memcpy(data_ptr + 4, &n_, 2);                                   \
846    memset(data_ptr + 4 + 2, 0, 2);                                 \
847    (mw)->mw_entry = (void *) (data_ptr + 8);                       \
848    (mw)->mw_p = data_ptr + 8 +                                     \
849                    (n_entries) * sizeof((mw)->mw_entry[0]);        \
850    (mw)->mw_first_dummy_entry.tag = 0;                             \
851    (mw)->mw_first_dummy_entry.off = 0;                             \
852    (mw)->mw_prev_entry = &(mw)->mw_first_dummy_entry;              \
853    (mw)->mw_end = (void *) (mw)->mw_p;                             \
854} while (0)
855
856#ifndef NDEBUG
857#   define MW_END(mw) do {                                          \
858        assert((mw)->mw_entry == (mw)->mw_end);                     \
859    } while (0)
860#else
861#   define MW_END(mw)
862#endif
863
864#define MW_P(mw) ((mw)->mw_p)
865
866#define MW_ADVANCE_P(mw, n) do {                                    \
867    MW_P(mw) += (n);                                                \
868} while (0)
869
870#define MW_WRITE_TABLE_ENTRY(mw, tag_, sz) do {                     \
871    assert((mw)->mw_prev_entry->tag < (tag_));                      \
872    assert((mw)->mw_entry < (mw)->mw_end);                          \
873    (mw)->mw_entry->tag = (tag_);                                   \
874    (mw)->mw_entry->off = (mw)->mw_prev_entry->off + (sz);          \
875    (mw)->mw_prev_entry = (mw)->mw_entry;                           \
876    ++(mw)->mw_entry;                                               \
877} while (0)
878
879#define MW_WRITE_BUFFER(mw, tag, buf, sz) do {                      \
880    MW_WRITE_TABLE_ENTRY(mw, tag, sz);                              \
881    memcpy(MW_P(mw), buf, sz);                                      \
882    MW_ADVANCE_P(mw, sz);                                           \
883} while (0)
884
885#define MW_WRITE_LS_STR(mw, tag, s) \
886    MW_WRITE_BUFFER(mw, tag, lsquic_str_buf(s), lsquic_str_len(s))
887
888#define MW_WRITE_UINT32(mw, tag, val) do {                          \
889    uint32_t v_ = (val);                                            \
890    MW_WRITE_BUFFER(mw, tag, &v_, sizeof(v_));                      \
891} while (0)
892
893#define MW_WRITE_UINT64(mw, tag, val) do {                          \
894    uint64_t v_ = (val);                                            \
895    MW_WRITE_BUFFER(mw, tag, &v_, sizeof(v_));                      \
896} while (0)
897
898
899/* MSG_LEN_ family of macros calculates buffer size required for a
900 * handshake message.
901 */
902#define MSG_LEN_INIT(len) do {                                      \
903    len = 4 /* Tag */ + 2 /* # tags */ + 2 /* Two zero bytes */;    \
904} while (0)
905
906#define MSG_LEN_ADD(len, payload_sz) do {                           \
907    len += 4 + 4 + (payload_sz);                                    \
908} while (0)
909
910#define MSG_LEN_VAL(len) (+(len))
911
912
913static int
914lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
915                        enum lsquic_version version, uint8_t *buf, size_t *len)
916{
917    int ret, include_pad;
918    const lsquic_str_t *const ccs = get_common_certs_hash();
919    const struct lsquic_engine_settings *const settings =
920                                        &enc_session->enpub->enp_settings;
921    c_cert_item_t *const cert_item = enc_session->cert_item;
922    unsigned char pub_key[32];
923    size_t ua_len;
924    uint32_t opts[1];  /* Only NSTP is supported for now */
925    unsigned n_opts, msg_len, n_tags, pad_size;
926    struct message_writer mw;
927
928    /* Before we do anything else, sanity check: */
929    if (*len < MIN_CHLO_SIZE)
930        return -1;
931
932    n_opts = 0;
933    /* CHLO is not regenerated during version negotiation.  Hence we always
934     * include this option to cover the case when Q044 gets negotiated down.
935     */
936    if (settings->es_support_nstp)
937        opts[ n_opts++ ] = QTAG_NSTP;
938
939    /* Count tags and calculate required buffer size: */
940    MSG_LEN_INIT(msg_len);                  n_tags = 0;
941    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* PDMD */
942    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* AEAD */
943    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* VER  */
944    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* MIDS */
945    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* SCLS */
946    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* CFCW */
947    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* SFCW */
948    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* ICSL */
949    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* SMHL */
950    MSG_LEN_ADD(msg_len, 4);                ++n_tags;           /* KEXS */
951    MSG_LEN_ADD(msg_len, 0);                ++n_tags;           /* CSCT */
952    if (n_opts > 0)
953    {
954        MSG_LEN_ADD(msg_len, sizeof(opts[0]) * n_opts);
955                                            ++n_tags;           /* COPT */
956    }
957    if (settings->es_ua)
958    {
959        ua_len = strlen(settings->es_ua);
960        if (ua_len > 0)
961        {
962            MSG_LEN_ADD(msg_len, ua_len);   ++n_tags;           /* UAID */
963        }
964    }
965    else
966        ua_len = 0;
967    if (settings->es_support_tcid0)
968    {
969        MSG_LEN_ADD(msg_len, 4);            ++n_tags;           /* TCID */
970    }
971    MSG_LEN_ADD(msg_len, lsquic_str_len(&enc_session->hs_ctx.sni));
972                                            ++n_tags;           /* SNI  */
973    MSG_LEN_ADD(msg_len, lsquic_str_len(ccs));  ++n_tags;           /* CCS  */
974    if (cert_item)
975    {
976        enc_session->cert_ptr = &cert_item->crts[0];
977        MSG_LEN_ADD(msg_len, lsquic_str_len(cert_item->hashs));
978                                            ++n_tags;           /* CCRT */
979        MSG_LEN_ADD(msg_len, 8);            ++n_tags;           /* XLCT */
980    }
981    MSG_LEN_ADD(msg_len, lsquic_str_len(&enc_session->ssno));
982                                            ++n_tags;           /* SNO  */
983    MSG_LEN_ADD(msg_len, lsquic_str_len(&enc_session->info->sstk));
984                                            ++n_tags;           /* STK  */
985    if (lsquic_str_len(&enc_session->info->scfg) > 0)
986    {
987        MSG_LEN_ADD(msg_len, sizeof(enc_session->info->sscid));
988                                            ++n_tags;           /* SCID */
989        if (enc_session->cert_ptr)
990        {
991            MSG_LEN_ADD(msg_len, sizeof(pub_key));
992                                            ++n_tags;           /* PUBS */
993            MSG_LEN_ADD(msg_len, sizeof(enc_session->hs_ctx.nonc));
994                                            ++n_tags;           /* NONC */
995            rand_bytes(enc_session->priv_key, 32);
996            c255_get_pub_key(enc_session->priv_key, pub_key);
997            gen_nonce_c(enc_session->hs_ctx.nonc, enc_session->info->orbt);
998        }
999    }
1000    include_pad = MSG_LEN_VAL(msg_len) < MIN_CHLO_SIZE;
1001    if (include_pad)
1002    {
1003        if (MSG_LEN_VAL(msg_len) + sizeof(struct table_entry) < MIN_CHLO_SIZE)
1004            pad_size = MIN_CHLO_SIZE - MSG_LEN_VAL(msg_len) -
1005                                                sizeof(struct table_entry);
1006        else
1007            pad_size = 0;
1008        MSG_LEN_ADD(msg_len, pad_size);     ++n_tags;           /* PAD  */
1009    }
1010#ifdef WIN32
1011    else
1012        pad_size = 0;
1013#endif
1014
1015    /* Check that we have enough room in the output buffer: */
1016    if (MSG_LEN_VAL(msg_len) > *len)
1017        return -1;
1018
1019    /* Write CHLO: */
1020    MW_BEGIN(&mw, QTAG_CHLO, n_tags, buf);
1021    if (include_pad)
1022    {
1023        memset(MW_P(&mw), '-', pad_size);
1024        MW_WRITE_TABLE_ENTRY(&mw, QTAG_PAD, pad_size);
1025        MW_ADVANCE_P(&mw, pad_size);
1026    }
1027    MW_WRITE_LS_STR(&mw, QTAG_SNI, &enc_session->hs_ctx.sni);
1028    MW_WRITE_LS_STR(&mw, QTAG_STK, &enc_session->info->sstk);
1029    MW_WRITE_LS_STR(&mw, QTAG_SNO, &enc_session->ssno);
1030    MW_WRITE_UINT32(&mw, QTAG_VER, lsquic_ver2tag(version));
1031    MW_WRITE_LS_STR(&mw, QTAG_CCS, ccs);
1032    if (lsquic_str_len(&enc_session->info->scfg) > 0 && enc_session->cert_ptr)
1033        MW_WRITE_BUFFER(&mw, QTAG_NONC, enc_session->hs_ctx.nonc,
1034                                        sizeof(enc_session->hs_ctx.nonc));
1035    MW_WRITE_UINT32(&mw, QTAG_AEAD, settings->es_aead);
1036    if (ua_len)
1037        MW_WRITE_BUFFER(&mw, QTAG_UAID, settings->es_ua, ua_len);
1038    if (lsquic_str_len(&enc_session->info->scfg) > 0)
1039        MW_WRITE_BUFFER(&mw, QTAG_SCID, enc_session->info->sscid,
1040                                        sizeof(enc_session->info->sscid));
1041    if (settings->es_support_tcid0)
1042        MW_WRITE_UINT32(&mw, QTAG_TCID, 0);
1043    MW_WRITE_UINT32(&mw, QTAG_PDMD, settings->es_pdmd);
1044    MW_WRITE_UINT32(&mw, QTAG_SMHL, 1);
1045    MW_WRITE_UINT32(&mw, QTAG_ICSL, settings->es_idle_conn_to / 1000000);
1046    if (lsquic_str_len(&enc_session->info->scfg) > 0 && enc_session->cert_ptr)
1047        MW_WRITE_BUFFER(&mw, QTAG_PUBS, pub_key, sizeof(pub_key));
1048    MW_WRITE_UINT32(&mw, QTAG_MIDS, settings->es_max_streams_in);
1049    MW_WRITE_UINT32(&mw, QTAG_SCLS, settings->es_silent_close);
1050    MW_WRITE_UINT32(&mw, QTAG_KEXS, settings->es_kexs);
1051    if (cert_item)
1052        MW_WRITE_BUFFER(&mw, QTAG_XLCT, lsquic_str_buf(cert_item->hashs), 8);
1053    /* CSCT is empty on purpose (retained from original code) */
1054    MW_WRITE_TABLE_ENTRY(&mw, QTAG_CSCT, 0);
1055    if (n_opts > 0)
1056        MW_WRITE_BUFFER(&mw, QTAG_COPT, opts, n_opts * sizeof(opts[0]));
1057    if (cert_item)
1058        MW_WRITE_LS_STR(&mw, QTAG_CCRT, cert_item->hashs);
1059    MW_WRITE_UINT32(&mw, QTAG_CFCW, settings->es_cfcw);
1060    MW_WRITE_UINT32(&mw, QTAG_SFCW, settings->es_sfcw);
1061    MW_END(&mw);
1062    assert(buf + *len >= MW_P(&mw));
1063
1064    *len = MW_P(&mw) - buf;
1065
1066    lsquic_str_setto(&enc_session->chlo, buf, *len);
1067
1068    if (lsquic_str_len(&enc_session->info->scfg) > 0 && enc_session->cert_ptr)
1069    {
1070        enc_session->have_key = 0;
1071        assert(lsquic_str_len(enc_session->cert_ptr) > 0);
1072        ret = determine_keys(enc_session
1073                                            );
1074        enc_session->have_key = 1;
1075    }
1076    else
1077        ret = 0;
1078
1079    LSQ_DEBUG("lsquic_enc_session_gen_chlo called, return %d, buf_len %zd.", ret, *len);
1080    return ret;
1081}
1082
1083
1084static int handle_chlo_reply_verify_prof(lsquic_enc_session_t *enc_session,
1085                                         lsquic_str_t **out_certs,
1086                                         size_t *out_certs_count,
1087                                         lsquic_str_t *cached_certs,
1088                                         int cached_certs_count)
1089{
1090    const unsigned char *const in =
1091                (const unsigned char *) lsquic_str_buf(&enc_session->hs_ctx.crt);
1092    const unsigned char *const in_end =
1093                                    in + lsquic_str_len(&enc_session->hs_ctx.crt);
1094    EVP_PKEY *pub_key;
1095    int ret;
1096    size_t i;
1097    X509 *cert, *server_cert;
1098    STACK_OF(X509) *chain = NULL;
1099    ret = decompress_certs(in, in_end,cached_certs, cached_certs_count,
1100                           out_certs, out_certs_count);
1101    if (ret)
1102        return ret;
1103
1104    server_cert = bio_to_crt((const char *)lsquic_str_cstr(out_certs[0]),
1105                      lsquic_str_len(out_certs[0]), 0);
1106    pub_key = X509_get_pubkey(server_cert);
1107    ret = verify_prof((const uint8_t *)lsquic_str_cstr(&enc_session->chlo),
1108                      (size_t)lsquic_str_len(&enc_session->chlo),
1109                      &enc_session->info->scfg,
1110                      pub_key,
1111                      (const uint8_t *)lsquic_str_cstr(&enc_session->hs_ctx.prof),
1112                      lsquic_str_len(&enc_session->hs_ctx.prof));
1113    EVP_PKEY_free(pub_key);
1114    if (ret != 0)
1115        goto cleanup;
1116
1117    if (enc_session->enpub->enp_verify_cert)
1118    {
1119        chain = sk_X509_new_null();
1120        sk_X509_push(chain, server_cert);
1121        for (i = 1; i < *out_certs_count; ++i)
1122        {
1123            cert = bio_to_crt((const char *)lsquic_str_cstr(out_certs[i]),
1124                                    lsquic_str_len(out_certs[i]), 0);
1125            if (cert)
1126                sk_X509_push(chain, cert);
1127            else
1128            {
1129                LSQ_WARN("cannot push certificate to stack");
1130                ret = -1;
1131                goto cleanup;
1132            }
1133        }
1134        ret = enc_session->enpub->enp_verify_cert(
1135                                enc_session->enpub->enp_verify_ctx, chain);
1136        LSQ_INFO("server certificate verification %ssuccessful",
1137                                                    ret == 0 ? "" : "not ");
1138    }
1139
1140  cleanup:
1141    if (chain)
1142        sk_X509_free(chain);
1143    X509_free(server_cert);
1144    return ret;
1145}
1146
1147
1148void setup_aead_ctx(EVP_AEAD_CTX **ctx, unsigned char key[], int key_len,
1149                    unsigned char *key_copy)
1150{
1151    const EVP_AEAD *aead_ = EVP_aead_aes_128_gcm();
1152    const int auth_tag_size = 12;
1153    if (*ctx)
1154    {
1155        EVP_AEAD_CTX_cleanup(*ctx);
1156    }
1157    else
1158        *ctx = (EVP_AEAD_CTX *)malloc(sizeof(EVP_AEAD_CTX));
1159
1160    EVP_AEAD_CTX_init(*ctx, aead_, key, key_len, auth_tag_size, NULL);
1161    if (key_copy)
1162        memcpy(key_copy, key, key_len);
1163}
1164
1165
1166static int
1167determine_diversification_key (lsquic_enc_session_t *enc_session,
1168                  uint8_t *diversification_nonce
1169                  )
1170{
1171    EVP_AEAD_CTX **ctx_s_key;
1172    unsigned char *key_i, *iv;
1173    uint8_t ikm[aes128_key_len + aes128_iv_len];
1174
1175    ctx_s_key = &enc_session->dec_ctx_i;
1176    key_i = enc_session->dec_key_i;
1177    iv = enc_session->dec_key_nonce_i;
1178    memcpy(ikm, key_i, aes128_key_len);
1179    memcpy(ikm + aes128_key_len, iv, aes128_iv_len);
1180    export_key_material(ikm, aes128_key_len + aes128_iv_len,
1181                        diversification_nonce, DNONC_LENGTH,
1182                        (const unsigned char *) "QUIC key diversification", 24,
1183                        0, NULL, aes128_key_len, key_i, 0, NULL,
1184                        aes128_iv_len, iv, NULL);
1185
1186    setup_aead_ctx(ctx_s_key, key_i, aes128_key_len, NULL);
1187    LSQ_DEBUG("determine_diversification_keys diversification_key: %s\n",
1188              get_bin_str(key_i, aes128_key_len, 512));
1189    LSQ_DEBUG("determine_diversification_keys diversification_key nonce: %s\n",
1190              get_bin_str(iv, aes128_iv_len, 512));
1191    return 0;
1192}
1193
1194
1195/* After CHLO msg generatered, call it to determine_keys */
1196static int determine_keys(lsquic_enc_session_t *enc_session)
1197{
1198    lsquic_str_t *chlo = &enc_session->chlo;
1199    uint8_t shared_key_c[32];
1200    struct lsquic_buf *nonce_c = lsquic_buf_create(100);
1201    struct lsquic_buf *hkdf_input = lsquic_buf_create(0);
1202
1203    unsigned char c_key[aes128_key_len];
1204    unsigned char s_key[aes128_key_len];
1205    unsigned char *c_key_bin = NULL;
1206    unsigned char *s_key_bin = NULL;
1207
1208    unsigned char *c_iv;
1209    unsigned char *s_iv;
1210    unsigned char sub_key[32];
1211    EVP_AEAD_CTX **ctx_c_key, **ctx_s_key;
1212    char key_flag;
1213
1214    lsquic_buf_clear(nonce_c);
1215    lsquic_buf_clear(hkdf_input);
1216    if (enc_session->have_key == 0)
1217    {
1218        lsquic_buf_append(hkdf_input, "QUIC key expansion\0", 18 + 1); // Add a 0x00 */
1219        key_flag = 'I';
1220    }
1221    else
1222    {
1223        lsquic_buf_append(hkdf_input, "QUIC forward secure key expansion\0", 33 + 1); // Add a 0x00 */
1224        key_flag = 'F';
1225    }
1226
1227    c255_gen_share_key(enc_session->priv_key,
1228                       enc_session->hs_ctx.pubs,
1229                       (unsigned char *)shared_key_c);
1230    {
1231        if (enc_session->have_key == 0)
1232        {
1233            ctx_c_key = &enc_session->enc_ctx_i;
1234            ctx_s_key = &enc_session->dec_ctx_i;
1235            c_iv = (unsigned char *) enc_session->enc_key_nonce_i;
1236            s_iv = (unsigned char *) enc_session->dec_key_nonce_i;
1237            c_key_bin = enc_session->enc_key_i;
1238            s_key_bin = enc_session->dec_key_i;
1239        }
1240        else
1241        {
1242            ctx_c_key = &enc_session->enc_ctx_f;
1243            ctx_s_key = &enc_session->dec_ctx_f;
1244            c_iv = (unsigned char *) enc_session->enc_key_nonce_f;
1245            s_iv = (unsigned char *) enc_session->dec_key_nonce_f;
1246        }
1247    }
1248
1249    LSQ_DEBUG("export_key_material c255_gen_share_key %s",
1250              get_bin_str(shared_key_c, 32, 512));
1251
1252    lsquic_buf_append(hkdf_input, (char *)&enc_session->cid, sizeof(enc_session->cid));
1253    lsquic_buf_append(hkdf_input, lsquic_str_cstr(chlo), lsquic_str_len(chlo)); /* CHLO msg */
1254    {
1255        lsquic_buf_append(hkdf_input, lsquic_str_cstr(&enc_session->info->scfg),
1256                       lsquic_str_len(&enc_session->info->scfg)); /* scfg msg */
1257    }
1258    lsquic_buf_append(hkdf_input, lsquic_str_cstr(enc_session->cert_ptr),
1259                   lsquic_str_len(enc_session->cert_ptr));
1260    LSQ_DEBUG("export_key_material hkdf_input %s",
1261              get_bin_str(lsquic_buf_begin(hkdf_input),
1262                          (size_t)lsquic_buf_size(hkdf_input), 512));
1263
1264    /* then need to use the salts and the shared_key_* to get the real aead key */
1265    lsquic_buf_append(nonce_c, (const char *) enc_session->hs_ctx.nonc, 32);
1266    lsquic_buf_append(nonce_c, lsquic_str_cstr(&enc_session->ssno),
1267                   lsquic_str_len(&enc_session->ssno));
1268    LSQ_DEBUG("export_key_material nonce %s",
1269              get_bin_str(lsquic_buf_begin(nonce_c),
1270                          (size_t)lsquic_buf_size(nonce_c), 512));
1271
1272    export_key_material(shared_key_c, 32,
1273                        (unsigned char *)lsquic_buf_begin(nonce_c), lsquic_buf_size(nonce_c),
1274                        (unsigned char *)lsquic_buf_begin(hkdf_input),
1275                        lsquic_buf_size(hkdf_input),
1276                        aes128_key_len, c_key,
1277                        aes128_key_len, s_key,
1278                        aes128_iv_len, c_iv,
1279                        aes128_iv_len, s_iv,
1280                        sub_key);
1281
1282    setup_aead_ctx(ctx_c_key, c_key, aes128_key_len, c_key_bin);
1283    setup_aead_ctx(ctx_s_key, s_key, aes128_key_len, s_key_bin);
1284
1285
1286    lsquic_buf_destroy(nonce_c);
1287    lsquic_buf_destroy(hkdf_input);
1288
1289    LSQ_DEBUG("***export_key_material '%c' c_key: %s", key_flag,
1290              get_bin_str(c_key, aes128_key_len, 512));
1291    LSQ_DEBUG("***export_key_material '%c' s_key: %s", key_flag,
1292              get_bin_str(s_key, aes128_key_len, 512));
1293    LSQ_DEBUG("***export_key_material '%c' c_iv: %s", key_flag,
1294              get_bin_str(c_iv, aes128_iv_len, 512));
1295    LSQ_DEBUG("***export_key_material '%c' s_iv: %s", key_flag,
1296              get_bin_str(s_iv, aes128_iv_len, 512));
1297    LSQ_DEBUG("***export_key_material '%c' subkey: %s", key_flag,
1298              get_bin_str(sub_key, 32, 512));
1299
1300    return 0;
1301}
1302
1303
1304/* 0 Match */
1305static int cached_certs_match(c_cert_item_t *item,
1306                                        lsquic_str_t **certs, int count)
1307{
1308    int i;
1309    if (!item || item->count != count)
1310        return -1;
1311
1312    for (i=0; i<count; ++i)
1313    {
1314        if (lsquic_str_bcmp(certs[i], &item->crts[i]) != 0)
1315            return -1;
1316    }
1317
1318    return 0;
1319}
1320
1321
1322static const char *
1323he2str (enum handshake_error he)
1324{
1325    switch (he)
1326    {
1327    case DATA_NOT_ENOUGH:   return "DATA_NOT_ENOUGH";
1328    case HS_ERROR:          return "HS_ERROR";
1329    case HS_SHLO:           return "HS_SHLO";
1330    case HS_1RTT:           return "HS_1RTT";
1331    case HS_2RTT:           return "HS_2RTT";
1332    default:
1333        assert(0);          return "<unknown enum value>";
1334    }
1335}
1336
1337
1338/* NOT packet, just the frames-data */
1339/* return rtt number:
1340 *      0 OK
1341 *      DATA_NOT_ENOUGH(-2) for not enough data,
1342 *      DATA_FORMAT_ERROR(-1) all other errors
1343 */
1344static int
1345lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
1346                                                const uint8_t *data, int len)
1347{
1348    uint32_t head_tag;
1349    int ret;
1350    lsquic_session_cache_info_t *info = enc_session->info;
1351    c_cert_item_t *cert_item = enc_session->cert_item;
1352
1353    /* FIXME get the number first */
1354    lsquic_str_t **out_certs = NULL;
1355    size_t out_certs_count = 0, i;
1356
1357    ret = parse_hs(enc_session, data, len, &head_tag);
1358    if (ret)
1359        goto end;
1360
1361    if (head_tag != QTAG_SREJ &&
1362        head_tag != QTAG_REJ &&
1363        head_tag != QTAG_SHLO)
1364    {
1365        ret = 1;
1366        goto end;
1367    }
1368
1369    if (head_tag == QTAG_SREJ || head_tag == QTAG_REJ)
1370    {
1371        enc_session->hsk_state = HSK_CHLO_REJ;
1372        enc_session->es_flags |= ES_RECV_REJ;
1373    }
1374    else if(head_tag == QTAG_SHLO)
1375    {
1376        enc_session->hsk_state = HSK_COMPLETED;
1377    }
1378
1379    if (info->scfg_flag == 1)
1380    {
1381        ret = parse_hs(enc_session, (uint8_t *)lsquic_str_cstr(&info->scfg),
1382                       lsquic_str_len(&info->scfg), &head_tag);
1383
1384        /* After handled, set the length to 0 to avoid do it again*/
1385        enc_session->info->scfg_flag = 2;
1386        if (ret)
1387            goto end;
1388
1389        if (lsquic_str_len(&enc_session->hs_ctx.crt) > 0)
1390        {
1391            out_certs_count = get_certs_count(&enc_session->hs_ctx.crt);
1392            if (out_certs_count > 0)
1393            {
1394                out_certs = malloc(out_certs_count * sizeof(lsquic_str_t *));
1395                if (!out_certs)
1396                {
1397                    ret = -1;
1398                    goto end;
1399                }
1400
1401                for (i=0; i<out_certs_count; ++i)
1402                    out_certs[i] = lsquic_str_new(NULL, 0);
1403
1404                ret = handle_chlo_reply_verify_prof(enc_session, out_certs,
1405                                            &out_certs_count,
1406                                            (cert_item ? cert_item->crts : NULL),
1407                                            (cert_item ? cert_item->count : 0));
1408                if (ret == 0)
1409                {
1410                    if (out_certs_count > 0)
1411                    {
1412                        if (cached_certs_match(cert_item, out_certs,
1413                                                        out_certs_count) != 0)
1414                        {
1415                            cert_item = make_c_cert_item(out_certs,
1416                                                            out_certs_count);
1417                            enc_session->cert_item = cert_item;
1418                            enc_session->cert_ptr = &cert_item->crts[0];
1419                        }
1420                    }
1421                }
1422                for (i=0; i<out_certs_count; ++i)
1423                    lsquic_str_delete(out_certs[i]);
1424                free(out_certs);
1425
1426                if (ret)
1427                    goto end;
1428            }
1429        }
1430    }
1431
1432    if (enc_session->hsk_state == HSK_COMPLETED)
1433    {
1434        ret = determine_keys(enc_session
1435                                           ); /* FIXME: check ret */
1436        enc_session->have_key = 3;
1437    }
1438
1439  end:
1440    LSQ_DEBUG("lsquic_enc_session_handle_chlo_reply called, buf in %d, return %d.", len, ret);
1441    EV_LOG_CONN_EVENT(enc_session->cid, "%s returning %s", __func__,
1442                                                                he2str(ret));
1443    return ret;
1444}
1445
1446
1447static uint64_t combine_path_id_pack_num(uint8_t path_id, uint64_t pack_num)
1448{
1449    uint64_t v = ((uint64_t)path_id << 56) | pack_num;
1450    return v;
1451}
1452
1453
1454#   define IS_SERVER(session) 0
1455
1456static int
1457verify_packet_hash (const lsquic_enc_session_t *enc_session,
1458    enum lsquic_version version, const unsigned char *buf, size_t *header_len,
1459    size_t data_len, unsigned char *buf_out, size_t max_out_len,
1460    size_t *out_len)
1461{
1462    uint8_t md[HS_PKT_HASH_LENGTH];
1463    uint128 hash;
1464    int ret;
1465
1466    if (data_len < HS_PKT_HASH_LENGTH)
1467        return -1;
1468
1469    if (version >= LSQVER_039)
1470    {
1471        hash = fnv1a_128_3(buf, *header_len,
1472                    buf + *header_len + HS_PKT_HASH_LENGTH,
1473                    data_len - HS_PKT_HASH_LENGTH,
1474                    (unsigned char *) "Server", 6);
1475    }
1476    else
1477    {
1478        hash = fnv1a_128_2(buf, *header_len,
1479                        buf + *header_len + HS_PKT_HASH_LENGTH,
1480                        data_len - HS_PKT_HASH_LENGTH);
1481    }
1482
1483    serialize_fnv128_short(hash, md);
1484    ret = memcmp(md, buf + *header_len, HS_PKT_HASH_LENGTH);
1485    if(ret == 0)
1486    {
1487        *header_len += HS_PKT_HASH_LENGTH;
1488        *out_len = data_len - HS_PKT_HASH_LENGTH;
1489        if (max_out_len < *header_len + *out_len)
1490            return -1;
1491
1492        memcpy(buf_out, buf, *header_len + *out_len);
1493        return 0;
1494    }
1495    else
1496        return -1;
1497}
1498
1499
1500static enum enc_level
1501decrypt_packet (lsquic_enc_session_t *enc_session, uint8_t path_id,
1502                uint64_t pack_num, unsigned char *buf, size_t *header_len,
1503                size_t data_len, unsigned char *buf_out, size_t max_out_len,
1504                size_t *out_len)
1505{
1506    int ret;
1507    /* Comment: 12 = sizeof(dec_key_iv] 4 + sizeof(pack_num) 8 */
1508    uint8_t nonce[12];
1509    uint64_t path_id_packet_number;
1510    EVP_AEAD_CTX *key = NULL;
1511    int try_times = 0;
1512    enum enc_level enc_level;
1513
1514    path_id_packet_number = combine_path_id_pack_num(path_id, pack_num);
1515    memcpy(buf_out, buf, *header_len);
1516    do
1517    {
1518        if (enc_session->have_key == 3 && try_times == 0)
1519        {
1520            key = enc_session->dec_ctx_f;
1521            memcpy(nonce, enc_session->dec_key_nonce_f, 4);
1522            LSQ_DEBUG("decrypt_packet using 'F' key...");
1523            enc_level = ENC_LEV_FORW;
1524        }
1525        else
1526        {
1527            key = enc_session->dec_ctx_i;
1528            memcpy(nonce, enc_session->dec_key_nonce_i, 4);
1529            LSQ_DEBUG("decrypt_packet using 'I' key...");
1530            enc_level = ENC_LEV_INIT;
1531        }
1532        memcpy(nonce + 4, &path_id_packet_number,
1533               sizeof(path_id_packet_number));
1534
1535        *out_len = data_len;
1536        ret = aes_aead_dec(key,
1537                           buf, *header_len,
1538                           nonce, 12,
1539                           buf + *header_len, data_len,
1540                           buf_out + *header_len, out_len);
1541
1542        if (ret != 0)
1543            ++try_times;
1544        else
1545        {
1546            if (enc_session->peer_have_final_key == 0 &&
1547                enc_session->have_key == 3 &&
1548                try_times == 0)
1549            {
1550                LSQ_DEBUG("!!!decrypt_packet find peer have final key.");
1551                enc_session->peer_have_final_key = 1;
1552                EV_LOG_CONN_EVENT(enc_session->cid, "settled on private key "
1553                    "'%c' after %d tries (packet number %"PRIu64")",
1554                    key == enc_session->dec_ctx_f ? 'F' : 'I',
1555                    try_times, pack_num);
1556            }
1557            break;
1558        }
1559    }
1560    while (try_times < 2);
1561
1562    LSQ_DEBUG("***decrypt_packet %s.", (ret == 0 ? "succeed" : "failed"));
1563    return ret == 0 ? enc_level : (enum enc_level) -1;
1564}
1565
1566
1567static int
1568lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session)
1569{
1570    return enc_session && enc_session->have_key > 1;
1571}
1572
1573
1574/* The size of `buf' is *header_len plus data_len.  The two parts of the
1575 * buffer correspond to the header and the payload of incoming QUIC packet.
1576 */
1577static enum enc_level
1578lsquic_enc_session_decrypt (lsquic_enc_session_t *enc_session,
1579               enum lsquic_version version,
1580               uint8_t path_id, uint64_t pack_num,
1581               unsigned char *buf, size_t *header_len, size_t data_len,
1582               unsigned char *diversification_nonce,
1583               unsigned char *buf_out, size_t max_out_len, size_t *out_len)
1584{
1585    /* Client: got SHLO which should have diversification_nonce */
1586    if (diversification_nonce && enc_session && enc_session->have_key == 1)
1587    {
1588        determine_diversification_key(enc_session, diversification_nonce);
1589        enc_session->have_key = 2;
1590    }
1591
1592    if (lsquic_enc_session_have_key_gt_one(enc_session))
1593        return decrypt_packet(enc_session, path_id, pack_num, buf,
1594                        header_len, data_len, buf_out, max_out_len, out_len);
1595    else if (0 == verify_packet_hash(enc_session, version, buf, header_len,
1596                                     data_len, buf_out, max_out_len, out_len))
1597        return ENC_LEV_CLEAR;
1598    else
1599        return -1;
1600}
1601
1602
1603static enum enc_level
1604lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
1605               enum lsquic_version version,
1606               uint8_t path_id, uint64_t pack_num,
1607               const unsigned char *header, size_t header_len,
1608               const unsigned char *data, size_t data_len,
1609               unsigned char *buf_out, size_t max_out_len, size_t *out_len,
1610               int is_hello)
1611{
1612    uint8_t md[HS_PKT_HASH_LENGTH];
1613    uint128 hash;
1614    int ret;
1615    enum enc_level enc_level;
1616    int is_chlo = (is_hello && ((IS_SERVER(enc_session)) == 0));
1617    int is_shlo = (is_hello && (IS_SERVER(enc_session)));
1618
1619    /* Comment: 12 = sizeof(dec_key_iv] 4 + sizeof(pack_num) 8 */
1620    uint8_t nonce[12];
1621    uint64_t path_id_packet_number;
1622    EVP_AEAD_CTX *key;
1623
1624    if (enc_session)
1625        LSQ_DEBUG("%s: hsk_state: %d", __func__, enc_session->hsk_state);
1626    else
1627        LSQ_DEBUG("%s: enc_session is not set", __func__);
1628
1629    if (!enc_session || enc_session->have_key == 0 || is_chlo)
1630    {
1631        *out_len = header_len + data_len + HS_PKT_HASH_LENGTH;
1632        if (max_out_len < *out_len)
1633            return -1;
1634
1635        if (version >= LSQVER_039)
1636        {
1637            hash = fnv1a_128_3(header, header_len, data, data_len,
1638                                        (unsigned char *) "Client", 6);
1639        }
1640        else
1641        {
1642            hash = fnv1a_128_2(header, header_len, data, data_len);
1643        }
1644
1645        serialize_fnv128_short(hash, md);
1646        memcpy(buf_out, header, header_len);
1647        memcpy(buf_out + header_len, md, HS_PKT_HASH_LENGTH);
1648        memcpy(buf_out + header_len + HS_PKT_HASH_LENGTH, data, data_len);
1649        return ENC_LEV_CLEAR;
1650    }
1651    else
1652    {
1653        if (enc_session->have_key != 3 || is_shlo ||
1654            ((IS_SERVER(enc_session)) &&
1655             enc_session->server_start_use_final_key == 0))
1656        {
1657            LSQ_DEBUG("lsquic_enc_session_encrypt using 'I' key...");
1658            key = enc_session->enc_ctx_i;
1659            memcpy(nonce, enc_session->enc_key_nonce_i, 4);
1660            if (is_shlo && enc_session->have_key == 3)
1661            {
1662                enc_session->server_start_use_final_key = 1;
1663            }
1664            enc_level = ENC_LEV_INIT;
1665        }
1666        else
1667        {
1668            LSQ_DEBUG("lsquic_enc_session_encrypt using 'F' key...");
1669            key = enc_session->enc_ctx_f;
1670            memcpy(nonce, enc_session->enc_key_nonce_f, 4);
1671            enc_level = ENC_LEV_FORW;
1672        }
1673        path_id_packet_number = combine_path_id_pack_num(path_id, pack_num);
1674        memcpy(nonce + 4, &path_id_packet_number,
1675               sizeof(path_id_packet_number));
1676
1677        memcpy(buf_out, header, header_len);
1678        *out_len = max_out_len - header_len;
1679
1680        ret = aes_aead_enc(key, header, header_len, nonce, 12, data,
1681                           data_len, buf_out + header_len, out_len);
1682        if (ret == 0)
1683        {
1684            *out_len += header_len;
1685            return enc_level;
1686        }
1687        else
1688            return -1;
1689    }
1690}
1691
1692
1693static int
1694lsquic_enc_session_get_peer_option (const lsquic_enc_session_t *enc_session,
1695                                                                uint32_t tag)
1696{
1697    switch (tag)
1698    {
1699    case QTAG_NSTP:
1700        return !!(enc_session->hs_ctx.opts & HOPT_NSTP);
1701    case QTAG_SREJ:
1702        return !!(enc_session->hs_ctx.opts & HOPT_SREJ);
1703    default:
1704        assert(0);
1705        return 0;
1706    }
1707}
1708
1709
1710/* Query a several parameters sent by the peer that are required by
1711 * connection.
1712 */
1713static int
1714lsquic_enc_session_get_peer_setting (const lsquic_enc_session_t *enc_session,
1715                                        uint32_t tag, uint32_t *val)
1716{
1717    switch (tag)
1718    {
1719    case QTAG_TCID:
1720        if (enc_session->hs_ctx.set & HSET_TCID)
1721        {
1722            *val = enc_session->hs_ctx.tcid;
1723            return 0;
1724        }
1725        else
1726            return -1;
1727    case QTAG_SMHL:
1728        if (enc_session->hs_ctx.set & HSET_SMHL)
1729        {
1730            *val = enc_session->hs_ctx.smhl;
1731            return 0;
1732        }
1733        else
1734            return -1;
1735    case QTAG_IRTT:
1736        if (enc_session->hs_ctx.set & HSET_IRTT)
1737        {
1738            *val = enc_session->hs_ctx.irtt;
1739            return 0;
1740        }
1741        else
1742            return -1;
1743    }
1744
1745    /* XXX For the following values, there is no record which were present
1746     *     in CHLO or SHLO and which were not.  Assume that zero means that
1747     *     they weren't present.
1748     */
1749        switch (tag)
1750        {
1751        case QTAG_CFCW:
1752            if (enc_session->hs_ctx.cfcw)
1753            {
1754                *val = enc_session->hs_ctx.cfcw;
1755                return 0;
1756            }
1757            else
1758                return -1;
1759        case QTAG_SFCW:
1760            if (enc_session->hs_ctx.sfcw)
1761            {
1762                *val = enc_session->hs_ctx.sfcw;
1763                return 0;
1764            }
1765            else
1766                return -1;
1767        case QTAG_MIDS:
1768            if (enc_session->hs_ctx.mids)
1769            {
1770                *val = enc_session->hs_ctx.mids;
1771                return 0;
1772            }
1773            else
1774                return -1;
1775        default:
1776            return -1;
1777        }
1778}
1779
1780
1781#if LSQUIC_KEEP_ENC_SESS_HISTORY
1782static void
1783lsquic_get_enc_hist (const lsquic_enc_session_t *enc_session,
1784                                        char buf[(1 << ESHIST_BITS) + 1])
1785{
1786    const unsigned hist_idx = ESHIST_MASK & enc_session->es_hist_idx;
1787    if (enc_session->es_hist_buf[hist_idx] == ESHE_EMPTY)
1788        memcpy(buf, enc_session->es_hist_buf, hist_idx + 1);
1789    else
1790    {
1791        memcpy(buf, enc_session->es_hist_buf + hist_idx, sizeof(enc_session->es_hist_buf) - hist_idx);
1792        memcpy(buf + hist_idx, enc_session->es_hist_buf, hist_idx);
1793        buf[(1 << ESHIST_BITS)] = '\0';
1794    }
1795}
1796
1797
1798#endif
1799
1800
1801
1802
1803static size_t
1804lsquic_enc_session_mem_used (struct lsquic_enc_session *enc_session)
1805{
1806    size_t size;
1807
1808    size = sizeof(*enc_session);
1809
1810    size += lsquic_str_len(&enc_session->chlo);
1811    size += lsquic_str_len(&enc_session->sstk);
1812    size += lsquic_str_len(&enc_session->ssno);
1813
1814    size += lsquic_str_len(&enc_session->hs_ctx.ccs);
1815    size += lsquic_str_len(&enc_session->hs_ctx.sni);
1816    size += lsquic_str_len(&enc_session->hs_ctx.ccrt);
1817    size += lsquic_str_len(&enc_session->hs_ctx.stk);
1818    size += lsquic_str_len(&enc_session->hs_ctx.sno);
1819    size += lsquic_str_len(&enc_session->hs_ctx.prof);
1820    size += lsquic_str_len(&enc_session->hs_ctx.csct);
1821    size += lsquic_str_len(&enc_session->hs_ctx.crt);
1822
1823    if (enc_session->info)
1824    {
1825        size += sizeof(*enc_session->info);
1826        size += lsquic_str_len(&enc_session->info->sstk);
1827        size += lsquic_str_len(&enc_session->info->scfg);
1828        size += lsquic_str_len(&enc_session->info->sni_key);
1829    }
1830
1831    /* TODO: calculate memory taken up by SSL stuff */
1832
1833    return size;
1834}
1835
1836
1837static int
1838lsquic_enc_session_verify_reset_token (lsquic_enc_session_t *enc_session,
1839                                        const unsigned char *buf, size_t bufsz)
1840{
1841    if (bufsz == SRST_LENGTH
1842            && (enc_session->hs_ctx.set & HSET_SRST)
1843            && 0 == memcmp(buf, enc_session->hs_ctx.srst, SRST_LENGTH))
1844        return 0;
1845    else
1846        return -1;
1847}
1848
1849
1850static int
1851lsquic_enc_session_did_zero_rtt_succeed (const lsquic_enc_session_t *enc_session)
1852{
1853    return !(enc_session->es_flags & ES_RECV_REJ);
1854}
1855
1856
1857static int
1858lsquic_enc_session_is_zero_rtt_enabled (const lsquic_enc_session_t *enc_session)
1859{
1860    return enc_session->info && enc_session->cert_item;
1861}
1862
1863
1864static c_cert_item_t *
1865lsquic_enc_session_get_cert_item (const lsquic_enc_session_t *enc_session)
1866{
1867    return enc_session->cert_item;
1868}
1869
1870
1871static STACK_OF(X509) *
1872lsquic_enc_session_get_server_cert_chain (lsquic_enc_session_t *enc_session)
1873{
1874    const struct c_cert_item_st *item;
1875    STACK_OF(X509) *chain;
1876    X509 *cert;
1877    int i;
1878
1879    item = enc_session->cert_item;
1880    if (!item)
1881    {
1882        LSQ_WARN("could not find certificates for `%.*s'",
1883                            (int) lsquic_str_len(&enc_session->hs_ctx.sni),
1884                            lsquic_str_cstr(&enc_session->hs_ctx.sni));
1885        return NULL;
1886    }
1887
1888    chain = sk_X509_new_null();
1889    for (i = 0; i < item->count; ++i)
1890    {
1891        cert = bio_to_crt(lsquic_str_cstr(&item->crts[i]),
1892                                lsquic_str_len(&item->crts[i]), 0);
1893        if (cert)
1894            sk_X509_push(chain, cert);
1895        else
1896        {
1897            sk_X509_free(chain);
1898            return NULL;
1899        }
1900    }
1901
1902    return chain;
1903}
1904
1905
1906ssize_t
1907lsquic_enc_session_get_zero_rtt (lsquic_enc_session_t *enc_session,
1908                                                enum lsquic_version version,
1909                                                        void *buf, size_t len)
1910{
1911    int i;
1912    size_t sz = 0;
1913    if (!enc_session->info || !enc_session->cert_item)
1914    {
1915        LSQ_DEBUG("client asked for rtt_into but it is not available");
1916        return 0;
1917    }
1918    for (i = 0; i < enc_session->cert_item->count; ++i)
1919    {
1920        sz += sizeof(uint32_t);
1921        sz += lsquic_str_len(&enc_session->cert_item->crts[i]);
1922    }
1923    sz += sizeof(struct lsquic_zero_rtt_storage);
1924    if (len < sz)
1925    {
1926        LSQ_DEBUG("client provided buf is too small %zu < %zu", len, sz);
1927        errno = ENOBUFS;
1928        return -1;
1929    }
1930    lsquic_enc_session_serialize_zero_rtt((struct lsquic_zero_rtt_storage *)buf,
1931                                                    version, enc_session->info,
1932                                                    enc_session->cert_item);
1933    return sz;
1934}
1935
1936
1937#ifdef NDEBUG
1938const
1939#endif
1940struct enc_session_funcs lsquic_enc_session_gquic_1 =
1941{
1942    .esf_global_init    = lsquic_handshake_init,
1943    .esf_global_cleanup = lsquic_handshake_cleanup,
1944#if LSQUIC_KEEP_ENC_SESS_HISTORY
1945    .esf_get_hist       = lsquic_get_enc_hist,
1946#endif
1947    .esf_destroy = lsquic_enc_session_destroy,
1948    .esf_is_hsk_done = lsquic_enc_session_is_hsk_done,
1949    .esf_encrypt = lsquic_enc_session_encrypt,
1950    .esf_decrypt = lsquic_enc_session_decrypt,
1951    .esf_get_peer_setting = lsquic_enc_session_get_peer_setting,
1952    .esf_get_peer_option = lsquic_enc_session_get_peer_option,
1953    .esf_create_client = lsquic_enc_session_create_client,
1954    .esf_generate_cid = lsquic_generate_cid,
1955    .esf_gen_chlo = lsquic_enc_session_gen_chlo,
1956    .esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply,
1957    .esf_mem_used = lsquic_enc_session_mem_used,
1958    .esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
1959    .esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed,
1960    .esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled,
1961    .esf_get_cert_item = lsquic_enc_session_get_cert_item,
1962    .esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
1963    .esf_get_zero_rtt = lsquic_enc_session_get_zero_rtt,
1964};
1965
1966
1967const char *const lsquic_enclev2str[] =
1968{
1969    [ENC_LEV_UNSET] = "unset",
1970    [ENC_LEV_CLEAR] = "clear",
1971    [ENC_LEV_INIT]  = "initial",
1972    [ENC_LEV_FORW]  = "forw-secure",
1973};
1974
1975
1976enum lsquic_version
1977lsquic_zero_rtt_version (const unsigned char *buf, size_t bufsz)
1978{
1979    lsquic_ver_tag_t tag;
1980
1981    if (bufsz >= sizeof(tag))
1982    {
1983        memcpy(&tag, buf, sizeof(tag));
1984        return lsquic_tag2ver(tag);
1985    }
1986    else
1987        return -1;
1988}
1989