Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

external PSK mode #481

Merged
merged 66 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
9592b5b
zero-length identity is not permitted
kazuho Aug 4, 2020
1c38583
it works
kazuho Aug 4, 2020
c2ddeee
but not if `ptls_context_t::key_exchanges` is set to NULL
kazuho Aug 4, 2020
db5af12
Never send a Retry if handshake using external PSK is possible.
kazuho Aug 4, 2020
4031113
remove "only"; client can offer (ec)dhe + external_psk. server can ac…
kazuho Aug 4, 2020
75f7dfa
Fix mistake during rebase
sshock Jul 18, 2023
d0451d3
Fix mistake during rebase
sshock Jul 18, 2023
92d9832
Add a todo comment about renaming
sshock Jul 25, 2023
fba3d96
Use correct binder key label on client
sshock Jul 25, 2023
b6b3c04
Default to SHA-256 with external PSK
sshock Jul 25, 2023
b6e55b8
Make cipher suite to use with PSK configurable
sshock Jul 26, 2023
9912af6
Use correct binder key label on server
sshock Jul 26, 2023
7782e0a
Fix bug where server was sending early data indicator
sshock Jul 26, 2023
ea44c61
Use PSK compatiable cipher suite on server
sshock Jul 26, 2023
415f5c4
Only accept early data if using the first PSK
sshock Jul 26, 2023
6e37a7e
Fix warning
sshock Jul 26, 2023
46cbf7a
Fix warning
sshock Jul 26, 2023
63c4724
Merge branch 'master' into tmp0045
kazuho Aug 3, 2023
291b329
identity should be part of `ptls_context_t`
kazuho Aug 5, 2023
a984308
ECH is orthogonal to PSK
kazuho Aug 5, 2023
38c37a0
rename
kazuho Aug 5, 2023
4022142
let psk be a composition of identity and secret (rather than key)
kazuho Aug 5, 2023
35f648a
[cli] -p option to specify PSK identity
kazuho Aug 5, 2023
bf31de4
send session ticket only when ECDHE is used
kazuho Aug 7, 2023
cba2448
restore guard
kazuho Aug 7, 2023
374fe53
retain the pointer to hash algorithm in psk object
kazuho Aug 7, 2023
65e77c9
adjust now that slot for `psk` has been added
kazuho Aug 7, 2023
ff788d7
clients can send KeyShare extension, we are not accepting them
kazuho Aug 7, 2023
fc41e2f
remove function no longer used (amends 374fe53)
kazuho Aug 7, 2023
fce9b09
revert unneccesary change
kazuho Aug 7, 2023
dd99f6f
no need to cache the value
kazuho Aug 7, 2023
63ba5e4
external PSK to be used only when not resuming
kazuho Aug 7, 2023
0670986
amends 65e77c9
kazuho Aug 8, 2023
e3e11fc
external PSK can be obtained via `tls->ctx`
kazuho Aug 8, 2023
135a2c8
clang-format
kazuho Aug 8, 2023
b331c21
`ptls_hash_algorithm_t` is const
kazuho Aug 8, 2023
eb696e1
msvc doesn't like `= {}`
kazuho Aug 8, 2023
8c2f340
Merge branch 'master' into kazuho/psk2
kazuho Aug 16, 2023
2a21e18
Merge branch 'master' into kazuho/psk2
kazuho Sep 29, 2023
1a1ecc8
if the client offered PSK but the server did not use it, call it a ha…
kazuho Oct 17, 2023
3aed2ae
ditto on server side
kazuho Oct 17, 2023
651a060
[on_client_hello_cb] pass list of PSK identities offerred by client, …
kazuho Oct 17, 2023
e220cda
external PSK mode is orthogonal to X.509 client auth
kazuho Oct 19, 2023
d4987ca
Merge branch 'master' into kazuho/psk2
kazuho Nov 14, 2023
90f1ab9
Merge branch 'master' into kazuho/psk2
kazuho Apr 1, 2024
48ffce5
follow the changes made to other backend tests
kazuho Apr 1, 2024
c7a825a
simplify, reducing diff from master
kazuho Apr 1, 2024
859ba9d
update picotest
kazuho Apr 1, 2024
12b2453
refactor
kazuho Apr 1, 2024
ddb2121
test various forms of psk handshakes (incl. retry)
kazuho Apr 2, 2024
a522cd9
[cli] add -P option for setting the PSK hash
kazuho Apr 2, 2024
de44a18
PSK+HRR works on the client side
kazuho Apr 2, 2024
5655ee1
[cli] add option to enforce PSK handshake rather than PSK-DHE
kazuho Apr 2, 2024
dfaa338
fix compile error when PTLS_DEBUG is set
kazuho Apr 2, 2024
9547f80
[psk] when HRR is involved at the server side, supply PSK to the key …
kazuho Apr 2, 2024
694dd69
more logging
kazuho Apr 2, 2024
a8e1af5
when HRR is involved, make sure called HKDF-Extract(PSK) only once pe…
kazuho Apr 5, 2024
436e433
fix test
kazuho Apr 5, 2024
388b26e
for readability, use one struct and initialize the variables consiste…
kazuho Apr 5, 2024
1fb276f
consistently refer to `ctx->ctx->psk`
kazuho Apr 5, 2024
96826a4
refine comments
kazuho Apr 5, 2024
3d9b469
[cli] update help following the changes
kazuho Apr 5, 2024
5643819
refine comment
kazuho Apr 6, 2024
9eb094c
omit typename as it is unused
kazuho Apr 6, 2024
71d4dfb
check consistency of `ptls_context_t` upon instantiation
kazuho Apr 8, 2024
2af3d24
more tests
kazuho Apr 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/picotest
Submodule picotest updated 2 files
+29 −23 picotest.c
+24 −3 picotest.h
23 changes: 23 additions & 0 deletions include/picotls.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ extern "C" {
#define PTLS_ALERT_MISSING_EXTENSION 109
#define PTLS_ALERT_UNSUPPORTED_EXTENSION 110
#define PTLS_ALERT_UNRECOGNIZED_NAME 112
#define PTLS_ALERT_UNKNOWN_PSK_IDENTITY 115
#define PTLS_ALERT_CERTIFICATE_REQUIRED 116
#define PTLS_ALERT_NO_APPLICATION_PROTOCOL 120
#define PTLS_ALERT_ECH_REQUIRED 121
Expand Down Expand Up @@ -671,6 +672,12 @@ typedef const struct st_ptls_hpke_cipher_suite_t {
ret (*cb)(struct st_ptls_##name##_t * self, __VA_ARGS__); \
} ptls_##name##_t

typedef struct st_ptls_client_hello_psk_identity_t {
ptls_iovec_t identity;
uint32_t obfuscated_ticket_age;
ptls_iovec_t binder;
} ptls_client_hello_psk_identity_t;

/**
* arguments passsed to the on_client_hello callback
*/
Expand Down Expand Up @@ -706,6 +713,10 @@ typedef struct st_ptls_on_client_hello_parameters_t {
const uint8_t *list;
size_t count;
} server_certificate_types;
struct {
const ptls_client_hello_psk_identity_t *list;
size_t count;
} psk_identities;
/**
* set to 1 if ClientHello is too old (or too new) to be handled by picotls
*/
Expand Down Expand Up @@ -849,6 +860,18 @@ struct st_ptls_context_t {
ptls_iovec_t *list;
size_t count;
} certificates;
/**
* External pre-shared key used for mutual authentication. Unless when using PSK, all the fields must be set to NULL / 0.
*/
struct {
ptls_iovec_t identity;
ptls_iovec_t secret;
/**
* (mandatory) hash algorithm associated to the PSK; cipher-suites not sharing the same `ptls_hash_algorithm_t` will be
* ignored
*/
ptls_hash_algorithm_t *hash;
} pre_shared_key;
/**
* ECH
*/
Expand Down
292 changes: 198 additions & 94 deletions lib/picotls.c

Large diffs are not rendered by default.

78 changes: 53 additions & 25 deletions t/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,9 @@ static void usage(const char *cmd)
" -K key-file ECH private key for each ECH config provided by -E\n"
" -l log-file file to log events (incl. traffic secrets)\n"
" -n negotiates the key exchange method (i.e. wait for HRR)\n"
" -N named-group named group to be used (default: secp256r1)\n"
" -N named-group named group to be used (default: secp256r1); if \"null\"\n"
" is specified alongside `-p`, external PSK handshake with\n"
" no ECDHE is performed\n"
" -s session-file file to read/write the session ticket\n"
" -S require public key exchange when resuming a session\n"
" -E echconfiglist file that contains ECHConfigList or an empty file to\n"
Expand All @@ -383,6 +385,9 @@ static void usage(const char *cmd)
" client, the argument specifies the public keys that the\n"
" server is expected to use. When running as a server, the\n"
" argument is ignored.\n"
" -p psk-identity name of the PSK key; if set, -c and -C specify the\n"
" pre-shared secret\n"
" -P psk-hash hash function associated to the PSK (default: sha256)\n"
" -u update the traffic key when handshake is complete\n"
" -v verify peer using the default certificates\n"
" -V CA-root-file verify peer using the CA Root File\n"
Expand Down Expand Up @@ -444,14 +449,14 @@ int main(int argc, char **argv)
.ech = {.client = {ptls_openssl_hpke_cipher_suites, ptls_openssl_hpke_kems}, .server = {NULL /* activated by -K option */}},
};
ptls_handshake_properties_t hsprop = {{{{NULL}}}};
const char *host, *port, *input_file = NULL;
const char *host, *port, *input_file = NULL, *psk_hash = "sha256";
int is_server = 0, use_early_data = 0, request_key_update = 0, keep_sender_open = 0, ch;
struct sockaddr_storage sa;
socklen_t salen;
int family = 0;
const char *raw_pub_key_file = NULL, *cert_location = NULL;

while ((ch = getopt(argc, argv, "46abBC:c:i:Ij:k:nN:es:Sr:E:K:l:y:vV:h")) != -1) {
while ((ch = getopt(argc, argv, "46abBC:c:i:Ij:k:nN:es:Sr:p:P:E:K:l:y:vV:h")) != -1) {
switch (ch) {
case '4':
family = AF_INET;
Expand Down Expand Up @@ -503,6 +508,12 @@ int main(int argc, char **argv)
case 'r':
raw_pub_key_file = optarg;
break;
case 'p':
ctx.pre_shared_key.identity = ptls_iovec_init(optarg, strlen(optarg));
break;
case 'P':
psk_hash = optarg;
break;
case 's':
setup_session_file(&ctx, &hsprop, optarg);
break;
Expand All @@ -524,31 +535,36 @@ int main(int argc, char **argv)
case 'V':
setup_verify_certificate(&ctx, optarg);
break;
case 'N': {
ptls_key_exchange_algorithm_t *algo = NULL;
case 'N':
if (strcasecmp(optarg, "null") == 0) {
/* disable use of key exchanges entirely */
ctx.key_exchanges = NULL;
} else {
ptls_key_exchange_algorithm_t *algo = NULL;
#define MATCH(name) \
if (algo == NULL && strcasecmp(optarg, #name) == 0) \
algo = (&ptls_openssl_##name)
MATCH(secp256r1);
MATCH(secp256r1);
#if PTLS_OPENSSL_HAVE_SECP384R1
MATCH(secp384r1);
MATCH(secp384r1);
#endif
#if PTLS_OPENSSL_HAVE_SECP521R1
MATCH(secp521r1);
MATCH(secp521r1);
#endif
#if PTLS_OPENSSL_HAVE_X25519
MATCH(x25519);
MATCH(x25519);
#endif
#undef MATCH
if (algo == NULL) {
fprintf(stderr, "could not find key exchange: %s\n", optarg);
return 1;
if (algo == NULL) {
fprintf(stderr, "could not find key exchange: %s\n", optarg);
return 1;
}
size_t i;
for (i = 0; key_exchanges[i] != NULL; ++i)
;
key_exchanges[i++] = algo;
}
size_t i;
for (i = 0; key_exchanges[i] != NULL; ++i)
;
key_exchanges[i++] = algo;
} break;
break;
case 'u':
request_key_update = 1;
break;
Expand Down Expand Up @@ -604,8 +620,14 @@ int main(int argc, char **argv)
EVP_PKEY_free(pubkey);
}
ctx.use_raw_public_keys = 1;
} else if (ctx.pre_shared_key.identity.base != NULL) {
if (cert_location == NULL) {
fprintf(stderr, "-p must be used with -C or -c\n");
return 1;
}
ctx.pre_shared_key.secret = load_file(cert_location);
} else {
if (cert_location)
if (cert_location != NULL)
load_certificate_chain(&ctx, cert_location);
}

Expand All @@ -615,12 +637,8 @@ int main(int argc, char **argv)
}

if (is_server) {
if (ctx.certificates.count == 0) {
fprintf(stderr, "-c and -k options must be set\n");
return 1;
}
#if PICOTLS_USE_BROTLI
if (ctx.decompress_certificate != NULL) {
if (ctx.certificates.count != 0 && ctx.decompress_certificate != NULL) {
static ptls_emit_compressed_certificate_t ecc;
if (ptls_init_compressed_certificate(&ecc, ctx.certificates.list, ctx.certificates.count, ptls_iovec_init(NULL, 0)) !=
0) {
Expand All @@ -644,10 +662,20 @@ int main(int argc, char **argv)
if (key_exchanges[0] == NULL)
key_exchanges[0] = &ptls_openssl_secp256r1;
if (cipher_suites[0] == NULL) {
size_t i;
for (i = 0; ptls_openssl_cipher_suites[i] != NULL; ++i)
for (size_t i = 0; ptls_openssl_cipher_suites[i] != NULL; ++i)
cipher_suites[i] = ptls_openssl_cipher_suites[i];
}
if (ctx.pre_shared_key.identity.base != NULL) {
size_t i;
for (i = 0; cipher_suites[i] != NULL; ++i)
if (strcmp(cipher_suites[i]->hash->name, psk_hash) == 0)
break;
if (cipher_suites[i] == NULL) {
fprintf(stderr, "no compatible cipher-suite for psk hash: %s\n", psk_hash);
exit(1);
}
ctx.pre_shared_key.hash = cipher_suites[i]->hash;
}
if (argc != 2) {
fprintf(stderr, "missing host and port\n");
return 1;
Expand Down
30 changes: 12 additions & 18 deletions t/mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,30 +112,24 @@ int main(int argc, char **argv)
ptls_minicrypto_secp256r1sha256_sign_certificate_t minicrypto_sign_certificate;
ptls_minicrypto_init_secp256r1sha256_sign_certificate(
&minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1));
ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes,
&ptls_get_time,
ptls_minicrypto_key_exchanges,
ptls_minicrypto_cipher_suites,
{&secp256r1_certificate, 1},
{{NULL}},
NULL,
NULL,
&minicrypto_sign_certificate.super};
ptls_context_t minicrypto_ctx = {.random_bytes = ptls_minicrypto_random_bytes,
.get_time = &ptls_get_time,
.key_exchanges = ptls_minicrypto_key_exchanges,
.cipher_suites = ptls_minicrypto_cipher_suites,
.certificates = {&secp256r1_certificate, 1},
.sign_certificate = &minicrypto_sign_certificate.super};

/* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the
* capability */
ptls_minicrypto_secp256r1sha256_sign_certificate_t mbedtls_sign_certificate;
ptls_minicrypto_init_secp256r1sha256_sign_certificate(
&mbedtls_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1));
ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes,
&ptls_get_time,
ptls_mbedtls_key_exchanges,
ptls_mbedtls_cipher_suites,
{&secp256r1_certificate, 1},
{{NULL}},
NULL,
NULL,
&mbedtls_sign_certificate.super};
ptls_context_t mbedtls_ctx = {.random_bytes = ptls_mbedtls_random_bytes,
.get_time = &ptls_get_time,
.key_exchanges = ptls_mbedtls_key_exchanges,
.cipher_suites = ptls_mbedtls_cipher_suites,
.certificates = {&secp256r1_certificate, 1},
.sign_certificate = &mbedtls_sign_certificate.super};

ctx = &mbedtls_ctx;
ctx_peer = &mbedtls_ctx;
Expand Down
15 changes: 6 additions & 9 deletions t/minicrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,12 @@ int main(int argc, char **argv)
ptls_minicrypto_init_secp256r1sha256_sign_certificate(&sign_certificate,
ptls_iovec_init(SECP256R1_PRIVATE_KEY, SECP256R1_PRIVATE_KEY_SIZE));

ptls_context_t ctxbuf = {ptls_minicrypto_random_bytes,
&ptls_get_time,
ptls_minicrypto_key_exchanges,
ptls_minicrypto_cipher_suites_all,
{&cert, 1},
{{NULL}},
NULL,
NULL,
&sign_certificate.super};
ptls_context_t ctxbuf = {.random_bytes = ptls_minicrypto_random_bytes,
.get_time = &ptls_get_time,
.key_exchanges = ptls_minicrypto_key_exchanges,
.cipher_suites = ptls_minicrypto_cipher_suites_all,
.certificates = {&cert, 1},
.sign_certificate = &sign_certificate.super};
ctx = ctx_peer = &ctxbuf;
ADD_FFX_AES128_ALGORITHMS(minicrypto);
ADD_FFX_CHACHA20_ALGORITHMS(minicrypto);
Expand Down
15 changes: 6 additions & 9 deletions t/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,12 @@ int main(int argc, char **argv)
ptls_iovec_t minicrypto_certificate = ptls_iovec_init(SECP256R1_CERTIFICATE, sizeof(SECP256R1_CERTIFICATE) - 1);
ptls_minicrypto_init_secp256r1sha256_sign_certificate(
&minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1));
ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes,
&ptls_get_time,
ptls_minicrypto_key_exchanges,
ptls_minicrypto_cipher_suites,
{&minicrypto_certificate, 1},
{{NULL}},
NULL,
NULL,
&minicrypto_sign_certificate.super};
ptls_context_t minicrypto_ctx = {.random_bytes = ptls_minicrypto_random_bytes,
.get_time = &ptls_get_time,
.key_exchanges = ptls_minicrypto_key_exchanges,
.cipher_suites = ptls_minicrypto_cipher_suites,
.certificates = {&minicrypto_certificate, 1},
.sign_certificate = &minicrypto_sign_certificate.super};
ctx = &openssl_ctx;
ctx_peer = &minicrypto_ctx;
subtest("vs. minicrypto", test_picotls);
Expand Down
Loading
Loading