lsquic_handshake.c revision 96f77e20
1/* Copyright (c) 2017 - 2018 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}; 64#endif 65 66 67typedef struct hs_ctx_st 68{ 69 enum { 70 HSET_TCID = (1 << 0), /* tcid is set */ 71 HSET_SMHL = (1 << 1), /* smhl is set */ 72 HSET_SCID = (1 << 2), 73 HSET_IRTT = (1 << 3), 74 } set; 75 enum { 76 HOPT_NSTP = (1 << 0), /* NSTP option present in COPT */ 77 HOPT_SREJ = (1 << 1), /* SREJ option present in COPT */ 78 } opts; 79 uint32_t pdmd; 80 uint32_t aead; 81 uint32_t kexs; 82 83 uint32_t mids; 84 uint32_t scls; 85 uint32_t cfcw; 86 uint32_t sfcw; 87 uint32_t icsl; 88 89 uint32_t irtt; 90 uint64_t rcid; 91 uint32_t tcid; 92 uint32_t smhl; 93 uint64_t sttl; 94 unsigned char scid[SCID_LENGTH]; 95 //unsigned char chlo_hash[32]; //SHA256 HASH of CHLO 96 unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */ 97 unsigned char pubs[32]; 98 99 uint32_t rrej; 100 struct lsquic_str ccs; 101 struct lsquic_str sni; /* 0 rtt */ 102 struct lsquic_str ccrt; 103 struct lsquic_str stk; 104 struct lsquic_str sno; 105 struct lsquic_str prof; 106 107 struct lsquic_str csct; 108 struct lsquic_str crt; /* compressed certs buffer */ 109} hs_ctx_t; 110 111 112struct lsquic_enc_session 113{ 114 enum handshake_state hsk_state; 115 116 uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */ 117 uint8_t peer_have_final_key; 118 uint8_t server_start_use_final_key; 119 120 lsquic_cid_t cid; 121 unsigned char priv_key[32]; 122 EVP_AEAD_CTX *enc_ctx_i; 123 EVP_AEAD_CTX *dec_ctx_i; 124 125 /* Have to save the initial key for diversification need */ 126 unsigned char enc_key_i[aes128_key_len]; 127 unsigned char dec_key_i[aes128_key_len]; 128 unsigned char enc_key_nonce_i[aes128_iv_len]; 129 unsigned char dec_key_nonce_i[aes128_iv_len]; 130 131 EVP_AEAD_CTX *enc_ctx_f; 132 EVP_AEAD_CTX *dec_ctx_f; 133 unsigned char enc_key_nonce_f[aes128_iv_len]; 134 unsigned char dec_key_nonce_f[aes128_iv_len]; 135 136 hs_ctx_t hs_ctx; 137 lsquic_session_cache_info_t *info; 138 SSL_CTX * ssl_ctx; 139 const struct lsquic_engine_public *enpub; 140 struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */ 141 struct lsquic_str chlo; /* real copy of CHLO message */ 142 struct lsquic_str sstk; 143 struct lsquic_str ssno; 144 145#if LSQUIC_KEEP_ENC_SESS_HISTORY 146 eshist_idx_t es_hist_idx; 147 unsigned char es_hist_buf[1 << ESHIST_BITS]; 148#endif 149}; 150 151 152/*** 153 * client side, it will store the domain/certs as cache cert 154 */ 155static struct lsquic_hash *s_cached_client_certs; 156 157/** 158 * client side will save the session_info for next time 0rtt 159 */ 160static struct lsquic_hash *s_cached_client_session_infos; 161 162/* save to hash table */ 163static lsquic_session_cache_info_t *retrieve_session_info_entry(const char *key); 164static void remove_expire_session_info_entry(); 165static void remove_session_info_entry(struct lsquic_str *key); 166 167static void free_info (lsquic_session_cache_info_t *); 168 169 170/* client */ 171static cert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count); 172static int c_insert_certs(cert_hash_item_t *item); 173static void c_free_cert_hash_item (cert_hash_item_t *item); 174 175static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val); 176static int init_hs_hash_tables(int flags); 177static uint32_t get_tag_value_i32(unsigned char *, int); 178static uint64_t get_tag_value_i64(unsigned char *, int); 179 180static int determine_keys(lsquic_enc_session_t *enc_session); 181 182 183#if LSQUIC_KEEP_ENC_SESS_HISTORY 184static void 185eshist_append (lsquic_enc_session_t *enc_session, 186 enum enc_sess_history_event eh_event) 187{ 188 enc_session->es_hist_buf[ 189 ESHIST_MASK & enc_session->es_hist_idx++ ] = eh_event; 190} 191 192 193# define ESHIST_APPEND(sess, event) eshist_append(sess, event) 194#else 195# define ESHIST_APPEND(sess, event) do { } while (0) 196#endif 197 198static int 199lsquic_handshake_init(int flags) 200{ 201 crypto_init(); 202 return init_hs_hash_tables(flags); 203} 204 205 206static void 207cleanup_hs_hash_tables (void) 208{ 209 struct lsquic_hash_elem *el; 210 211 if (s_cached_client_session_infos) 212 { 213 for (el = lsquic_hash_first(s_cached_client_session_infos); el; 214 el = lsquic_hash_next(s_cached_client_session_infos)) 215 { 216 lsquic_session_cache_info_t *entry = lsquic_hashelem_getdata(el); 217 free_info(entry); 218 } 219 lsquic_hash_destroy(s_cached_client_session_infos); 220 s_cached_client_session_infos = NULL; 221 } 222 223 if (s_cached_client_certs) 224 { 225 for (el = lsquic_hash_first(s_cached_client_certs); el; 226 el = lsquic_hash_next(s_cached_client_certs)) 227 { 228 cert_hash_item_t *item = lsquic_hashelem_getdata(el); 229 c_free_cert_hash_item(item); 230 } 231 lsquic_hash_destroy(s_cached_client_certs); 232 s_cached_client_certs = NULL; 233 } 234 235} 236 237 238static void 239lsquic_handshake_cleanup (void) 240{ 241 cleanup_hs_hash_tables(); 242 lsquic_crt_cleanup(); 243} 244 245 246/* return -1 for fail, 0 OK*/ 247static int init_hs_hash_tables(int flags) 248{ 249 if (flags & LSQUIC_GLOBAL_CLIENT) 250 { 251 s_cached_client_session_infos = lsquic_hash_create(); 252 if (!s_cached_client_session_infos) 253 return -1; 254 255 s_cached_client_certs = lsquic_hash_create(); 256 if (!s_cached_client_certs) 257 return -1; 258 } 259 260 return 0; 261} 262 263 264/* client */ 265cert_hash_item_t * 266c_find_certs (const lsquic_str_t *domain) 267{ 268 struct lsquic_hash_elem *el; 269 270 if (!s_cached_client_certs) 271 return NULL; 272 273 el = lsquic_hash_find(s_cached_client_certs, lsquic_str_cstr(domain), 274 lsquic_str_len(domain)); 275 if (el == NULL) 276 return NULL; 277 278 return lsquic_hashelem_getdata(el); 279} 280 281 282/* client */ 283/* certs is an array of lsquic_str_t * */ 284static cert_hash_item_t * 285make_cert_hash_item (lsquic_str_t *domain, lsquic_str_t **certs, int count) 286{ 287 int i; 288 uint64_t hash; 289 cert_hash_item_t *item = (cert_hash_item_t *)malloc(sizeof(cert_hash_item_t)); 290 item->crts = (lsquic_str_t *)malloc(count * sizeof(lsquic_str_t)); 291 item->domain = lsquic_str_new(NULL, 0); 292 item->hashs = lsquic_str_new(NULL, 0); 293 lsquic_str_copy(item->domain, domain); 294 item->count = count; 295 for(i=0; i<count; ++i) 296 { 297 lsquic_str_copy(&item->crts[i], certs[i]); 298 hash = fnv1a_64((const uint8_t *)lsquic_str_cstr(certs[i]), lsquic_str_len(certs[i])); 299 lsquic_str_append(item->hashs, (char *)&hash, 8); 300 } 301 return item; 302} 303 304 305/* client */ 306static void 307c_free_cert_hash_item (cert_hash_item_t *item) 308{ 309 int i; 310 if (item) 311 { 312 lsquic_str_delete(item->hashs); 313 lsquic_str_delete(item->domain); 314 for(i=0; i<item->count; ++i) 315 lsquic_str_d(&item->crts[i]); 316 free(item->crts); 317 free(item); 318 } 319} 320 321 322/* client */ 323static int 324c_insert_certs (cert_hash_item_t *item) 325{ 326 if (lsquic_hash_insert(s_cached_client_certs, 327 lsquic_str_cstr(item->domain), 328 lsquic_str_len(item->domain), item) == NULL) 329 return -1; 330 else 331 return 0; 332} 333 334 335static int save_session_info_entry(lsquic_str_t *key, lsquic_session_cache_info_t *entry) 336{ 337 lsquic_str_setto(&entry->sni_key, lsquic_str_cstr(key), lsquic_str_len(key)); 338 if (lsquic_hash_insert(s_cached_client_session_infos, 339 lsquic_str_cstr(&entry->sni_key), 340 lsquic_str_len(&entry->sni_key), entry) == NULL) 341 { 342 lsquic_str_d(&entry->sni_key); 343 return -1; 344 } 345 else 346 return 0; 347} 348 349 350/* If entry updated and need to remove cached entry */ 351static void 352remove_session_info_entry (lsquic_str_t *key) 353{ 354 lsquic_session_cache_info_t *entry; 355 struct lsquic_hash_elem *el; 356 el = lsquic_hash_find(s_cached_client_session_infos, 357 lsquic_str_cstr(key), lsquic_str_len(key)); 358 if (el) 359 { 360 entry = lsquic_hashelem_getdata(el); 361 lsquic_str_d(&entry->sni_key); 362 lsquic_hash_erase(s_cached_client_session_infos, el); 363 } 364} 365 366 367/* client */ 368static lsquic_session_cache_info_t * 369retrieve_session_info_entry (const char *key) 370{ 371 lsquic_session_cache_info_t *entry; 372 struct lsquic_hash_elem *el; 373 374 if (!s_cached_client_session_infos) 375 return NULL; 376 377 if (!key) 378 return NULL; 379 380 el = lsquic_hash_find(s_cached_client_session_infos, key, strlen(key)); 381 if (el == NULL) 382 return NULL; 383 384 entry = lsquic_hashelem_getdata(el); 385 LSQ_DEBUG("[QUIC]retrieve_session_info_entry find cached session info %p.\n", entry); 386 return entry; 387} 388 389 390/* call it in timer() */ 391#if __GNUC__ 392__attribute__((unused)) 393#endif 394static void 395remove_expire_session_info_entry (void) 396{ 397 time_t tm = time(NULL); 398 struct lsquic_hash_elem *el; 399 400 for (el = lsquic_hash_first(s_cached_client_session_infos); el; 401 el = lsquic_hash_next(s_cached_client_session_infos)) 402 { 403 lsquic_session_cache_info_t *entry = lsquic_hashelem_getdata(el); 404 if ((uint64_t)tm > entry->expy) 405 { 406 free_info(entry); 407 lsquic_hash_erase(s_cached_client_session_infos, el); 408 } 409 } 410} 411 412 413static lsquic_enc_session_t * 414lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid, 415 const struct lsquic_engine_public *enpub) 416{ 417 lsquic_session_cache_info_t *info; 418 lsquic_enc_session_t *enc_session; 419 420 if (!domain) 421 { 422 errno = EINVAL; 423 return NULL; 424 } 425 426 enc_session = calloc(1, sizeof(*enc_session)); 427 if (!enc_session) 428 return NULL; 429 430 info = retrieve_session_info_entry(domain); 431 if (info) 432 memcpy(enc_session->hs_ctx.pubs, info->spubs, 32); 433 else 434 { 435 info = calloc(1, sizeof(*info)); 436 if (!info) 437 { 438 free(enc_session); 439 return NULL; 440 } 441 } 442 443 enc_session->enpub = enpub; 444 enc_session->cid = cid; 445 enc_session->info = info; 446 /* FIXME: allocation may fail */ 447 lsquic_str_append(&enc_session->hs_ctx.sni, domain, strlen(domain)); 448 return enc_session; 449} 450 451 452static void 453lsquic_enc_session_destroy (lsquic_enc_session_t *enc_session) 454{ 455 if (!enc_session) 456 return ; 457 458 hs_ctx_t *hs_ctx = &enc_session->hs_ctx; 459 lsquic_str_d(&hs_ctx->sni); 460 lsquic_str_d(&hs_ctx->ccs); 461 lsquic_str_d(&hs_ctx->ccrt); 462 lsquic_str_d(&hs_ctx->stk); 463 lsquic_str_d(&hs_ctx->sno); 464 lsquic_str_d(&hs_ctx->prof); 465 lsquic_str_d(&hs_ctx->csct); 466 lsquic_str_d(&hs_ctx->crt); 467 lsquic_str_d(&enc_session->chlo); 468 lsquic_str_d(&enc_session->sstk); 469 lsquic_str_d(&enc_session->ssno); 470 if (enc_session->dec_ctx_i) 471 { 472 EVP_AEAD_CTX_cleanup(enc_session->dec_ctx_i); 473 free(enc_session->dec_ctx_i); 474 } 475 if (enc_session->enc_ctx_i) 476 { 477 EVP_AEAD_CTX_cleanup(enc_session->enc_ctx_i); 478 free(enc_session->enc_ctx_i); 479 } 480 if (enc_session->dec_ctx_f) 481 { 482 EVP_AEAD_CTX_cleanup(enc_session->dec_ctx_f); 483 free(enc_session->dec_ctx_f); 484 } 485 if (enc_session->enc_ctx_f) 486 { 487 EVP_AEAD_CTX_cleanup(enc_session->enc_ctx_f); 488 free(enc_session->enc_ctx_f); 489 } 490 free(enc_session); 491 492} 493 494 495static void 496free_info (lsquic_session_cache_info_t *info) 497{ 498 lsquic_str_d(&info->sstk); 499 lsquic_str_d(&info->scfg); 500 lsquic_str_d(&info->sni_key); 501 free(info); 502} 503 504 505static int get_hs_state(lsquic_enc_session_t *enc_session) 506{ 507 return enc_session->hsk_state; 508} 509 510 511/* make sure have more room for encrypt */ 512static int 513lsquic_enc_session_is_hsk_done (lsquic_enc_session_t *enc_session) 514{ 515 return (get_hs_state(enc_session) == HSK_COMPLETED); 516} 517 518 519static void 520process_copt (lsquic_enc_session_t *enc_session, const uint32_t *const opts, 521 unsigned n_opts) 522{ 523 unsigned i; 524 for (i = 0; i < n_opts; ++i) 525 switch (opts[i]) 526 { 527 case QTAG_NSTP: 528 enc_session->hs_ctx.opts |= HOPT_NSTP; 529 break; 530 case QTAG_SREJ: 531 enc_session->hs_ctx.opts |= HOPT_SREJ; 532 break; 533 } 534} 535 536 537static int parse_hs_data (lsquic_enc_session_t *enc_session, uint32_t tag, 538 unsigned char *val, int len, uint32_t head_tag) 539{ 540 hs_ctx_t * hs_ctx = &enc_session->hs_ctx; 541 542 switch(tag) 543 { 544 case QTAG_PDMD: 545 hs_ctx->pdmd = get_tag_value_i32(val, len); 546 break; 547 548 case QTAG_MIDS: 549 if (0 != get_tag_val_u32(val, len, &hs_ctx->mids)) 550 return -1; 551 break; 552 553 case QTAG_SCLS: 554 hs_ctx->scls = get_tag_value_i32(val, len); 555 break; 556 557 case QTAG_CFCW: 558 if (0 != get_tag_val_u32(val, len, &hs_ctx->cfcw)) 559 return -1; 560 break; 561 562 case QTAG_SFCW: 563 if (0 != get_tag_val_u32(val, len, &hs_ctx->sfcw)) 564 return -1; 565 break; 566 567 case QTAG_ICSL: 568 hs_ctx->icsl = get_tag_value_i32(val, len); 569 break; 570 571 case QTAG_IRTT: 572 if (0 != get_tag_val_u32(val, len, &hs_ctx->irtt)) 573 return -1; 574 hs_ctx->set |= HSET_IRTT; 575 break; 576 577 case QTAG_COPT: 578 if (0 == len % sizeof(uint32_t)) 579 process_copt(enc_session, (uint32_t *) val, len / sizeof(uint32_t)); 580 /* else ignore, following the reference implementation */ 581 break; 582 583 case QTAG_SNI: 584 lsquic_str_setto(&hs_ctx->sni, val, len); 585 ESHIST_APPEND(enc_session, ESHE_SET_SNI); 586 break; 587 588 case QTAG_CCS: 589 lsquic_str_setto(&hs_ctx->ccs, val, len); 590 break; 591 592 case QTAG_CCRT: 593 lsquic_str_setto(&hs_ctx->ccrt, val, len); 594 break; 595 596 case QTAG_CRT: 597 lsquic_str_setto(&hs_ctx->crt, val, len); 598 break; 599 600 case QTAG_PUBS: 601 /* FIXME:Server side may send a list of pubs, 602 * we support only ONE kenx now. 603 * REJ is 35 bytes, SHLO is 32 bytes 604 * Only save other peer's pubs to hs_ctx 605 */ 606 if( len < 32) 607 break; 608 memcpy(hs_ctx->pubs, val + (len - 32), 32); 609 if (head_tag == QTAG_SCFG) 610 { 611 memcpy(enc_session->info->spubs, hs_ctx->pubs, 32); 612 } 613 break; 614 615 case QTAG_RCID: 616 hs_ctx->rcid = get_tag_value_i64(val, len); 617 break; 618 619 620 case QTAG_SMHL: 621 if (0 != get_tag_val_u32(val, len, &hs_ctx->smhl)) 622 return -1; 623 hs_ctx->set |= HSET_SMHL; 624 break; 625 626 case QTAG_TCID: 627 if (0 != get_tag_val_u32(val, len, &hs_ctx->tcid)) 628 return -1; 629 hs_ctx->set |= HSET_TCID; 630 break; 631 632 case QTAG_EXPY: 633 enc_session->info->expy = get_tag_value_i64(val, len); 634 break; 635 636 case QTAG_ORBT: 637 enc_session->info->orbt = get_tag_value_i64(val, len); 638 break; 639 640 case QTAG_SNO: 641 lsquic_str_setto(&enc_session->ssno, val, len); 642 ESHIST_APPEND(enc_session, ESHE_SET_SNO); 643 break; 644 645 case QTAG_STK: 646 if (lsquic_str_len(&enc_session->info->sstk) > 0) 647 remove_session_info_entry(&enc_session->info->sstk); 648 lsquic_str_setto(&enc_session->info->sstk, val, len); 649 ESHIST_APPEND(enc_session, ESHE_SET_STK); 650 break; 651 652 case QTAG_SCID: 653 if (len != SCID_LENGTH) 654 return -1; 655 memcpy(enc_session->info->sscid, val, len); 656 ESHIST_APPEND(enc_session, ESHE_SET_SCID); 657 break; 658 659 case QTAG_AEAD: 660 enc_session->info->aead = get_tag_value_i32(val, len); 661 break; 662 663 case QTAG_KEXS: 664 enc_session->info->kexs = get_tag_value_i32(val, len); 665 break; 666 667 case QTAG_NONC: 668 if (len != sizeof(hs_ctx->nonc)) 669 return -1; 670 memcpy(hs_ctx->nonc, val, len); 671 break; 672 673 case QTAG_SCFG: 674 lsquic_str_setto(&enc_session->info->scfg, val, len); 675 enc_session->info->scfg_flag = 1; 676 break; 677 678 case QTAG_PROF: 679 lsquic_str_setto(&hs_ctx->prof, val, len); 680 ESHIST_APPEND(enc_session, ESHE_SET_PROF); 681 break; 682 683 case QTAG_STTL: 684 hs_ctx->sttl = get_tag_value_i64(val, len); 685 break; 686 687 default: 688 LSQ_DEBUG("Ignored tag '%.*s'", 4, (char *)&tag); 689 break; 690 } 691 692 return 0; 693} 694 695 696/* only for the hs stream-frame data, NOT with the packet header or frame header*/ 697static enum handshake_error parse_hs (lsquic_enc_session_t *enc_session, 698 const unsigned char *buf, int buf_len, 699 uint32_t *head_tag) 700{ 701 uint16_t i; 702 const unsigned char *p = buf; 703 const unsigned char *pend = buf + buf_len; 704 705 unsigned char *data; 706 uint32_t len = 0, offset = 0; 707 uint16_t num; 708 uint32_t tag; 709 if (buf_len < 6) 710 return DATA_FORMAT_ERROR; 711 712 memcpy(&tag, p, 4); 713 p += 4; 714 715 { 716 if (tag != QTAG_SREJ && tag != QTAG_REJ && tag != QTAG_SHLO && 717 tag != QTAG_SCFG) 718 return DATA_FORMAT_ERROR; 719 } 720 721 *head_tag = tag; 722 723 memcpy((char *)&num, p, 2); 724 p += 2 + 2; /* the 2 bytes padding 0x0000 need to be bypassed */ 725 726 if (num < 1) 727 return DATA_FORMAT_ERROR; 728 729 data = (uint8_t *)(buf + 4 * 2 * (1 + num)); 730 if ((const char *)data > (const char *)pend) 731 { 732 LSQ_DEBUG("parse_hs tag '%.*s' error: data not enough", 4, (char *)head_tag); 733 return DATA_NOT_ENOUGH; 734 } 735 736 /* check last offset */ 737 memcpy((char *)&len, data - 4, 4); 738 if ((const char *)data + len > (const char *)pend) 739 { 740 LSQ_DEBUG("parse_hs tag '%.*s' error: data not enough!!!", 4, (char *)head_tag); 741 return DATA_NOT_ENOUGH; 742 } 743 744 for (i=0; i<num; ++i) 745 { 746 memcpy((char *)&tag, p, 4); 747 p += 4; 748 memcpy((char *)&len, p, 4); 749 len -= offset; 750 p += 4; 751 752 if ((const char *)data + offset + len > (const char *)pend) 753 return DATA_FORMAT_ERROR; 754 755 if (0 != parse_hs_data(enc_session, tag, data + offset, len, 756 *head_tag)) 757 return DATA_FORMAT_ERROR; 758 offset += len; 759 } 760 761 LSQ_DEBUG("parse_hs tag '%.*s' no error.", 4, (char *)head_tag); 762 return DATA_NO_ERROR; 763} 764 765 766static uint32_t get_tag_value_i32(unsigned char *val, int len) 767{ 768 uint32_t v; 769 if (len < 4) 770 return 0; 771 memcpy(&v, val, 4); 772 return v; 773} 774 775 776static uint64_t get_tag_value_i64(unsigned char *val, int len) 777{ 778 uint64_t v; 779 if (len < 8) 780 return 0; 781 memcpy(&v, val, 8); 782 return v; 783} 784 785 786static int 787get_tag_val_u32 (unsigned char *v, int len, uint32_t *val) 788{ 789 if (len != 4) 790 return -1; 791 memcpy(val, v, 4); 792 return 0; 793} 794 795 796static void 797generate_cid_buf (void *buf, size_t bufsz) 798{ 799 RAND_bytes(buf, bufsz); 800} 801 802 803static lsquic_cid_t 804lsquic_generate_cid (void) 805{ 806 lsquic_cid_t cid; 807 generate_cid_buf(&cid, sizeof(cid)); 808 return cid; 809} 810 811 812/* From "QUIC Crypto" for easy reference: 813 * 814 * A handshake message consists of: 815 * - The tag of the message. 816 * - A uint16 containing the number of tag-value pairs. 817 * - Two bytes of padding which should be zero when sent but ignored when 818 * received. 819 * - A series of uint32 tags and uint32 end offsets, one for each 820 * tag-value pair. The tags must be strictly monotonically 821 * increasing, and the end-offsets must be monotonic non-decreasing. 822 * The end offset gives the offset, from the start of the value 823 * data, to a byte one beyond the end of the data for that tag. 824 * (Thus the end offset of the last tag contains the length of the 825 * value data). 826 * - The value data, concatenated without padding. 827 */ 828 829struct table_entry { uint32_t tag, off; }; 830 831struct message_writer 832{ 833 unsigned char *mw_p; 834 struct table_entry mw_first_dummy_entry; 835 struct table_entry *mw_entry, 836 *mw_prev_entry, 837 *mw_end; 838}; 839 840/* MW_ family of macros is used to write entries to handshake message 841 * (MW stands for "message writer"). 842 */ 843#define MW_BEGIN(mw, msg_tag, n_entries, data_ptr) do { \ 844 uint32_t t_ = msg_tag; \ 845 uint16_t n_ = n_entries; \ 846 memcpy(data_ptr, &t_, 4); \ 847 memcpy(data_ptr + 4, &n_, 2); \ 848 memset(data_ptr + 4 + 2, 0, 2); \ 849 (mw)->mw_entry = (void *) (data_ptr + 8); \ 850 (mw)->mw_p = data_ptr + 8 + \ 851 n_entries * sizeof((mw)->mw_entry[0]); \ 852 (mw)->mw_first_dummy_entry.tag = 0; \ 853 (mw)->mw_first_dummy_entry.off = 0; \ 854 (mw)->mw_prev_entry = &(mw)->mw_first_dummy_entry; \ 855 (mw)->mw_end = (void *) (mw)->mw_p; \ 856} while (0) 857 858#ifndef NDEBUG 859# define MW_END(mw) do { \ 860 assert((mw)->mw_entry == (mw)->mw_end); \ 861 } while (0) 862#else 863# define MW_END(mw) 864#endif 865 866#define MW_P(mw) ((mw)->mw_p) 867 868#define MW_ADVANCE_P(mw, n) do { \ 869 MW_P(mw) += (n); \ 870} while (0) 871 872#define MW_WRITE_TABLE_ENTRY(mw, tag_, sz) do { \ 873 assert((mw)->mw_prev_entry->tag < (tag_)); \ 874 assert((mw)->mw_entry < (mw)->mw_end); \ 875 (mw)->mw_entry->tag = (tag_); \ 876 (mw)->mw_entry->off = (mw)->mw_prev_entry->off + (sz); \ 877 (mw)->mw_prev_entry = (mw)->mw_entry; \ 878 ++(mw)->mw_entry; \ 879} while (0) 880 881#define MW_WRITE_BUFFER(mw, tag, buf, sz) do { \ 882 MW_WRITE_TABLE_ENTRY(mw, tag, sz); \ 883 memcpy(MW_P(mw), buf, sz); \ 884 MW_ADVANCE_P(mw, sz); \ 885} while (0) 886 887#define MW_WRITE_LS_STR(mw, tag, s) \ 888 MW_WRITE_BUFFER(mw, tag, lsquic_str_buf(s), lsquic_str_len(s)) 889 890#define MW_WRITE_UINT32(mw, tag, val) do { \ 891 uint32_t v_ = (val); \ 892 MW_WRITE_BUFFER(mw, tag, &v_, sizeof(v_)); \ 893} while (0) 894 895#define MW_WRITE_UINT64(mw, tag, val) do { \ 896 uint64_t v_ = (val); \ 897 MW_WRITE_BUFFER(mw, tag, &v_, sizeof(v_)); \ 898} while (0) 899 900 901/* MSG_LEN_ family of macros calculates buffer size required for a 902 * handshake message. 903 */ 904#define MSG_LEN_INIT(len) do { \ 905 len = 4 /* Tag */ + 2 /* # tags */ + 2 /* Two zero bytes */; \ 906} while (0) 907 908#define MSG_LEN_ADD(len, payload_sz) do { \ 909 len += 4 + 4 + (payload_sz); \ 910} while (0) 911 912#define MSG_LEN_VAL(len) (+(len)) 913 914 915static int 916lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session, 917 enum lsquic_version version, uint8_t *buf, size_t *len) 918{ 919 int ret, include_pad; 920 const lsquic_str_t *const ccs = get_common_certs_hash(); 921 const struct lsquic_engine_settings *const settings = 922 &enc_session->enpub->enp_settings; 923 cert_hash_item_t *const cached_certs_item = 924 c_find_certs(&enc_session->hs_ctx.sni); 925 unsigned char pub_key[32]; 926 size_t ua_len; 927 uint32_t opts[1]; /* Only NSTP is supported for now */ 928 unsigned n_opts, msg_len, n_tags, pad_size; 929 struct message_writer mw; 930 931 /* Before we do anything else, sanity check: */ 932 if (*len < MIN_CHLO_SIZE) 933 return -1; 934 935 n_opts = 0; 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 (cached_certs_item) 975 { 976 enc_session->cert_ptr = &cached_certs_item->crts[0]; 977 MSG_LEN_ADD(msg_len, lsquic_str_len(cached_certs_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 (cached_certs_item) 1052 MW_WRITE_BUFFER(&mw, QTAG_XLCT, lsquic_str_buf(cached_certs_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 (cached_certs_item) 1058 MW_WRITE_LS_STR(&mw, QTAG_CCRT, cached_certs_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 X509 *cert; 1097 ret = decompress_certs(in, in_end,cached_certs, cached_certs_count, 1098 out_certs, out_certs_count); 1099 if (ret) 1100 return ret; 1101 1102 cert = bio_to_crt((const char *)lsquic_str_cstr(out_certs[0]), 1103 lsquic_str_len(out_certs[0]), 0); 1104 pub_key = X509_get_pubkey(cert); 1105 ret = verify_prof((const uint8_t *)lsquic_str_cstr(&enc_session->chlo), 1106 (size_t)lsquic_str_len(&enc_session->chlo), 1107 &enc_session->info->scfg, 1108 pub_key, 1109 (const uint8_t *)lsquic_str_cstr(&enc_session->hs_ctx.prof), 1110 lsquic_str_len(&enc_session->hs_ctx.prof)); 1111 EVP_PKEY_free(pub_key); 1112 X509_free(cert); 1113 return ret; 1114} 1115 1116 1117void setup_aead_ctx(EVP_AEAD_CTX **ctx, unsigned char key[], int key_len, 1118 unsigned char *key_copy) 1119{ 1120 const EVP_AEAD *aead_ = EVP_aead_aes_128_gcm(); 1121 const int auth_tag_size = 12; 1122 if (*ctx) 1123 { 1124 EVP_AEAD_CTX_cleanup(*ctx); 1125 } 1126 else 1127 *ctx = (EVP_AEAD_CTX *)malloc(sizeof(EVP_AEAD_CTX)); 1128 1129 EVP_AEAD_CTX_init(*ctx, aead_, key, key_len, auth_tag_size, NULL); 1130 if (key_copy) 1131 memcpy(key_copy, key, key_len); 1132} 1133 1134 1135static int 1136determine_diversification_key (lsquic_enc_session_t *enc_session, 1137 uint8_t *diversification_nonce 1138 ) 1139{ 1140 EVP_AEAD_CTX **ctx_s_key; 1141 unsigned char *key_i, *iv; 1142 uint8_t ikm[aes128_key_len + aes128_iv_len]; 1143 1144 ctx_s_key = &enc_session->dec_ctx_i; 1145 key_i = enc_session->dec_key_i; 1146 iv = enc_session->dec_key_nonce_i; 1147 memcpy(ikm, key_i, aes128_key_len); 1148 memcpy(ikm + aes128_key_len, iv, aes128_iv_len); 1149 export_key_material(ikm, aes128_key_len + aes128_iv_len, 1150 diversification_nonce, DNONC_LENGTH, 1151 (const unsigned char *) "QUIC key diversification", 24, 1152 0, NULL, aes128_key_len, key_i, 0, NULL, 1153 aes128_iv_len, iv, NULL); 1154 1155 setup_aead_ctx(ctx_s_key, key_i, aes128_key_len, NULL); 1156 LSQ_DEBUG("determine_diversification_keys diversification_key: %s\n", 1157 get_bin_str(key_i, aes128_key_len, 512)); 1158 LSQ_DEBUG("determine_diversification_keys diversification_key nonce: %s\n", 1159 get_bin_str(iv, aes128_iv_len, 512)); 1160 return 0; 1161} 1162 1163 1164/* After CHLO msg generatered, call it to determine_keys */ 1165static int determine_keys(lsquic_enc_session_t *enc_session) 1166{ 1167 lsquic_str_t *chlo = &enc_session->chlo; 1168 uint8_t shared_key_c[32]; 1169 struct lsquic_buf *nonce_c = lsquic_buf_create(100); 1170 struct lsquic_buf *hkdf_input = lsquic_buf_create(0); 1171 1172 unsigned char c_key[aes128_key_len]; 1173 unsigned char s_key[aes128_key_len]; 1174 unsigned char *c_key_bin = NULL; 1175 unsigned char *s_key_bin = NULL; 1176 1177 unsigned char *c_iv; 1178 unsigned char *s_iv; 1179 unsigned char sub_key[32]; 1180 EVP_AEAD_CTX **ctx_c_key, **ctx_s_key; 1181 char key_flag; 1182 1183 lsquic_buf_clear(nonce_c); 1184 lsquic_buf_clear(hkdf_input); 1185 if (enc_session->have_key == 0) 1186 { 1187 lsquic_buf_append(hkdf_input, "QUIC key expansion\0", 18 + 1); // Add a 0x00 */ 1188 key_flag = 'I'; 1189 } 1190 else 1191 { 1192 lsquic_buf_append(hkdf_input, "QUIC forward secure key expansion\0", 33 + 1); // Add a 0x00 */ 1193 key_flag = 'F'; 1194 } 1195 1196 c255_gen_share_key(enc_session->priv_key, 1197 enc_session->hs_ctx.pubs, 1198 (unsigned char *)shared_key_c); 1199 { 1200 if (enc_session->have_key == 0) 1201 { 1202 ctx_c_key = &enc_session->enc_ctx_i; 1203 ctx_s_key = &enc_session->dec_ctx_i; 1204 c_iv = (unsigned char *) enc_session->enc_key_nonce_i; 1205 s_iv = (unsigned char *) enc_session->dec_key_nonce_i; 1206 c_key_bin = enc_session->enc_key_i; 1207 s_key_bin = enc_session->dec_key_i; 1208 } 1209 else 1210 { 1211 ctx_c_key = &enc_session->enc_ctx_f; 1212 ctx_s_key = &enc_session->dec_ctx_f; 1213 c_iv = (unsigned char *) enc_session->enc_key_nonce_f; 1214 s_iv = (unsigned char *) enc_session->dec_key_nonce_f; 1215 } 1216 } 1217 1218 LSQ_DEBUG("export_key_material c255_gen_share_key %s", 1219 get_bin_str(shared_key_c, 32, 512)); 1220 1221 lsquic_buf_append(hkdf_input, (char *)&enc_session->cid, sizeof(enc_session->cid)); 1222 lsquic_buf_append(hkdf_input, lsquic_str_cstr(chlo), lsquic_str_len(chlo)); /* CHLO msg */ 1223 { 1224 lsquic_buf_append(hkdf_input, lsquic_str_cstr(&enc_session->info->scfg), 1225 lsquic_str_len(&enc_session->info->scfg)); /* scfg msg */ 1226 } 1227 lsquic_buf_append(hkdf_input, lsquic_str_cstr(enc_session->cert_ptr), 1228 lsquic_str_len(enc_session->cert_ptr)); 1229 LSQ_DEBUG("export_key_material hkdf_input %s", 1230 get_bin_str(lsquic_buf_begin(hkdf_input), 1231 (size_t)lsquic_buf_size(hkdf_input), 512)); 1232 1233 /* then need to use the salts and the shared_key_* to get the real aead key */ 1234 lsquic_buf_append(nonce_c, (const char *) enc_session->hs_ctx.nonc, 32); 1235 lsquic_buf_append(nonce_c, lsquic_str_cstr(&enc_session->ssno), 1236 lsquic_str_len(&enc_session->ssno)); 1237 LSQ_DEBUG("export_key_material nonce %s", 1238 get_bin_str(lsquic_buf_begin(nonce_c), 1239 (size_t)lsquic_buf_size(nonce_c), 512)); 1240 1241 export_key_material(shared_key_c, 32, 1242 (unsigned char *)lsquic_buf_begin(nonce_c), lsquic_buf_size(nonce_c), 1243 (unsigned char *)lsquic_buf_begin(hkdf_input), 1244 lsquic_buf_size(hkdf_input), 1245 aes128_key_len, c_key, 1246 aes128_key_len, s_key, 1247 aes128_iv_len, c_iv, 1248 aes128_iv_len, s_iv, 1249 sub_key); 1250 1251 setup_aead_ctx(ctx_c_key, c_key, aes128_key_len, c_key_bin); 1252 setup_aead_ctx(ctx_s_key, s_key, aes128_key_len, s_key_bin); 1253 1254 1255 lsquic_buf_destroy(nonce_c); 1256 lsquic_buf_destroy(hkdf_input); 1257 1258 LSQ_DEBUG("***export_key_material '%c' c_key: %s", key_flag, 1259 get_bin_str(c_key, aes128_key_len, 512)); 1260 LSQ_DEBUG("***export_key_material '%c' s_key: %s", key_flag, 1261 get_bin_str(s_key, aes128_key_len, 512)); 1262 LSQ_DEBUG("***export_key_material '%c' c_iv: %s", key_flag, 1263 get_bin_str(c_iv, aes128_iv_len, 512)); 1264 LSQ_DEBUG("***export_key_material '%c' s_iv: %s", key_flag, 1265 get_bin_str(s_iv, aes128_iv_len, 512)); 1266 LSQ_DEBUG("***export_key_material '%c' subkey: %s", key_flag, 1267 get_bin_str(sub_key, 32, 512)); 1268 1269 return 0; 1270} 1271 1272 1273/* 0 Match */ 1274static int cached_certs_match(cert_hash_item_t *cached_certs_item, lsquic_str_t **certs, 1275 int certs_count) 1276{ 1277 int i; 1278 if (!cached_certs_item || cached_certs_item->count != certs_count) 1279 return -1; 1280 1281 for (i=0; i<certs_count; ++i) 1282 { 1283 if (lsquic_str_bcmp(certs[i], &cached_certs_item->crts[i]) != 0) 1284 return -1; 1285 } 1286 1287 return 0; 1288} 1289 1290 1291static const char * 1292he2str (enum handshake_error he) 1293{ 1294 switch (he) 1295 { 1296 case DATA_NOT_ENOUGH: return "DATA_NOT_ENOUGH"; 1297 case HS_ERROR: return "HS_ERROR"; 1298 case HS_SHLO: return "HS_SHLO"; 1299 case HS_1RTT: return "HS_1RTT"; 1300 case HS_2RTT: return "HS_2RTT"; 1301 default: 1302 assert(0); return "<unknown enum value>"; 1303 } 1304} 1305 1306 1307/* NOT packet, just the frames-data */ 1308/* return rtt number: 1309 * 0 OK 1310 * DATA_NOT_ENOUGH(-2) for not enough data, 1311 * DATA_FORMAT_ERROR(-1) all other errors 1312 */ 1313static int 1314lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session, 1315 const uint8_t *data, int len) 1316{ 1317 uint32_t head_tag; 1318 int ret; 1319 lsquic_session_cache_info_t *info = enc_session->info; 1320 hs_ctx_t * hs_ctx = &enc_session->hs_ctx; 1321 cert_hash_item_t *cached_certs_item = c_find_certs(&hs_ctx->sni); 1322 1323 /* FIXME get the number first */ 1324 lsquic_str_t **out_certs = NULL; 1325 size_t out_certs_count = 0, i; 1326 1327 ret = parse_hs(enc_session, data, len, &head_tag); 1328 if (ret) 1329 goto end; 1330 1331 if (head_tag != QTAG_SREJ && 1332 head_tag != QTAG_REJ && 1333 head_tag != QTAG_SHLO) 1334 { 1335 ret = 1; 1336 goto end; 1337 } 1338 1339 if (head_tag == QTAG_SREJ || head_tag == QTAG_REJ) 1340 enc_session->hsk_state = HSK_CHLO_REJ; 1341 else if(head_tag == QTAG_SHLO) 1342 { 1343 enc_session->hsk_state = HSK_COMPLETED; 1344 } 1345 1346 if (info->scfg_flag == 1) 1347 { 1348 ret = parse_hs(enc_session, (uint8_t *)lsquic_str_cstr(&info->scfg), 1349 lsquic_str_len(&info->scfg), &head_tag); 1350 1351 /* After handled, set the length to 0 to avoid do it again*/ 1352 enc_session->info->scfg_flag = 2; 1353 if (ret) 1354 goto end; 1355 1356 if (lsquic_str_len(&enc_session->hs_ctx.crt) > 0) 1357 { 1358 out_certs_count = get_certs_count(&enc_session->hs_ctx.crt); 1359 if (out_certs_count > 0) 1360 { 1361 out_certs = (lsquic_str_t **)malloc(out_certs_count * sizeof(lsquic_str_t *)); 1362 if (!out_certs) 1363 { 1364 ret = -1; 1365 goto end; 1366 } 1367 1368 for (i=0; i<out_certs_count; ++i) 1369 out_certs[i] = lsquic_str_new(NULL, 0); 1370 1371 ret = handle_chlo_reply_verify_prof(enc_session, out_certs, 1372 &out_certs_count, 1373 (cached_certs_item ? cached_certs_item->crts : NULL), 1374 (cached_certs_item ? cached_certs_item->count : 0)); 1375 if (ret == 0) 1376 { 1377 if (out_certs_count > 0) 1378 { 1379 if (cached_certs_item && 1380 cached_certs_match(cached_certs_item, out_certs, out_certs_count) == 0) 1381 ; 1382 else 1383 { 1384 if (cached_certs_item) 1385 c_free_cert_hash_item(cached_certs_item); 1386 1387 cached_certs_item = make_cert_hash_item(&hs_ctx->sni, 1388 out_certs, out_certs_count); 1389 c_insert_certs(cached_certs_item); 1390 } 1391 enc_session->cert_ptr = &cached_certs_item->crts[0]; 1392 } 1393 } 1394 1395 for (i=0; i<out_certs_count; ++i) 1396 lsquic_str_delete(out_certs[i]); 1397 free(out_certs); 1398 1399 if (ret) 1400 goto end; 1401 } 1402 } 1403 } 1404 1405 if (enc_session->hsk_state == HSK_COMPLETED) 1406 { 1407 if (!lsquic_str_buf(&info->sni_key)) 1408 save_session_info_entry(&enc_session->hs_ctx.sni, info); 1409 ret = determine_keys(enc_session 1410 ); /* FIXME: check ret */ 1411 enc_session->have_key = 3; 1412 } 1413 1414 end: 1415 LSQ_DEBUG("lsquic_enc_session_handle_chlo_reply called, buf in %d, return %d.", len, ret); 1416 EV_LOG_CONN_EVENT(enc_session->cid, "%s returning %s", __func__, 1417 he2str(ret)); 1418 return ret; 1419} 1420 1421 1422static uint64_t combine_path_id_pack_num(uint8_t path_id, uint64_t pack_num) 1423{ 1424 uint64_t v = ((uint64_t)path_id << 56) | pack_num; 1425 return v; 1426} 1427 1428 1429# define IS_SERVER(session) 0 1430 1431static int 1432verify_packet_hash (const lsquic_enc_session_t *enc_session, 1433 enum lsquic_version version, const unsigned char *buf, size_t *header_len, 1434 size_t data_len, unsigned char *buf_out, size_t max_out_len, 1435 size_t *out_len) 1436{ 1437 uint8_t md[HS_PKT_HASH_LENGTH]; 1438 uint128 hash; 1439 int ret; 1440 1441 if (data_len < HS_PKT_HASH_LENGTH) 1442 return -1; 1443 1444 if (version >= LSQVER_039) 1445 { 1446 hash = fnv1a_128_3(buf, *header_len, 1447 buf + *header_len + HS_PKT_HASH_LENGTH, 1448 data_len - HS_PKT_HASH_LENGTH, 1449 (unsigned char *) "Server", 6); 1450 } 1451 else 1452 { 1453 hash = fnv1a_128_2(buf, *header_len, 1454 buf + *header_len + HS_PKT_HASH_LENGTH, 1455 data_len - HS_PKT_HASH_LENGTH); 1456 } 1457 1458 serialize_fnv128_short(hash, md); 1459 ret = memcmp(md, buf + *header_len, HS_PKT_HASH_LENGTH); 1460 if(ret == 0) 1461 { 1462 *header_len += HS_PKT_HASH_LENGTH; 1463 *out_len = data_len - HS_PKT_HASH_LENGTH; 1464 if (max_out_len < *header_len + *out_len) 1465 return -1; 1466 1467 memcpy(buf_out, buf, *header_len + *out_len); 1468 return 0; 1469 } 1470 else 1471 return -1; 1472} 1473 1474 1475static enum enc_level 1476decrypt_packet (lsquic_enc_session_t *enc_session, uint8_t path_id, 1477 uint64_t pack_num, unsigned char *buf, size_t *header_len, 1478 size_t data_len, unsigned char *buf_out, size_t max_out_len, 1479 size_t *out_len) 1480{ 1481 int ret; 1482 /* Comment: 12 = sizeof(dec_key_iv] 4 + sizeof(pack_num) 8 */ 1483 uint8_t nonce[12]; 1484 uint64_t path_id_packet_number; 1485 EVP_AEAD_CTX *key = NULL; 1486 int try_times = 0; 1487 enum enc_level enc_level; 1488 1489 path_id_packet_number = combine_path_id_pack_num(path_id, pack_num); 1490 memcpy(buf_out, buf, *header_len); 1491 do 1492 { 1493 if (enc_session->have_key == 3 && try_times == 0) 1494 { 1495 key = enc_session->dec_ctx_f; 1496 memcpy(nonce, enc_session->dec_key_nonce_f, 4); 1497 LSQ_DEBUG("decrypt_packet using 'F' key..."); 1498 enc_level = ENC_LEV_FORW; 1499 } 1500 else 1501 { 1502 key = enc_session->dec_ctx_i; 1503 memcpy(nonce, enc_session->dec_key_nonce_i, 4); 1504 LSQ_DEBUG("decrypt_packet using 'I' key..."); 1505 enc_level = ENC_LEV_INIT; 1506 } 1507 memcpy(nonce + 4, &path_id_packet_number, 1508 sizeof(path_id_packet_number)); 1509 1510 *out_len = data_len; 1511 ret = aes_aead_dec(key, 1512 buf, *header_len, 1513 nonce, 12, 1514 buf + *header_len, data_len, 1515 buf_out + *header_len, out_len); 1516 1517 if (ret != 0) 1518 ++try_times; 1519 else 1520 { 1521 if (enc_session->peer_have_final_key == 0 && 1522 enc_session->have_key == 3 && 1523 try_times == 0) 1524 { 1525 LSQ_DEBUG("!!!decrypt_packet find peer have final key."); 1526 enc_session->peer_have_final_key = 1; 1527 EV_LOG_CONN_EVENT(enc_session->cid, "settled on private key " 1528 "'%c' after %d tries (packet number %"PRIu64")", 1529 key == enc_session->dec_ctx_f ? 'F' : 'I', 1530 try_times, pack_num); 1531 } 1532 break; 1533 } 1534 } 1535 while (try_times < 2); 1536 1537 LSQ_DEBUG("***decrypt_packet %s.", (ret == 0 ? "succeed" : "failed")); 1538 return ret == 0 ? enc_level : (enum enc_level) -1; 1539} 1540 1541 1542static int 1543lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session) 1544{ 1545 return enc_session && enc_session->have_key > 1; 1546} 1547 1548 1549/* The size of `buf' is *header_len plus data_len. The two parts of the 1550 * buffer correspond to the header and the payload of incoming QUIC packet. 1551 */ 1552static enum enc_level 1553lsquic_enc_session_decrypt (lsquic_enc_session_t *enc_session, 1554 enum lsquic_version version, 1555 uint8_t path_id, uint64_t pack_num, 1556 unsigned char *buf, size_t *header_len, size_t data_len, 1557 unsigned char *diversification_nonce, 1558 unsigned char *buf_out, size_t max_out_len, size_t *out_len) 1559{ 1560 /* Client: got SHLO which should have diversification_nonce */ 1561 if (diversification_nonce && enc_session && enc_session->have_key == 1) 1562 { 1563 determine_diversification_key(enc_session, diversification_nonce); 1564 enc_session->have_key = 2; 1565 } 1566 1567 if (lsquic_enc_session_have_key_gt_one(enc_session)) 1568 return decrypt_packet(enc_session, path_id, pack_num, buf, 1569 header_len, data_len, buf_out, max_out_len, out_len); 1570 else if (0 == verify_packet_hash(enc_session, version, buf, header_len, 1571 data_len, buf_out, max_out_len, out_len)) 1572 return ENC_LEV_CLEAR; 1573 else 1574 return -1; 1575} 1576 1577 1578static int 1579lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session, 1580 enum lsquic_version version, 1581 uint8_t path_id, uint64_t pack_num, 1582 const unsigned char *header, size_t header_len, 1583 const unsigned char *data, size_t data_len, 1584 unsigned char *buf_out, size_t max_out_len, size_t *out_len, 1585 int is_hello) 1586{ 1587 uint8_t md[HS_PKT_HASH_LENGTH]; 1588 uint128 hash; 1589 int ret; 1590 int is_chlo = (is_hello && ((IS_SERVER(enc_session)) == 0)); 1591 int is_shlo = (is_hello && (IS_SERVER(enc_session))); 1592 1593 /* Comment: 12 = sizeof(dec_key_iv] 4 + sizeof(pack_num) 8 */ 1594 uint8_t nonce[12]; 1595 uint64_t path_id_packet_number; 1596 EVP_AEAD_CTX *key; 1597 1598 if (enc_session) 1599 LSQ_DEBUG("%s: hsk_state: %d", __func__, enc_session->hsk_state); 1600 else 1601 LSQ_DEBUG("%s: enc_session is not set", __func__); 1602 1603 if (!enc_session || enc_session->have_key == 0 || is_chlo) 1604 { 1605 *out_len = header_len + data_len + HS_PKT_HASH_LENGTH; 1606 if (max_out_len < *out_len) 1607 return -1; 1608 1609 if (version >= LSQVER_039) 1610 { 1611 hash = fnv1a_128_3(header, header_len, data, data_len, 1612 (unsigned char *) "Client", 6); 1613 } 1614 else 1615 { 1616 hash = fnv1a_128_2(header, header_len, data, data_len); 1617 } 1618 1619 serialize_fnv128_short(hash, md); 1620 memcpy(buf_out, header, header_len); 1621 memcpy(buf_out + header_len, md, HS_PKT_HASH_LENGTH); 1622 memcpy(buf_out + header_len + HS_PKT_HASH_LENGTH, data, data_len); 1623 return 0; 1624 } 1625 else 1626 { 1627 if (enc_session->have_key != 3 || is_shlo || 1628 ((IS_SERVER(enc_session)) && 1629 enc_session->server_start_use_final_key == 0)) 1630 { 1631 LSQ_DEBUG("lsquic_enc_session_encrypt using 'I' key..."); 1632 key = enc_session->enc_ctx_i; 1633 memcpy(nonce, enc_session->enc_key_nonce_i, 4); 1634 if (is_shlo && enc_session->have_key == 3) 1635 { 1636 enc_session->server_start_use_final_key = 1; 1637 } 1638 } 1639 else 1640 { 1641 LSQ_DEBUG("lsquic_enc_session_encrypt using 'F' key..."); 1642 key = enc_session->enc_ctx_f; 1643 memcpy(nonce, enc_session->enc_key_nonce_f, 4); 1644 } 1645 path_id_packet_number = combine_path_id_pack_num(path_id, pack_num); 1646 memcpy(nonce + 4, &path_id_packet_number, 1647 sizeof(path_id_packet_number)); 1648 1649 memcpy(buf_out, header, header_len); 1650 *out_len = max_out_len - header_len; 1651 1652 ret = aes_aead_enc(key, header, header_len, nonce, 12, data, 1653 data_len, buf_out + header_len, out_len); 1654 *out_len += header_len; 1655 return ret; 1656 } 1657} 1658 1659 1660static int 1661lsquic_enc_session_get_peer_option (const lsquic_enc_session_t *enc_session, 1662 uint32_t tag) 1663{ 1664 switch (tag) 1665 { 1666 case QTAG_NSTP: 1667 return !!(enc_session->hs_ctx.opts & HOPT_NSTP); 1668 case QTAG_SREJ: 1669 return !!(enc_session->hs_ctx.opts & HOPT_SREJ); 1670 default: 1671 assert(0); 1672 return 0; 1673 } 1674} 1675 1676 1677/* Query a several parameters sent by the peer that are required by 1678 * connection. 1679 */ 1680static int 1681lsquic_enc_session_get_peer_setting (const lsquic_enc_session_t *enc_session, 1682 uint32_t tag, uint32_t *val) 1683{ 1684 switch (tag) 1685 { 1686 case QTAG_TCID: 1687 if (enc_session->hs_ctx.set & HSET_TCID) 1688 { 1689 *val = enc_session->hs_ctx.tcid; 1690 return 0; 1691 } 1692 else 1693 return -1; 1694 case QTAG_SMHL: 1695 if (enc_session->hs_ctx.set & HSET_SMHL) 1696 { 1697 *val = enc_session->hs_ctx.smhl; 1698 return 0; 1699 } 1700 else 1701 return -1; 1702 case QTAG_IRTT: 1703 if (enc_session->hs_ctx.set & HSET_IRTT) 1704 { 1705 *val = enc_session->hs_ctx.irtt; 1706 return 0; 1707 } 1708 else 1709 return -1; 1710 } 1711 1712 /* XXX For the following values, there is no record which were present 1713 * in CHLO or SHLO and which were not. Assume that zero means that 1714 * they weren't present. 1715 */ 1716 switch (tag) 1717 { 1718 case QTAG_CFCW: 1719 if (enc_session->hs_ctx.cfcw) 1720 { 1721 *val = enc_session->hs_ctx.cfcw; 1722 return 0; 1723 } 1724 else 1725 return -1; 1726 case QTAG_SFCW: 1727 if (enc_session->hs_ctx.sfcw) 1728 { 1729 *val = enc_session->hs_ctx.sfcw; 1730 return 0; 1731 } 1732 else 1733 return -1; 1734 case QTAG_MIDS: 1735 if (enc_session->hs_ctx.mids) 1736 { 1737 *val = enc_session->hs_ctx.mids; 1738 return 0; 1739 } 1740 else 1741 return -1; 1742 default: 1743 return -1; 1744 } 1745} 1746 1747 1748#if LSQUIC_KEEP_ENC_SESS_HISTORY 1749static void 1750lsquic_get_enc_hist (const lsquic_enc_session_t *enc_session, 1751 char buf[(1 << ESHIST_BITS) + 1]) 1752{ 1753 const unsigned hist_idx = ESHIST_MASK & enc_session->es_hist_idx; 1754 if (enc_session->es_hist_buf[hist_idx] == ESHE_EMPTY) 1755 memcpy(buf, enc_session->es_hist_buf, hist_idx + 1); 1756 else 1757 { 1758 memcpy(buf, enc_session->es_hist_buf + hist_idx, sizeof(enc_session->es_hist_buf) - hist_idx); 1759 memcpy(buf + hist_idx, enc_session->es_hist_buf, hist_idx); 1760 buf[(1 << ESHIST_BITS)] = '\0'; 1761 } 1762} 1763 1764 1765#endif 1766 1767 1768 1769 1770static size_t 1771lsquic_enc_session_mem_used (struct lsquic_enc_session *enc_session) 1772{ 1773 size_t size; 1774 1775 size = sizeof(*enc_session); 1776 1777 size += lsquic_str_len(&enc_session->chlo); 1778 size += lsquic_str_len(&enc_session->sstk); 1779 size += lsquic_str_len(&enc_session->ssno); 1780 1781 size += lsquic_str_len(&enc_session->hs_ctx.ccs); 1782 size += lsquic_str_len(&enc_session->hs_ctx.sni); 1783 size += lsquic_str_len(&enc_session->hs_ctx.ccrt); 1784 size += lsquic_str_len(&enc_session->hs_ctx.stk); 1785 size += lsquic_str_len(&enc_session->hs_ctx.sno); 1786 size += lsquic_str_len(&enc_session->hs_ctx.prof); 1787 size += lsquic_str_len(&enc_session->hs_ctx.csct); 1788 size += lsquic_str_len(&enc_session->hs_ctx.crt); 1789 1790 if (enc_session->info) 1791 { 1792 size += sizeof(*enc_session->info); 1793 size += lsquic_str_len(&enc_session->info->sstk); 1794 size += lsquic_str_len(&enc_session->info->scfg); 1795 size += lsquic_str_len(&enc_session->info->sni_key); 1796 } 1797 1798 /* TODO: calculate memory taken up by SSL stuff */ 1799 1800 return size; 1801} 1802 1803 1804#ifdef NDEBUG 1805const 1806#endif 1807struct enc_session_funcs lsquic_enc_session_gquic_1 = 1808{ 1809 .esf_global_init = lsquic_handshake_init, 1810 .esf_global_cleanup = lsquic_handshake_cleanup, 1811#if LSQUIC_KEEP_ENC_SESS_HISTORY 1812 .esf_get_hist = lsquic_get_enc_hist, 1813#endif 1814 .esf_destroy = lsquic_enc_session_destroy, 1815 .esf_is_hsk_done = lsquic_enc_session_is_hsk_done, 1816 .esf_encrypt = lsquic_enc_session_encrypt, 1817 .esf_decrypt = lsquic_enc_session_decrypt, 1818 .esf_get_peer_setting = lsquic_enc_session_get_peer_setting, 1819 .esf_get_peer_option = lsquic_enc_session_get_peer_option, 1820 .esf_create_client = lsquic_enc_session_create_client, 1821 .esf_generate_cid = lsquic_generate_cid, 1822 .esf_gen_chlo = lsquic_enc_session_gen_chlo, 1823 .esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply, 1824 .esf_mem_used = lsquic_enc_session_mem_used, 1825}; 1826