diff options
author | Todd Short <tshort@akamai.com> | 2021-01-27 14:23:33 -0500 |
---|---|---|
committer | Todd Short <todd.short@me.com> | 2023-03-28 13:49:54 -0400 |
commit | 3c95ef22df55cb2d9dc64ce1f3be6e5a8ee63206 (patch) | |
tree | 0f7fcff4ec4735c778595db4f4a85bce70715d8b /apps | |
parent | 5ab3f71a33cb0140fc29ae9244cd4f8331c2f3a5 (diff) |
RFC7250 (RPK) support
Add support for the RFC7250 certificate-type extensions.
Alows the use of only private keys for connection (i.e. certs not needed).
Add APIs
Add unit tests
Add documentation
Add s_client/s_server support
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18185)
Diffstat (limited to 'apps')
-rw-r--r-- | apps/lib/s_cb.c | 34 | ||||
-rw-r--r-- | apps/s_client.c | 45 | ||||
-rw-r--r-- | apps/s_server.c | 43 |
3 files changed, 105 insertions, 17 deletions
diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index 04464bec03..dcfea55dc5 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -673,6 +673,8 @@ static STRINT_PAIR tlsext_types[] = { {"session ticket", TLSEXT_TYPE_session_ticket}, {"renegotiation info", TLSEXT_TYPE_renegotiate}, {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, + {"client cert type", TLSEXT_TYPE_client_cert_type}, + {"server cert type", TLSEXT_TYPE_server_cert_type}, {"TLS padding", TLSEXT_TYPE_padding}, #ifdef TLSEXT_TYPE_next_proto_neg {"next protocol", TLSEXT_TYPE_next_proto_neg}, @@ -1171,7 +1173,7 @@ static char *hexencode(const unsigned char *data, size_t len) void print_verify_detail(SSL *s, BIO *bio) { int mdpth; - EVP_PKEY *mspki; + EVP_PKEY *mspki = NULL; long verify_err = SSL_get_verify_result(s); if (verify_err == X509_V_OK) { @@ -1206,12 +1208,15 @@ void print_verify_detail(SSL *s, BIO *bio) hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); else hexdata = hexencode(data, dlen); - BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + BIO_printf(bio, "DANE TLSA %d %d %d %s%s ", usage, selector, mtype, - (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, - (mspki != NULL) ? "signed the certificate" : - mdpth ? "matched TA certificate" : "matched EE certificate", - mdpth); + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata); + if (SSL_get0_peer_rpk(s) == NULL) + BIO_printf(bio, "%s certificate at depth %d\n", + (mspki != NULL) ? "signed the peer" : + mdpth ? "matched the TA" : "matched the EE", mdpth); + else + BIO_printf(bio, "matched the peer raw public key\n"); OPENSSL_free(hexdata); } } @@ -1219,17 +1224,16 @@ void print_verify_detail(SSL *s, BIO *bio) void print_ssl_summary(SSL *s) { const SSL_CIPHER *c; - X509 *peer; + X509 *peer = SSL_get0_peer_certificate(s); + EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s); + int nid; BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); print_raw_cipherlist(s); c = SSL_get_current_cipher(s); BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); do_print_sigalgs(bio_err, s, 0); - peer = SSL_get0_peer_certificate(s); if (peer != NULL) { - int nid; - BIO_puts(bio_err, "Peer certificate: "); X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), 0, get_nameopt()); @@ -1239,8 +1243,13 @@ void print_ssl_summary(SSL *s) if (SSL_get_peer_signature_type_nid(s, &nid)) BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); print_verify_detail(s, bio_err); + } else if (peer_rpk != NULL) { + BIO_printf(bio_err, "Peer used raw public key\n"); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); + print_verify_detail(s, bio_err); } else { - BIO_puts(bio_err, "No peer certificate\n"); + BIO_puts(bio_err, "No peer certificate or raw public key\n"); } #ifndef OPENSSL_NO_EC ssl_print_point_formats(bio_err, s); @@ -1595,4 +1604,3 @@ int progress_cb(EVP_PKEY_CTX *ctx) (void)BIO_flush(b); return 1; } - diff --git a/apps/s_client.c b/apps/s_client.c index 9942893bd3..408be290f3 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2005 Nokia. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -75,6 +75,9 @@ static int ocsp_resp_cb(SSL *s, void *arg); static int ldap_ExtendedResponse_parse(const char *buf, long rem); static int is_dNS_name(const char *host); +static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 }; +static int enable_server_rpk = 0; + static int saved_errno; static void save_errno(void) @@ -468,6 +471,8 @@ typedef enum OPTION_choice { #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, OPT_ENABLE_PHA, + OPT_ENABLE_SERVER_RPK, + OPT_ENABLE_CLIENT_RPK, OPT_SCTP_LABEL_BUG, OPT_KTLS, OPT_R_ENUM, OPT_PROV_ENUM @@ -658,6 +663,8 @@ const OPTIONS s_client_options[] = { #endif {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"}, + {"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"}, + {"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"}, #ifndef OPENSSL_NO_SRTP {"use_srtp", OPT_USE_SRTP, 's', "Offer SRTP key management with a colon-separated profile list"}, @@ -896,6 +903,7 @@ int s_client_main(int argc, char **argv) #endif char *psksessf = NULL; int enable_pha = 0; + int enable_client_rpk = 0; #ifndef OPENSSL_NO_SCTP int sctp_label_bug = 0; #endif @@ -1489,6 +1497,12 @@ int s_client_main(int argc, char **argv) enable_ktls = 1; #endif break; + case OPT_ENABLE_SERVER_RPK: + enable_server_rpk = 1; + break; + case OPT_ENABLE_CLIENT_RPK: + enable_client_rpk = 1; + break; } } @@ -1980,6 +1994,18 @@ int s_client_main(int argc, char **argv) if (enable_pha) SSL_set_post_handshake_auth(con, 1); + if (enable_client_rpk) + if (!SSL_set1_client_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_err, "Error setting client certificate types\n"); + goto end; + } + if (enable_server_rpk) { + if (!SSL_set1_server_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_err, "Error setting server certificate types\n"); + goto end; + } + } + if (sess_in != NULL) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); @@ -3254,6 +3280,23 @@ static void print_stuff(BIO *bio, SSL *s, int full) } else { BIO_printf(bio, "no peer certificate available\n"); } + + /* Only display RPK information if configured */ + if (SSL_get_negotiated_client_cert_type(s) == TLSEXT_cert_type_rpk) + BIO_printf(bio, "Client-to-server raw public key negotiated\n"); + if (SSL_get_negotiated_server_cert_type(s) == TLSEXT_cert_type_rpk) + BIO_printf(bio, "Server-to-client raw public key negotiated\n"); + if (enable_server_rpk) { + EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s); + + if (peer_rpk != NULL) { + BIO_printf(bio, "Server raw public key\n"); + EVP_PKEY_print_public(bio, peer_rpk, 2, NULL); + } else { + BIO_printf(bio, "no peer rpk available\n"); + } + } + print_ca_names(bio, s); ssl_print_sigalgs(bio, s); diff --git a/apps/s_server.c b/apps/s_server.c index e822bcc090..7c18f9ad65 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -100,6 +100,9 @@ static int use_zc_sendfile = 0; static const char *session_id_prefix = NULL; +static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 }; +static int enable_client_rpk = 0; + #ifndef OPENSSL_NO_DTLS static int enable_timeouts = 0; static long socket_mtu; @@ -720,6 +723,8 @@ typedef enum OPTION_choice { OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_KTLS, OPT_USE_ZC_SENDFILE, OPT_TFO, OPT_CERT_COMP, + OPT_ENABLE_SERVER_RPK, + OPT_ENABLE_CLIENT_RPK, OPT_R_ENUM, OPT_S_ENUM, OPT_V_ENUM, @@ -971,7 +976,8 @@ const OPTIONS s_server_options[] = { {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"}, {"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"}, #endif - + {"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"}, + {"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"}, OPT_R_OPTIONS, OPT_S_OPTIONS, OPT_V_OPTIONS, @@ -1069,6 +1075,7 @@ int s_server_main(int argc, char *argv[]) #endif int tfo = 0; int cert_comp = 0; + int enable_server_rpk = 0; /* Init of few remaining global variables */ local_argc = argc; @@ -1675,6 +1682,12 @@ int s_server_main(int argc, char *argv[]) case OPT_CERT_COMP: cert_comp = 1; break; + case OPT_ENABLE_SERVER_RPK: + enable_server_rpk = 1; + break; + case OPT_ENABLE_CLIENT_RPK: + enable_client_rpk = 1; + break; } } @@ -2274,6 +2287,16 @@ int s_server_main(int argc, char *argv[]) if (ctx2 != NULL && !SSL_CTX_compress_certs(ctx2, 0)) BIO_printf(bio_s_out, "Error compressing certs on ctx2\n"); } + if (enable_server_rpk) + if (!SSL_CTX_set1_server_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_s_out, "Error setting server certificate types\n"); + goto end; + } + if (enable_client_rpk) + if (!SSL_CTX_set1_client_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_s_out, "Error setting server certificate types\n"); + goto end; + } if (rev) server_cb = rev_body; @@ -3025,6 +3048,19 @@ static void print_connection_info(SSL *con) dump_cert_text(bio_s_out, peer); peer = NULL; } + /* Only display RPK information if configured */ + if (SSL_get_negotiated_server_cert_type(con) == TLSEXT_cert_type_rpk) + BIO_printf(bio_s_out, "Server-to-client raw public key negotiated\n"); + if (SSL_get_negotiated_client_cert_type(con) == TLSEXT_cert_type_rpk) + BIO_printf(bio_s_out, "Client-to-server raw public key negotiated\n"); + if (enable_client_rpk) { + EVP_PKEY *client_rpk = SSL_get0_peer_rpk(con); + + if (client_rpk != NULL) { + BIO_printf(bio_s_out, "Client raw public key\n"); + EVP_PKEY_print_public(bio_s_out, client_rpk, 2, NULL); + } + } if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL) BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); @@ -3792,7 +3828,8 @@ static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) { const unsigned char *p = sess->der; BIO_printf(bio_err, "Lookup session: cache hit\n"); - return d2i_SSL_SESSION(NULL, &p, sess->derlen); + return d2i_SSL_SESSION_ex(NULL, &p, sess->derlen, app_get0_libctx(), + app_get0_propq()); } } BIO_printf(bio_err, "Lookup session: cache miss\n"); |