Merge branch 'master' into mbed-tls-sign-certificate
diff --git a/include/picotls.h b/include/picotls.h
index 3b7a96d..218f682 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -130,8 +130,8 @@
#define PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384"
#define PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 0x1303
#define PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256"
-#define PTLS_CIPHER_SUITE_AEGIS256_SHA384 0x1306
-#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384 "TLS_AEGIS_256_SHA384"
+#define PTLS_CIPHER_SUITE_AEGIS256_SHA512 0x1306
+#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512 "TLS_AEGIS_256_SHA512"
#define PTLS_CIPHER_SUITE_AEGIS128L_SHA256 0x1307
#define PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256 "TLS_AEGIS_128L_SHA256"
@@ -248,6 +248,7 @@
#define PTLS_ERROR_REJECT_EARLY_DATA (PTLS_ERROR_CLASS_INTERNAL + 9)
#define PTLS_ERROR_DELEGATE (PTLS_ERROR_CLASS_INTERNAL + 10)
#define PTLS_ERROR_ASYNC_OPERATION (PTLS_ERROR_CLASS_INTERNAL + 11)
+#define PTLS_ERROR_BLOCK_OVERFLOW (PTLS_ERROR_CLASS_INTERNAL + 12)
#define PTLS_ERROR_INCORRECT_BASE64 (PTLS_ERROR_CLASS_INTERNAL + 50)
#define PTLS_ERROR_PEM_LABEL_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 51)
@@ -919,8 +920,7 @@
*/
unsigned send_change_cipher_spec : 1;
/**
- * if set, the server requests client certificates
- * to authenticate the client.
+ * if set, the server requests client certificates to authenticate the client
*/
unsigned require_client_authentication : 1;
/**
@@ -981,6 +981,21 @@
* (optional) list of supported tls12 cipher-suites terminated by NULL
*/
ptls_cipher_suite_t **tls12_cipher_suites;
+ /**
+ * (optional) session ID Context to segment resumption
+ */
+ struct {
+ uint8_t bytes[PTLS_SHA256_DIGEST_SIZE];
+ unsigned is_set : 1;
+ } ticket_context;
+ /**
+ * (optional) list of CAs advertised to clients as supported in the CertificateRequest message; each item must be DNs in DER
+ * format. The values are sent to the client only when `ptls_context_t::require_client_authentication` is set to true.
+ */
+ struct {
+ const ptls_iovec_t *list;
+ size_t count;
+ } client_ca_names;
};
typedef struct st_ptls_raw_extension_t {
@@ -1203,6 +1218,10 @@
} while (0); \
size_t body_size = (buf)->off - body_start; \
if (capacity != -1) { \
+ if (capacity < sizeof(size_t) && body_size >= (size_t)1 << (capacity * 8)) { \
+ ret = PTLS_ERROR_BLOCK_OVERFLOW; \
+ goto Exit; \
+ } \
for (; capacity != 0; --capacity) \
(buf)->base[body_start - capacity] = (uint8_t)(body_size >> (8 * (capacity - 1))); \
} else { \
@@ -1569,6 +1588,7 @@
int ptls_is_psk_handshake(ptls_t *tls);
/**
* return if a ECH handshake was performed, as well as optionally the kem and cipher-suite being used
+ * FIXME: this function always return false when the TLS session is exported and imported
*/
int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher);
/**
diff --git a/include/picotls/minicrypto.h b/include/picotls/minicrypto.h
index ca3a31d..a6202d0 100644
--- a/include/picotls/minicrypto.h
+++ b/include/picotls/minicrypto.h
@@ -51,11 +51,11 @@
extern ptls_aead_algorithm_t ptls_minicrypto_aegis128l;
extern ptls_aead_algorithm_t ptls_minicrypto_aegis256;
#endif
-extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384;
+extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384, ptls_minicrypto_sha512;
extern ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256, ptls_minicrypto_aes256gcmsha384, ptls_minicrypto_chacha20poly1305sha256;
#ifdef PTLS_HAVE_AEGIS
extern ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256;
-extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha384;
+extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha512;
#endif
extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[];
extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[];
diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h
index 987b9b1..de777c8 100644
--- a/include/picotls/openssl.h
+++ b/include/picotls/openssl.h
@@ -98,7 +98,7 @@
extern ptls_aead_algorithm_t ptls_openssl_aegis128l;
extern ptls_aead_algorithm_t ptls_openssl_aegis256;
extern ptls_cipher_suite_t ptls_openssl_aegis128lsha256;
-extern ptls_cipher_suite_t ptls_openssl_aegis256sha384;
+extern ptls_cipher_suite_t ptls_openssl_aegis256sha512;
#endif
extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256;
diff --git a/lib/chacha20poly1305.h b/lib/chacha20poly1305.h
index ad2d7fe..9bdc9cc 100644
--- a/lib/chacha20poly1305.h
+++ b/lib/chacha20poly1305.h
@@ -161,7 +161,7 @@
struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv));
- }
+}
static int chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv,
ptls_cipher_algorithm_t *chacha,
diff --git a/lib/cifra.c b/lib/cifra.c
index d51f2b7..6be752f 100644
--- a/lib/cifra.c
+++ b/lib/cifra.c
@@ -23,24 +23,20 @@
#include "picotls.h"
#include "picotls/minicrypto.h"
-ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha384 (must be first)
- &ptls_minicrypto_aes256gcmsha384,
+ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = { // ciphers used with sha512 and sha384 (must be first)
+ &ptls_minicrypto_aes256gcmsha384,
- // ciphers used with sha256
- &ptls_minicrypto_aes128gcmsha256,
- &ptls_minicrypto_chacha20poly1305sha256,
- NULL};
+ // ciphers used with sha256
+ &ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_chacha20poly1305sha256, NULL};
-ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha384 (must be first)
+ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = { // ciphers used with sha512 and sha384 (must be first)
#ifdef PTLS_HAVE_AEGIS
- &ptls_minicrypto_aegis256sha384,
+ &ptls_minicrypto_aegis256sha512,
#endif
- &ptls_minicrypto_aes256gcmsha384,
+ &ptls_minicrypto_aes256gcmsha384,
- // ciphers used with sha256
+// ciphers used with sha256
#ifdef PTLS_HAVE_AEGIS
- &ptls_minicrypto_aegis128lsha256,
+ &ptls_minicrypto_aegis128lsha256,
#endif
- &ptls_minicrypto_aes128gcmsha256,
- &ptls_minicrypto_chacha20poly1305sha256,
- NULL};
+ &ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_chacha20poly1305sha256, NULL};
diff --git a/lib/cifra/aes256.c b/lib/cifra/aes256.c
index d4cefa9..e074dea 100644
--- a/lib/cifra/aes256.c
+++ b/lib/cifra/aes256.c
@@ -41,6 +41,11 @@
ptls_hash_algorithm_t ptls_minicrypto_sha384 = {"sha384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create,
PTLS_ZERO_DIGEST_SHA384};
+ptls_define_hash(sha512, cf_sha512_context, cf_sha512_init, cf_sha512_update, cf_sha512_digest_final);
+
+ptls_hash_algorithm_t ptls_minicrypto_sha512 = {"sha512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, sha512_create,
+ PTLS_ZERO_DIGEST_SHA512};
+
ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = {
"AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t),
aes256ecb_setup_crypto};
diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c
index 0b4af93..8956ee4 100644
--- a/lib/cifra/libaegis.c
+++ b/lib/cifra/libaegis.c
@@ -20,11 +20,9 @@
* IN THE SOFTWARE.
*/
+#include "picotls/minicrypto.h"
#include "../libaegis.h"
-extern ptls_hash_algorithm_t ptls_minicrypto_sha256;
-extern ptls_hash_algorithm_t ptls_minicrypto_sha384;
-
ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L",
PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT,
PTLS_AEGIS128L_INTEGRITY_LIMIT,
@@ -33,7 +31,7 @@
PTLS_AEGIS128L_KEY_SIZE,
PTLS_AEGIS128L_IV_SIZE,
PTLS_AEGIS128L_TAG_SIZE,
- { 0, 0 },
+ {0, 0},
0,
0,
sizeof(struct aegis128l_context_t),
@@ -51,12 +49,12 @@
PTLS_AEGIS256_KEY_SIZE,
PTLS_AEGIS256_IV_SIZE,
PTLS_AEGIS256_TAG_SIZE,
- { 0, 0 },
+ {0, 0},
0,
0,
sizeof(struct aegis256_context_t),
aegis256_setup_crypto};
-ptls_cipher_suite_t ptls_minicrypto_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384,
- .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384,
+ptls_cipher_suite_t ptls_minicrypto_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512,
+ .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512,
.aead = &ptls_minicrypto_aegis256,
- .hash = &ptls_minicrypto_sha384};
+ .hash = &ptls_minicrypto_sha512};
diff --git a/lib/libaegis.h b/lib/libaegis.h
index ec78a4b..bc82042 100644
--- a/lib/libaegis.h
+++ b/lib/libaegis.h
@@ -63,7 +63,8 @@
struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx;
size_t written;
- aegis128l_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis128l_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen);
+ aegis128l_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis128l_TAILBYTES_MAX, &written, (const uint8_t *)input,
+ inlen);
return written;
}
@@ -73,7 +74,8 @@
struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx;
size_t written;
- aegis128l_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis128l_TAILBYTES_MAX + PTLS_AEGIS128L_TAG_SIZE, &written, PTLS_AEGIS128L_TAG_SIZE);
+ aegis128l_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis128l_TAILBYTES_MAX + PTLS_AEGIS128L_TAG_SIZE, &written,
+ PTLS_AEGIS128L_TAG_SIZE);
return written;
}
@@ -177,7 +179,8 @@
struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx;
size_t written;
- aegis256_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis256_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen);
+ aegis256_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis256_TAILBYTES_MAX, &written, (const uint8_t *)input,
+ inlen);
return written;
}
@@ -187,7 +190,8 @@
struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx;
size_t written;
- aegis256_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis256_TAILBYTES_MAX + PTLS_AEGIS256_TAG_SIZE, &written, PTLS_AEGIS256_TAG_SIZE);
+ aegis256_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis256_TAILBYTES_MAX + PTLS_AEGIS256_TAG_SIZE, &written,
+ PTLS_AEGIS256_TAG_SIZE);
return written;
}
diff --git a/lib/mbedtls_sign.c b/lib/mbedtls_sign.c
index 750dad5..c774cb2 100644
--- a/lib/mbedtls_sign.c
+++ b/lib/mbedtls_sign.c
@@ -20,6 +20,7 @@
* IN THE SOFTWARE.
*/
+
#ifdef _WINDOWS
#include "wincompat.h"
#endif
@@ -36,6 +37,8 @@
#include <psa/crypto.h>
#include <psa/crypto_struct.h>
#include <psa/crypto_values.h>
+#include "ptls_mbedtls.h"
+
typedef struct st_ptls_mbedtls_signature_scheme_t {
uint16_t scheme_id;
@@ -58,6 +61,7 @@
{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, PSA_ALG_SHA_384},
{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PSA_ALG_SHA_512},
{UINT16_MAX, PSA_ALG_NONE}};
+
static const ptls_mbedtls_signature_scheme_t secp256r1_signature_schemes[] = {
{PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, PSA_ALG_SHA_256}, {UINT16_MAX, PSA_ALG_NONE}};
static const ptls_mbedtls_signature_scheme_t secp384r1_signature_schemes[] = {
@@ -178,6 +182,7 @@
ret = -1;
}
else {
+
*key_index = x;
*key_length = l_key;
}
@@ -325,6 +330,7 @@
return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
}
else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+
return ret;
}
#endif /* MBEDTLS_RSA_C */
@@ -401,6 +407,7 @@
const uint16_t *algorithms, size_t num_algorithms)
{
const ptls_mbedtls_signature_scheme_t* scheme;
+
/* select the algorithm, driven by server-isde preference of `available` */
for (scheme = available; scheme->scheme_id != UINT16_MAX; ++scheme) {
for (size_t i = 0; i != num_algorithms; ++i) {
@@ -498,6 +505,7 @@
/* First prepare the hash */
unsigned char hash_buffer[PTLS_MAX_DIGEST_SIZE];
unsigned char* hash_value = NULL;
+
size_t hash_length = 0;
if (scheme->hash_algo == PSA_ALG_NONE) {
@@ -530,7 +538,6 @@
}
if ((ret = ptls_buffer_reserve(outbuf, nb_bytes)) == 0) {
size_t signature_length = 0;
-
if (psa_sign_hash(self->key_id, sign_algo, hash_value, hash_length,
outbuf->base + outbuf->off, nb_bytes, &signature_length) != 0) {
ret = PTLS_ERROR_INCOMPATIBLE_KEY;
@@ -662,7 +669,6 @@
return ret;
}
-
int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/lib/openssl.c b/lib/openssl.c
index a6abafe..8ca5a6c 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -101,22 +101,21 @@
#endif
static const ptls_openssl_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, EVP_sha256},
- {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384},
- {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512},
- {UINT16_MAX, NULL}};
-static const ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256}, {UINT16_MAX, NULL}};
+ {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384},
+ {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512},
+ {UINT16_MAX, NULL}};
+static const ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256},
+ {UINT16_MAX, NULL}};
#if PTLS_OPENSSL_HAVE_SECP384R1
-static const ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384}, {UINT16_MAX, NULL}};
+static const ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384},
+ {UINT16_MAX, NULL}};
#endif
#if PTLS_OPENSSL_HAVE_SECP521R1
-static const ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = {
- {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512}, {UINT16_MAX, NULL}};
+static const ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512},
+ {UINT16_MAX, NULL}};
#endif
#if PTLS_OPENSSL_HAVE_ED25519
-static const ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL},
- {UINT16_MAX, NULL}};
+static const ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL}, {UINT16_MAX, NULL}};
#endif
/**
@@ -854,8 +853,8 @@
#endif
-static int do_sign(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf,
- ptls_iovec_t input, ptls_async_job_t **async)
+static int do_sign(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf, ptls_iovec_t input,
+ ptls_async_job_t **async)
{
EVP_MD_CTX *ctx = NULL;
const EVP_MD *md = scheme->scheme_md != NULL ? scheme->scheme_md() : NULL;
@@ -2183,7 +2182,6 @@
.hash = &ptls_openssl_sha256};
#endif
-
#if PTLS_HAVE_AEGIS
ptls_aead_algorithm_t ptls_openssl_aegis128l = {
.name = "AEGIS-128L",
@@ -2194,7 +2192,7 @@
.key_size = PTLS_AEGIS128L_KEY_SIZE,
.iv_size = PTLS_AEGIS128L_IV_SIZE,
.tag_size = PTLS_AEGIS128L_TAG_SIZE,
- .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 },
+ .tls12 = {.fixed_iv_size = 0, .record_iv_size = 0},
.non_temporal = 0,
.align_bits = 0,
.context_size = sizeof(struct aegis128l_context_t),
@@ -2214,45 +2212,43 @@
.key_size = PTLS_AEGIS256_KEY_SIZE,
.iv_size = PTLS_AEGIS256_IV_SIZE,
.tag_size = PTLS_AEGIS256_TAG_SIZE,
- .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 },
+ .tls12 = {.fixed_iv_size = 0, .record_iv_size = 0},
.non_temporal = 0,
.align_bits = 0,
.context_size = sizeof(struct aegis256_context_t),
.setup_crypto = aegis256_setup_crypto,
};
-ptls_cipher_suite_t ptls_openssl_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384,
- .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384,
- .aead = &ptls_openssl_aegis256,
- .hash = &ptls_openssl_sha384};
+ptls_cipher_suite_t ptls_openssl_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512,
+ .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512,
+ .aead = &ptls_openssl_aegis256,
+ .hash = &ptls_openssl_sha512};
#endif
+ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = { // ciphers used with sha384 (must be first)
+ &ptls_openssl_aes256gcmsha384,
-
-ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 (must be first)
- &ptls_openssl_aes256gcmsha384,
-
- // ciphers used with sha256
- &ptls_openssl_aes128gcmsha256,
+ // ciphers used with sha256
+ &ptls_openssl_aes128gcmsha256,
#if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305
- &ptls_openssl_chacha20poly1305sha256,
+ &ptls_openssl_chacha20poly1305sha256,
#endif
- NULL};
+ NULL};
-ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = {// ciphers used with sha384 (must be first)
+ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = { // ciphers used with sha384 (must be first)
#if PTLS_HAVE_AEGIS
- &ptls_openssl_aegis256sha384,
+ &ptls_openssl_aegis256sha512,
#endif
- &ptls_openssl_aes256gcmsha384,
+ &ptls_openssl_aes256gcmsha384,
- // ciphers used with sha256
+// ciphers used with sha256
#if PTLS_HAVE_AEGIS
- &ptls_openssl_aegis128lsha256,
+ &ptls_openssl_aegis128lsha256,
#endif
- &ptls_openssl_aes128gcmsha256,
+ &ptls_openssl_aes128gcmsha256,
#if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305
- &ptls_openssl_chacha20poly1305sha256,
+ &ptls_openssl_chacha20poly1305sha256,
#endif
- NULL};
+ NULL};
ptls_cipher_suite_t *ptls_openssl_tls12_cipher_suites[] = {&ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256,
&ptls_openssl_tls12_ecdhe_ecdsa_aes128gcmsha256,
diff --git a/lib/picotls.c b/lib/picotls.c
index b00b429..2feba7e 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -39,10 +39,6 @@
#include "picotls-probes.h"
#endif
-#ifdef PTLS_HAVE_AEGIS
-#include <aegis.h>
-#endif
-
#define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384
#define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256)
@@ -71,6 +67,7 @@
#define PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS 43
#define PTLS_EXTENSION_TYPE_COOKIE 44
#define PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES 45
+#define PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES 47
#define PTLS_EXTENSION_TYPE_KEY_SHARE 51
#define PTLS_EXTENSION_TYPE_ECH_OUTER_EXTENSIONS 0xfd00
#define PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO 0xfe0d
@@ -1618,7 +1615,7 @@
return ret;
}
-static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify)
+static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, uint64_t seq, int skip_notify)
{
static const char *log_labels[2][4] = {
{NULL, "CLIENT_EARLY_TRAFFIC_SECRET", "CLIENT_HANDSHAKE_TRAFFIC_SECRET", "CLIENT_TRAFFIC_SECRET_0"},
@@ -1648,7 +1645,7 @@
if ((ctx->aead = ptls_aead_new(tls->cipher_suite->aead, tls->cipher_suite->hash, is_enc, ctx->secret,
tls->ctx->hkdf_label_prefix__obsolete)) == NULL)
return PTLS_ERROR_NO_MEMORY; /* TODO obtain error from ptls_aead_new */
- ctx->seq = 0;
+ ctx->seq = seq;
PTLS_DEBUGF("[%s] %02x%02x,%02x%02x\n", log_labels[ptls_is_server(tls)][epoch], (unsigned)ctx->secret[0],
(unsigned)ctx->secret[1], (unsigned)ctx->aead->static_iv[0], (unsigned)ctx->aead->static_iv[1]);
@@ -1667,7 +1664,7 @@
free(tls->pending_handshake_secret);
tls->pending_handshake_secret = NULL;
- return setup_traffic_protection(tls, is_enc, NULL, 2, 1);
+ return setup_traffic_protection(tls, is_enc, NULL, 2, 0, 1);
}
static void log_client_random(ptls_t *tls)
@@ -1706,10 +1703,13 @@
ptls_buffer_push16(buf, csid);
/* ticket_age_add */
ptls_buffer_push32(buf, ticket_age_add);
- /* server-name */
+ /* session ID context */
ptls_buffer_push_block(buf, 2, {
- if (server_name != NULL)
+ if (ctx->ticket_context.is_set) {
+ ptls_buffer_pushv(buf, ctx->ticket_context.bytes, sizeof(ctx->ticket_context.bytes));
+ } else if (server_name != NULL) {
ptls_buffer_pushv(buf, server_name, strlen(server_name));
+ }
});
/* alpn */
ptls_buffer_push_block(buf, 1, {
@@ -1722,7 +1722,7 @@
return ret;
}
-int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *server_name,
+int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *ticket_ctx,
uint16_t *key_exchange_id, uint16_t *csid, ptls_iovec_t *negotiated_protocol, const uint8_t *src,
const uint8_t *const end)
{
@@ -1748,7 +1748,7 @@
if ((ret = ptls_decode32(ticket_age_add, &src, end)) != 0)
goto Exit;
ptls_decode_open_block(src, end, 2, {
- *server_name = ptls_iovec_init(src, end - src);
+ *ticket_ctx = ptls_iovec_init(src, end - src);
src = end;
});
ptls_decode_open_block(src, end, 1, {
@@ -2479,7 +2479,7 @@
if (tls->client.using_early_data) {
assert(!is_second_flight);
- if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0, 0)) != 0)
goto Exit;
if ((ret = push_change_cipher_spec(tls, emitter)) != 0)
goto Exit;
@@ -2795,7 +2795,7 @@
if ((ret = key_schedule_extract(tls->key_schedule, ecdh_secret)) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (tls->client.using_early_data) {
if ((tls->pending_handshake_secret = malloc(PTLS_MAX_DIGEST_SIZE)) == NULL) {
@@ -2808,7 +2808,7 @@
(ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 1, 2, tls->pending_handshake_secret)) != 0)
goto Exit;
} else {
- if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0, 0)) != 0)
goto Exit;
}
@@ -3373,7 +3373,7 @@
/* update traffic keys by using messages upto ServerFinished, but commission them after sending ClientFinished */
if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0, 0)) != 0)
goto Exit;
if ((ret = derive_secret(tls->key_schedule, send_secret, "c ap traffic")) != 0)
goto Exit;
@@ -3407,7 +3407,7 @@
ret = send_finished(tls, emitter);
memcpy(tls->traffic_protection.enc.secret, send_secret, sizeof(send_secret));
- if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0, 0)) != 0)
goto Exit;
tls->state = PTLS_STATE_CLIENT_POST_HANDSHAKE;
@@ -4009,7 +4009,7 @@
ptls_iovec_t ch_trunc)
{
ptls_buffer_t decbuf;
- ptls_iovec_t ticket_psk, ticket_server_name, ticket_negotiated_protocol;
+ ptls_iovec_t ticket_psk, ticket_ctx, ticket_negotiated_protocol;
uint64_t issue_at, now = tls->ctx->get_time->cb(tls->ctx->get_time);
uint32_t age_add;
uint16_t ticket_key_exchange_id, ticket_csid;
@@ -4032,7 +4032,7 @@
default: /* decryption failure */
continue;
}
- if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_server_name, &ticket_key_exchange_id, &ticket_csid,
+ if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_ctx, &ticket_key_exchange_id, &ticket_csid,
&ticket_negotiated_protocol, decbuf.base, decbuf.base + decbuf.off) != 0)
continue;
/* check age */
@@ -4049,15 +4049,22 @@
if (tls->ctx->max_early_data_size != 0 && delta <= PTLS_EARLY_DATA_MAX_DELAY)
*accept_early_data = 1;
}
- /* check server-name */
- if (ticket_server_name.len != 0) {
- if (tls->server_name == NULL)
- continue;
- if (!vec_is_string(ticket_server_name, tls->server_name))
+ /* check ticket context */
+ if (tls->ctx->ticket_context.is_set) {
+ if (!(ticket_ctx.len == sizeof(tls->ctx->ticket_context.bytes) &&
+ memcmp(ticket_ctx.base, tls->ctx->ticket_context.bytes, ticket_ctx.len) == 0))
continue;
} else {
- if (tls->server_name != NULL)
- continue;
+ /* check server-name */
+ if (ticket_ctx.len != 0) {
+ if (tls->server_name == NULL)
+ continue;
+ if (!vec_is_string(ticket_ctx, tls->server_name))
+ continue;
+ } else {
+ if (tls->server_name != NULL)
+ continue;
+ }
}
{ /* check key-exchange */
ptls_key_exchange_algorithm_t **a;
@@ -4364,8 +4371,9 @@
{ /* select (or check) cipher-suite, create key_schedule */
ptls_cipher_suite_t *cs;
- if ((ret = select_cipher(&cs, tls->ctx->cipher_suites, ch->cipher_suites.base,
- ch->cipher_suites.base + ch->cipher_suites.len, tls->ctx->server_cipher_preference, tls->ctx->server_cipher_chacha_priority)) != 0)
+ if ((ret =
+ select_cipher(&cs, tls->ctx->cipher_suites, ch->cipher_suites.base, ch->cipher_suites.base + ch->cipher_suites.len,
+ tls->ctx->server_cipher_preference, tls->ctx->server_cipher_chacha_priority)) != 0)
goto Exit;
if (!is_second_flight) {
tls->cipher_suite = cs;
@@ -4564,7 +4572,7 @@
}
if ((ret = derive_exporter_secret(tls, 1)) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0, 0)) != 0)
goto Exit;
}
@@ -4623,7 +4631,7 @@
/* create protection contexts for the handshake */
assert(tls->key_schedule->generation == 1);
key_schedule_extract(tls->key_schedule, ecdh_secret);
- if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (tls->pending_handshake_secret != NULL) {
if ((ret = derive_secret(tls->key_schedule, tls->pending_handshake_secret, "c hs traffic")) != 0)
@@ -4632,7 +4640,7 @@
(ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 0, 2, tls->pending_handshake_secret)) != 0)
goto Exit;
} else {
- if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (ch->psk.early_data_indication)
tls->server.early_data_skipped_bytes = 0;
@@ -4677,10 +4685,9 @@
/* send certificate request if client authentication is activated */
if (tls->ctx->require_client_authentication) {
ptls_push_message(emitter, tls->key_schedule, PTLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST, {
- /* certificate_request_context, this field SHALL be zero length, unless the certificate
- * request is used for post-handshake authentication.
- */
ptls_buffer_t *sendbuf = emitter->buf;
+ /* certificate_request_context: this field SHALL be zero length, unless the certificate request is used for post-
+ * handshake authentication. */
ptls_buffer_push(sendbuf, 0);
/* extensions */
ptls_buffer_push_block(sendbuf, 2, {
@@ -4688,6 +4695,19 @@
if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0)
goto Exit;
});
+ /* certificate authorities entension */
+ if (tls->ctx->client_ca_names.count > 0) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ for (size_t i = 0; i != tls->ctx->client_ca_names.count; ++i) {
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_iovec_t name = tls->ctx->client_ca_names.list[i];
+ ptls_buffer_pushv(sendbuf, name.base, name.len);
+ });
+ }
+ });
+ });
+ }
});
});
@@ -4746,7 +4766,7 @@
assert(tls->key_schedule->generation == 2);
if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0, 0)) != 0)
goto Exit;
if ((ret = derive_secret(tls->key_schedule, tls->server.pending_traffic_secret, "c ap traffic")) != 0)
goto Exit;
@@ -4807,7 +4827,7 @@
memcpy(tls->traffic_protection.dec.secret, tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
ptls_clear_memory(tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
- if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0, 0)) != 0)
return ret;
ptls__key_schedule_update_hash(tls->key_schedule, message.base, message.len, 0);
@@ -4827,7 +4847,7 @@
"traffic upd", ptls_iovec_init(NULL, 0), NULL)) != 0)
goto Exit;
memcpy(tp->secret, secret, sizeof(secret));
- ret = setup_traffic_protection(tls, is_enc, NULL, 3, 1);
+ ret = setup_traffic_protection(tls, is_enc, NULL, 3, 0, 1);
Exit:
ptls_clear_memory(secret, sizeof(secret));
@@ -4997,6 +5017,28 @@
return tls;
}
+#define export_tls_params(output, is_server, session_reused, protocol_version, cipher, client_random, server_name, \
+ negotiated_protocol, ver_block) \
+ do { \
+ const char *_server_name = (server_name); \
+ ptls_iovec_t _negotiated_protocol = (negotiated_protocol); \
+ ptls_buffer_push_block((output), 2, { \
+ ptls_buffer_push((output), (is_server)); \
+ ptls_buffer_push((output), (session_reused)); \
+ ptls_buffer_push16((output), (protocol_version)); \
+ ptls_buffer_push16((output), (cipher)->id); \
+ ptls_buffer_pushv((output), (client_random), PTLS_HELLO_RANDOM_SIZE); \
+ ptls_buffer_push_block((output), 2, { \
+ size_t len = _server_name != NULL ? strlen(_server_name) : 0; \
+ ptls_buffer_pushv((output), _server_name, len); \
+ }); \
+ ptls_buffer_push_block((output), 2, \
+ { ptls_buffer_pushv((output), _negotiated_protocol.base, _negotiated_protocol.len); }); \
+ ptls_buffer_push_block((output), 2, {ver_block}); /* version-specific block */ \
+ ptls_buffer_push_block((output), 2, {}); /* for future extensions */ \
+ }); \
+ } while (0)
+
static int export_tls12_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher,
const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol,
const void *enc_key, const void *enc_iv, uint64_t enc_seq, uint64_t enc_record_iv,
@@ -5004,29 +5046,18 @@
{
int ret;
- ptls_buffer_push_block(output, 2, {
- ptls_buffer_push(output, is_server);
- ptls_buffer_push(output, session_reused);
- ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS12);
- ptls_buffer_push16(output, cipher->id);
- ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE);
- ptls_buffer_push_block(output, 2, {
- size_t len = server_name != NULL ? strlen(server_name) : 0;
- ptls_buffer_pushv(output, server_name, len);
- });
- ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); });
- ptls_buffer_push_block(output, 2, {
- ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
- ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
- ptls_buffer_push64(output, enc_seq);
- if (cipher->aead->tls12.record_iv_size != 0)
- ptls_buffer_push64(output, enc_record_iv);
- ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
- ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
- ptls_buffer_push64(output, dec_seq);
- });
- ptls_buffer_push_block(output, 2, {}); /* for future extensions */
- });
+ export_tls_params(output, is_server, session_reused, PTLS_PROTOCOL_VERSION_TLS12, cipher, client_random, server_name,
+ negotiated_protocol, {
+ ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
+ ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
+ ptls_buffer_push64(output, enc_seq);
+ if (cipher->aead->tls12.record_iv_size != 0)
+ ptls_buffer_push64(output, enc_record_iv);
+ ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
+ ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
+ ptls_buffer_push64(output, dec_seq);
+ });
+ ret = 0;
Exit:
return ret;
@@ -5074,20 +5105,39 @@
int ptls_export(ptls_t *tls, ptls_buffer_t *output)
{
- /* TODO add tls13 support */
- if (!tls->traffic_protection.enc.tls12)
- return PTLS_ERROR_LIBRARY;
-
ptls_iovec_t negotiated_protocol =
ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0);
- return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
- tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
- tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
- tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
- tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq);
+ int ret;
+
+ if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+
+ if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) {
+ export_tls_params(output, tls->is_server, tls->is_psk_handshake, PTLS_PROTOCOL_VERSION_TLS13, tls->cipher_suite,
+ tls->client_random, tls->server_name, negotiated_protocol, {
+ ptls_buffer_pushv(output, tls->traffic_protection.enc.secret, tls->cipher_suite->hash->digest_size);
+ ptls_buffer_push64(output, tls->traffic_protection.enc.seq);
+ ptls_buffer_pushv(output, tls->traffic_protection.dec.secret, tls->cipher_suite->hash->digest_size);
+ ptls_buffer_push64(output, tls->traffic_protection.dec.seq);
+ });
+ ret = 0;
+ } else {
+ if ((ret = export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
+ tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
+ tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
+ tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
+ tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE,
+ tls->traffic_protection.dec.seq)) != 0)
+ goto Exit;
+ }
+
+Exit:
+ return ret;
}
-static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
+static int import_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
{
struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
@@ -5114,6 +5164,22 @@
return 0;
}
+static int import_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
+{
+ struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
+
+ /* set properties */
+ memcpy(tp->secret, *src, tls->cipher_suite->hash->digest_size);
+ *src += tls->cipher_suite->hash->digest_size;
+ if (ptls_decode64(&tp->seq, src, end) != 0)
+ return PTLS_ALERT_DECODE_ERROR;
+
+ if (setup_traffic_protection(tls, is_enc, NULL, 3, tp->seq, 0) != 0)
+ return PTLS_ERROR_INCOMPATIBLE_KEY;
+
+ return 0;
+}
+
int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params)
{
const uint8_t *src = params.base, *const end = src + params.len;
@@ -5139,11 +5205,6 @@
goto Exit;
if ((ret = ptls_decode16(&csid, &src, end)) != 0)
goto Exit;
- (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid);
- if ((*tls)->cipher_suite == NULL) {
- ret = PTLS_ALERT_HANDSHAKE_FAILURE;
- goto Exit;
- }
/* other version-independent stuff */
if (end - src < PTLS_HELLO_RANDOM_SIZE) {
ret = PTLS_ALERT_DECODE_ERROR;
@@ -5169,15 +5230,36 @@
ptls_decode_open_block(src, end, 2, {
switch (protocol_version) {
case PTLS_PROTOCOL_VERSION_TLS12:
- /* setup AEAD keys */
- if ((ret = build_tls12_traffic_protection(*tls, 1, &src, end)) != 0)
+ (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid);
+ if ((*tls)->cipher_suite == NULL) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
goto Exit;
- if ((ret = build_tls12_traffic_protection(*tls, 0, &src, end)) != 0)
+ }
+ /* setup AEAD keys */
+ if ((ret = import_tls12_traffic_protection(*tls, 1, &src, end)) != 0)
+ goto Exit;
+ if ((ret = import_tls12_traffic_protection(*tls, 0, &src, end)) != 0)
+ goto Exit;
+ break;
+ case PTLS_PROTOCOL_VERSION_TLS13:
+ (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->cipher_suites, csid);
+ if ((*tls)->cipher_suite == NULL) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ /* setup AEAD keys */
+ if (((*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((ret = import_tls13_traffic_protection(*tls, 1, &src, end)) != 0)
+ goto Exit;
+ if ((ret = import_tls13_traffic_protection(*tls, 0, &src, end)) != 0)
goto Exit;
break;
default:
ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- break;
+ goto Exit;
}
});
/* extensions */
@@ -6212,7 +6294,6 @@
if ((ret = get_traffic_keys(aead, hash, key_iv.key, key_iv.iv, secret, hash_value, label_prefix)) != 0)
goto Exit;
ctx = ptls_aead_new_direct(aead, is_enc, key_iv.key, key_iv.iv);
-
Exit:
ptls_clear_memory(&key_iv, sizeof(key_iv));
return ctx;
diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj
index 053d89e..338535e 100644
--- a/picotls.xcodeproj/project.pbxproj
+++ b/picotls.xcodeproj/project.pbxproj
@@ -205,6 +205,8 @@
081F00CC291A358800534A86 /* asn1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asn1.h; sourceTree = "<group>"; };
081F00CD291A358800534A86 /* pembase64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pembase64.h; sourceTree = "<group>"; };
081F00CE291A358800534A86 /* ptlsbcrypt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptlsbcrypt.h; sourceTree = "<group>"; };
+ 085BDAE52B1D618E002851EA /* libaegis.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libaegis.c; sourceTree = "<group>"; };
+ 085BDAE62B1D6238002851EA /* libaegis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libaegis.h; sourceTree = "<group>"; };
087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindMbedTLS.cmake; sourceTree = "<group>"; };
0883D3272AEF8F2500B711CC /* fusion.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = fusion.cmake; sourceTree = "<group>"; };
0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = "<group>"; };
@@ -448,6 +450,7 @@
E97577022212405D00D1EF74 /* ffx.c */,
E9B43DBF24619D1700824E51 /* fusion.c */,
08F0FDF52910F67A00EE657D /* hpke.c */,
+ 085BDAE62B1D6238002851EA /* libaegis.h */,
0883D32B2AF601B900B711CC /* mbedtls.c */,
E949EF272073629300511ECA /* minicrypto-pem.c */,
106530C21D9B004B005B2C60 /* openssl.c */,
@@ -556,6 +559,7 @@
E9F20BE222E34B340018D260 /* aes128.c */,
E9F20BE022E34B340018D260 /* aes256.c */,
E9F20BE422E34B340018D260 /* chacha20.c */,
+ 085BDAE52B1D618E002851EA /* libaegis.c */,
E9F20BF922E34C110018D260 /* random.c */,
E9F20BE122E34B340018D260 /* x25519.c */,
);
diff --git a/t/openssl.c b/t/openssl.c
index b3188ff..d487445 100644
--- a/t/openssl.c
+++ b/t/openssl.c
@@ -564,7 +564,8 @@
.sign_certificate = &openssl_sign_certificate.super};
ptls_context_t openssl_ctx_sha256only = openssl_ctx;
while (openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size != 32) {
- assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */
+ assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 64 || /* sha512 */
+ openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */
++openssl_ctx_sha256only.cipher_suites;
}
assert(openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size == 32); /* sha256 */
diff --git a/t/picotls.c b/t/picotls.c
index 80c8543..1ce5925 100644
--- a/t/picotls.c
+++ b/t/picotls.c
@@ -87,7 +87,8 @@
}
{
- ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, NULL};
+ ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_aes256gcmsha384,
+ &ptls_minicrypto_chacha20poly1305sha256, NULL};
static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)};
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0);
ok(selected == &ptls_minicrypto_aes128gcmsha256);
@@ -96,8 +97,10 @@
}
{
- ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL};
- static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
+ ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256,
+ &ptls_minicrypto_aes128gcmsha256, NULL};
+ static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256),
+ C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0);
ok(selected == &ptls_minicrypto_aes256gcmsha384);
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0);
@@ -107,8 +110,10 @@
}
{
- ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL};
- static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
+ ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256,
+ &ptls_minicrypto_aes128gcmsha256, NULL};
+ static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256),
+ C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0);
ok(selected == &ptls_minicrypto_aes256gcmsha384);
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0);
@@ -117,7 +122,8 @@
{
ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256, NULL};
- static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
+ static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256),
+ C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)};
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0);
ok(selected == &ptls_minicrypto_aes256gcmsha384);
ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0);
@@ -506,8 +512,8 @@
static void test_aegis256(void)
{
- ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA384),
- *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA384);
+ ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA512),
+ *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA512);
if (cs != NULL && cs_peer != NULL) {
test_ciphersuite(cs, cs_peer);
@@ -858,7 +864,50 @@
}
}
-static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication)
+static void check_clone(ptls_t *src, ptls_t *dest)
+{
+ ok(src->cipher_suite->hash->digest_size == dest->cipher_suite->hash->digest_size);
+ size_t digest_size = dest->cipher_suite->hash->digest_size;
+ ok(memcmp(src->traffic_protection.enc.secret, dest->traffic_protection.enc.secret, digest_size) == 0);
+ ok(memcmp(src->traffic_protection.dec.secret, dest->traffic_protection.dec.secret, digest_size) == 0);
+ const unsigned enc_idx = 0;
+ const unsigned dec_idx = 1;
+ struct {
+ uint8_t key[PTLS_MAX_SECRET_SIZE];
+ uint8_t iv[PTLS_MAX_IV_SIZE];
+ uint64_t seq;
+ } src_keys[2] = {0}, dest_keys[2] = {0};
+ ok(ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(dest, 1, dest_keys[enc_idx].key, dest_keys[enc_idx].iv, &dest_keys[enc_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(dest, 0, dest_keys[dec_idx].key, dest_keys[dec_idx].iv, &dest_keys[dec_idx].seq) == 0);
+ ok(src_keys[enc_idx].seq == dest_keys[enc_idx].seq);
+ ok(src_keys[dec_idx].seq == dest_keys[dec_idx].seq);
+ ok(memcmp(src_keys[enc_idx].key, dest_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE) == 0);
+ ok(memcmp(src_keys[dec_idx].key, dest_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE) == 0);
+ ok(memcmp(src_keys[enc_idx].iv, dest_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0);
+ ok(memcmp(src_keys[dec_idx].iv, dest_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0);
+}
+
+static ptls_t *clone_tls(ptls_t *src)
+{
+ ptls_t *dest = NULL;
+ ptls_buffer_t sess_data;
+
+ ptls_buffer_init(&sess_data, "", 0);
+ int r = ptls_export(src, &sess_data);
+ assert(r == 0);
+ r = ptls_import(ctx_peer, &dest, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off});
+ assert(r == 0);
+ ptls_buffer_dispose(&sess_data);
+
+ check_clone(src, dest);
+
+ return dest;
+}
+
+static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication,
+ int transfer_session)
{
ptls_t *client, *server;
ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}};
@@ -1049,6 +1098,9 @@
cbuf.off = 0;
}
+ /* holds the ptls_t pointer of server prior to migration */
+ ptls_t *original_server = server;
+
if (mode != TEST_HANDSHAKE_EARLY_DATA || require_client_authentication) {
ret = ptls_send(client, &cbuf, req, strlen(req));
ok(ret == 0);
@@ -1062,6 +1114,8 @@
ok(ptls_handshake_is_complete(server));
decbuf.off = 0;
cbuf.off = 0;
+ if (transfer_session)
+ server = clone_tls(original_server);
ret = ptls_send(server, &sbuf, resp, strlen(resp));
ok(ret == 0);
@@ -1119,18 +1173,21 @@
decbuf.off = 0;
}
+ /* original_server is used for the server-side checks because handshake data is never migrated */
if (can_ech(ctx_peer, 1) && can_ech(ctx, 0)) {
ok(ptls_is_ech_handshake(client, NULL, NULL, NULL));
- ok(ptls_is_ech_handshake(server, NULL, NULL, NULL));
+ ok(ptls_is_ech_handshake(original_server, NULL, NULL, NULL));
} else {
ok(!ptls_is_ech_handshake(client, NULL, NULL, NULL));
- ok(!ptls_is_ech_handshake(server, NULL, NULL, NULL));
+ ok(!ptls_is_ech_handshake(original_server, NULL, NULL, NULL));
}
ptls_buffer_dispose(&cbuf);
ptls_buffer_dispose(&sbuf);
ptls_buffer_dispose(&decbuf);
ptls_free(client);
+ if (original_server != server)
+ ptls_free(original_server);
ptls_free(server);
if (check_ch)
@@ -1196,19 +1253,19 @@
return second_sc_orig->cb(second_sc_orig, tls, async, selected_algorithm, output, input, algorithms, num_algorithms);
}
-static void test_full_handshake_impl(int require_client_authentication, int is_async)
+static void test_full_handshake_impl(int require_client_authentication, int is_async, int transfer_session)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
@@ -1216,28 +1273,32 @@
static void test_full_handshake(void)
{
- test_full_handshake_impl(0, 0);
+ test_full_handshake_impl(0, 0, 0);
+ test_full_handshake_impl(0, 0, 0);
}
static void test_full_handshake_with_client_authentication(void)
{
- test_full_handshake_impl(1, 0);
+ test_full_handshake_impl(1, 0, 0);
+ test_full_handshake_impl(1, 0, 1);
}
static void test_key_update(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 1);
}
static void test_hrr_handshake(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0);
ok(server_sc_callcnt == 1);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0);
}
static void test_hrr_stateless_handshake(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0, 0);
ok(server_sc_callcnt == 1);
}
@@ -1263,7 +1324,7 @@
return 0;
}
-static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication)
+static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication, int transfer_session)
{
assert(ctx->key_exchanges[0]->id == ctx_peer->key_exchanges[0]->id);
assert(ctx->key_exchanges[1] == NULL);
@@ -1289,29 +1350,30 @@
ctx_peer->encrypt_ticket = &et;
ctx->save_ticket = &st;
- test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0);
+ test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0,
+ transfer_session);
ok(server_sc_callcnt == 1);
ok(saved_ticket.base != NULL);
/* psk using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
/* 0-rtt psk using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
ctx->require_dhe_on_psk = 1;
/* psk-dhe using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
/* 0-rtt psk-dhe using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
@@ -1325,19 +1387,22 @@
static void test_resumption(void)
{
- test_resumption_impl(0, 0);
+ test_resumption_impl(0, 0, 0);
+ test_resumption_impl(0, 0, 1);
}
static void test_resumption_different_preferred_key_share(void)
{
if (ctx == ctx_peer)
return;
- test_resumption_impl(1, 0);
+ test_resumption_impl(1, 0, 0);
+ test_resumption_impl(0, 0, 1);
}
static void test_resumption_with_client_authentication(void)
{
- test_resumption_impl(0, 1);
+ test_resumption_impl(0, 0, 0);
+ test_resumption_impl(0, 1, 1);
}
static void test_async_sign_certificate(void)
@@ -1347,7 +1412,7 @@
ptls_sign_certificate_t async_sc = {async_sign_certificate}, *orig_sc = ctx_peer->sign_certificate;
ctx_peer->sign_certificate = &async_sc;
- test_full_handshake_impl(0, 1);
+ test_full_handshake_impl(0, 1, 0);
ctx_peer->sign_certificate = orig_sc;
}
@@ -1901,6 +1966,60 @@
ctx->sign_certificate = second_sc_orig;
}
+static void do_test_tlsblock(size_t len_encoded, size_t max_bytes)
+{
+ ptls_buffer_t buf;
+ const uint8_t *src, *end;
+ int expect_overflow = 0, ret;
+
+ /* block that fits in */
+ ptls_buffer_init(&buf, "", 0);
+ ptls_buffer_push_block(&buf, len_encoded, {
+ for (size_t i = 0; i < max_bytes; ++i)
+ ptls_buffer_push(&buf, (uint8_t)i);
+ });
+ src = buf.base;
+ end = buf.base + buf.off;
+ ptls_decode_block(src, end, len_encoded, {
+ ok(end - src == max_bytes);
+ int bytes_eq = 1;
+ for (size_t i = 0; i < max_bytes; ++i) {
+ if (src[i] != (uint8_t)i)
+ bytes_eq = 0;
+ }
+ ok(bytes_eq);
+ src = end;
+ });
+
+ /* block that does not fit in */
+ ptls_buffer_push_block(&buf, len_encoded, {
+ for (size_t i = 0; i < max_bytes + 1; i++)
+ ptls_buffer_push(&buf, 1);
+ expect_overflow = 1;
+ });
+ ok(!"fail");
+
+Exit:
+ if (ret != 0) {
+ if (expect_overflow) {
+ ok(ret == PTLS_ERROR_BLOCK_OVERFLOW);
+ } else {
+ ok(!"fail");
+ }
+ }
+ ptls_buffer_dispose(&buf);
+}
+
+static void test_tlsblock8(void)
+{
+ do_test_tlsblock(1, 255);
+}
+
+static void test_tlsblock16(void)
+{
+ do_test_tlsblock(2, 65535);
+}
+
static void test_quicint(void)
{
#define CHECK_PATTERN(output, ...) \
@@ -2161,6 +2280,8 @@
subtest("chacha20", test_chacha20);
subtest("ffx", test_ffx);
subtest("base64-decode", test_base64_decode);
+ subtest("tls-block8", test_tlsblock8);
+ subtest("tls-block16", test_tlsblock16);
subtest("ech", test_ech);
subtest("fragmented-message", test_fragmented_message);
subtest("handshake", test_all_handshakes);