mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-27 07:33:41 +08:00
Add QUIC
This commit is contained in:
@@ -148,6 +148,7 @@ option(ENABLE_SDF "Enable SDF module" ON)
|
||||
option(ENABLE_ASM_UNDERSCORE_PREFIX "Add prefix `_` to assembly symbols" ON)
|
||||
|
||||
option(ENABLE_TLS "Enable TLS and TLCP protocol support" ON)
|
||||
option(ENABLE_QUIC "Enable QUIC support" ON)
|
||||
option(ENABLE_TLS_DEBUG "Enable TLS and TLCP print debug message" OFF)
|
||||
|
||||
option (ENABLE_SM2_ENC_PRE_COMPUTE "Enable SM2 encryption precomputing" ON)
|
||||
@@ -616,7 +617,6 @@ if (ENABLE_TLS)
|
||||
src/tls_sct.c
|
||||
src/tls_ocsp.c
|
||||
src/tls_cookie.c
|
||||
src/quic.c
|
||||
src/tls_trace.c
|
||||
src/tls_vrf.c
|
||||
src/tlcp.c
|
||||
@@ -630,7 +630,18 @@ if (ENABLE_TLS)
|
||||
tools/tls13_client.c
|
||||
tools/tls13_server.c
|
||||
tools/sctverify.c)
|
||||
list(APPEND tests tls tls13 tls_ocsp quic)
|
||||
list(APPEND tests tls tls13 tls_ocsp)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QUIC)
|
||||
if (ENABLE_TLS AND ENABLE_SHA2)
|
||||
message(STATUS "ENABLE_QUIC is ON")
|
||||
add_definitions(-DENABLE_QUIC)
|
||||
list(APPEND src src/quic.c)
|
||||
list(APPEND tests quic)
|
||||
else()
|
||||
message(STATUS "ENABLE_QUIC requires ENABLE_TLS and ENABLE_SHA2; disabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -920,7 +931,7 @@ endif()
|
||||
#
|
||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1160")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1161")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
include(CPack)
|
||||
|
||||
112
include/gmssl/quic.h
Normal file
112
include/gmssl/quic.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#ifndef GMSSL_QUIC_H
|
||||
#define GMSSL_QUIC_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define QUIC_VERSION_V1 0x00000001
|
||||
|
||||
#define QUIC_INITIAL_SECRET_SIZE 32
|
||||
#define QUIC_INITIAL_KEY_SIZE 16
|
||||
#define QUIC_INITIAL_IV_SIZE 12
|
||||
#define QUIC_INITIAL_HP_KEY_SIZE 16
|
||||
|
||||
#define QUIC_TRANSPORT_PARAM_MAX_COUNT 32
|
||||
#define QUIC_TRANSPORT_PARAM_MAX_SIZE 512
|
||||
|
||||
|
||||
typedef enum {
|
||||
QUIC_transport_param_original_destination_connection_id = 0x00,
|
||||
QUIC_transport_param_max_idle_timeout = 0x01,
|
||||
QUIC_transport_param_stateless_reset_token = 0x02,
|
||||
QUIC_transport_param_max_udp_payload_size = 0x03,
|
||||
QUIC_transport_param_initial_max_data = 0x04,
|
||||
QUIC_transport_param_initial_max_stream_data_bidi_local = 0x05,
|
||||
QUIC_transport_param_initial_max_stream_data_bidi_remote = 0x06,
|
||||
QUIC_transport_param_initial_max_stream_data_uni = 0x07,
|
||||
QUIC_transport_param_initial_max_streams_bidi = 0x08,
|
||||
QUIC_transport_param_initial_max_streams_uni = 0x09,
|
||||
QUIC_transport_param_ack_delay_exponent = 0x0a,
|
||||
QUIC_transport_param_max_ack_delay = 0x0b,
|
||||
QUIC_transport_param_disable_active_migration = 0x0c,
|
||||
QUIC_transport_param_preferred_address = 0x0d,
|
||||
QUIC_transport_param_active_connection_id_limit = 0x0e,
|
||||
QUIC_transport_param_initial_source_connection_id = 0x0f,
|
||||
QUIC_transport_param_retry_source_connection_id = 0x10,
|
||||
} QUIC_TRANSPORT_PARAM_ID;
|
||||
|
||||
typedef enum {
|
||||
QUIC_encryption_initial = 0,
|
||||
QUIC_encryption_early_data = 1,
|
||||
QUIC_encryption_handshake = 2,
|
||||
QUIC_encryption_application = 3,
|
||||
} QUIC_ENCRYPTION_LEVEL;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t client_secret[QUIC_INITIAL_SECRET_SIZE];
|
||||
uint8_t server_secret[QUIC_INITIAL_SECRET_SIZE];
|
||||
} QUIC_INITIAL_SECRETS;
|
||||
|
||||
typedef struct {
|
||||
uint8_t key[QUIC_INITIAL_KEY_SIZE];
|
||||
uint8_t iv[QUIC_INITIAL_IV_SIZE];
|
||||
uint8_t hp[QUIC_INITIAL_HP_KEY_SIZE]; // hp = header protection key
|
||||
} QUIC_INITIAL_KEYS;
|
||||
|
||||
typedef struct {
|
||||
uint64_t id;
|
||||
uint8_t data[QUIC_TRANSPORT_PARAM_MAX_SIZE];
|
||||
size_t datalen;
|
||||
} QUIC_TRANSPORT_PARAM;
|
||||
|
||||
typedef struct {
|
||||
QUIC_TRANSPORT_PARAM params[QUIC_TRANSPORT_PARAM_MAX_COUNT];
|
||||
size_t params_count;
|
||||
} QUIC_TRANSPORT_PARAMS;
|
||||
|
||||
|
||||
size_t quic_varint_size(uint64_t val);
|
||||
int quic_varint_to_bytes(uint64_t val, uint8_t **out, size_t *outlen);
|
||||
int quic_varint_from_bytes(uint64_t *val, const uint8_t **in, size_t *inlen);
|
||||
|
||||
void quic_transport_params_init(QUIC_TRANSPORT_PARAMS *params);
|
||||
int quic_transport_params_add(QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, const uint8_t *data, size_t datalen);
|
||||
int quic_transport_params_add_varint(QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, uint64_t val);
|
||||
int quic_transport_params_get(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, const uint8_t **data, size_t *datalen);
|
||||
int quic_transport_params_get_varint(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, uint64_t *val);
|
||||
int quic_transport_params_to_bytes(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int quic_transport_params_from_bytes(QUIC_TRANSPORT_PARAMS *params,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
|
||||
int quic_derive_initial_secrets(const uint8_t *dcid, size_t dcid_len, QUIC_INITIAL_SECRETS *secrets);
|
||||
int quic_derive_initial_client_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
||||
int quic_derive_initial_server_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
||||
int quic_derive_initial_keys(const uint8_t secret[QUIC_INITIAL_SECRET_SIZE], QUIC_INITIAL_KEYS *keys);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
|
||||
|
||||
#define GMSSL_VERSION_NUM 30300
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1160"
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1161"
|
||||
|
||||
int gmssl_version_num(void);
|
||||
const char *gmssl_version_str(void);
|
||||
|
||||
371
src/quic.c
Normal file
371
src/quic.c
Normal file
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <gmssl/quic.h>
|
||||
#include <gmssl/tls.h>
|
||||
#include <gmssl/hkdf.h>
|
||||
#include <gmssl/digest.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static const uint8_t quic_v1_initial_salt[20] = {
|
||||
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3,
|
||||
0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad,
|
||||
0xcc, 0xbb, 0x7f, 0x0a,
|
||||
};
|
||||
|
||||
|
||||
size_t quic_varint_size(uint64_t val)
|
||||
{
|
||||
if (val <= 63) {
|
||||
return 1;
|
||||
} else if (val <= 16383) {
|
||||
return 2;
|
||||
} else if (val <= 1073741823) {
|
||||
return 4;
|
||||
} else if (val <= 4611686018427387903ULL) {
|
||||
return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int quic_varint_to_bytes(uint64_t val, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = quic_varint_size(val);
|
||||
if (!len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (out && *out) {
|
||||
switch (len) {
|
||||
case 1:
|
||||
*(*out)++ = (uint8_t)val;
|
||||
break;
|
||||
case 2:
|
||||
*(*out)++ = (uint8_t)(0x40 | (val >> 8));
|
||||
*(*out)++ = (uint8_t)val;
|
||||
break;
|
||||
case 4:
|
||||
*(*out)++ = (uint8_t)(0x80 | (val >> 24));
|
||||
*(*out)++ = (uint8_t)(val >> 16);
|
||||
*(*out)++ = (uint8_t)(val >> 8);
|
||||
*(*out)++ = (uint8_t)val;
|
||||
break;
|
||||
case 8:
|
||||
*(*out)++ = (uint8_t)(0xc0 | (val >> 56));
|
||||
*(*out)++ = (uint8_t)(val >> 48);
|
||||
*(*out)++ = (uint8_t)(val >> 40);
|
||||
*(*out)++ = (uint8_t)(val >> 32);
|
||||
*(*out)++ = (uint8_t)(val >> 24);
|
||||
*(*out)++ = (uint8_t)(val >> 16);
|
||||
*(*out)++ = (uint8_t)(val >> 8);
|
||||
*(*out)++ = (uint8_t)val;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_varint_from_bytes(uint64_t *val, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
uint8_t first;
|
||||
size_t len;
|
||||
uint64_t ret;
|
||||
size_t i;
|
||||
|
||||
if (!val || !in || !*in || !inlen || !*inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
first = **in;
|
||||
len = (size_t)1 << (first >> 6);
|
||||
if (*inlen < len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = first & 0x3f;
|
||||
for (i = 1; i < len; i++) {
|
||||
ret <<= 8;
|
||||
ret |= (*in)[i];
|
||||
}
|
||||
|
||||
*val = ret;
|
||||
*in += len;
|
||||
*inlen -= len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void quic_transport_params_init(QUIC_TRANSPORT_PARAMS *params)
|
||||
{
|
||||
if (params) {
|
||||
memset(params, 0, sizeof(*params));
|
||||
}
|
||||
}
|
||||
|
||||
int quic_transport_params_add(QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
QUIC_TRANSPORT_PARAM *param;
|
||||
size_t i;
|
||||
|
||||
if (!params || (!data && datalen)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!quic_varint_size(id) || datalen > QUIC_TRANSPORT_PARAM_MAX_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (params->params_count >= QUIC_TRANSPORT_PARAM_MAX_COUNT) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < params->params_count; i++) {
|
||||
if (params->params[i].id == id) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
param = ¶ms->params[params->params_count++];
|
||||
param->id = id;
|
||||
param->datalen = datalen;
|
||||
if (datalen) {
|
||||
memcpy(param->data, data, datalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_transport_params_add_varint(QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, uint64_t val)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (quic_varint_to_bytes(val, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_transport_params_add(params, id, buf, len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_transport_params_get(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, const uint8_t **data, size_t *datalen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!params || !data || !datalen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < params->params_count; i++) {
|
||||
if (params->params[i].id == id) {
|
||||
*data = params->params[i].datalen ? params->params[i].data : NULL;
|
||||
*datalen = params->params[i].datalen;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int quic_transport_params_get_varint(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint64_t id, uint64_t *val)
|
||||
{
|
||||
const uint8_t *data;
|
||||
size_t datalen;
|
||||
int ret;
|
||||
|
||||
if (!val) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = quic_transport_params_get(params, id, &data, &datalen)) != 1) {
|
||||
return ret;
|
||||
}
|
||||
if (quic_varint_from_bytes(val, &data, &datalen) != 1 || datalen != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_transport_params_to_bytes(const QUIC_TRANSPORT_PARAMS *params,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!params || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < params->params_count; i++) {
|
||||
if (quic_varint_to_bytes(params->params[i].id, out, outlen) != 1
|
||||
|| quic_varint_to_bytes(params->params[i].datalen, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (out && *out) {
|
||||
memcpy(*out, params->params[i].data, params->params[i].datalen);
|
||||
*out += params->params[i].datalen;
|
||||
}
|
||||
*outlen += params->params[i].datalen;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_transport_params_from_bytes(QUIC_TRANSPORT_PARAMS *params,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
uint64_t id;
|
||||
uint64_t len;
|
||||
|
||||
if (!params || !in || !inlen || (!*in && *inlen)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
quic_transport_params_init(params);
|
||||
|
||||
while (*inlen) {
|
||||
if (quic_varint_from_bytes(&id, in, inlen) != 1
|
||||
|| quic_varint_from_bytes(&len, in, inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len > *inlen || len > QUIC_TRANSPORT_PARAM_MAX_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_transport_params_add(params, id, *in, (size_t)len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*in += len;
|
||||
*inlen -= len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_derive_initial_secrets(const uint8_t *dcid, size_t dcid_len, QUIC_INITIAL_SECRETS *secrets)
|
||||
{
|
||||
#if defined(ENABLE_SHA2)
|
||||
/* QUIC v1 Initial secrets always use SHA-256, independent of the TLS cipher suite. */
|
||||
const DIGEST *digest = DIGEST_sha256();
|
||||
uint8_t initial_secret[QUIC_INITIAL_SECRET_SIZE];
|
||||
size_t initial_secret_len;
|
||||
int ret = -1;
|
||||
|
||||
if ((!dcid && dcid_len) || !secrets) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hkdf_extract(digest, quic_v1_initial_salt, sizeof(quic_v1_initial_salt),
|
||||
dcid, dcid_len, initial_secret, &initial_secret_len) != 1
|
||||
|| initial_secret_len != QUIC_INITIAL_SECRET_SIZE
|
||||
|| tls13_hkdf_expand_label(digest, initial_secret, "client in", NULL, 0,
|
||||
QUIC_INITIAL_SECRET_SIZE, secrets->client_secret) != 1
|
||||
|| tls13_hkdf_expand_label(digest, initial_secret, "server in", NULL, 0,
|
||||
QUIC_INITIAL_SECRET_SIZE, secrets->server_secret) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(initial_secret, sizeof(initial_secret));
|
||||
return ret;
|
||||
#else
|
||||
error_print();
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int quic_derive_initial_client_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys)
|
||||
{
|
||||
if (!secrets) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_derive_initial_keys(secrets->client_secret, keys) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_derive_initial_server_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys)
|
||||
{
|
||||
if (!secrets) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_derive_initial_keys(secrets->server_secret, keys) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int quic_derive_initial_keys(const uint8_t secret[QUIC_INITIAL_SECRET_SIZE], QUIC_INITIAL_KEYS *keys)
|
||||
{
|
||||
#if defined(ENABLE_SHA2)
|
||||
const DIGEST *digest = DIGEST_sha256();
|
||||
|
||||
if (!secret || !keys) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls13_hkdf_expand_label(digest, secret, "quic key", NULL, 0,
|
||||
QUIC_INITIAL_KEY_SIZE, keys->key) != 1
|
||||
|| tls13_hkdf_expand_label(digest, secret, "quic iv", NULL, 0,
|
||||
QUIC_INITIAL_IV_SIZE, keys->iv) != 1
|
||||
|| tls13_hkdf_expand_label(digest, secret, "quic hp", NULL, 0,
|
||||
QUIC_INITIAL_HP_KEY_SIZE, keys->hp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
error_print();
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
195
tests/quictest.c
Normal file
195
tests/quictest.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/quic.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static int quic_test_varint(void)
|
||||
{
|
||||
static const struct {
|
||||
uint64_t val;
|
||||
size_t len;
|
||||
} tests[] = {
|
||||
{ 0, 1 },
|
||||
{ 63, 1 },
|
||||
{ 64, 2 },
|
||||
{ 16383, 2 },
|
||||
{ 16384, 4 },
|
||||
{ 1073741823, 4 },
|
||||
{ 1073741824, 8 },
|
||||
{ 4611686018427387903ULL, 8 },
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
uint8_t buf[8];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
size_t inlen;
|
||||
uint64_t val;
|
||||
|
||||
if (quic_varint_size(tests[i].val) != tests[i].len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_varint_to_bytes(tests[i].val, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len != tests[i].len || p != buf + tests[i].len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
inlen = len;
|
||||
if (quic_varint_from_bytes(&val, &cp, &inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (val != tests[i].val || inlen != 0 || cp != buf + len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quic_test_transport_params(void)
|
||||
{
|
||||
const uint8_t odcid[] = {
|
||||
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08,
|
||||
};
|
||||
QUIC_TRANSPORT_PARAMS params;
|
||||
QUIC_TRANSPORT_PARAMS decoded;
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
size_t inlen;
|
||||
const uint8_t *data;
|
||||
size_t datalen;
|
||||
uint64_t val;
|
||||
|
||||
quic_transport_params_init(¶ms);
|
||||
|
||||
if (quic_transport_params_add(¶ms,
|
||||
QUIC_transport_param_original_destination_connection_id,
|
||||
odcid, sizeof(odcid)) != 1
|
||||
|| quic_transport_params_add_varint(¶ms,
|
||||
QUIC_transport_param_max_idle_timeout, 30) != 1
|
||||
|| quic_transport_params_add_varint(¶ms,
|
||||
QUIC_transport_param_initial_max_data, 4096) != 1
|
||||
|| quic_transport_params_add(¶ms,
|
||||
QUIC_transport_param_disable_active_migration, NULL, 0) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quic_transport_params_to_bytes(¶ms, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
inlen = len;
|
||||
if (quic_transport_params_from_bytes(&decoded, &cp, &inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen != 0 || cp != buf + len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quic_transport_params_get(&decoded,
|
||||
QUIC_transport_param_original_destination_connection_id,
|
||||
&data, &datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (datalen != sizeof(odcid) || memcmp(data, odcid, sizeof(odcid)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quic_transport_params_get_varint(&decoded,
|
||||
QUIC_transport_param_max_idle_timeout, &val) != 1 || val != 30) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_transport_params_get_varint(&decoded,
|
||||
QUIC_transport_param_initial_max_data, &val) != 1 || val != 4096) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (quic_transport_params_get(&decoded,
|
||||
QUIC_transport_param_disable_active_migration,
|
||||
&data, &datalen) != 1 || data != NULL || datalen != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quic_test_initial_keys(void)
|
||||
{
|
||||
#ifdef ENABLE_SHA2
|
||||
const uint8_t dcid[] = {
|
||||
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08,
|
||||
};
|
||||
QUIC_INITIAL_SECRETS secrets;
|
||||
QUIC_INITIAL_KEYS client_keys;
|
||||
QUIC_INITIAL_KEYS server_keys;
|
||||
|
||||
memset(&secrets, 0, sizeof(secrets));
|
||||
memset(&client_keys, 0, sizeof(client_keys));
|
||||
memset(&server_keys, 0, sizeof(server_keys));
|
||||
|
||||
if (quic_derive_initial_secrets(dcid, sizeof(dcid), &secrets) != 1
|
||||
|| quic_derive_initial_client_keys(&secrets, &client_keys) != 1
|
||||
|| quic_derive_initial_server_keys(&secrets, &server_keys) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(secrets.client_secret, secrets.server_secret,
|
||||
QUIC_INITIAL_SECRET_SIZE) == 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(client_keys.key, server_keys.key, QUIC_INITIAL_KEY_SIZE) == 0
|
||||
|| memcmp(client_keys.iv, server_keys.iv, QUIC_INITIAL_IV_SIZE) == 0
|
||||
|| memcmp(client_keys.hp, server_keys.hp, QUIC_INITIAL_HP_KEY_SIZE) == 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (quic_test_varint() != 1
|
||||
|| quic_test_transport_params() != 1
|
||||
|| quic_test_initial_keys() != 1) {
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user