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