lsquic_tokgen.c revision 7d09751d
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 25392f7a3SLiteSpeed Tech#include <assert.h> 35392f7a3SLiteSpeed Tech#include <netinet/in.h> 45392f7a3SLiteSpeed Tech#include <stddef.h> 55392f7a3SLiteSpeed Tech#include <stdlib.h> 65392f7a3SLiteSpeed Tech#include <string.h> 75392f7a3SLiteSpeed Tech#include <sys/queue.h> 85392f7a3SLiteSpeed Tech#include <sys/socket.h> 95392f7a3SLiteSpeed Tech#include <time.h> 105392f7a3SLiteSpeed Tech 115392f7a3SLiteSpeed Tech#include <openssl/aead.h> 125392f7a3SLiteSpeed Tech#include <openssl/hkdf.h> 135392f7a3SLiteSpeed Tech#include <openssl/rand.h> 145392f7a3SLiteSpeed Tech#include <openssl/ssl.h> 155392f7a3SLiteSpeed Tech 165392f7a3SLiteSpeed Tech#include "lsquic.h" 175392f7a3SLiteSpeed Tech#include "lsquic_int_types.h" 185392f7a3SLiteSpeed Tech#include "lsquic_sizes.h" 195392f7a3SLiteSpeed Tech#include "lsquic_types.h" 205392f7a3SLiteSpeed Tech#include "lsquic_packet_common.h" 215392f7a3SLiteSpeed Tech#include "lsquic_packet_in.h" 225392f7a3SLiteSpeed Tech#include "lsquic_tokgen.h" 235392f7a3SLiteSpeed Tech#include "lsquic_trans_params.h" 245392f7a3SLiteSpeed Tech#include "lsquic_util.h" 255392f7a3SLiteSpeed Tech#include "lsquic_mm.h" 265392f7a3SLiteSpeed Tech#include "lsquic_engine_public.h" 275392f7a3SLiteSpeed Tech 285392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_TOKGEN 295392f7a3SLiteSpeed Tech#include "lsquic_logger.h" 305392f7a3SLiteSpeed Tech 315392f7a3SLiteSpeed Tech#define STRINGIFY(x) #x 325392f7a3SLiteSpeed Tech#define TOSTRING(x) STRINGIFY(x) 335392f7a3SLiteSpeed Tech 345392f7a3SLiteSpeed Tech#define TOKGEN_VERSION 1 355392f7a3SLiteSpeed Tech 365392f7a3SLiteSpeed Tech#define CRYPTER_KEY_SIZE 16 375392f7a3SLiteSpeed Tech#define SRST_MAX_PRK_SIZE EVP_MAX_MD_SIZE 385392f7a3SLiteSpeed Tech 395392f7a3SLiteSpeed Tech#define TOKGEN_SHM_KEY "TOKGEN" TOSTRING(TOKGEN_VERSION) 405392f7a3SLiteSpeed Tech#define TOKGEN_SHM_KEY_SIZE (sizeof(TOKGEN_SHM_KEY) - 1) 415392f7a3SLiteSpeed Tech 425392f7a3SLiteSpeed Tech#define TOKGEN_SHM_MAGIC_TOP "Feliz" 435392f7a3SLiteSpeed Tech#define TOKGEN_SHM_MAGIC_BOTTOM "Navidad" 445392f7a3SLiteSpeed Tech 455392f7a3SLiteSpeed Techstruct tokgen_shm_state 465392f7a3SLiteSpeed Tech{ 475392f7a3SLiteSpeed Tech uint8_t tgss_version; 485392f7a3SLiteSpeed Tech uint8_t tgss_magic_top[sizeof(TOKGEN_SHM_MAGIC_TOP) - 1]; 495392f7a3SLiteSpeed Tech uint8_t tgss_crypter_key[N_TOKEN_TYPES][CRYPTER_KEY_SIZE]; 505392f7a3SLiteSpeed Tech uint8_t tgss_srst_prk_size; 515392f7a3SLiteSpeed Tech uint8_t tgss_srst_prk[SRST_MAX_PRK_SIZE]; 525392f7a3SLiteSpeed Tech uint8_t tgss_magic_bottom[sizeof(TOKGEN_SHM_MAGIC_BOTTOM) - 1]; 535392f7a3SLiteSpeed Tech}; 545392f7a3SLiteSpeed Tech 555392f7a3SLiteSpeed Tech 565392f7a3SLiteSpeed Tech 575392f7a3SLiteSpeed Techstatic const uint8_t srst_salt[8] = "\x28\x6e\x81\x02\x40\x5b\x2c\x2b"; 585392f7a3SLiteSpeed Tech 595392f7a3SLiteSpeed Techstruct crypter 605392f7a3SLiteSpeed Tech{ 615392f7a3SLiteSpeed Tech EVP_AEAD_CTX ctx; 625392f7a3SLiteSpeed Tech unsigned long nonce_counter; 635392f7a3SLiteSpeed Tech size_t nonce_prk_sz; 645392f7a3SLiteSpeed Tech uint8_t nonce_prk_buf[EVP_MAX_MD_SIZE]; 655392f7a3SLiteSpeed Tech}; 665392f7a3SLiteSpeed Tech 675392f7a3SLiteSpeed Tech 685392f7a3SLiteSpeed Techstruct token_generator 695392f7a3SLiteSpeed Tech{ 705392f7a3SLiteSpeed Tech /* We encrypt different token types using different keys. */ 715392f7a3SLiteSpeed Tech struct crypter tg_crypters[N_TOKEN_TYPES]; 725392f7a3SLiteSpeed Tech 735392f7a3SLiteSpeed Tech /* Stateless reset token is generated using HKDF with CID as the 745392f7a3SLiteSpeed Tech * `info' parameter to HKDF-Expand. 755392f7a3SLiteSpeed Tech */ 765392f7a3SLiteSpeed Tech size_t tg_srst_prk_sz; 775392f7a3SLiteSpeed Tech uint8_t tg_srst_prk_buf[SRST_MAX_PRK_SIZE]; 785392f7a3SLiteSpeed Tech}; 795392f7a3SLiteSpeed Tech 805392f7a3SLiteSpeed Tech 815392f7a3SLiteSpeed Tech 825392f7a3SLiteSpeed Tech 835392f7a3SLiteSpeed Techstatic int 845392f7a3SLiteSpeed Techget_or_generate_state (struct lsquic_engine_public *enpub, time_t now, 855392f7a3SLiteSpeed Tech struct tokgen_shm_state *shm_state) 865392f7a3SLiteSpeed Tech{ 875392f7a3SLiteSpeed Tech const struct lsquic_shared_hash_if *const shi = enpub->enp_shi; 885392f7a3SLiteSpeed Tech void *const ctx = enpub->enp_shi_ctx; 895392f7a3SLiteSpeed Tech void *data, *copy, *key_copy; 905392f7a3SLiteSpeed Tech int s; 915392f7a3SLiteSpeed Tech unsigned sz; 925392f7a3SLiteSpeed Tech size_t bufsz; 935392f7a3SLiteSpeed Tech struct { 945392f7a3SLiteSpeed Tech time_t now; 955392f7a3SLiteSpeed Tech unsigned char buf[20]; 965392f7a3SLiteSpeed Tech } srst_ikm; 975392f7a3SLiteSpeed Tech 985392f7a3SLiteSpeed Tech data = shm_state; 995392f7a3SLiteSpeed Tech sz = sizeof(shm_state); 1005392f7a3SLiteSpeed Tech s = shi->shi_lookup(ctx, TOKGEN_SHM_KEY, TOKGEN_SHM_KEY_SIZE, &data, &sz); 1015392f7a3SLiteSpeed Tech 1025392f7a3SLiteSpeed Tech if (s == 1) 1035392f7a3SLiteSpeed Tech { 1045392f7a3SLiteSpeed Tech if (sz != sizeof(*shm_state)) 1055392f7a3SLiteSpeed Tech { 1065392f7a3SLiteSpeed Tech LSQ_WARN("found SHM data has non-matching size %u", sz); 1075392f7a3SLiteSpeed Tech return -1; 1085392f7a3SLiteSpeed Tech } 1095392f7a3SLiteSpeed Tech if (data != (void *) shm_state) 1105392f7a3SLiteSpeed Tech memcpy(shm_state, data, sizeof(*shm_state)); 1115392f7a3SLiteSpeed Tech if (shm_state->tgss_version != TOKGEN_VERSION) 1125392f7a3SLiteSpeed Tech { 1135392f7a3SLiteSpeed Tech LSQ_DEBUG("found SHM data has non-matching version %u", 1145392f7a3SLiteSpeed Tech shm_state->tgss_version); 1155392f7a3SLiteSpeed Tech return -1; 1165392f7a3SLiteSpeed Tech } 1175392f7a3SLiteSpeed Tech LSQ_DEBUG("found SHM data: size %u; version %u", sz, 1185392f7a3SLiteSpeed Tech shm_state->tgss_version); 1195392f7a3SLiteSpeed Tech return 0; 1205392f7a3SLiteSpeed Tech } 1215392f7a3SLiteSpeed Tech 1225392f7a3SLiteSpeed Tech if (s != 0) 1235392f7a3SLiteSpeed Tech { 1245392f7a3SLiteSpeed Tech if (s != -1) 1255392f7a3SLiteSpeed Tech LSQ_WARN("SHM lookup returned unexpected value %d", s); 1265392f7a3SLiteSpeed Tech LSQ_DEBUG("SHM lookup returned an error: generate"); 1275392f7a3SLiteSpeed Tech goto generate; 1285392f7a3SLiteSpeed Tech } 1295392f7a3SLiteSpeed Tech 1305392f7a3SLiteSpeed Tech assert(s == 0); 1315392f7a3SLiteSpeed Tech LSQ_DEBUG("%s does not exist: generate", TOKGEN_SHM_KEY); 1325392f7a3SLiteSpeed Tech generate: 1335392f7a3SLiteSpeed Tech now = time(NULL); 1345392f7a3SLiteSpeed Tech memset(shm_state, 0, sizeof(*shm_state)); 1355392f7a3SLiteSpeed Tech shm_state->tgss_version = TOKGEN_VERSION; 1365392f7a3SLiteSpeed Tech memcpy(shm_state->tgss_magic_top, TOKGEN_SHM_MAGIC_TOP, 1375392f7a3SLiteSpeed Tech sizeof(TOKGEN_SHM_MAGIC_TOP) - 1); 1385392f7a3SLiteSpeed Tech if (getenv("LSQUIC_NULL_TOKGEN")) 1395392f7a3SLiteSpeed Tech { 1405392f7a3SLiteSpeed Tech memset(&srst_ikm, 0, sizeof(srst_ikm)); 1415392f7a3SLiteSpeed Tech LSQ_NOTICE("using NULL tokgen"); 1425392f7a3SLiteSpeed Tech } 1435392f7a3SLiteSpeed Tech else 1445392f7a3SLiteSpeed Tech { 1455392f7a3SLiteSpeed Tech srst_ikm.now = now; 1465392f7a3SLiteSpeed Tech RAND_bytes(srst_ikm.buf, sizeof(srst_ikm.buf)); 1475392f7a3SLiteSpeed Tech } 1485392f7a3SLiteSpeed Tech if (!HKDF_extract(shm_state->tgss_srst_prk, &bufsz, 1495392f7a3SLiteSpeed Tech EVP_sha256(), (uint8_t *) &srst_ikm, sizeof(srst_ikm), 1505392f7a3SLiteSpeed Tech srst_salt, sizeof(srst_salt))) 1515392f7a3SLiteSpeed Tech { 1525392f7a3SLiteSpeed Tech LSQ_ERROR("HKDF_extract failed"); 1535392f7a3SLiteSpeed Tech return -1; 1545392f7a3SLiteSpeed Tech } 1555392f7a3SLiteSpeed Tech shm_state->tgss_srst_prk_size = (uint8_t) bufsz; 1565392f7a3SLiteSpeed Tech memcpy(shm_state->tgss_magic_bottom, TOKGEN_SHM_MAGIC_BOTTOM, 1575392f7a3SLiteSpeed Tech sizeof(TOKGEN_SHM_MAGIC_BOTTOM) - 1); 1585392f7a3SLiteSpeed Tech 1595392f7a3SLiteSpeed Tech data = malloc(sizeof(*shm_state)); 1605392f7a3SLiteSpeed Tech if (!data) 1615392f7a3SLiteSpeed Tech { 1625392f7a3SLiteSpeed Tech LSQ_ERROR("%s: malloc", __func__); 1635392f7a3SLiteSpeed Tech return -1; 1645392f7a3SLiteSpeed Tech } 1655392f7a3SLiteSpeed Tech memcpy(data, shm_state, sizeof(*shm_state)); 1665392f7a3SLiteSpeed Tech key_copy = malloc(TOKGEN_SHM_KEY_SIZE); 1675392f7a3SLiteSpeed Tech if (!key_copy) 1685392f7a3SLiteSpeed Tech { 1695392f7a3SLiteSpeed Tech LSQ_ERROR("%s: malloc", __func__); 1705392f7a3SLiteSpeed Tech free(data); 1715392f7a3SLiteSpeed Tech return -1; 1725392f7a3SLiteSpeed Tech } 1735392f7a3SLiteSpeed Tech memcpy(key_copy, TOKGEN_SHM_KEY, TOKGEN_SHM_KEY_SIZE); 1745392f7a3SLiteSpeed Tech s = shi->shi_insert(ctx, key_copy, TOKGEN_SHM_KEY_SIZE, data, 1755392f7a3SLiteSpeed Tech sizeof(*shm_state), 0); 1765392f7a3SLiteSpeed Tech if (s != 0) 1775392f7a3SLiteSpeed Tech { 1785392f7a3SLiteSpeed Tech LSQ_ERROR("cannot insert into SHM"); 1795392f7a3SLiteSpeed Tech free(data); 1805392f7a3SLiteSpeed Tech free(key_copy); 1815392f7a3SLiteSpeed Tech return -1; 1825392f7a3SLiteSpeed Tech } 1835392f7a3SLiteSpeed Tech sz = sizeof(*shm_state); 1845392f7a3SLiteSpeed Tech s = shi->shi_lookup(ctx, TOKGEN_SHM_KEY, TOKGEN_SHM_KEY_SIZE, ©, &sz); 1855392f7a3SLiteSpeed Tech if (s != 1 || sz != sizeof(*shm_state)) 1865392f7a3SLiteSpeed Tech { 1875392f7a3SLiteSpeed Tech LSQ_ERROR("cannot lookup after insert: s=%d; sz=%u", s, sz); 1885392f7a3SLiteSpeed Tech return -1; 1895392f7a3SLiteSpeed Tech } 1905392f7a3SLiteSpeed Tech if (copy != data) 1915392f7a3SLiteSpeed Tech memcpy(shm_state, copy, sizeof(*shm_state)); 1925392f7a3SLiteSpeed Tech LSQ_INFO("inserted %s of size %u", TOKGEN_SHM_KEY, sz); 1935392f7a3SLiteSpeed Tech return 0; 1945392f7a3SLiteSpeed Tech} 1955392f7a3SLiteSpeed Tech 1965392f7a3SLiteSpeed Tech 1975392f7a3SLiteSpeed Techstruct token_generator * 1985392f7a3SLiteSpeed Techlsquic_tg_new (struct lsquic_engine_public *enpub) 1995392f7a3SLiteSpeed Tech{ 2005392f7a3SLiteSpeed Tech struct token_generator *tokgen; 2015392f7a3SLiteSpeed Tech time_t now; 2025392f7a3SLiteSpeed Tech struct tokgen_shm_state shm_state; 2035392f7a3SLiteSpeed Tech 2045392f7a3SLiteSpeed Tech tokgen = calloc(1, sizeof(*tokgen)); 2055392f7a3SLiteSpeed Tech if (!tokgen) 2065392f7a3SLiteSpeed Tech goto err; 2075392f7a3SLiteSpeed Tech 2085392f7a3SLiteSpeed Tech now = time(NULL); 2095392f7a3SLiteSpeed Tech if (0 != get_or_generate_state(enpub, now, &shm_state)) 2105392f7a3SLiteSpeed Tech goto err; 2115392f7a3SLiteSpeed Tech 2125392f7a3SLiteSpeed Tech 2135392f7a3SLiteSpeed Tech tokgen->tg_srst_prk_sz = shm_state.tgss_srst_prk_size; 2145392f7a3SLiteSpeed Tech if (tokgen->tg_srst_prk_sz > sizeof(tokgen->tg_srst_prk_buf)) 2155392f7a3SLiteSpeed Tech { 2165392f7a3SLiteSpeed Tech LSQ_WARN("bad stateless reset key size"); 2175392f7a3SLiteSpeed Tech goto err; 2185392f7a3SLiteSpeed Tech } 2195392f7a3SLiteSpeed Tech memcpy(tokgen->tg_srst_prk_buf, shm_state.tgss_srst_prk, 2205392f7a3SLiteSpeed Tech tokgen->tg_srst_prk_sz); 2215392f7a3SLiteSpeed Tech 2225392f7a3SLiteSpeed Tech LSQ_DEBUG("initialized"); 2235392f7a3SLiteSpeed Tech return tokgen; 2245392f7a3SLiteSpeed Tech 2255392f7a3SLiteSpeed Tech err: 2265392f7a3SLiteSpeed Tech LSQ_ERROR("error initializing"); 2275392f7a3SLiteSpeed Tech free(tokgen); 2285392f7a3SLiteSpeed Tech return NULL; 2295392f7a3SLiteSpeed Tech} 2305392f7a3SLiteSpeed Tech 2315392f7a3SLiteSpeed Tech 2325392f7a3SLiteSpeed Techvoid 2335392f7a3SLiteSpeed Techlsquic_tg_destroy (struct token_generator *tokgen) 2345392f7a3SLiteSpeed Tech{ 2355392f7a3SLiteSpeed Tech free(tokgen); 2365392f7a3SLiteSpeed Tech LSQ_DEBUG("destroyed"); 2375392f7a3SLiteSpeed Tech} 2385392f7a3SLiteSpeed Tech 2395392f7a3SLiteSpeed Tech 2405392f7a3SLiteSpeed Techvoid 2415392f7a3SLiteSpeed Techlsquic_tg_generate_sreset (struct token_generator *tokgen, 2425392f7a3SLiteSpeed Tech const struct lsquic_cid *cid, unsigned char *reset_token) 2435392f7a3SLiteSpeed Tech{ 2445392f7a3SLiteSpeed Tech char str[IQUIC_SRESET_TOKEN_SZ * 2 + 1]; 2455392f7a3SLiteSpeed Tech 2465392f7a3SLiteSpeed Tech (void) HKDF_expand(reset_token, IQUIC_SRESET_TOKEN_SZ, EVP_sha256(), 2475392f7a3SLiteSpeed Tech tokgen->tg_srst_prk_buf, tokgen->tg_srst_prk_sz, cid->idbuf, cid->len); 2485392f7a3SLiteSpeed Tech LSQ_DEBUGC("generated stateless reset token %s for CID %"CID_FMT, 2495392f7a3SLiteSpeed Tech HEXSTR(reset_token, IQUIC_SRESET_TOKEN_SZ, str), CID_BITS(cid)); 2505392f7a3SLiteSpeed Tech} 251