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)
This commit is contained in:
parent
5ab3f71a33
commit
3c95ef22df
@ -25,6 +25,14 @@ OpenSSL 3.2
|
|||||||
|
|
||||||
### Changes between 3.1 and 3.2 [xx XXX xxxx]
|
### Changes between 3.1 and 3.2 [xx XXX xxxx]
|
||||||
|
|
||||||
|
* Add Raw Public Key (RFC7250) support. Authentication is supported
|
||||||
|
by matching keys against either local policy (TLSA records synthesised
|
||||||
|
from the expected keys) or DANE (TLSA records obtained by the
|
||||||
|
application from DNS). TLSA records will also match the same key in
|
||||||
|
the server certificate, should RPK use not happen to be negotiated.
|
||||||
|
|
||||||
|
*Todd Short*
|
||||||
|
|
||||||
* Added EC_GROUP_to_params which creates an OSSL_PARAM array
|
* Added EC_GROUP_to_params which creates an OSSL_PARAM array
|
||||||
from a given EC_GROUP.
|
from a given EC_GROUP.
|
||||||
|
|
||||||
|
1
NEWS.md
1
NEWS.md
@ -22,6 +22,7 @@ OpenSSL 3.2
|
|||||||
|
|
||||||
### Major changes between OpenSSL 3.1 and OpenSSL 3.2 [under development]
|
### Major changes between OpenSSL 3.1 and OpenSSL 3.2 [under development]
|
||||||
|
|
||||||
|
* Add Raw Public Key (RFC7250) support.
|
||||||
* Added support for certificate compression (RFC8879), including
|
* Added support for certificate compression (RFC8879), including
|
||||||
library support for Brotli and Zstandard compression.
|
library support for Brotli and Zstandard compression.
|
||||||
* Subject or issuer names in X.509 objects are now displayed as UTF-8 strings
|
* Subject or issuer names in X.509 objects are now displayed as UTF-8 strings
|
||||||
|
@ -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
|
* 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
|
* 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},
|
{"session ticket", TLSEXT_TYPE_session_ticket},
|
||||||
{"renegotiation info", TLSEXT_TYPE_renegotiate},
|
{"renegotiation info", TLSEXT_TYPE_renegotiate},
|
||||||
{"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
|
{"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},
|
{"TLS padding", TLSEXT_TYPE_padding},
|
||||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||||
{"next protocol", 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)
|
void print_verify_detail(SSL *s, BIO *bio)
|
||||||
{
|
{
|
||||||
int mdpth;
|
int mdpth;
|
||||||
EVP_PKEY *mspki;
|
EVP_PKEY *mspki = NULL;
|
||||||
long verify_err = SSL_get_verify_result(s);
|
long verify_err = SSL_get_verify_result(s);
|
||||||
|
|
||||||
if (verify_err == X509_V_OK) {
|
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);
|
hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
|
||||||
else
|
else
|
||||||
hexdata = hexencode(data, dlen);
|
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,
|
usage, selector, mtype,
|
||||||
(dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
|
(dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata);
|
||||||
(mspki != NULL) ? "signed the certificate" :
|
if (SSL_get0_peer_rpk(s) == NULL)
|
||||||
mdpth ? "matched TA certificate" : "matched EE certificate",
|
BIO_printf(bio, "%s certificate at depth %d\n",
|
||||||
mdpth);
|
(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);
|
OPENSSL_free(hexdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1219,17 +1224,16 @@ void print_verify_detail(SSL *s, BIO *bio)
|
|||||||
void print_ssl_summary(SSL *s)
|
void print_ssl_summary(SSL *s)
|
||||||
{
|
{
|
||||||
const SSL_CIPHER *c;
|
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));
|
BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
|
||||||
print_raw_cipherlist(s);
|
print_raw_cipherlist(s);
|
||||||
c = SSL_get_current_cipher(s);
|
c = SSL_get_current_cipher(s);
|
||||||
BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
|
BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
|
||||||
do_print_sigalgs(bio_err, s, 0);
|
do_print_sigalgs(bio_err, s, 0);
|
||||||
peer = SSL_get0_peer_certificate(s);
|
|
||||||
if (peer != NULL) {
|
if (peer != NULL) {
|
||||||
int nid;
|
|
||||||
|
|
||||||
BIO_puts(bio_err, "Peer certificate: ");
|
BIO_puts(bio_err, "Peer certificate: ");
|
||||||
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
|
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
|
||||||
0, get_nameopt());
|
0, get_nameopt());
|
||||||
@ -1239,8 +1243,13 @@ void print_ssl_summary(SSL *s)
|
|||||||
if (SSL_get_peer_signature_type_nid(s, &nid))
|
if (SSL_get_peer_signature_type_nid(s, &nid))
|
||||||
BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
|
BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
|
||||||
print_verify_detail(s, bio_err);
|
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 {
|
} 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
|
#ifndef OPENSSL_NO_EC
|
||||||
ssl_print_point_formats(bio_err, s);
|
ssl_print_point_formats(bio_err, s);
|
||||||
@ -1595,4 +1604,3 @@ int progress_cb(EVP_PKEY_CTX *ctx)
|
|||||||
(void)BIO_flush(b);
|
(void)BIO_flush(b);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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 ldap_ExtendedResponse_parse(const char *buf, long rem);
|
||||||
static int is_dNS_name(const char *host);
|
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 int saved_errno;
|
||||||
|
|
||||||
static void save_errno(void)
|
static void save_errno(void)
|
||||||
@ -468,6 +471,8 @@ typedef enum OPTION_choice {
|
|||||||
#endif
|
#endif
|
||||||
OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
|
OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
|
||||||
OPT_ENABLE_PHA,
|
OPT_ENABLE_PHA,
|
||||||
|
OPT_ENABLE_SERVER_RPK,
|
||||||
|
OPT_ENABLE_CLIENT_RPK,
|
||||||
OPT_SCTP_LABEL_BUG,
|
OPT_SCTP_LABEL_BUG,
|
||||||
OPT_KTLS,
|
OPT_KTLS,
|
||||||
OPT_R_ENUM, OPT_PROV_ENUM
|
OPT_R_ENUM, OPT_PROV_ENUM
|
||||||
@ -658,6 +663,8 @@ const OPTIONS s_client_options[] = {
|
|||||||
#endif
|
#endif
|
||||||
{"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
|
{"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
|
||||||
{"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
|
{"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
|
#ifndef OPENSSL_NO_SRTP
|
||||||
{"use_srtp", OPT_USE_SRTP, 's',
|
{"use_srtp", OPT_USE_SRTP, 's',
|
||||||
"Offer SRTP key management with a colon-separated profile list"},
|
"Offer SRTP key management with a colon-separated profile list"},
|
||||||
@ -896,6 +903,7 @@ int s_client_main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
char *psksessf = NULL;
|
char *psksessf = NULL;
|
||||||
int enable_pha = 0;
|
int enable_pha = 0;
|
||||||
|
int enable_client_rpk = 0;
|
||||||
#ifndef OPENSSL_NO_SCTP
|
#ifndef OPENSSL_NO_SCTP
|
||||||
int sctp_label_bug = 0;
|
int sctp_label_bug = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1489,6 +1497,12 @@ int s_client_main(int argc, char **argv)
|
|||||||
enable_ktls = 1;
|
enable_ktls = 1;
|
||||||
#endif
|
#endif
|
||||||
break;
|
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)
|
if (enable_pha)
|
||||||
SSL_set_post_handshake_auth(con, 1);
|
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) {
|
if (sess_in != NULL) {
|
||||||
SSL_SESSION *sess;
|
SSL_SESSION *sess;
|
||||||
BIO *stmp = BIO_new_file(sess_in, "r");
|
BIO *stmp = BIO_new_file(sess_in, "r");
|
||||||
@ -3254,6 +3280,23 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
|||||||
} else {
|
} else {
|
||||||
BIO_printf(bio, "no peer certificate available\n");
|
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);
|
print_ca_names(bio, s);
|
||||||
|
|
||||||
ssl_print_sigalgs(bio, s);
|
ssl_print_sigalgs(bio, s);
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. 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 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
|
#ifndef OPENSSL_NO_DTLS
|
||||||
static int enable_timeouts = 0;
|
static int enable_timeouts = 0;
|
||||||
static long socket_mtu;
|
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_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_KTLS,
|
||||||
OPT_USE_ZC_SENDFILE,
|
OPT_USE_ZC_SENDFILE,
|
||||||
OPT_TFO, OPT_CERT_COMP,
|
OPT_TFO, OPT_CERT_COMP,
|
||||||
|
OPT_ENABLE_SERVER_RPK,
|
||||||
|
OPT_ENABLE_CLIENT_RPK,
|
||||||
OPT_R_ENUM,
|
OPT_R_ENUM,
|
||||||
OPT_S_ENUM,
|
OPT_S_ENUM,
|
||||||
OPT_V_ENUM,
|
OPT_V_ENUM,
|
||||||
@ -971,7 +976,8 @@ const OPTIONS s_server_options[] = {
|
|||||||
{"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
|
{"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
|
||||||
{"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"},
|
{"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"},
|
||||||
#endif
|
#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_R_OPTIONS,
|
||||||
OPT_S_OPTIONS,
|
OPT_S_OPTIONS,
|
||||||
OPT_V_OPTIONS,
|
OPT_V_OPTIONS,
|
||||||
@ -1069,6 +1075,7 @@ int s_server_main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
int tfo = 0;
|
int tfo = 0;
|
||||||
int cert_comp = 0;
|
int cert_comp = 0;
|
||||||
|
int enable_server_rpk = 0;
|
||||||
|
|
||||||
/* Init of few remaining global variables */
|
/* Init of few remaining global variables */
|
||||||
local_argc = argc;
|
local_argc = argc;
|
||||||
@ -1675,6 +1682,12 @@ int s_server_main(int argc, char *argv[])
|
|||||||
case OPT_CERT_COMP:
|
case OPT_CERT_COMP:
|
||||||
cert_comp = 1;
|
cert_comp = 1;
|
||||||
break;
|
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))
|
if (ctx2 != NULL && !SSL_CTX_compress_certs(ctx2, 0))
|
||||||
BIO_printf(bio_s_out, "Error compressing certs on ctx2\n");
|
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)
|
if (rev)
|
||||||
server_cb = rev_body;
|
server_cb = rev_body;
|
||||||
@ -3025,6 +3048,19 @@ static void print_connection_info(SSL *con)
|
|||||||
dump_cert_text(bio_s_out, peer);
|
dump_cert_text(bio_s_out, peer);
|
||||||
peer = NULL;
|
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)
|
if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL)
|
||||||
BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
|
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)) {
|
if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
|
||||||
const unsigned char *p = sess->der;
|
const unsigned char *p = sess->der;
|
||||||
BIO_printf(bio_err, "Lookup session: cache hit\n");
|
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");
|
BIO_printf(bio_err, "Lookup session: cache miss\n");
|
||||||
|
@ -1280,6 +1280,7 @@ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
|
|||||||
attempt to reuse session in different context
|
attempt to reuse session in different context
|
||||||
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
|
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
|
||||||
at least (D)TLS 1.2 needed in Suite B mode
|
at least (D)TLS 1.2 needed in Suite B mode
|
||||||
|
SSL_R_BAD_CERTIFICATE:348:bad certificate
|
||||||
SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec
|
SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec
|
||||||
SSL_R_BAD_CIPHER:186:bad cipher
|
SSL_R_BAD_CIPHER:186:bad cipher
|
||||||
SSL_R_BAD_COMPRESSION_ALGORITHM:326:bad compression algorithm
|
SSL_R_BAD_COMPRESSION_ALGORITHM:326:bad compression algorithm
|
||||||
@ -1369,6 +1370,7 @@ SSL_R_DUPLICATE_COMPRESSION_ID:309:duplicate compression id
|
|||||||
SSL_R_ECC_CERT_NOT_FOR_SIGNING:318:ecc cert not for signing
|
SSL_R_ECC_CERT_NOT_FOR_SIGNING:318:ecc cert not for signing
|
||||||
SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode
|
SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode
|
||||||
SSL_R_EE_KEY_TOO_SMALL:399:ee key too small
|
SSL_R_EE_KEY_TOO_SMALL:399:ee key too small
|
||||||
|
SSL_R_EMPTY_RAW_PUBLIC_KEY:349:empty raw public key
|
||||||
SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST:354:empty srtp protection profile list
|
SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST:354:empty srtp protection profile list
|
||||||
SSL_R_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long
|
SSL_R_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long
|
||||||
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:151:error in received cipher list
|
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:151:error in received cipher list
|
||||||
@ -1404,6 +1406,7 @@ SSL_R_INVALID_CT_VALIDATION_TYPE:212:invalid ct validation type
|
|||||||
SSL_R_INVALID_KEY_UPDATE_TYPE:120:invalid key update type
|
SSL_R_INVALID_KEY_UPDATE_TYPE:120:invalid key update type
|
||||||
SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data
|
SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data
|
||||||
SSL_R_INVALID_NULL_CMD_NAME:385:invalid null cmd name
|
SSL_R_INVALID_NULL_CMD_NAME:385:invalid null cmd name
|
||||||
|
SSL_R_INVALID_RAW_PUBLIC_KEY:350:invalid raw public key
|
||||||
SSL_R_INVALID_RECORD:317:invalid record
|
SSL_R_INVALID_RECORD:317:invalid record
|
||||||
SSL_R_INVALID_SEQUENCE_NUMBER:402:invalid sequence number
|
SSL_R_INVALID_SEQUENCE_NUMBER:402:invalid sequence number
|
||||||
SSL_R_INVALID_SERVERINFO_DATA:388:invalid serverinfo data
|
SSL_R_INVALID_SERVERINFO_DATA:388:invalid serverinfo data
|
||||||
@ -1612,6 +1615,7 @@ SSL_R_VERSION_TOO_LOW:396:version too low
|
|||||||
SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type
|
SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type
|
||||||
SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned
|
SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned
|
||||||
SSL_R_WRONG_CURVE:378:wrong curve
|
SSL_R_WRONG_CURVE:378:wrong curve
|
||||||
|
SSL_R_WRONG_RPK_TYPE:351:wrong rpk type
|
||||||
SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length
|
SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length
|
||||||
SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size
|
SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size
|
||||||
SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type
|
SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1995-2020 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
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -212,6 +212,8 @@ const char *X509_verify_cert_error_string(long n)
|
|||||||
return "Using cert extension requires at least X509v3";
|
return "Using cert extension requires at least X509v3";
|
||||||
case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS:
|
case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS:
|
||||||
return "Certificate public key has explicit ECC parameters";
|
return "Certificate public key has explicit ECC parameters";
|
||||||
|
case X509_V_ERR_RPK_UNTRUSTED:
|
||||||
|
return "Raw public key untrusted, no trusted keys configured";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entries must be kept consistent with include/openssl/x509_vfy.h.in
|
* Entries must be kept consistent with include/openssl/x509_vfy.h.in
|
||||||
|
@ -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
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -41,9 +41,13 @@
|
|||||||
#define CRL_SCORE_AKID 0x004 /* CRL issuer matches CRL AKID */
|
#define CRL_SCORE_AKID 0x004 /* CRL issuer matches CRL AKID */
|
||||||
#define CRL_SCORE_TIME_DELTA 0x002 /* Have a delta CRL with valid times */
|
#define CRL_SCORE_TIME_DELTA 0x002 /* Have a delta CRL with valid times */
|
||||||
|
|
||||||
|
static int x509_verify_x509(X509_STORE_CTX *ctx);
|
||||||
|
static int x509_verify_rpk(X509_STORE_CTX *ctx);
|
||||||
static int build_chain(X509_STORE_CTX *ctx);
|
static int build_chain(X509_STORE_CTX *ctx);
|
||||||
static int verify_chain(X509_STORE_CTX *ctx);
|
static int verify_chain(X509_STORE_CTX *ctx);
|
||||||
|
static int verify_rpk(X509_STORE_CTX *ctx);
|
||||||
static int dane_verify(X509_STORE_CTX *ctx);
|
static int dane_verify(X509_STORE_CTX *ctx);
|
||||||
|
static int dane_verify_rpk(X509_STORE_CTX *ctx);
|
||||||
static int null_callback(int ok, X509_STORE_CTX *e);
|
static int null_callback(int ok, X509_STORE_CTX *e);
|
||||||
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
|
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
|
||||||
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
|
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
|
||||||
@ -56,7 +60,8 @@ static int check_cert(X509_STORE_CTX *ctx);
|
|||||||
static int check_policy(X509_STORE_CTX *ctx);
|
static int check_policy(X509_STORE_CTX *ctx);
|
||||||
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
|
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
|
||||||
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
|
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
|
||||||
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert);
|
static int check_cert_key_level(X509_STORE_CTX *ctx, X509 *cert);
|
||||||
|
static int check_key_level(X509_STORE_CTX *ctx, EVP_PKEY *pkey);
|
||||||
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert);
|
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert);
|
||||||
static int check_curve(X509 *cert);
|
static int check_curve(X509 *cert);
|
||||||
|
|
||||||
@ -197,7 +202,7 @@ static int check_auth_level(X509_STORE_CTX *ctx)
|
|||||||
* We've already checked the security of the leaf key, so here we only
|
* We've already checked the security of the leaf key, so here we only
|
||||||
* check the security of issuer keys.
|
* check the security of issuer keys.
|
||||||
*/
|
*/
|
||||||
CB_FAIL_IF(i > 0 && !check_key_level(ctx, cert),
|
CB_FAIL_IF(i > 0 && !check_cert_key_level(ctx, cert),
|
||||||
ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL);
|
ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL);
|
||||||
/*
|
/*
|
||||||
* We also check the signature algorithm security of all certificates
|
* We also check the signature algorithm security of all certificates
|
||||||
@ -209,6 +214,20 @@ static int check_auth_level(X509_STORE_CTX *ctx)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Returns -1 on internal error.
|
||||||
|
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
||||||
|
*/
|
||||||
|
static int verify_rpk(X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
/* Not much to verify on a RPK */
|
||||||
|
if (ctx->verify != NULL)
|
||||||
|
return ctx->verify(ctx);
|
||||||
|
|
||||||
|
return !!ctx->verify_cb(ctx->error == X509_V_OK, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Returns -1 on internal error.
|
* Returns -1 on internal error.
|
||||||
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
||||||
@ -258,23 +277,58 @@ int X509_STORE_CTX_verify(X509_STORE_CTX *ctx)
|
|||||||
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
|
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (ctx->rpk != NULL)
|
||||||
|
return x509_verify_rpk(ctx);
|
||||||
if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1)
|
if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1)
|
||||||
ctx->cert = sk_X509_value(ctx->untrusted, 0);
|
ctx->cert = sk_X509_value(ctx->untrusted, 0);
|
||||||
return X509_verify_cert(ctx);
|
return x509_verify_x509(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (ctx == NULL) {
|
||||||
|
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (ctx->rpk != NULL) ? x509_verify_rpk(ctx) : x509_verify_x509(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Returns -1 on internal error.
|
* Returns -1 on internal error.
|
||||||
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
||||||
*/
|
*/
|
||||||
int X509_verify_cert(X509_STORE_CTX *ctx)
|
static int x509_verify_rpk(X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* If the peer's public key is too weak, we can stop early. */
|
||||||
|
if (!check_key_level(ctx, ctx->rpk)
|
||||||
|
&& verify_cb_cert(ctx, NULL, 0, X509_V_ERR_EE_KEY_TOO_SMALL) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Barring any data to verify the RPK, simply report it as untrusted */
|
||||||
|
ctx->error = X509_V_ERR_RPK_UNTRUSTED;
|
||||||
|
|
||||||
|
ret = DANETLS_ENABLED(ctx->dane) ? dane_verify_rpk(ctx) : verify_rpk(ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safety-net. If we are returning an error, we must also set ctx->error,
|
||||||
|
* so that the chain is not considered verified should the error be ignored
|
||||||
|
* (e.g. TLS with SSL_VERIFY_NONE).
|
||||||
|
*/
|
||||||
|
if (ret <= 0 && ctx->error == X509_V_OK)
|
||||||
|
ctx->error = X509_V_ERR_UNSPECIFIED;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Returns -1 on internal error.
|
||||||
|
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
||||||
|
*/
|
||||||
|
static int x509_verify_x509(X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ctx == NULL) {
|
|
||||||
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ctx->cert == NULL) {
|
if (ctx->cert == NULL) {
|
||||||
ERR_raise(ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
|
ERR_raise(ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
|
||||||
ctx->error = X509_V_ERR_INVALID_CALL;
|
ctx->error = X509_V_ERR_INVALID_CALL;
|
||||||
@ -298,7 +352,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
|||||||
ctx->num_untrusted = 1;
|
ctx->num_untrusted = 1;
|
||||||
|
|
||||||
/* If the peer's public key is too weak, we can stop early. */
|
/* If the peer's public key is too weak, we can stop early. */
|
||||||
CB_FAIL_IF(!check_key_level(ctx, ctx->cert),
|
CB_FAIL_IF(!check_cert_key_level(ctx, ctx->cert),
|
||||||
ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL);
|
ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL);
|
||||||
|
|
||||||
ret = DANETLS_ENABLED(ctx->dane) ? dane_verify(ctx) : verify_chain(ctx);
|
ret = DANETLS_ENABLED(ctx->dane) ? dane_verify(ctx) : verify_chain(ctx);
|
||||||
@ -1758,9 +1812,19 @@ int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
|
|||||||
*/
|
*/
|
||||||
static int internal_verify(X509_STORE_CTX *ctx)
|
static int internal_verify(X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
int n = sk_X509_num(ctx->chain) - 1;
|
int n;
|
||||||
X509 *xi = sk_X509_value(ctx->chain, n);
|
X509 *xi;
|
||||||
X509 *xs = xi;
|
X509 *xs;
|
||||||
|
|
||||||
|
/* For RPK: just do the verify callback */
|
||||||
|
if (ctx->rpk != NULL) {
|
||||||
|
if (!ctx->verify_cb(ctx->error == X509_V_OK, ctx))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
n = sk_X509_num(ctx->chain) - 1;
|
||||||
|
xi = sk_X509_value(ctx->chain, n);
|
||||||
|
xs = xi;
|
||||||
|
|
||||||
ctx->error_depth = n;
|
ctx->error_depth = n;
|
||||||
if (ctx->bare_ta_signed) {
|
if (ctx->bare_ta_signed) {
|
||||||
@ -2227,6 +2291,11 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
|
|||||||
ctx->cert = x;
|
ctx->cert = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *rpk)
|
||||||
|
{
|
||||||
|
ctx->rpk = rpk;
|
||||||
|
}
|
||||||
|
|
||||||
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
|
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
|
||||||
{
|
{
|
||||||
ctx->crls = sk;
|
ctx->crls = sk;
|
||||||
@ -2348,6 +2417,15 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
|
|||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *store, EVP_PKEY *rpk)
|
||||||
|
{
|
||||||
|
if (!X509_STORE_CTX_init(ctx, store, NULL, NULL))
|
||||||
|
return 0;
|
||||||
|
ctx->rpk = rpk;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||||
STACK_OF(X509) *chain)
|
STACK_OF(X509) *chain)
|
||||||
{
|
{
|
||||||
@ -2377,6 +2455,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
|||||||
ctx->parent = NULL;
|
ctx->parent = NULL;
|
||||||
ctx->dane = NULL;
|
ctx->dane = NULL;
|
||||||
ctx->bare_ta_signed = 0;
|
ctx->bare_ta_signed = 0;
|
||||||
|
ctx->rpk = NULL;
|
||||||
/* Zero ex_data to make sure we're cleanup-safe */
|
/* Zero ex_data to make sure we're cleanup-safe */
|
||||||
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
|
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
|
||||||
|
|
||||||
@ -2540,6 +2619,11 @@ X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx)
|
|||||||
return ctx->cert;
|
return ctx->cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *X509_STORE_CTX_get0_rpk(const X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
return ctx->rpk;
|
||||||
|
}
|
||||||
|
|
||||||
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx)
|
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
return ctx->untrusted;
|
return ctx->untrusted;
|
||||||
@ -2712,7 +2796,7 @@ static unsigned char *dane_i2d(X509 *cert, uint8_t selector,
|
|||||||
#define DANETLS_NONE 256 /* impossible uint8_t */
|
#define DANETLS_NONE 256 /* impossible uint8_t */
|
||||||
|
|
||||||
/* Returns -1 on internal error */
|
/* Returns -1 on internal error */
|
||||||
static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
|
static int dane_match_cert(X509_STORE_CTX *ctx, X509 *cert, int depth)
|
||||||
{
|
{
|
||||||
SSL_DANE *dane = ctx->dane;
|
SSL_DANE *dane = ctx->dane;
|
||||||
unsigned usage = DANETLS_NONE;
|
unsigned usage = DANETLS_NONE;
|
||||||
@ -2870,7 +2954,7 @@ static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
|
|||||||
* for an exact match for the leaf certificate).
|
* for an exact match for the leaf certificate).
|
||||||
*/
|
*/
|
||||||
cert = sk_X509_value(ctx->chain, depth);
|
cert = sk_X509_value(ctx->chain, depth);
|
||||||
if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0)
|
if (cert != NULL && (matched = dane_match_cert(ctx, cert, depth)) < 0)
|
||||||
return matched;
|
return matched;
|
||||||
if (matched > 0) {
|
if (matched > 0) {
|
||||||
ctx->num_untrusted = depth - 1;
|
ctx->num_untrusted = depth - 1;
|
||||||
@ -2917,6 +3001,62 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
|
|||||||
return X509_TRUST_UNTRUSTED;
|
return X509_TRUST_UNTRUSTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only DANE-EE and SPKI are supported
|
||||||
|
* Returns -1 on internal error
|
||||||
|
*/
|
||||||
|
static int dane_match_rpk(X509_STORE_CTX *ctx, EVP_PKEY *rpk)
|
||||||
|
{
|
||||||
|
SSL_DANE *dane = ctx->dane;
|
||||||
|
danetls_record *t = NULL;
|
||||||
|
int mtype = DANETLS_MATCHING_FULL;
|
||||||
|
unsigned char *i2dbuf = NULL;
|
||||||
|
unsigned int i2dlen = 0;
|
||||||
|
unsigned char mdbuf[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned char *cmpbuf;
|
||||||
|
unsigned int cmplen = 0;
|
||||||
|
int len;
|
||||||
|
int recnum = sk_danetls_record_num(dane->trecs);
|
||||||
|
int i;
|
||||||
|
int matched = 0;
|
||||||
|
|
||||||
|
/* Calculate ASN.1 DER of RPK */
|
||||||
|
if ((len = i2d_PUBKEY(rpk, &i2dbuf)) <= 0)
|
||||||
|
return -1;
|
||||||
|
cmplen = i2dlen = (unsigned int)len;
|
||||||
|
cmpbuf = i2dbuf;
|
||||||
|
|
||||||
|
for (i = 0; i < recnum; i++) {
|
||||||
|
t = sk_danetls_record_value(dane->trecs, i);
|
||||||
|
if (t->usage != DANETLS_USAGE_DANE_EE || t->selector != DANETLS_SELECTOR_SPKI)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Calculate hash - keep only one around */
|
||||||
|
if (t->mtype != mtype) {
|
||||||
|
const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype];
|
||||||
|
|
||||||
|
cmpbuf = i2dbuf;
|
||||||
|
cmplen = i2dlen;
|
||||||
|
|
||||||
|
if (md != NULL) {
|
||||||
|
cmpbuf = mdbuf;
|
||||||
|
if (!EVP_Digest(i2dbuf, i2dlen, cmpbuf, &cmplen, md, 0)) {
|
||||||
|
matched = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cmplen == t->dlen && memcmp(cmpbuf, t->data, cmplen) == 0) {
|
||||||
|
matched = 1;
|
||||||
|
dane->mdpth = 0;
|
||||||
|
dane->mtlsa = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OPENSSL_free(i2dbuf);
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
static void dane_reset(SSL_DANE *dane)
|
static void dane_reset(SSL_DANE *dane)
|
||||||
{
|
{
|
||||||
/* Reset state to verify another chain, or clear after failure. */
|
/* Reset state to verify another chain, or clear after failure. */
|
||||||
@ -2936,6 +3076,36 @@ static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns -1 on internal error */
|
||||||
|
static int dane_verify_rpk(X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
SSL_DANE *dane = ctx->dane;
|
||||||
|
int matched;
|
||||||
|
|
||||||
|
dane_reset(dane);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for a DANE record for RPK
|
||||||
|
* If error, return -1
|
||||||
|
* If found, call ctx->verify_cb(1, ctx)
|
||||||
|
* If not found call ctx->verify_cb(0, ctx)
|
||||||
|
*/
|
||||||
|
matched = dane_match_rpk(ctx, ctx->rpk);
|
||||||
|
ctx->error_depth = 0;
|
||||||
|
|
||||||
|
if (matched < 0) {
|
||||||
|
ctx->error = X509_V_ERR_UNSPECIFIED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched > 0)
|
||||||
|
ctx->error = X509_V_OK;
|
||||||
|
else
|
||||||
|
ctx->error = X509_V_ERR_DANE_NO_MATCH;
|
||||||
|
|
||||||
|
return verify_rpk(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns -1 on internal error */
|
/* Returns -1 on internal error */
|
||||||
static int dane_verify(X509_STORE_CTX *ctx)
|
static int dane_verify(X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
@ -2958,7 +3128,7 @@ static int dane_verify(X509_STORE_CTX *ctx)
|
|||||||
* + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no
|
* + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no
|
||||||
* DANE-TA(2) or PKIX-TA(0) to test.
|
* DANE-TA(2) or PKIX-TA(0) to test.
|
||||||
*/
|
*/
|
||||||
matched = dane_match(ctx, ctx->cert, 0);
|
matched = dane_match_cert(ctx, ctx->cert, 0);
|
||||||
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
|
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
|
||||||
|
|
||||||
if (done && !X509_get_pubkey_parameters(NULL, ctx->chain))
|
if (done && !X509_get_pubkey_parameters(NULL, ctx->chain))
|
||||||
@ -3416,12 +3586,11 @@ static const int minbits_table[] = { 80, 112, 128, 192, 256 };
|
|||||||
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
|
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Check whether the public key of `cert` meets the security level of `ctx`.
|
* Check whether the given public key meets the security level of `ctx`.
|
||||||
* Returns 1 on success, 0 otherwise.
|
* Returns 1 on success, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
|
static int check_key_level(X509_STORE_CTX *ctx, EVP_PKEY *pkey)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey = X509_get0_pubkey(cert);
|
|
||||||
int level = ctx->param->auth_level;
|
int level = ctx->param->auth_level;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3443,6 +3612,15 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
|
|||||||
return EVP_PKEY_get_security_bits(pkey) >= minbits_table[level - 1];
|
return EVP_PKEY_get_security_bits(pkey) >= minbits_table[level - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Check whether the public key of `cert` meets the security level of `ctx`.
|
||||||
|
* Returns 1 on success, 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int check_cert_key_level(X509_STORE_CTX *ctx, X509 *cert)
|
||||||
|
{
|
||||||
|
return check_key_level(ctx, X509_get0_pubkey(cert));
|
||||||
|
}
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Check whether the public key of ``cert`` does not use explicit params
|
* Check whether the public key of ``cert`` does not use explicit params
|
||||||
* for an elliptic curve.
|
* for an elliptic curve.
|
||||||
|
@ -2483,6 +2483,10 @@ DEPEND[html/man3/SSL_free.html]=man3/SSL_free.pod
|
|||||||
GENERATE[html/man3/SSL_free.html]=man3/SSL_free.pod
|
GENERATE[html/man3/SSL_free.html]=man3/SSL_free.pod
|
||||||
DEPEND[man/man3/SSL_free.3]=man3/SSL_free.pod
|
DEPEND[man/man3/SSL_free.3]=man3/SSL_free.pod
|
||||||
GENERATE[man/man3/SSL_free.3]=man3/SSL_free.pod
|
GENERATE[man/man3/SSL_free.3]=man3/SSL_free.pod
|
||||||
|
DEPEND[html/man3/SSL_get0_peer_rpk.html]=man3/SSL_get0_peer_rpk.pod
|
||||||
|
GENERATE[html/man3/SSL_get0_peer_rpk.html]=man3/SSL_get0_peer_rpk.pod
|
||||||
|
DEPEND[man/man3/SSL_get0_peer_rpk.3]=man3/SSL_get0_peer_rpk.pod
|
||||||
|
GENERATE[man/man3/SSL_get0_peer_rpk.3]=man3/SSL_get0_peer_rpk.pod
|
||||||
DEPEND[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
|
DEPEND[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
|
||||||
GENERATE[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
|
GENERATE[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
|
||||||
DEPEND[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
|
DEPEND[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
|
||||||
@ -2627,6 +2631,10 @@ DEPEND[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
|
|||||||
GENERATE[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
|
GENERATE[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
|
||||||
DEPEND[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
|
DEPEND[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
|
||||||
GENERATE[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
|
GENERATE[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
|
||||||
|
DEPEND[html/man3/SSL_set1_server_cert_type.html]=man3/SSL_set1_server_cert_type.pod
|
||||||
|
GENERATE[html/man3/SSL_set1_server_cert_type.html]=man3/SSL_set1_server_cert_type.pod
|
||||||
|
DEPEND[man/man3/SSL_set1_server_cert_type.3]=man3/SSL_set1_server_cert_type.pod
|
||||||
|
GENERATE[man/man3/SSL_set1_server_cert_type.3]=man3/SSL_set1_server_cert_type.pod
|
||||||
DEPEND[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
|
DEPEND[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
|
||||||
GENERATE[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
|
GENERATE[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
|
||||||
DEPEND[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
|
DEPEND[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
|
||||||
@ -3468,6 +3476,7 @@ html/man3/SSL_do_handshake.html \
|
|||||||
html/man3/SSL_export_keying_material.html \
|
html/man3/SSL_export_keying_material.html \
|
||||||
html/man3/SSL_extension_supported.html \
|
html/man3/SSL_extension_supported.html \
|
||||||
html/man3/SSL_free.html \
|
html/man3/SSL_free.html \
|
||||||
|
html/man3/SSL_get0_peer_rpk.html \
|
||||||
html/man3/SSL_get0_peer_scts.html \
|
html/man3/SSL_get0_peer_scts.html \
|
||||||
html/man3/SSL_get_SSL_CTX.html \
|
html/man3/SSL_get_SSL_CTX.html \
|
||||||
html/man3/SSL_get_all_async_fds.html \
|
html/man3/SSL_get_all_async_fds.html \
|
||||||
@ -3504,6 +3513,7 @@ html/man3/SSL_read_early_data.html \
|
|||||||
html/man3/SSL_rstate_string.html \
|
html/man3/SSL_rstate_string.html \
|
||||||
html/man3/SSL_session_reused.html \
|
html/man3/SSL_session_reused.html \
|
||||||
html/man3/SSL_set1_host.html \
|
html/man3/SSL_set1_host.html \
|
||||||
|
html/man3/SSL_set1_server_cert_type.html \
|
||||||
html/man3/SSL_set_async_callback.html \
|
html/man3/SSL_set_async_callback.html \
|
||||||
html/man3/SSL_set_bio.html \
|
html/man3/SSL_set_bio.html \
|
||||||
html/man3/SSL_set_blocking_mode.html \
|
html/man3/SSL_set_blocking_mode.html \
|
||||||
@ -4092,6 +4102,7 @@ man/man3/SSL_do_handshake.3 \
|
|||||||
man/man3/SSL_export_keying_material.3 \
|
man/man3/SSL_export_keying_material.3 \
|
||||||
man/man3/SSL_extension_supported.3 \
|
man/man3/SSL_extension_supported.3 \
|
||||||
man/man3/SSL_free.3 \
|
man/man3/SSL_free.3 \
|
||||||
|
man/man3/SSL_get0_peer_rpk.3 \
|
||||||
man/man3/SSL_get0_peer_scts.3 \
|
man/man3/SSL_get0_peer_scts.3 \
|
||||||
man/man3/SSL_get_SSL_CTX.3 \
|
man/man3/SSL_get_SSL_CTX.3 \
|
||||||
man/man3/SSL_get_all_async_fds.3 \
|
man/man3/SSL_get_all_async_fds.3 \
|
||||||
@ -4128,6 +4139,7 @@ man/man3/SSL_read_early_data.3 \
|
|||||||
man/man3/SSL_rstate_string.3 \
|
man/man3/SSL_rstate_string.3 \
|
||||||
man/man3/SSL_session_reused.3 \
|
man/man3/SSL_session_reused.3 \
|
||||||
man/man3/SSL_set1_host.3 \
|
man/man3/SSL_set1_host.3 \
|
||||||
|
man/man3/SSL_set1_server_cert_type.3 \
|
||||||
man/man3/SSL_set_async_callback.3 \
|
man/man3/SSL_set_async_callback.3 \
|
||||||
man/man3/SSL_set_bio.3 \
|
man/man3/SSL_set_bio.3 \
|
||||||
man/man3/SSL_set_blocking_mode.3 \
|
man/man3/SSL_set_blocking_mode.3 \
|
||||||
|
@ -132,6 +132,8 @@ B<openssl> B<s_client>
|
|||||||
{- $OpenSSL::safe::opt_provider_synopsis -}
|
{- $OpenSSL::safe::opt_provider_synopsis -}
|
||||||
{- $OpenSSL::safe::opt_engine_synopsis -}[B<-ssl_client_engine> I<id>]
|
{- $OpenSSL::safe::opt_engine_synopsis -}[B<-ssl_client_engine> I<id>]
|
||||||
{- $OpenSSL::safe::opt_v_synopsis -}
|
{- $OpenSSL::safe::opt_v_synopsis -}
|
||||||
|
[B<-enable_server_rpk>]
|
||||||
|
[B<-enable_client_rpk>]
|
||||||
[I<host>:I<port>]
|
[I<host>:I<port>]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
@ -825,6 +827,22 @@ Specify engine to be used for client certificate operations.
|
|||||||
Verification errors are displayed, for debugging, but the command will
|
Verification errors are displayed, for debugging, but the command will
|
||||||
proceed unless the B<-verify_return_error> option is used.
|
proceed unless the B<-verify_return_error> option is used.
|
||||||
|
|
||||||
|
=item B<-enable_server_rpk>
|
||||||
|
|
||||||
|
Enable support for receiving raw public keys (RFC7250) from the server.
|
||||||
|
Use of X.509 certificates by the server becomes optional, and servers that
|
||||||
|
support raw public keys may elect to use them.
|
||||||
|
Servers that don't support raw public keys or prefer to use X.509
|
||||||
|
certificates can still elect to send X.509 certificates as usual.
|
||||||
|
|
||||||
|
=item B<-enable_client_rpk>
|
||||||
|
|
||||||
|
Enable support for sending raw public keys (RFC7250) to the server.
|
||||||
|
A raw public key will be sent by the client, if solicited by the server,
|
||||||
|
provided a suitable key and public certificate pair is configured.
|
||||||
|
Some servers may nevertheless not request any client credentials,
|
||||||
|
or may request a certificate.
|
||||||
|
|
||||||
=item I<host>:I<port>
|
=item I<host>:I<port>
|
||||||
|
|
||||||
Rather than providing B<-connect>, the target hostname and optional port may
|
Rather than providing B<-connect>, the target hostname and optional port may
|
||||||
@ -940,13 +958,17 @@ The B<-certform> option has become obsolete in OpenSSL 3.0.0 and has no effect.
|
|||||||
|
|
||||||
The B<-engine> option was deprecated in OpenSSL 3.0.
|
The B<-engine> option was deprecated in OpenSSL 3.0.
|
||||||
|
|
||||||
|
The
|
||||||
The B<-tfo>, B<-no_tx_cert_comp>, and B<-no_rx_cert_comp> options were added
|
B<-enable_client_rpk>,
|
||||||
in OpenSSL 3.2.
|
B<-enable_server_rpk>,
|
||||||
|
B<-no_rx_cert_comp>,
|
||||||
|
B<-no_tx_cert_comp>,
|
||||||
|
and B<-tfo>
|
||||||
|
options were added in OpenSSL 3.2.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -151,6 +151,8 @@ B<openssl> B<s_server>
|
|||||||
{- $OpenSSL::safe::opt_trust_synopsis -}
|
{- $OpenSSL::safe::opt_trust_synopsis -}
|
||||||
{- $OpenSSL::safe::opt_r_synopsis -}
|
{- $OpenSSL::safe::opt_r_synopsis -}
|
||||||
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
|
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
|
||||||
|
[B<-enable_server_rpk>]
|
||||||
|
[B<-enable_client_rpk>]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
@ -867,6 +869,26 @@ If the server requests a client certificate, then
|
|||||||
verification errors are displayed, for debugging, but the command will
|
verification errors are displayed, for debugging, but the command will
|
||||||
proceed unless the B<-verify_return_error> option is used.
|
proceed unless the B<-verify_return_error> option is used.
|
||||||
|
|
||||||
|
=item B<-enable_server_rpk>
|
||||||
|
|
||||||
|
Enable support for sending raw public keys (RFC7250) to the client.
|
||||||
|
A raw public key will be sent by the server, if solicited by the client,
|
||||||
|
provided a suitable key and public certificate pair is configured.
|
||||||
|
Clients that don't support raw public keys or prefer to use X.509
|
||||||
|
certificates can still elect to receive X.509 certificates as usual.
|
||||||
|
|
||||||
|
Raw public keys are extracted from the configured certificate/private key.
|
||||||
|
|
||||||
|
=item B<-enable_client_rpk>
|
||||||
|
|
||||||
|
Enable support for receiving raw public keys (RFC7250) from the client.
|
||||||
|
Use of X.509 certificates by the client becomes optional, and clients that
|
||||||
|
support raw public keys may elect to use them.
|
||||||
|
Clients that don't support raw public keys or prefer to use X.509
|
||||||
|
certificates can still elect to send X.509 certificates as usual.
|
||||||
|
|
||||||
|
Raw public keys are extracted from the configured certificate/private key.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 CONNECTED COMMANDS
|
=head1 CONNECTED COMMANDS
|
||||||
@ -971,12 +993,17 @@ The
|
|||||||
The B<-srpvfile>, B<-srpuserseed>, and B<-engine>
|
The B<-srpvfile>, B<-srpuserseed>, and B<-engine>
|
||||||
option were deprecated in OpenSSL 3.0.
|
option were deprecated in OpenSSL 3.0.
|
||||||
|
|
||||||
The B<-tfo>, B<-no_tx_cert_comp>, and B<-no_rx_cert_comp> options were added
|
The
|
||||||
in OpenSSL 3.2.
|
B<-enable_client_rpk>,
|
||||||
|
B<-enable_server_rpk>,
|
||||||
|
B<-no_rx_cert_comp>,
|
||||||
|
B<-no_tx_cert_comp>,
|
||||||
|
and B<-tfo>
|
||||||
|
options were added in OpenSSL 3.2.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -306,10 +306,13 @@ the lifetime of the SSL connection.
|
|||||||
int depth = SSL_get0_dane_authority(ssl, NULL, &mspki);
|
int depth = SSL_get0_dane_authority(ssl, NULL, &mspki);
|
||||||
if (depth >= 0) {
|
if (depth >= 0) {
|
||||||
(void) SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, NULL, NULL);
|
(void) SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, NULL, NULL);
|
||||||
printf("DANE TLSA %d %d %d %s at depth %d\n", usage, selector, mtype,
|
printf("DANE TLSA %d %d %d ", usage, selector, mtype);
|
||||||
(mspki != NULL) ? "TA public key verified certificate" :
|
if (SSL_get0_peer_rpk(ssl) == NULL)
|
||||||
depth ? "matched TA certificate" : "matched EE certificate",
|
printf("%s certificate at depth %d\n",
|
||||||
depth);
|
(mspki != NULL) ? "signed the peer" :
|
||||||
|
mdpth ? "matched the TA" : "matched the EE", mdpth);
|
||||||
|
else
|
||||||
|
printf(bio, "matched the peer raw public key\n");
|
||||||
}
|
}
|
||||||
if (peername != NULL) {
|
if (peername != NULL) {
|
||||||
/* Name checks were in scope and matched the peername */
|
/* Name checks were in scope and matched the peername */
|
||||||
|
99
doc/man3/SSL_get0_peer_rpk.pod
Normal file
99
doc/man3/SSL_get0_peer_rpk.pod
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
SSL_add_expected_rpk,
|
||||||
|
SSL_get_negotiated_client_cert_type,
|
||||||
|
SSL_get_negotiated_server_cert_type,
|
||||||
|
SSL_get0_peer_rpk,
|
||||||
|
SSL_SESSION_get0_peer_rpk - raw public key (RFC7250) support
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk);
|
||||||
|
int SSL_get_negotiated_client_cert_type(const SSL *s);
|
||||||
|
int SSL_get_negotiated_server_cert_type(const SSL *s);
|
||||||
|
EVP_PKEY *SSL_get0_peer_rpk(const SSL *s);
|
||||||
|
EVP_PKEY *SSL_SESSION_get0_peer_rpk(const SSL_SESSION *ss);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
SSL_add_expected_rpk() adds a DANE TLSA record matching public key B<rpk>
|
||||||
|
to SSL B<s>'s DANE validation policy.
|
||||||
|
|
||||||
|
SSL_get_negotiated_client_cert_type() returns the connection's negotiated
|
||||||
|
client certificate type.
|
||||||
|
|
||||||
|
SSL_get_negotiated_server_cert_type() returns the connection's negotiated
|
||||||
|
server certificate type.
|
||||||
|
|
||||||
|
SSL_get0_peer_rpk() returns the peer's raw public key from SSL B<s>.
|
||||||
|
|
||||||
|
SSL_SESSION_get0_peer_rpk() returns the peer's raw public key from
|
||||||
|
SSL_SESSION B<ss>.
|
||||||
|
|
||||||
|
=head1 NOTES
|
||||||
|
|
||||||
|
Raw public keys are used in place of certificates when the option is
|
||||||
|
negotiated.
|
||||||
|
B<SSL_add_expected_rpk()> may be called multiple times to configure
|
||||||
|
multiple trusted keys, this makes it possible to allow for key rotation,
|
||||||
|
where a peer might be expected to offer an "old" or "new" key and the
|
||||||
|
endpoint must be able to accept either one.
|
||||||
|
|
||||||
|
When raw public keys are used, the certificate verify callback is called, and
|
||||||
|
may be used to inspect the public key via X509_STORE_CTX_get0_rpk(3).
|
||||||
|
Raw public keys have no subject, issuer, validity dates nor digital signature
|
||||||
|
to verify. They can, however, be matched verbatim or by their digest value, this
|
||||||
|
is done by specifying one or more TLSA records, see L<SSL_CTX_dane_enable(3)>.
|
||||||
|
|
||||||
|
The raw public key is typically taken from the certificate assigned to the
|
||||||
|
connection (e.g. via L<SSL_use_certificate(3)>), but if a certificate is not
|
||||||
|
configured, then the public key will be extracted from the assigned
|
||||||
|
private key.
|
||||||
|
|
||||||
|
The SSL_add_expected_rpk() function is a wrapper around
|
||||||
|
L<SSL_dane_tlsa_add(3)>.
|
||||||
|
When DANE is enabled via L<SSL_dane_enable(3)>, the configured TLSA records
|
||||||
|
will be used to validate the peer's public key or certificate.
|
||||||
|
If DANE is not enabled, then no validation will occur.
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
SSL_add_expected_rpk() returns 1 on success and 0 on failure.
|
||||||
|
|
||||||
|
SSL_get0_peer_rpk() and SSL_SESSION_get0_peer_rpk() return the peer's raw
|
||||||
|
public key as an EVP_PKEY or NULL when the raw public key is not available.
|
||||||
|
|
||||||
|
SSL_get_negotiated_client_cert_type() and SSL_get_negotiated_server_cert_type()
|
||||||
|
return one of the following values:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item TLSEXT_cert_type_x509
|
||||||
|
|
||||||
|
=item TLSEXT_cert_type_rpk
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<SSL_CTX_dane_enable(3)>,
|
||||||
|
L<SSL_CTX_set_options(3)>,
|
||||||
|
L<SSL_dane_enable(3)>,
|
||||||
|
L<SSL_get_verify_result(3)>,
|
||||||
|
L<SSL_set_verify(3)>,
|
||||||
|
L<SSL_use_certificate(3)>,
|
||||||
|
L<X509_STORE_CTX_get0_rpk(3)>
|
||||||
|
|
||||||
|
=head1 HISTORY
|
||||||
|
|
||||||
|
These functions were added in OpenSSL 3.2.
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
=cut
|
196
doc/man3/SSL_set1_server_cert_type.pod
Normal file
196
doc/man3/SSL_set1_server_cert_type.pod
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
SSL_set1_client_cert_type,
|
||||||
|
SSL_set1_server_cert_type,
|
||||||
|
SSL_CTX_set1_client_cert_type,
|
||||||
|
SSL_CTX_set1_server_cert_type,
|
||||||
|
SSL_get0_client_cert_type,
|
||||||
|
SSL_get0_server_cert_type,
|
||||||
|
SSL_CTX_get0_client_cert_type,
|
||||||
|
SSL_CTX_get0_server_cert_type - certificate type (RFC7250) support
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
int SSL_set1_client_cert_type(SSL *s, const unsigned char *val, size_t len);
|
||||||
|
int SSL_set1_server_cert_type(SSL *s, const unsigned char *val, size_t len);
|
||||||
|
int SSL_CTX_set1_client_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
|
||||||
|
int SSL_CTX_set1_server_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
|
||||||
|
int SSL_get0_client_cert_type(const SSL *s, unsigned char **val, size_t *len);
|
||||||
|
int SSL_get0_server_cert_type(const SSL *s, unsigned char **val, size_t *len);
|
||||||
|
int SSL_CTX_get0_client_cert_type(const SSL_CTX *ctx, unsigned char **val, size_t *len);
|
||||||
|
int SSL_CTX_get0_server_cert_type(const SSL_CTX *s, unsigned char **val, size_t *len);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
The SSL_set1_client_cert_type() and SSL_CTX_set1_client_cert_type() functions
|
||||||
|
set the values for the client certificate type extension.
|
||||||
|
The SSL_get0_client_cert_type() and SSL_CTX_get0_client_cert_type() functions
|
||||||
|
retrieve the local values to be used in the client certificate type extension.
|
||||||
|
|
||||||
|
The SSL_set1_server_cert_type() and SSL_CTX_set1_server_cert_type() functions
|
||||||
|
set the values for the server certificate type extension.
|
||||||
|
The SSL_get0_server_cert_type() and SSL_CTX_get0_server_cert_type() functions
|
||||||
|
retrieve the local values to be used in the server certificate type extension.
|
||||||
|
|
||||||
|
=head1 NOTES
|
||||||
|
|
||||||
|
The certificate type extensions are used to negotiate the certificate type to
|
||||||
|
be used in the handshake.
|
||||||
|
These extensions let each side know what its peer is able to accept.
|
||||||
|
|
||||||
|
The client certificate type is sent from the client to the server to indicate
|
||||||
|
what certificate types the client is able to present.
|
||||||
|
Values are configured in preference order.
|
||||||
|
On the server, this setting determines which certificate types the server is
|
||||||
|
willing to accept.
|
||||||
|
The server ultimately chooses what type to request (if any) from the values
|
||||||
|
that are mutually supported.
|
||||||
|
By default (if no explicit settings are specified), only X.509 certificates
|
||||||
|
are supported.
|
||||||
|
|
||||||
|
The server certificate type is sent from the client to the server to indicate
|
||||||
|
what certificate types the client accepts.
|
||||||
|
Values are configured in preference order.
|
||||||
|
On the server, this setting determines which certificate types the server is
|
||||||
|
willing to present.
|
||||||
|
The server ultimately chooses what type to use from the values that are
|
||||||
|
mutually supported.
|
||||||
|
By default (if no explicit settings are specified), only X.509 certificates
|
||||||
|
are supported.
|
||||||
|
|
||||||
|
Having RPK specified first means that side will attempt to send (or request)
|
||||||
|
RPKs if its peer also supports RPKs, otherwise X.509 certificate will be used
|
||||||
|
if both have specified that (or have not configured these options).
|
||||||
|
|
||||||
|
The two supported values in the B<val> array are:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item TLSEXT_cert_type_x509
|
||||||
|
|
||||||
|
Which corresponds to an X.509 certificate normally used in TLS.
|
||||||
|
|
||||||
|
=item TLSEXT_cert_type_rpk
|
||||||
|
|
||||||
|
Which corresponds to a raw public key.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
If B<val> is set to a non-NULL value, then the extension is sent in the handshake.
|
||||||
|
If b<val> is set to a NULL value (and B<len> is 0), then the extension is
|
||||||
|
disabled. The default value is NULL, meaning the extension is not sent, and
|
||||||
|
X.509 certificates are used in the handshake.
|
||||||
|
|
||||||
|
Raw public keys may be used in place of certificates when specified in the
|
||||||
|
certificate type and negotiated.
|
||||||
|
Raw public keys have no subject, issuer, validity dates or digital signature.
|
||||||
|
|
||||||
|
Use the L<SSL_get_negotiated_client_cert_type(3)> and
|
||||||
|
L<SSL_get_negotiated_server_cert_type(3)> functions to get the negotiated cert
|
||||||
|
type values (at the conclusion of the handshake, or in callbacks that happen
|
||||||
|
after the TLS ServerHello has been processed).
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
All functions return 1 on success and 0 on failure.
|
||||||
|
|
||||||
|
The memory returned from the get0 functions must not be freed.
|
||||||
|
|
||||||
|
=head1 EXAMPLES
|
||||||
|
|
||||||
|
To use raw public keys on the server, set up the SSL_CTX and SSL as follows:
|
||||||
|
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
SSL *ssl;
|
||||||
|
unsigned char cert_type[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||||
|
EVP_PKEY *rpk;
|
||||||
|
|
||||||
|
/* Assign rpk to an EVP_PKEY from a file or other means */
|
||||||
|
|
||||||
|
if ((ctx = SSL_CTX_new(TLS_server_method())) == NULL)
|
||||||
|
/* error */
|
||||||
|
if ((ssl = SSL_new(ctx)) == NULL)
|
||||||
|
/* error */
|
||||||
|
if (!SSL_set1_server_cert_type(ssl, cert_type, sizeof(cert_type)))
|
||||||
|
/* error */
|
||||||
|
|
||||||
|
/* A certificate does not need to be specified when using raw public keys */
|
||||||
|
if (!SSL_use_PrivateKey(ssl, rpk))
|
||||||
|
/* error */
|
||||||
|
|
||||||
|
/* Perform SSL_accept() operations */
|
||||||
|
|
||||||
|
To connect to this server, set the client SSL_CTX and SSL as follows:
|
||||||
|
|
||||||
|
/* Connect function */
|
||||||
|
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
SSL *ssl;
|
||||||
|
const char *dane_tlsa_domain = "smtp.example.com";
|
||||||
|
unsigned char cert_type[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||||
|
EVP_PKEY *rpk;
|
||||||
|
int verify_result;
|
||||||
|
|
||||||
|
/* Assign rpk to an EVP_PKEY from a file or other means */
|
||||||
|
|
||||||
|
if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
|
||||||
|
/* error */
|
||||||
|
if (SSL_CTX_dane_enable(ctx) <= 0)
|
||||||
|
/* error */
|
||||||
|
if ((ssl = SSL_new(ctx)) == NULL)
|
||||||
|
/* error */
|
||||||
|
/*
|
||||||
|
* The `dane_tlsa_domain` arguments sets the default SNI hostname.
|
||||||
|
* It may be set to NULL when enabling DANE on the server side.
|
||||||
|
*/
|
||||||
|
if (SSL_dane_enable(ssl, dane_tlsa_domain) <= 0)
|
||||||
|
/* error */
|
||||||
|
if (!SSL_set1_server_cert_type(ssl, cert_type, sizeof(cert_type)))
|
||||||
|
/* error */
|
||||||
|
if (!SSL_add_expected_rpk(ssl, rpk))
|
||||||
|
/* error */
|
||||||
|
|
||||||
|
/* Do SSL_connect() handshake and handle errors here */
|
||||||
|
|
||||||
|
/* Optional: verify the peer RPK */
|
||||||
|
verify_result = SSL_get_verify_result(ssl);
|
||||||
|
if (verify_result == X509_V_OK) {
|
||||||
|
/* The server's raw public key matched the TLSA record */
|
||||||
|
} else if (verify_result == X509_V_ERR_DANE_NO_MATCH) {
|
||||||
|
/*
|
||||||
|
* The server's raw public key, or public key in certificate, did not
|
||||||
|
* match the TLSA record
|
||||||
|
*/
|
||||||
|
} else if (verify_result == X509_V_ERR_RPK_UNTRUSTED) {
|
||||||
|
/*
|
||||||
|
* No TLSA records of the correct type are available to verify the
|
||||||
|
* server's raw public key. This would not happen in this example,
|
||||||
|
* as a TLSA record is configured.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* Some other verify error */
|
||||||
|
}
|
||||||
|
|
||||||
|
To validate client raw public keys, code from the client example may need to be
|
||||||
|
incorporated into the server side.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<SSL_get0_peer_rpk(3)>,
|
||||||
|
L<SSL_get_negotiated_client_cert_type(3)>,
|
||||||
|
L<SSL_get_negotiated_server_cert_type(3)>,
|
||||||
|
L<SSL_use_certificate(3)>
|
||||||
|
|
||||||
|
=head1 HISTORY
|
||||||
|
|
||||||
|
These functions were added in OpenSSL 3.2.
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
=cut
|
@ -67,7 +67,8 @@ Once such a I<saved> certificate is no longer needed it can be freed with
|
|||||||
L<X509_free(3)>.
|
L<X509_free(3)>.
|
||||||
|
|
||||||
X509_STORE_CTX_get0_cert() retrieves an internal pointer to the
|
X509_STORE_CTX_get0_cert() retrieves an internal pointer to the
|
||||||
certificate being verified by the I<ctx>.
|
certificate being verified by the I<ctx>. It may be NULL if a raw public
|
||||||
|
key is being verified.
|
||||||
|
|
||||||
X509_STORE_CTX_get1_chain() returns a complete validate chain if a previous
|
X509_STORE_CTX_get1_chain() returns a complete validate chain if a previous
|
||||||
verification is successful. Otherwise the returned chain may be incomplete or
|
verification is successful. Otherwise the returned chain may be incomplete or
|
||||||
@ -460,6 +461,11 @@ The algorithm given in the certificate info is inconsistent
|
|||||||
A CA certificate is invalid. Either it is not a CA or its extensions are not
|
A CA certificate is invalid. Either it is not a CA or its extensions are not
|
||||||
consistent with the supplied purpose.
|
consistent with the supplied purpose.
|
||||||
|
|
||||||
|
=item B<X509_V_ERR_RPK_UNTRUSTED: raw public key untrusted, no trusted keys configured>
|
||||||
|
|
||||||
|
No TLS records were configured to validate the raw public key, or DANE was not
|
||||||
|
enabled on the connection.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
@ -490,7 +496,7 @@ L<X509_free(3)>.
|
|||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -3,12 +3,16 @@
|
|||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
X509_STORE_CTX_new_ex, X509_STORE_CTX_new, X509_STORE_CTX_cleanup,
|
X509_STORE_CTX_new_ex, X509_STORE_CTX_new, X509_STORE_CTX_cleanup,
|
||||||
X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack,
|
X509_STORE_CTX_free, X509_STORE_CTX_init,
|
||||||
|
X509_STORE_CTX_init_rpk,
|
||||||
|
X509_STORE_CTX_set0_trusted_stack,
|
||||||
X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls,
|
X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls,
|
||||||
|
X509_STORE_CTX_set0_rpk,
|
||||||
X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
|
X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
|
||||||
X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted,
|
X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted,
|
||||||
X509_STORE_CTX_get_num_untrusted,
|
X509_STORE_CTX_get_num_untrusted,
|
||||||
X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
|
X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
|
||||||
|
X509_STORE_CTX_get0_rpk,
|
||||||
X509_STORE_CTX_set_default,
|
X509_STORE_CTX_set_default,
|
||||||
X509_STORE_CTX_set_verify,
|
X509_STORE_CTX_set_verify,
|
||||||
X509_STORE_CTX_verify_fn,
|
X509_STORE_CTX_verify_fn,
|
||||||
@ -28,11 +32,14 @@ X509_STORE_CTX_purpose_inherit
|
|||||||
|
|
||||||
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
||||||
X509 *target, STACK_OF(X509) *untrusted);
|
X509 *target, STACK_OF(X509) *untrusted);
|
||||||
|
int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
||||||
|
EVP_PKEY *rpk);
|
||||||
|
|
||||||
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
||||||
|
|
||||||
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
|
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
|
||||||
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
||||||
|
void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *target);
|
||||||
|
|
||||||
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx);
|
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx);
|
||||||
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
|
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
|
||||||
@ -43,6 +50,7 @@ X509_STORE_CTX_purpose_inherit
|
|||||||
int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx);
|
int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx);
|
||||||
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
|
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
|
||||||
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
|
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
|
||||||
|
EVP_PKEY *X509_STORE_CTX_get0_rpk(const X509_STORE_CTX *ctx);
|
||||||
|
|
||||||
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
|
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
|
||||||
typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
|
typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
|
||||||
@ -85,6 +93,8 @@ they are provided simply as a list using X509_STORE_CTX_set0_trusted_stack().
|
|||||||
The certificate to be verified is set to I<target>,
|
The certificate to be verified is set to I<target>,
|
||||||
and a list of additional certificates may be provided in I<untrusted>,
|
and a list of additional certificates may be provided in I<untrusted>,
|
||||||
which will be untrusted but may be used to build the chain.
|
which will be untrusted but may be used to build the chain.
|
||||||
|
The I<target> certificate is not copied (its reference count is not updated),
|
||||||
|
and the caller must not free it before verification is complete.
|
||||||
Each of the I<trust_store>, I<target> and I<untrusted> parameters can be NULL.
|
Each of the I<trust_store>, I<target> and I<untrusted> parameters can be NULL.
|
||||||
Yet note that L<X509_verify_cert(3)> and L<X509_STORE_CTX_verify(3)>
|
Yet note that L<X509_verify_cert(3)> and L<X509_STORE_CTX_verify(3)>
|
||||||
will need a verification target.
|
will need a verification target.
|
||||||
@ -93,6 +103,14 @@ For L<X509_STORE_CTX_verify(3)>, which takes by default the first element of the
|
|||||||
list of untrusted certificates as its verification target,
|
list of untrusted certificates as its verification target,
|
||||||
this can be also set indirectly using X509_STORE_CTX_set0_untrusted().
|
this can be also set indirectly using X509_STORE_CTX_set0_untrusted().
|
||||||
|
|
||||||
|
X509_STORE_CTX_init_rpk() sets up I<ctx> for a subsequent verification
|
||||||
|
operation for the I<target> raw public key.
|
||||||
|
It behaves similarly to X509_STORE_CTX_init().
|
||||||
|
The I<target> raw public key can aslo be supplied separately, via
|
||||||
|
X509_STORE_CTX_set0_rpk().
|
||||||
|
The I<target> public key is not copied (its reference count is not updated),
|
||||||
|
and the caller must not free it before verification is complete.
|
||||||
|
|
||||||
X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of
|
X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of
|
||||||
I<ctx> to I<sk>. This is an alternative way of specifying trusted certificates
|
I<ctx> to I<sk>. This is an alternative way of specifying trusted certificates
|
||||||
instead of using an B<X509_STORE> where its complexity is not needed
|
instead of using an B<X509_STORE> where its complexity is not needed
|
||||||
@ -100,6 +118,14 @@ or to make sure that only the given set I<sk> of certificates are trusted.
|
|||||||
|
|
||||||
X509_STORE_CTX_set_cert() sets the target certificate to be verified in I<ctx>
|
X509_STORE_CTX_set_cert() sets the target certificate to be verified in I<ctx>
|
||||||
to I<target>.
|
to I<target>.
|
||||||
|
The target certificate is not copied (its reference count is not updated),
|
||||||
|
and the caller must not free it before verification is complete.
|
||||||
|
|
||||||
|
X509_STORE_CTX_set0_rpk() sets the target raw public key to be verified in I<ctx>
|
||||||
|
to I<target>, a non-NULL raw public key preempts any target certificate, which
|
||||||
|
is then ignored.
|
||||||
|
The I<target> public key is not copied (its reference count is not updated),
|
||||||
|
and the caller must not free it before verification is complete.
|
||||||
|
|
||||||
X509_STORE_CTX_set0_verified_chain() sets the validated chain to I<chain>.
|
X509_STORE_CTX_set0_verified_chain() sets the validated chain to I<chain>.
|
||||||
Ownership of the chain is transferred to I<ctx>,
|
Ownership of the chain is transferred to I<ctx>,
|
||||||
@ -108,6 +134,9 @@ and so it should not be free'd by the caller.
|
|||||||
X509_STORE_CTX_get0_chain() returns the internal pointer used by the
|
X509_STORE_CTX_get0_chain() returns the internal pointer used by the
|
||||||
I<ctx> that contains the constructed (output) chain.
|
I<ctx> that contains the constructed (output) chain.
|
||||||
|
|
||||||
|
X509_STORE_CTX_get0_rpk() returns the internal pointer used by the
|
||||||
|
I<ctx> that contains the raw public key.
|
||||||
|
|
||||||
X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate
|
X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate
|
||||||
verification to I<sk>. These CRLs will only be used if CRL verification is
|
verification to I<sk>. These CRLs will only be used if CRL verification is
|
||||||
enabled in the associated B<X509_VERIFY_PARAM> structure. This might be
|
enabled in the associated B<X509_VERIFY_PARAM> structure. This might be
|
||||||
@ -247,11 +276,15 @@ should be made or reference counts increased instead.
|
|||||||
X509_STORE_CTX_new() returns a newly allocated context or NULL if an
|
X509_STORE_CTX_new() returns a newly allocated context or NULL if an
|
||||||
error occurred.
|
error occurred.
|
||||||
|
|
||||||
X509_STORE_CTX_init() returns 1 for success or 0 if an error occurred.
|
X509_STORE_CTX_init() and X509_STORE_CTX_init_rpk() return 1 for success
|
||||||
|
or 0 if an error occurred.
|
||||||
|
|
||||||
X509_STORE_CTX_get0_param() returns a pointer to an B<X509_VERIFY_PARAM>
|
X509_STORE_CTX_get0_param() returns a pointer to an B<X509_VERIFY_PARAM>
|
||||||
structure or NULL if an error occurred.
|
structure or NULL if an error occurred.
|
||||||
|
|
||||||
|
X509_STORE_CTX_get0_rpk() returns a pointer to an B<EVP_PKEY> structure if
|
||||||
|
present, or NULL if absent.
|
||||||
|
|
||||||
X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(),
|
X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(),
|
||||||
X509_STORE_CTX_set0_trusted_stack(),
|
X509_STORE_CTX_set0_trusted_stack(),
|
||||||
X509_STORE_CTX_set_cert(),
|
X509_STORE_CTX_set_cert(),
|
||||||
@ -273,12 +306,14 @@ L<X509_VERIFY_PARAM_set_flags(3)>
|
|||||||
The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0.
|
The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0.
|
||||||
The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0.
|
The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0.
|
||||||
The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0.
|
The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0.
|
||||||
|
The X509_STORE_CTX_init_rpk(), X509_STORE_CTX_get0_rpk(), and
|
||||||
|
X509_STORE_CTX_set0_rpk() functions were added in OpenSSL 3.2.
|
||||||
|
|
||||||
There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0.
|
There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -73,7 +73,7 @@ X509_REQ_verify_ex(), and X509_self_signed() were added in OpenSSL 3.0.
|
|||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -59,6 +59,14 @@ The X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its
|
|||||||
target certificate is the first element of the list of untrusted certificates
|
target certificate is the first element of the list of untrusted certificates
|
||||||
in I<ctx> unless a target certificate is set explicitly.
|
in I<ctx> unless a target certificate is set explicitly.
|
||||||
|
|
||||||
|
When the verification target is a raw public key, rather than a certificate,
|
||||||
|
both functions validate the target raw public key.
|
||||||
|
In that case the number of possible checks is significantly reduced.
|
||||||
|
The raw public key can be authenticated only via DANE TLSA records, either
|
||||||
|
locally synthesised or obtained by the application from DNS.
|
||||||
|
Raw public key DANE TLSA records may be added via L<SSL_add_expected_rpk(3)> or
|
||||||
|
L<SSL_dane_tlsa_add(3)>.
|
||||||
|
|
||||||
=head1 RETURN VALUES
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
X509_build_chain() returns NULL on error, else a stack of certificates.
|
X509_build_chain() returns NULL on error, else a stack of certificates.
|
||||||
@ -80,7 +88,12 @@ X509_V_OK, likely because a verification callback function has waived the error.
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<X509_STORE_CTX_new(3)>, L<X509_STORE_CTX_init(3)>,
|
L<SSL_add_expected_rpk(3)>,
|
||||||
|
L<SSL_CTX_dane_enable(3)>,
|
||||||
|
L<SSL_dane_tlsa_add(3)>,
|
||||||
|
L<X509_STORE_CTX_new(3)>,
|
||||||
|
L<X509_STORE_CTX_init(3)>,
|
||||||
|
L<X509_STORE_CTX_init_rpk(3)>,
|
||||||
L<X509_STORE_CTX_get_error(3)>
|
L<X509_STORE_CTX_get_error(3)>
|
||||||
|
|
||||||
=head1 HISTORY
|
=head1 HISTORY
|
||||||
@ -89,7 +102,7 @@ X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0.
|
|||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
d2i_SSL_SESSION, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 representation
|
d2i_SSL_SESSION, d2i_SSL_SESSION_ex, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 representation
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@ -10,6 +10,9 @@ d2i_SSL_SESSION, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 repre
|
|||||||
|
|
||||||
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||||
long length);
|
long length);
|
||||||
|
SSL_SESSION *d2i_SSL_SESSION_ex(SSL_SESSION **a, const unsigned char **pp,
|
||||||
|
long length, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq);
|
||||||
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
|
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
@ -25,8 +28,9 @@ from this SSL_CTX object).
|
|||||||
|
|
||||||
=head1 RETURN VALUES
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
d2i_SSL_SESSION() returns a pointer to the newly allocated SSL_SESSION
|
d2i_SSL_SESSION() and d2i_SSL_SESSION_ex() return a pointer to the newly
|
||||||
object. In case of failure the NULL-pointer is returned and the error message
|
allocated SSL_SESSION object.
|
||||||
|
In case of failure the NULL-pointer is returned and the error message
|
||||||
can be retrieved from the error stack.
|
can be retrieved from the error stack.
|
||||||
|
|
||||||
i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes.
|
i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes.
|
||||||
@ -40,7 +44,7 @@ L<d2i_X509(3)>
|
|||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -278,6 +278,8 @@ struct x509_store_ctx_st { /* X509_STORE_CTX */
|
|||||||
SSL_DANE *dane;
|
SSL_DANE *dane;
|
||||||
/* signed via bare TA public key, rather than CA certificate */
|
/* signed via bare TA public key, rather than CA certificate */
|
||||||
int bare_ta_signed;
|
int bare_ta_signed;
|
||||||
|
/* Raw Public Key */
|
||||||
|
EVP_PKEY *rpk;
|
||||||
|
|
||||||
OSSL_LIB_CTX *libctx;
|
OSSL_LIB_CTX *libctx;
|
||||||
char *propq;
|
char *propq;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* {- join("\n * ", @autowarntext) -}
|
* {- join("\n * ", @autowarntext) -}
|
||||||
*
|
*
|
||||||
* 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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -258,29 +258,31 @@ typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
|
|||||||
|
|
||||||
/* Extension context codes */
|
/* Extension context codes */
|
||||||
/* This extension is only allowed in TLS */
|
/* This extension is only allowed in TLS */
|
||||||
#define SSL_EXT_TLS_ONLY 0x0001
|
#define SSL_EXT_TLS_ONLY 0x00001
|
||||||
/* This extension is only allowed in DTLS */
|
/* This extension is only allowed in DTLS */
|
||||||
#define SSL_EXT_DTLS_ONLY 0x0002
|
#define SSL_EXT_DTLS_ONLY 0x00002
|
||||||
/* Some extensions may be allowed in DTLS but we don't implement them for it */
|
/* Some extensions may be allowed in DTLS but we don't implement them for it */
|
||||||
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004
|
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x00004
|
||||||
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
|
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
|
||||||
#define SSL_EXT_SSL3_ALLOWED 0x0008
|
#define SSL_EXT_SSL3_ALLOWED 0x00008
|
||||||
/* Extension is only defined for TLS1.2 and below */
|
/* Extension is only defined for TLS1.2 and below */
|
||||||
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010
|
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x00010
|
||||||
/* Extension is only defined for TLS1.3 and above */
|
/* Extension is only defined for TLS1.3 and above */
|
||||||
#define SSL_EXT_TLS1_3_ONLY 0x0020
|
#define SSL_EXT_TLS1_3_ONLY 0x00020
|
||||||
/* Ignore this extension during parsing if we are resuming */
|
/* Ignore this extension during parsing if we are resuming */
|
||||||
#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040
|
#define SSL_EXT_IGNORE_ON_RESUMPTION 0x00040
|
||||||
#define SSL_EXT_CLIENT_HELLO 0x0080
|
#define SSL_EXT_CLIENT_HELLO 0x00080
|
||||||
/* Really means TLS1.2 or below */
|
/* Really means TLS1.2 or below */
|
||||||
#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100
|
#define SSL_EXT_TLS1_2_SERVER_HELLO 0x00100
|
||||||
#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200
|
#define SSL_EXT_TLS1_3_SERVER_HELLO 0x00200
|
||||||
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400
|
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x00400
|
||||||
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800
|
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x00800
|
||||||
#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
|
#define SSL_EXT_TLS1_3_CERTIFICATE 0x01000
|
||||||
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
|
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x02000
|
||||||
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
|
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x04000
|
||||||
#define SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION 0x8000
|
#define SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION 0x08000
|
||||||
|
/* When sending a raw public key in a certificate message */
|
||||||
|
#define SSL_EXT_TLS1_3_RAW_PUBLIC_KEY 0x10000
|
||||||
|
|
||||||
/* Typedefs for handling custom extensions */
|
/* Typedefs for handling custom extensions */
|
||||||
|
|
||||||
@ -566,6 +568,8 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
|
|||||||
# define CERT_PKEY_CERT_TYPE 0x400
|
# define CERT_PKEY_CERT_TYPE 0x400
|
||||||
/* Cert chain suitable to Suite B */
|
/* Cert chain suitable to Suite B */
|
||||||
# define CERT_PKEY_SUITEB 0x800
|
# define CERT_PKEY_SUITEB 0x800
|
||||||
|
/* Cert pkey valid for raw public key use */
|
||||||
|
# define CERT_PKEY_RPK 0x1000
|
||||||
|
|
||||||
# define SSL_CONF_FLAG_CMDLINE 0x1
|
# define SSL_CONF_FLAG_CMDLINE 0x1
|
||||||
# define SSL_CONF_FLAG_FILE 0x2
|
# define SSL_CONF_FLAG_FILE 0x2
|
||||||
@ -1734,6 +1738,9 @@ __owur int SSL_has_matching_session_id(const SSL *s,
|
|||||||
unsigned int id_len);
|
unsigned int id_len);
|
||||||
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||||
long length);
|
long length);
|
||||||
|
SSL_SESSION *d2i_SSL_SESSION_ex(SSL_SESSION **a, const unsigned char **pp,
|
||||||
|
long length, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq);
|
||||||
|
|
||||||
# ifdef OPENSSL_X509_H
|
# ifdef OPENSSL_X509_H
|
||||||
__owur X509 *SSL_get0_peer_certificate(const SSL *s);
|
__owur X509 *SSL_get0_peer_certificate(const SSL *s);
|
||||||
@ -2592,6 +2599,20 @@ int SSL_set1_compressed_cert(SSL *ssl, int algorithm, unsigned char *comp_data,
|
|||||||
size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, size_t *orig_len);
|
size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, size_t *orig_len);
|
||||||
size_t SSL_get1_compressed_cert(SSL *ssl, int alg, unsigned char **data, size_t *orig_len);
|
size_t SSL_get1_compressed_cert(SSL *ssl, int alg, unsigned char **data, size_t *orig_len);
|
||||||
|
|
||||||
|
__owur int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk);
|
||||||
|
__owur EVP_PKEY *SSL_get0_peer_rpk(const SSL *s);
|
||||||
|
__owur EVP_PKEY *SSL_SESSION_get0_peer_rpk(SSL_SESSION *s);
|
||||||
|
__owur int SSL_get_negotiated_client_cert_type(const SSL *s);
|
||||||
|
__owur int SSL_get_negotiated_server_cert_type(const SSL *s);
|
||||||
|
|
||||||
|
__owur int SSL_set1_client_cert_type(SSL *s, const unsigned char *val, size_t len);
|
||||||
|
__owur int SSL_set1_server_cert_type(SSL *s, const unsigned char *val, size_t len);
|
||||||
|
__owur int SSL_CTX_set1_client_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
|
||||||
|
__owur int SSL_CTX_set1_server_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len);
|
||||||
|
__owur int SSL_get0_client_cert_type(const SSL *s, unsigned char **t, size_t *len);
|
||||||
|
__owur int SSL_get0_server_cert_type(const SSL *s, unsigned char **t, size_t *len);
|
||||||
|
__owur int SSL_CTX_get0_client_cert_type(const SSL_CTX *ctx, unsigned char **t, size_t *len);
|
||||||
|
__owur int SSL_CTX_get0_server_cert_type(const SSL_CTX *s, unsigned char **t, size_t *len);
|
||||||
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||||
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
|
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
|
||||||
# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158
|
# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158
|
||||||
|
# define SSL_R_BAD_CERTIFICATE 348
|
||||||
# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
|
# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
|
||||||
# define SSL_R_BAD_CIPHER 186
|
# define SSL_R_BAD_CIPHER 186
|
||||||
# define SSL_R_BAD_COMPRESSION_ALGORITHM 326
|
# define SSL_R_BAD_COMPRESSION_ALGORITHM 326
|
||||||
@ -111,6 +112,7 @@
|
|||||||
# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318
|
# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318
|
||||||
# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374
|
# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374
|
||||||
# define SSL_R_EE_KEY_TOO_SMALL 399
|
# define SSL_R_EE_KEY_TOO_SMALL 399
|
||||||
|
# define SSL_R_EMPTY_RAW_PUBLIC_KEY 349
|
||||||
# define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354
|
# define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354
|
||||||
# define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150
|
# define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150
|
||||||
# define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151
|
# define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151
|
||||||
@ -146,6 +148,7 @@
|
|||||||
# define SSL_R_INVALID_KEY_UPDATE_TYPE 120
|
# define SSL_R_INVALID_KEY_UPDATE_TYPE 120
|
||||||
# define SSL_R_INVALID_MAX_EARLY_DATA 174
|
# define SSL_R_INVALID_MAX_EARLY_DATA 174
|
||||||
# define SSL_R_INVALID_NULL_CMD_NAME 385
|
# define SSL_R_INVALID_NULL_CMD_NAME 385
|
||||||
|
# define SSL_R_INVALID_RAW_PUBLIC_KEY 350
|
||||||
# define SSL_R_INVALID_RECORD 317
|
# define SSL_R_INVALID_RECORD 317
|
||||||
# define SSL_R_INVALID_SEQUENCE_NUMBER 402
|
# define SSL_R_INVALID_SEQUENCE_NUMBER 402
|
||||||
# define SSL_R_INVALID_SERVERINFO_DATA 388
|
# define SSL_R_INVALID_SERVERINFO_DATA 388
|
||||||
@ -342,6 +345,7 @@
|
|||||||
# define SSL_R_WRONG_CERTIFICATE_TYPE 383
|
# define SSL_R_WRONG_CERTIFICATE_TYPE 383
|
||||||
# define SSL_R_WRONG_CIPHER_RETURNED 261
|
# define SSL_R_WRONG_CIPHER_RETURNED 261
|
||||||
# define SSL_R_WRONG_CURVE 378
|
# define SSL_R_WRONG_CURVE 378
|
||||||
|
# define SSL_R_WRONG_RPK_TYPE 351
|
||||||
# define SSL_R_WRONG_SIGNATURE_LENGTH 264
|
# define SSL_R_WRONG_SIGNATURE_LENGTH 264
|
||||||
# define SSL_R_WRONG_SIGNATURE_SIZE 265
|
# define SSL_R_WRONG_SIGNATURE_SIZE 265
|
||||||
# define SSL_R_WRONG_SIGNATURE_TYPE 370
|
# define SSL_R_WRONG_SIGNATURE_TYPE 370
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1995-2021 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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -122,6 +122,14 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
# define TLSEXT_TYPE_signed_certificate_timestamp 18
|
# define TLSEXT_TYPE_signed_certificate_timestamp 18
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extension type for Raw Public Keys
|
||||||
|
* https://tools.ietf.org/html/rfc7250
|
||||||
|
* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
|
||||||
|
*/
|
||||||
|
# define TLSEXT_TYPE_client_cert_type 19
|
||||||
|
# define TLSEXT_TYPE_server_cert_type 20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExtensionType value for TLS padding extension.
|
* ExtensionType value for TLS padding extension.
|
||||||
* http://tools.ietf.org/html/draft-agl-tls-padding
|
* http://tools.ietf.org/html/draft-agl-tls-padding
|
||||||
@ -224,6 +232,15 @@ extern "C" {
|
|||||||
# define TLSEXT_max_fragment_length_2048 3
|
# define TLSEXT_max_fragment_length_2048 3
|
||||||
# define TLSEXT_max_fragment_length_4096 4
|
# define TLSEXT_max_fragment_length_4096 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS Certificate Type (for RFC7250)
|
||||||
|
* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-extensiontype-values-3
|
||||||
|
*/
|
||||||
|
# define TLSEXT_cert_type_x509 0
|
||||||
|
# define TLSEXT_cert_type_pgp 1 /* recognized, but not supported */
|
||||||
|
# define TLSEXT_cert_type_rpk 2
|
||||||
|
# define TLSEXT_cert_type_1609dot2 3 /* recognized, but not supported */
|
||||||
|
|
||||||
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
|
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
|
||||||
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
|
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* {- join("\n * ", @autowarntext) -}
|
* {- join("\n * ", @autowarntext) -}
|
||||||
*
|
*
|
||||||
* Copyright 1995-2021 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
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -314,6 +314,7 @@ X509_LOOKUP_ctrl_ex((x), X509_L_ADD_STORE, (name), 0, NULL, \
|
|||||||
# define X509_V_ERR_CA_CERT_MISSING_KEY_USAGE 92
|
# define X509_V_ERR_CA_CERT_MISSING_KEY_USAGE 92
|
||||||
# define X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 93
|
# define X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 93
|
||||||
# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94
|
# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94
|
||||||
|
# define X509_V_ERR_RPK_UNTRUSTED 95
|
||||||
|
|
||||||
/* Certificate verify flags */
|
/* Certificate verify flags */
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
||||||
@ -468,11 +469,14 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
|
|||||||
void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
|
void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
|
||||||
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
||||||
X509 *target, STACK_OF(X509) *untrusted);
|
X509 *target, STACK_OF(X509) *untrusted);
|
||||||
|
int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
||||||
|
EVP_PKEY* rpk);
|
||||||
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
||||||
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
|
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
|
||||||
|
|
||||||
X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx);
|
X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx);
|
||||||
X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx);
|
X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx);
|
||||||
|
EVP_PKEY *X509_STORE_CTX_get0_rpk(const X509_STORE_CTX *ctx);
|
||||||
STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx);
|
STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx);
|
||||||
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
|
||||||
void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
|
void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
|
||||||
@ -665,6 +669,7 @@ X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx);
|
|||||||
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
|
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx);
|
||||||
STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx);
|
STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx);
|
||||||
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
|
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
|
||||||
|
void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *target);
|
||||||
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
|
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
|
||||||
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
||||||
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ssl_local.h"
|
#include "ssl_local.h"
|
||||||
#include <openssl/asn1t.h>
|
#include <openssl/asn1t.h>
|
||||||
|
#include <openssl/encoder.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -44,6 +45,7 @@ typedef struct {
|
|||||||
uint32_t tlsext_max_fragment_len_mode;
|
uint32_t tlsext_max_fragment_len_mode;
|
||||||
ASN1_OCTET_STRING *ticket_appdata;
|
ASN1_OCTET_STRING *ticket_appdata;
|
||||||
uint32_t kex_group;
|
uint32_t kex_group;
|
||||||
|
ASN1_OCTET_STRING *peer_rpk;
|
||||||
} SSL_SESSION_ASN1;
|
} SSL_SESSION_ASN1;
|
||||||
|
|
||||||
ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
||||||
@ -75,7 +77,8 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
|
|||||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16),
|
ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16),
|
||||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17),
|
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17),
|
||||||
ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18),
|
ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18),
|
||||||
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, kex_group, UINT32, 19)
|
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, kex_group, UINT32, 19),
|
||||||
|
ASN1_EXP_OPT(SSL_SESSION_ASN1, peer_rpk, ASN1_OCTET_STRING, 20)
|
||||||
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
|
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
|
||||||
|
|
||||||
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
|
||||||
@ -125,8 +128,10 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
|||||||
#endif
|
#endif
|
||||||
ASN1_OCTET_STRING alpn_selected;
|
ASN1_OCTET_STRING alpn_selected;
|
||||||
ASN1_OCTET_STRING ticket_appdata;
|
ASN1_OCTET_STRING ticket_appdata;
|
||||||
|
ASN1_OCTET_STRING peer_rpk;
|
||||||
|
|
||||||
long l;
|
long l;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
|
if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
|
||||||
return 0;
|
return 0;
|
||||||
@ -169,6 +174,14 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
|||||||
|
|
||||||
as.peer = in->peer;
|
as.peer = in->peer;
|
||||||
|
|
||||||
|
as.peer_rpk = NULL;
|
||||||
|
peer_rpk.data = NULL;
|
||||||
|
if (in->peer_rpk != NULL) {
|
||||||
|
peer_rpk.length = i2d_PUBKEY(in->peer_rpk, &peer_rpk.data);
|
||||||
|
if (peer_rpk.length > 0 && peer_rpk.data != NULL)
|
||||||
|
as.peer_rpk = &peer_rpk;
|
||||||
|
}
|
||||||
|
|
||||||
ssl_session_sinit(&as.tlsext_hostname, &tlsext_hostname,
|
ssl_session_sinit(&as.tlsext_hostname, &tlsext_hostname,
|
||||||
in->ext.hostname);
|
in->ext.hostname);
|
||||||
if (in->ext.tick) {
|
if (in->ext.tick) {
|
||||||
@ -204,8 +217,9 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
|||||||
ssl_session_oinit(&as.ticket_appdata, &ticket_appdata,
|
ssl_session_oinit(&as.ticket_appdata, &ticket_appdata,
|
||||||
in->ticket_appdata, in->ticket_appdata_len);
|
in->ticket_appdata, in->ticket_appdata_len);
|
||||||
|
|
||||||
return i2d_SSL_SESSION_ASN1(&as, pp);
|
ret = i2d_SSL_SESSION_ASN1(&as, pp);
|
||||||
|
OPENSSL_free(peer_rpk.data);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Utility functions for d2i_SSL_SESSION */
|
/* Utility functions for d2i_SSL_SESSION */
|
||||||
@ -242,6 +256,12 @@ static int ssl_session_memcpy(unsigned char *dst, size_t *pdstlen,
|
|||||||
|
|
||||||
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||||
long length)
|
long length)
|
||||||
|
{
|
||||||
|
return d2i_SSL_SESSION_ex(a, pp, length, NULL, NULL);
|
||||||
|
}
|
||||||
|
SSL_SESSION *d2i_SSL_SESSION_ex(SSL_SESSION **a, const unsigned char **pp,
|
||||||
|
long length, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq)
|
||||||
{
|
{
|
||||||
long id;
|
long id;
|
||||||
size_t tmpl;
|
size_t tmpl;
|
||||||
@ -316,6 +336,19 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
|||||||
ret->peer = as->peer;
|
ret->peer = as->peer;
|
||||||
as->peer = NULL;
|
as->peer = NULL;
|
||||||
|
|
||||||
|
EVP_PKEY_free(ret->peer_rpk);
|
||||||
|
ret->peer_rpk = NULL;
|
||||||
|
if (as->peer_rpk != NULL) {
|
||||||
|
const unsigned char *data = as->peer_rpk->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* |data| is incremented; we don't want to lose original ptr
|
||||||
|
*/
|
||||||
|
ret->peer_rpk = d2i_PUBKEY_ex(NULL, &data, as->peer_rpk->length, libctx, propq);
|
||||||
|
if (ret->peer_rpk == NULL)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length,
|
if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length,
|
||||||
as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
|
as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
@ -414,13 +414,13 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify a certificate chain
|
* Verify a certificate chain/raw public key
|
||||||
* Return codes:
|
* Return codes:
|
||||||
* 1: Verify success
|
* 1: Verify success
|
||||||
* 0: Verify failure or error
|
* 0: Verify failure or error
|
||||||
* -1: Retry required
|
* -1: Retry required
|
||||||
*/
|
*/
|
||||||
int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY *rpk)
|
||||||
{
|
{
|
||||||
X509 *x;
|
X509 *x;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -429,7 +429,12 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
|||||||
X509_VERIFY_PARAM *param;
|
X509_VERIFY_PARAM *param;
|
||||||
SSL_CTX *sctx;
|
SSL_CTX *sctx;
|
||||||
|
|
||||||
if ((sk == NULL) || (sk_X509_num(sk) == 0))
|
/* Something must be passed in */
|
||||||
|
if ((sk == NULL || sk_X509_num(sk) == 0) && rpk == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Only one can be set */
|
||||||
|
if (sk != NULL && rpk != NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sctx = SSL_CONNECTION_GET_CTX(s);
|
sctx = SSL_CONNECTION_GET_CTX(s);
|
||||||
@ -444,11 +449,18 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sk != NULL) {
|
||||||
x = sk_X509_value(sk, 0);
|
x = sk_X509_value(sk, 0);
|
||||||
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
|
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
|
||||||
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!X509_STORE_CTX_init_rpk(ctx, verify_store, rpk)) {
|
||||||
|
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
param = X509_STORE_CTX_get0_param(ctx);
|
param = X509_STORE_CTX_get0_param(ctx);
|
||||||
/*
|
/*
|
||||||
* XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
|
* XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
|
||||||
@ -496,7 +508,8 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
|||||||
s->verify_result = X509_STORE_CTX_get_error(ctx);
|
s->verify_result = X509_STORE_CTX_get_error(ctx);
|
||||||
OSSL_STACK_OF_X509_free(s->verified_chain);
|
OSSL_STACK_OF_X509_free(s->verified_chain);
|
||||||
s->verified_chain = NULL;
|
s->verified_chain = NULL;
|
||||||
if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
|
|
||||||
|
if (sk != NULL && X509_STORE_CTX_get0_chain(ctx) != NULL) {
|
||||||
s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
|
s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
|
||||||
if (s->verified_chain == NULL) {
|
if (s->verified_chain == NULL) {
|
||||||
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
||||||
@ -512,6 +525,30 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify a raw public key
|
||||||
|
* Return codes:
|
||||||
|
* 1: Verify success
|
||||||
|
* 0: Verify failure or error
|
||||||
|
* -1: Retry required
|
||||||
|
*/
|
||||||
|
int ssl_verify_rpk(SSL_CONNECTION *s, EVP_PKEY *rpk)
|
||||||
|
{
|
||||||
|
return ssl_verify_internal(s, NULL, rpk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify a certificate chain
|
||||||
|
* Return codes:
|
||||||
|
* 1: Verify success
|
||||||
|
* 0: Verify failure or error
|
||||||
|
* -1: Retry required
|
||||||
|
*/
|
||||||
|
int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
||||||
|
{
|
||||||
|
return ssl_verify_internal(s, sk, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
|
static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
|
||||||
STACK_OF(X509_NAME) *name_list)
|
STACK_OF(X509_NAME) *name_list)
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
|||||||
"attempt to reuse session in different context"},
|
"attempt to reuse session in different context"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
|
||||||
"at least (D)TLS 1.2 needed in Suite B mode"},
|
"at least (D)TLS 1.2 needed in Suite B mode"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CERTIFICATE), "bad certificate"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC),
|
||||||
"bad change cipher spec"},
|
"bad change cipher spec"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CIPHER), "bad cipher"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CIPHER), "bad cipher"},
|
||||||
@ -154,6 +155,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
|||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE),
|
||||||
"ecdh required for suiteb mode"},
|
"ecdh required for suiteb mode"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EE_KEY_TOO_SMALL), "ee key too small"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EE_KEY_TOO_SMALL), "ee key too small"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_RAW_PUBLIC_KEY),
|
||||||
|
"empty raw public key"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST),
|
||||||
"empty srtp protection profile list"},
|
"empty srtp protection profile list"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ENCRYPTED_LENGTH_TOO_LONG),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ENCRYPTED_LENGTH_TOO_LONG),
|
||||||
@ -218,6 +221,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
|||||||
"invalid max early data"},
|
"invalid max early data"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_NULL_CMD_NAME),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_NULL_CMD_NAME),
|
||||||
"invalid null cmd name"},
|
"invalid null cmd name"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_RAW_PUBLIC_KEY),
|
||||||
|
"invalid raw public key"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_RECORD), "invalid record"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_RECORD), "invalid record"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SEQUENCE_NUMBER),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SEQUENCE_NUMBER),
|
||||||
"invalid sequence number"},
|
"invalid sequence number"},
|
||||||
@ -561,6 +566,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
|||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CIPHER_RETURNED),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CIPHER_RETURNED),
|
||||||
"wrong cipher returned"},
|
"wrong cipher returned"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CURVE), "wrong curve"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CURVE), "wrong curve"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_RPK_TYPE), "wrong rpk type"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_LENGTH),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_LENGTH),
|
||||||
"wrong signature length"},
|
"wrong signature length"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_SIZE),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_SIZE),
|
||||||
|
212
ssl/ssl_lib.c
212
ssl/ssl_lib.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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -883,6 +883,20 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method)
|
|||||||
#ifndef OPENSSL_NO_COMP_ALG
|
#ifndef OPENSSL_NO_COMP_ALG
|
||||||
memcpy(s->cert_comp_prefs, ctx->cert_comp_prefs, sizeof(s->cert_comp_prefs));
|
memcpy(s->cert_comp_prefs, ctx->cert_comp_prefs, sizeof(s->cert_comp_prefs));
|
||||||
#endif
|
#endif
|
||||||
|
if (ctx->client_cert_type != NULL) {
|
||||||
|
s->client_cert_type = OPENSSL_memdup(ctx->client_cert_type,
|
||||||
|
ctx->client_cert_type_len);
|
||||||
|
if (s->client_cert_type == NULL)
|
||||||
|
goto sslerr;
|
||||||
|
s->client_cert_type_len = ctx->client_cert_type_len;
|
||||||
|
}
|
||||||
|
if (ctx->server_cert_type != NULL) {
|
||||||
|
s->server_cert_type = OPENSSL_memdup(ctx->server_cert_type,
|
||||||
|
ctx->server_cert_type_len);
|
||||||
|
if (s->server_cert_type == NULL)
|
||||||
|
goto sslerr;
|
||||||
|
s->server_cert_type_len = ctx->server_cert_type_len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_CT
|
#ifndef OPENSSL_NO_CT
|
||||||
if (!SSL_set_ct_validation_callback(ssl, ctx->ct_validation_callback,
|
if (!SSL_set_ct_validation_callback(ssl, ctx->ct_validation_callback,
|
||||||
@ -1408,6 +1422,9 @@ void ossl_ssl_connection_free(SSL *ssl)
|
|||||||
sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free);
|
sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free);
|
||||||
sk_X509_NAME_pop_free(s->client_ca_names, X509_NAME_free);
|
sk_X509_NAME_pop_free(s->client_ca_names, X509_NAME_free);
|
||||||
|
|
||||||
|
OPENSSL_free(s->client_cert_type);
|
||||||
|
OPENSSL_free(s->server_cert_type);
|
||||||
|
|
||||||
OSSL_STACK_OF_X509_free(s->verified_chain);
|
OSSL_STACK_OF_X509_free(s->verified_chain);
|
||||||
|
|
||||||
if (ssl->method != NULL)
|
if (ssl->method != NULL)
|
||||||
@ -4099,6 +4116,9 @@ void SSL_CTX_free(SSL_CTX *a)
|
|||||||
OPENSSL_free(a->sigalg_lookup_cache);
|
OPENSSL_free(a->sigalg_lookup_cache);
|
||||||
OPENSSL_free(a->tls12_sigalgs);
|
OPENSSL_free(a->tls12_sigalgs);
|
||||||
|
|
||||||
|
OPENSSL_free(a->client_cert_type);
|
||||||
|
OPENSSL_free(a->server_cert_type);
|
||||||
|
|
||||||
CRYPTO_THREAD_lock_free(a->lock);
|
CRYPTO_THREAD_lock_free(a->lock);
|
||||||
#ifdef TSAN_REQUIRES_LOCKING
|
#ifdef TSAN_REQUIRES_LOCKING
|
||||||
CRYPTO_THREAD_lock_free(a->tsan_lock);
|
CRYPTO_THREAD_lock_free(a->tsan_lock);
|
||||||
@ -4266,6 +4286,24 @@ void ssl_set_masks(SSL_CONNECTION *s)
|
|||||||
|
|
||||||
mask_a |= SSL_aNULL;
|
mask_a |= SSL_aNULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You can do anything with an RPK key, since there's no cert to restrict it
|
||||||
|
* But we need to check for private keys
|
||||||
|
*/
|
||||||
|
if (pvalid[SSL_PKEY_RSA] & CERT_PKEY_RPK) {
|
||||||
|
mask_a |= SSL_aRSA;
|
||||||
|
mask_k |= SSL_kRSA;
|
||||||
|
}
|
||||||
|
if (pvalid[SSL_PKEY_ECC] & CERT_PKEY_RPK)
|
||||||
|
mask_a |= SSL_aECDSA;
|
||||||
|
if (TLS1_get_version(&s->ssl) == TLS1_2_VERSION) {
|
||||||
|
if (pvalid[SSL_PKEY_RSA_PSS_SIGN] & CERT_PKEY_RPK)
|
||||||
|
mask_a |= SSL_aRSA;
|
||||||
|
if (pvalid[SSL_PKEY_ED25519] & CERT_PKEY_RPK
|
||||||
|
|| pvalid[SSL_PKEY_ED448] & CERT_PKEY_RPK)
|
||||||
|
mask_a |= SSL_aECDSA;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
|
* An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
|
||||||
* depending on the key usage extension.
|
* depending on the key usage extension.
|
||||||
@ -7254,3 +7292,175 @@ int SSL_stream_conclude(SSL *ssl, uint64_t flags)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
|
||||||
|
{
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
SSL_DANE *dane = SSL_get0_dane(s);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (dane == NULL || dane->dctx == NULL)
|
||||||
|
return 0;
|
||||||
|
if ((ret = i2d_PUBKEY(rpk, &data)) <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = SSL_dane_tlsa_add(s, DANETLS_USAGE_DANE_EE,
|
||||||
|
DANETLS_SELECTOR_SPKI,
|
||||||
|
DANETLS_MATCHING_FULL,
|
||||||
|
data, (size_t)ret) > 0;
|
||||||
|
OPENSSL_free(data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *SSL_get0_peer_rpk(const SSL *s)
|
||||||
|
{
|
||||||
|
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||||
|
|
||||||
|
if (sc == NULL || sc->session == NULL)
|
||||||
|
return NULL;
|
||||||
|
return sc->session->peer_rpk;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_get_negotiated_client_cert_type(const SSL *s)
|
||||||
|
{
|
||||||
|
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sc->ext.client_cert_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_get_negotiated_server_cert_type(const SSL *s)
|
||||||
|
{
|
||||||
|
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sc->ext.server_cert_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int validate_cert_type(const unsigned char *val, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int saw_rpk = 0;
|
||||||
|
int saw_x509 = 0;
|
||||||
|
|
||||||
|
if (val == NULL && len == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (val == NULL || len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
switch (val[i]) {
|
||||||
|
case TLSEXT_cert_type_rpk:
|
||||||
|
if (saw_rpk)
|
||||||
|
return 0;
|
||||||
|
saw_rpk = 1;
|
||||||
|
break;
|
||||||
|
case TLSEXT_cert_type_x509:
|
||||||
|
if (saw_x509)
|
||||||
|
return 0;
|
||||||
|
saw_x509 = 1;
|
||||||
|
break;
|
||||||
|
case TLSEXT_cert_type_pgp:
|
||||||
|
case TLSEXT_cert_type_1609dot2:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_cert_type(unsigned char **cert_type,
|
||||||
|
size_t *cert_type_len,
|
||||||
|
const unsigned char *val,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = NULL;
|
||||||
|
|
||||||
|
if (!validate_cert_type(val, len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (val != NULL && (tmp = OPENSSL_memdup(val, len)) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
OPENSSL_free(*cert_type);
|
||||||
|
*cert_type = tmp;
|
||||||
|
*cert_type_len = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_set1_client_cert_type(SSL *s, const unsigned char *val, size_t len)
|
||||||
|
{
|
||||||
|
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||||
|
|
||||||
|
return set_cert_type(&sc->client_cert_type, &sc->client_cert_type_len,
|
||||||
|
val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_set1_server_cert_type(SSL *s, const unsigned char *val, size_t len)
|
||||||
|
{
|
||||||
|
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||||
|
|
||||||
|
return set_cert_type(&sc->server_cert_type, &sc->server_cert_type_len,
|
||||||
|
val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_set1_client_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len)
|
||||||
|
{
|
||||||
|
return set_cert_type(&ctx->client_cert_type, &ctx->client_cert_type_len,
|
||||||
|
val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_set1_server_cert_type(SSL_CTX *ctx, const unsigned char *val, size_t len)
|
||||||
|
{
|
||||||
|
return set_cert_type(&ctx->server_cert_type, &ctx->server_cert_type_len,
|
||||||
|
val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_get0_client_cert_type(const SSL *s, unsigned char **t, size_t *len)
|
||||||
|
{
|
||||||
|
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s);
|
||||||
|
|
||||||
|
if (t == NULL || len == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*t = sc->client_cert_type;
|
||||||
|
*len = sc->client_cert_type_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_get0_server_cert_type(const SSL *s, unsigned char **t, size_t *len)
|
||||||
|
{
|
||||||
|
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s);
|
||||||
|
|
||||||
|
if (t == NULL || len == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*t = sc->server_cert_type;
|
||||||
|
*len = sc->server_cert_type_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_get0_client_cert_type(const SSL_CTX *ctx, unsigned char **t, size_t *len)
|
||||||
|
{
|
||||||
|
if (t == NULL || len == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*t = ctx->client_cert_type;
|
||||||
|
*len = ctx->client_cert_type_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_CTX_get0_server_cert_type(const SSL_CTX *ctx, unsigned char **t, size_t *len)
|
||||||
|
{
|
||||||
|
if (t == NULL || len == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*t = ctx->server_cert_type;
|
||||||
|
*len = ctx->server_cert_type_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -371,6 +371,11 @@
|
|||||||
#define CERT_PRIVATE_KEY 2
|
#define CERT_PRIVATE_KEY 2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Certificate Type State */
|
||||||
|
# define OSSL_CERT_TYPE_CTOS_NONE 0
|
||||||
|
# define OSSL_CERT_TYPE_CTOS_GOOD 1
|
||||||
|
# define OSSL_CERT_TYPE_CTOS_ERROR 2
|
||||||
|
|
||||||
/* Post-Handshake Authentication state */
|
/* Post-Handshake Authentication state */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SSL_PHA_NONE = 0,
|
SSL_PHA_NONE = 0,
|
||||||
@ -510,6 +515,8 @@ struct ssl_session_st {
|
|||||||
* to disable session caching and tickets.
|
* to disable session caching and tickets.
|
||||||
*/
|
*/
|
||||||
int not_resumable;
|
int not_resumable;
|
||||||
|
/* Peer raw public key, if available */
|
||||||
|
EVP_PKEY *peer_rpk;
|
||||||
/* This is the cert and type for the other end. */
|
/* This is the cert and type for the other end. */
|
||||||
X509 *peer;
|
X509 *peer;
|
||||||
/* Certificate chain peer sent. */
|
/* Certificate chain peer sent. */
|
||||||
@ -684,6 +691,8 @@ typedef enum tlsext_index_en {
|
|||||||
TLSEXT_IDX_extended_master_secret,
|
TLSEXT_IDX_extended_master_secret,
|
||||||
TLSEXT_IDX_signature_algorithms_cert,
|
TLSEXT_IDX_signature_algorithms_cert,
|
||||||
TLSEXT_IDX_post_handshake_auth,
|
TLSEXT_IDX_post_handshake_auth,
|
||||||
|
TLSEXT_IDX_client_cert_type,
|
||||||
|
TLSEXT_IDX_server_cert_type,
|
||||||
TLSEXT_IDX_signature_algorithms,
|
TLSEXT_IDX_signature_algorithms,
|
||||||
TLSEXT_IDX_supported_versions,
|
TLSEXT_IDX_supported_versions,
|
||||||
TLSEXT_IDX_psk_kex_modes,
|
TLSEXT_IDX_psk_kex_modes,
|
||||||
@ -1170,6 +1179,12 @@ struct ssl_ctx_st {
|
|||||||
/* certificate compression preferences */
|
/* certificate compression preferences */
|
||||||
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Certificate Type stuff - for RPK vs X.509 */
|
||||||
|
unsigned char *client_cert_type;
|
||||||
|
size_t client_cert_type_len;
|
||||||
|
unsigned char *server_cert_type;
|
||||||
|
size_t server_cert_type_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct cert_pkey_st CERT_PKEY;
|
typedef struct cert_pkey_st CERT_PKEY;
|
||||||
@ -1651,6 +1666,11 @@ struct ssl_connection_st {
|
|||||||
int compress_certificate_from_peer[TLSEXT_comp_cert_limit];
|
int compress_certificate_from_peer[TLSEXT_comp_cert_limit];
|
||||||
/* indicate that we sent the extension, so we'll accept it */
|
/* indicate that we sent the extension, so we'll accept it */
|
||||||
int compress_certificate_sent;
|
int compress_certificate_sent;
|
||||||
|
|
||||||
|
uint8_t client_cert_type;
|
||||||
|
uint8_t client_cert_type_ctos;
|
||||||
|
uint8_t server_cert_type;
|
||||||
|
uint8_t server_cert_type_ctos;
|
||||||
} ext;
|
} ext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1771,6 +1791,12 @@ struct ssl_connection_st {
|
|||||||
/* certificate compression preferences */
|
/* certificate compression preferences */
|
||||||
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Certificate Type stuff - for RPK vs X.509 */
|
||||||
|
unsigned char *client_cert_type;
|
||||||
|
size_t client_cert_type_len;
|
||||||
|
unsigned char *server_cert_type;
|
||||||
|
size_t server_cert_type_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
# define SSL_CONNECTION_FROM_SSL_ONLY_int(ssl, c) \
|
# define SSL_CONNECTION_FROM_SSL_ONLY_int(ssl, c) \
|
||||||
@ -2380,11 +2406,47 @@ struct openssl_ssl_test_functions {
|
|||||||
|
|
||||||
const char *ssl_protocol_to_string(int version);
|
const char *ssl_protocol_to_string(int version);
|
||||||
|
|
||||||
|
static ossl_inline int tls12_rpk_and_privkey(const SSL_CONNECTION *sc, int idx)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is to check for special cases when using RPK with just
|
||||||
|
* a private key, and NO CERTIFICATE
|
||||||
|
*/
|
||||||
|
return ((sc->server && sc->ext.server_cert_type == TLSEXT_cert_type_rpk)
|
||||||
|
|| (!sc->server && sc->ext.client_cert_type == TLSEXT_cert_type_rpk))
|
||||||
|
&& sc->cert->pkeys[idx].privatekey != NULL
|
||||||
|
&& sc->cert->pkeys[idx].x509 == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ossl_inline int ssl_has_cert_type(const SSL_CONNECTION *sc, unsigned char ct)
|
||||||
|
{
|
||||||
|
unsigned char *ptr;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (sc->server) {
|
||||||
|
ptr = sc->server_cert_type;
|
||||||
|
len = sc->server_cert_type_len;
|
||||||
|
} else {
|
||||||
|
ptr = sc->client_cert_type;
|
||||||
|
len = sc->client_cert_type_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return memchr(ptr, ct, len) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns true if certificate and private key for 'idx' are present */
|
/* Returns true if certificate and private key for 'idx' are present */
|
||||||
static ossl_inline int ssl_has_cert(const SSL_CONNECTION *s, int idx)
|
static ossl_inline int ssl_has_cert(const SSL_CONNECTION *s, int idx)
|
||||||
{
|
{
|
||||||
if (idx < 0 || idx >= (int)s->ssl_pkey_num)
|
if (idx < 0 || idx >= (int)s->ssl_pkey_num)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* If RPK is enabled for this SSL... only require private key */
|
||||||
|
if (ssl_has_cert_type(s, TLSEXT_cert_type_rpk))
|
||||||
|
return s->cert->pkeys[idx].privatekey != NULL;
|
||||||
|
|
||||||
return s->cert->pkeys[idx].x509 != NULL
|
return s->cert->pkeys[idx].x509 != NULL
|
||||||
&& s->cert->pkeys[idx].privatekey != NULL;
|
&& s->cert->pkeys[idx].privatekey != NULL;
|
||||||
}
|
}
|
||||||
@ -2461,6 +2523,7 @@ __owur int ssl_cert_set_current(CERT *c, long arg);
|
|||||||
void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg);
|
void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg);
|
||||||
|
|
||||||
__owur int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk);
|
__owur int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk);
|
||||||
|
__owur int ssl_verify_rpk(SSL_CONNECTION *s, EVP_PKEY *rpk);
|
||||||
__owur int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags);
|
__owur int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags);
|
||||||
__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
|
__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
|
||||||
int ref);
|
int ref);
|
||||||
|
@ -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.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
@ -165,6 +165,7 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
|
|||||||
#endif
|
#endif
|
||||||
dest->peer_chain = NULL;
|
dest->peer_chain = NULL;
|
||||||
dest->peer = NULL;
|
dest->peer = NULL;
|
||||||
|
dest->peer_rpk = NULL;
|
||||||
dest->ticket_appdata = NULL;
|
dest->ticket_appdata = NULL;
|
||||||
memset(&dest->ex_data, 0, sizeof(dest->ex_data));
|
memset(&dest->ex_data, 0, sizeof(dest->ex_data));
|
||||||
|
|
||||||
@ -200,6 +201,13 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src->peer_rpk != NULL) {
|
||||||
|
if (!EVP_PKEY_up_ref(src->peer_rpk))
|
||||||
|
goto err;
|
||||||
|
dest->peer_rpk = src->peer_rpk;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_PSK
|
#ifndef OPENSSL_NO_PSK
|
||||||
if (src->psk_identity_hint) {
|
if (src->psk_identity_hint) {
|
||||||
dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint);
|
dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint);
|
||||||
@ -823,6 +831,7 @@ void SSL_SESSION_free(SSL_SESSION *ss)
|
|||||||
OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key));
|
OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key));
|
||||||
OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id));
|
OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id));
|
||||||
X509_free(ss->peer);
|
X509_free(ss->peer);
|
||||||
|
EVP_PKEY_free(ss->peer_rpk);
|
||||||
OSSL_STACK_OF_X509_free(ss->peer_chain);
|
OSSL_STACK_OF_X509_free(ss->peer_chain);
|
||||||
OPENSSL_free(ss->ext.hostname);
|
OPENSSL_free(ss->ext.hostname);
|
||||||
OPENSSL_free(ss->ext.tick);
|
OPENSSL_free(ss->ext.tick);
|
||||||
@ -1042,6 +1051,11 @@ X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
|
|||||||
return s->peer;
|
return s->peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *SSL_SESSION_get0_peer_rpk(SSL_SESSION *s)
|
||||||
|
{
|
||||||
|
return s->peer_rpk;
|
||||||
|
}
|
||||||
|
|
||||||
int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
|
int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
|
||||||
unsigned int sid_ctx_len)
|
unsigned int sid_ctx_len)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -34,6 +34,8 @@ static int init_alpn(SSL_CONNECTION *s, unsigned int context);
|
|||||||
static int final_alpn(SSL_CONNECTION *s, unsigned int context, int sent);
|
static int final_alpn(SSL_CONNECTION *s, unsigned int context, int sent);
|
||||||
static int init_sig_algs_cert(SSL_CONNECTION *s, unsigned int context);
|
static int init_sig_algs_cert(SSL_CONNECTION *s, unsigned int context);
|
||||||
static int init_sig_algs(SSL_CONNECTION *s, unsigned int context);
|
static int init_sig_algs(SSL_CONNECTION *s, unsigned int context);
|
||||||
|
static int init_server_cert_type(SSL_CONNECTION *sc, unsigned int context);
|
||||||
|
static int init_client_cert_type(SSL_CONNECTION *sc, unsigned int context);
|
||||||
static int init_certificate_authorities(SSL_CONNECTION *s,
|
static int init_certificate_authorities(SSL_CONNECTION *s,
|
||||||
unsigned int context);
|
unsigned int context);
|
||||||
static EXT_RETURN tls_construct_certificate_authorities(SSL_CONNECTION *s,
|
static EXT_RETURN tls_construct_certificate_authorities(SSL_CONNECTION *s,
|
||||||
@ -309,6 +311,24 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||||||
NULL, tls_construct_ctos_post_handshake_auth,
|
NULL, tls_construct_ctos_post_handshake_auth,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TLSEXT_TYPE_client_cert_type,
|
||||||
|
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||||
|
| SSL_EXT_TLS1_2_SERVER_HELLO,
|
||||||
|
init_client_cert_type,
|
||||||
|
tls_parse_ctos_client_cert_type, tls_parse_stoc_client_cert_type,
|
||||||
|
tls_construct_stoc_client_cert_type, tls_construct_ctos_client_cert_type,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TLSEXT_TYPE_server_cert_type,
|
||||||
|
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||||
|
| SSL_EXT_TLS1_2_SERVER_HELLO,
|
||||||
|
init_server_cert_type,
|
||||||
|
tls_parse_ctos_server_cert_type, tls_parse_stoc_server_cert_type,
|
||||||
|
tls_construct_stoc_server_cert_type, tls_construct_ctos_server_cert_type,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
{
|
{
|
||||||
TLSEXT_TYPE_signature_algorithms,
|
TLSEXT_TYPE_signature_algorithms,
|
||||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
||||||
@ -1779,6 +1799,18 @@ static EXT_RETURN tls_construct_compress_certificate(SSL_CONNECTION *sc, WPACKET
|
|||||||
if (!ossl_comp_has_alg(0))
|
if (!ossl_comp_has_alg(0))
|
||||||
return EXT_RETURN_NOT_SENT;
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
|
||||||
|
/* Server: Don't attempt to compress a non-X509 (i.e. an RPK) */
|
||||||
|
if (sc->server && sc->ext.server_cert_type != TLSEXT_cert_type_x509) {
|
||||||
|
sc->cert_comp_prefs[0] = TLSEXT_comp_cert_none;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Client: If we sent a client cert-type extension, don't indicate compression */
|
||||||
|
if (!sc->server && sc->ext.client_cert_type_ctos) {
|
||||||
|
sc->cert_comp_prefs[0] = TLSEXT_comp_cert_none;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do not indicate we support receiving compressed certificates */
|
/* Do not indicate we support receiving compressed certificates */
|
||||||
if ((sc->options & SSL_OP_NO_RX_CERTIFICATE_COMPRESSION) != 0)
|
if ((sc->options & SSL_OP_NO_RX_CERTIFICATE_COMPRESSION) != 0)
|
||||||
return EXT_RETURN_NOT_SENT;
|
return EXT_RETURN_NOT_SENT;
|
||||||
@ -1843,6 +1875,12 @@ int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt, unsigned int
|
|||||||
if (!ossl_comp_has_alg(0))
|
if (!ossl_comp_has_alg(0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* Don't attempt to compress a non-X509 (i.e. an RPK) */
|
||||||
|
if (sc->server && sc->ext.server_cert_type != TLSEXT_cert_type_x509)
|
||||||
|
return 1;
|
||||||
|
if (!sc->server && sc->ext.client_cert_type != TLSEXT_cert_type_x509)
|
||||||
|
return 1;
|
||||||
|
|
||||||
/* Ignore the extension and don't send compressed certificates */
|
/* Ignore the extension and don't send compressed certificates */
|
||||||
if ((sc->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
|
if ((sc->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
@ -1869,3 +1907,23 @@ int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt, unsigned int
|
|||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int init_server_cert_type(SSL_CONNECTION *sc, unsigned int context)
|
||||||
|
{
|
||||||
|
/* Only reset when parsing client hello */
|
||||||
|
if (sc->server) {
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.server_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_client_cert_type(SSL_CONNECTION *sc, unsigned int context)
|
||||||
|
{
|
||||||
|
/* Only reset when parsing client hello */
|
||||||
|
if (sc->server) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.client_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -2015,3 +2015,107 @@ int tls_parse_stoc_psk(SSL_CONNECTION *s, PACKET *pkt,
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXT_RETURN tls_construct_ctos_client_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
if (sc->client_cert_type == NULL)
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
|
||||||
|
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_client_cert_type)
|
||||||
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|
|| !WPACKET_sub_memcpy_u8(pkt, sc->client_cert_type, sc->client_cert_type_len)
|
||||||
|
|| !WPACKET_close(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_GOOD;
|
||||||
|
return EXT_RETURN_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_parse_stoc_client_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
unsigned int type;
|
||||||
|
|
||||||
|
if (PACKET_remaining(pkt) != 1) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!PACKET_get_1(pkt, &type)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* We did not send/ask for this */
|
||||||
|
if (!ossl_assert(sc->ext.client_cert_type_ctos == OSSL_CERT_TYPE_CTOS_GOOD)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* We don't have this enabled */
|
||||||
|
if (sc->client_cert_type == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Given back a value we didn't configure */
|
||||||
|
if (memchr(sc->client_cert_type, type, sc->client_cert_type_len) == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_VALUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sc->ext.client_cert_type = type;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXT_RETURN tls_construct_ctos_server_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
if (sc->server_cert_type == NULL)
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
|
||||||
|
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_cert_type)
|
||||||
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|
|| !WPACKET_sub_memcpy_u8(pkt, sc->server_cert_type, sc->server_cert_type_len)
|
||||||
|
|| !WPACKET_close(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_GOOD;
|
||||||
|
return EXT_RETURN_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_parse_stoc_server_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
unsigned int type;
|
||||||
|
|
||||||
|
if (PACKET_remaining(pkt) != 1) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!PACKET_get_1(pkt, &type)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* We did not send/ask for this */
|
||||||
|
if (!ossl_assert(sc->ext.server_cert_type_ctos == OSSL_CERT_TYPE_CTOS_GOOD)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* We don't have this enabled */
|
||||||
|
if (sc->server_cert_type == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Given back a value we didn't configure */
|
||||||
|
if (memchr(sc->server_cert_type, type, sc->server_cert_type_len) == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_VALUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sc->ext.server_cert_type = type;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -193,6 +193,7 @@ int custom_ext_add(SSL_CONNECTION *s, int context, WPACKET *pkt, X509 *x,
|
|||||||
| SSL_EXT_TLS1_3_SERVER_HELLO
|
| SSL_EXT_TLS1_3_SERVER_HELLO
|
||||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||||
| SSL_EXT_TLS1_3_CERTIFICATE
|
| SSL_EXT_TLS1_3_CERTIFICATE
|
||||||
|
| SSL_EXT_TLS1_3_RAW_PUBLIC_KEY
|
||||||
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
|
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
|
||||||
/* Only send extensions present in ClientHello/CertificateRequest */
|
/* Only send extensions present in ClientHello/CertificateRequest */
|
||||||
if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
|
if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
|
||||||
@ -534,6 +535,8 @@ int SSL_extension_supported(unsigned int ext_type)
|
|||||||
case TLSEXT_TYPE_psk:
|
case TLSEXT_TYPE_psk:
|
||||||
case TLSEXT_TYPE_post_handshake_auth:
|
case TLSEXT_TYPE_post_handshake_auth:
|
||||||
case TLSEXT_TYPE_compress_certificate:
|
case TLSEXT_TYPE_compress_certificate:
|
||||||
|
case TLSEXT_TYPE_client_cert_type:
|
||||||
|
case TLSEXT_TYPE_server_cert_type:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -1948,3 +1948,164 @@ EXT_RETURN tls_construct_stoc_psk(SSL_CONNECTION *s, WPACKET *pkt,
|
|||||||
|
|
||||||
return EXT_RETURN_SENT;
|
return EXT_RETURN_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXT_RETURN tls_construct_stoc_client_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
if (sc->ext.client_cert_type_ctos == OSSL_CERT_TYPE_CTOS_ERROR
|
||||||
|
&& (send_certificate_request(sc)
|
||||||
|
|| sc->post_handshake_auth == SSL_PHA_EXT_RECEIVED)) {
|
||||||
|
/* Did not receive an acceptable cert type - and doing client auth */
|
||||||
|
SSLfatal(sc, SSL_AD_UNSUPPORTED_CERTIFICATE, SSL_R_BAD_EXTENSION);
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sc->ext.client_cert_type == TLSEXT_cert_type_x509) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: only supposed to send this if we are going to do a cert request,
|
||||||
|
* but TLSv1.3 could do a PHA request if the client supports it
|
||||||
|
*/
|
||||||
|
if ((!send_certificate_request(sc) && sc->post_handshake_auth != SSL_PHA_EXT_RECEIVED)
|
||||||
|
|| sc->ext.client_cert_type_ctos != OSSL_CERT_TYPE_CTOS_GOOD
|
||||||
|
|| sc->client_cert_type == NULL) {
|
||||||
|
/* if we don't send it, reset to TLSEXT_cert_type_x509 */
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.client_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_client_cert_type)
|
||||||
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|
|| !WPACKET_put_bytes_u8(pkt, sc->ext.client_cert_type)
|
||||||
|
|| !WPACKET_close(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
return EXT_RETURN_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One of |pref|, |other| is configured and the values are sanitized */
|
||||||
|
static int reconcile_cert_type(const unsigned char *pref, size_t pref_len,
|
||||||
|
const unsigned char *other, size_t other_len,
|
||||||
|
uint8_t *chosen_cert_type)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < pref_len; i++) {
|
||||||
|
if (memchr(other, pref[i], other_len) != NULL) {
|
||||||
|
*chosen_cert_type = pref[i];
|
||||||
|
return OSSL_CERT_TYPE_CTOS_GOOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OSSL_CERT_TYPE_CTOS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_parse_ctos_client_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
PACKET supported_cert_types;
|
||||||
|
const unsigned char *data;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* Ignore the extension */
|
||||||
|
if (sc->client_cert_type == NULL) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.client_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PACKET_as_length_prefixed_1(pkt, &supported_cert_types)) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_ERROR;
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((len = PACKET_remaining(&supported_cert_types)) == 0) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_ERROR;
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!PACKET_get_bytes(&supported_cert_types, &data, len)) {
|
||||||
|
sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_ERROR;
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* client_cert_type: client (peer) has priority */
|
||||||
|
sc->ext.client_cert_type_ctos = reconcile_cert_type(data, len,
|
||||||
|
sc->client_cert_type, sc->client_cert_type_len,
|
||||||
|
&sc->ext.client_cert_type);
|
||||||
|
|
||||||
|
/* Ignore the error until sending - so we can check cert auth*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXT_RETURN tls_construct_stoc_server_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
if (sc->ext.server_cert_type == TLSEXT_cert_type_x509) {
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
if (sc->ext.server_cert_type_ctos != OSSL_CERT_TYPE_CTOS_GOOD
|
||||||
|
|| sc->server_cert_type == NULL) {
|
||||||
|
/* if we don't send it, reset to TLSEXT_cert_type_x509 */
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.server_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_cert_type)
|
||||||
|
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||||
|
|| !WPACKET_put_bytes_u8(pkt, sc->ext.server_cert_type)
|
||||||
|
|| !WPACKET_close(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
return EXT_RETURN_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_parse_ctos_server_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
PACKET supported_cert_types;
|
||||||
|
const unsigned char *data;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* Ignore the extension */
|
||||||
|
if (sc->server_cert_type == NULL) {
|
||||||
|
sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
|
||||||
|
sc->ext.server_cert_type = TLSEXT_cert_type_x509;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PACKET_as_length_prefixed_1(pkt, &supported_cert_types)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len = PACKET_remaining(&supported_cert_types)) == 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!PACKET_get_bytes(&supported_cert_types, &data, len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* server_cert_type: server (this) has priority */
|
||||||
|
sc->ext.server_cert_type_ctos = reconcile_cert_type(sc->server_cert_type, sc->server_cert_type_len,
|
||||||
|
data, len,
|
||||||
|
&sc->ext.server_cert_type);
|
||||||
|
if (sc->ext.server_cert_type_ctos == OSSL_CERT_TYPE_CTOS_GOOD)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Did not receive an acceptable cert type */
|
||||||
|
SSLfatal(sc, SSL_AD_UNSUPPORTED_CERTIFICATE, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -38,6 +38,11 @@ static int key_exchange_expected(SSL_CONNECTION *s);
|
|||||||
static int ssl_cipher_list_to_bytes(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *sk,
|
static int ssl_cipher_list_to_bytes(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *sk,
|
||||||
WPACKET *pkt);
|
WPACKET *pkt);
|
||||||
|
|
||||||
|
static ossl_inline int received_server_cert(SSL_CONNECTION *sc)
|
||||||
|
{
|
||||||
|
return sc->session->peer_rpk != NULL || sc->session->peer != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is a CertificateRequest message allowed at the moment or not?
|
* Is a CertificateRequest message allowed at the moment or not?
|
||||||
*
|
*
|
||||||
@ -419,6 +424,13 @@ int ossl_statem_client_read_transition(SSL_CONNECTION *s, int mt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_compressed_cert(SSL_CONNECTION *sc)
|
||||||
|
{
|
||||||
|
/* If we negotiated RPK, we won't try to compress it */
|
||||||
|
return sc->ext.client_cert_type == TLSEXT_cert_type_x509
|
||||||
|
&& sc->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ossl_statem_client13_write_transition() works out what handshake state to
|
* ossl_statem_client13_write_transition() works out what handshake state to
|
||||||
* move to next when the TLSv1.3 client is writing messages to be sent to the
|
* move to next when the TLSv1.3 client is writing messages to be sent to the
|
||||||
@ -441,7 +453,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL_CONNECTION *s)
|
|||||||
|
|
||||||
case TLS_ST_CR_CERT_REQ:
|
case TLS_ST_CR_CERT_REQ:
|
||||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||||
if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
|
if (do_compressed_cert(s))
|
||||||
st->hand_state = TLS_ST_CW_COMP_CERT;
|
st->hand_state = TLS_ST_CW_COMP_CERT;
|
||||||
else
|
else
|
||||||
st->hand_state = TLS_ST_CW_CERT;
|
st->hand_state = TLS_ST_CW_CERT;
|
||||||
@ -468,7 +480,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL_CONNECTION *s)
|
|||||||
st->hand_state = TLS_ST_CW_CHANGE;
|
st->hand_state = TLS_ST_CW_CHANGE;
|
||||||
else if (s->s3.tmp.cert_req == 0)
|
else if (s->s3.tmp.cert_req == 0)
|
||||||
st->hand_state = TLS_ST_CW_FINISHED;
|
st->hand_state = TLS_ST_CW_FINISHED;
|
||||||
else if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
|
else if (do_compressed_cert(s))
|
||||||
st->hand_state = TLS_ST_CW_COMP_CERT;
|
st->hand_state = TLS_ST_CW_COMP_CERT;
|
||||||
else
|
else
|
||||||
st->hand_state = TLS_ST_CW_CERT;
|
st->hand_state = TLS_ST_CW_CERT;
|
||||||
@ -485,7 +497,7 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL_CONNECTION *s)
|
|||||||
case TLS_ST_CW_CHANGE:
|
case TLS_ST_CW_CHANGE:
|
||||||
if (s->s3.tmp.cert_req == 0)
|
if (s->s3.tmp.cert_req == 0)
|
||||||
st->hand_state = TLS_ST_CW_FINISHED;
|
st->hand_state = TLS_ST_CW_FINISHED;
|
||||||
else if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
|
else if (do_compressed_cert(s))
|
||||||
st->hand_state = TLS_ST_CW_COMP_CERT;
|
st->hand_state = TLS_ST_CW_COMP_CERT;
|
||||||
else
|
else
|
||||||
st->hand_state = TLS_ST_CW_CERT;
|
st->hand_state = TLS_ST_CW_CERT;
|
||||||
@ -1849,6 +1861,81 @@ static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL_CONNECTION *s,
|
|||||||
return MSG_PROCESS_ERROR;
|
return MSG_PROCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MSG_PROCESS_RETURN tls_process_server_rpk(SSL_CONNECTION *sc, PACKET *pkt)
|
||||||
|
{
|
||||||
|
EVP_PKEY *peer_rpk;
|
||||||
|
|
||||||
|
if (!tls_process_rpk(sc, pkt, &peer_rpk)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
return MSG_PROCESS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_rpk == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_CERTIFICATE);
|
||||||
|
return MSG_PROCESS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_free(sc->session->peer_rpk);
|
||||||
|
sc->session->peer_rpk = peer_rpk;
|
||||||
|
|
||||||
|
return MSG_PROCESS_CONTINUE_PROCESSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WORK_STATE tls_post_process_server_rpk(SSL_CONNECTION *sc,
|
||||||
|
WORK_STATE wst)
|
||||||
|
{
|
||||||
|
size_t certidx;
|
||||||
|
const SSL_CERT_LOOKUP *clu;
|
||||||
|
|
||||||
|
if (sc->session->peer_rpk == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER,
|
||||||
|
SSL_R_INVALID_RAW_PUBLIC_KEY);
|
||||||
|
return WORK_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sc->rwstate == SSL_RETRY_VERIFY)
|
||||||
|
sc->rwstate = SSL_NOTHING;
|
||||||
|
if (ssl_verify_rpk(sc, sc->session->peer_rpk) > 0
|
||||||
|
&& sc->rwstate == SSL_RETRY_VERIFY)
|
||||||
|
return WORK_MORE_A;
|
||||||
|
|
||||||
|
if ((clu = ssl_cert_lookup_by_pkey(sc->session->peer_rpk, &certidx,
|
||||||
|
SSL_CONNECTION_GET_CTX(sc))) == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||||
|
return WORK_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check certificate type is consistent with ciphersuite. For TLS 1.3
|
||||||
|
* skip check since TLS 1.3 ciphersuites can be used with any certificate
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
if (!SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
if ((clu->amask & sc->s3.tmp.new_cipher->algorithm_auth) == 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_RPK_TYPE);
|
||||||
|
return WORK_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure there is no peer/peer_chain */
|
||||||
|
X509_free(sc->session->peer);
|
||||||
|
sc->session->peer = NULL;
|
||||||
|
sk_X509_pop_free(sc->session->peer_chain, X509_free);
|
||||||
|
sc->session->peer_chain = NULL;
|
||||||
|
sc->session->verify_result = sc->verify_result;
|
||||||
|
|
||||||
|
/* Save the current hash state for when we receive the CertificateVerify */
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)
|
||||||
|
&& !ssl_handshake_hash(sc, sc->cert_verify_hash,
|
||||||
|
sizeof(sc->cert_verify_hash),
|
||||||
|
&sc->cert_verify_hash_len)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
return WORK_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WORK_FINISHED_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* prepare server cert verification by setting s->session->peer_chain from pkt */
|
/* prepare server cert verification by setting s->session->peer_chain from pkt */
|
||||||
MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
||||||
PACKET *pkt)
|
PACKET *pkt)
|
||||||
@ -1860,6 +1947,14 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
|||||||
unsigned int context = 0;
|
unsigned int context = 0;
|
||||||
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
||||||
|
|
||||||
|
if (s->ext.server_cert_type == TLSEXT_cert_type_rpk)
|
||||||
|
return tls_process_server_rpk(s, pkt);
|
||||||
|
if (s->ext.server_cert_type != TLSEXT_cert_type_x509) {
|
||||||
|
SSLfatal(s, SSL_AD_UNSUPPORTED_CERTIFICATE,
|
||||||
|
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if ((s->session->peer_chain = sk_X509_new_null()) == NULL) {
|
if ((s->session->peer_chain = sk_X509_new_null()) == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
@ -1947,6 +2042,9 @@ WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s,
|
|||||||
size_t certidx;
|
size_t certidx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (s->ext.server_cert_type == TLSEXT_cert_type_rpk)
|
||||||
|
return tls_post_process_server_rpk(s, wst);
|
||||||
|
|
||||||
if (s->rwstate == SSL_RETRY_VERIFY)
|
if (s->rwstate == SSL_RETRY_VERIFY)
|
||||||
s->rwstate = SSL_NOTHING;
|
s->rwstate = SSL_NOTHING;
|
||||||
i = ssl_verify_cert_chain(s, s->session->peer_chain);
|
i = ssl_verify_cert_chain(s, s->session->peer_chain);
|
||||||
@ -2009,6 +2107,9 @@ WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s,
|
|||||||
X509_up_ref(x);
|
X509_up_ref(x);
|
||||||
s->session->peer = x;
|
s->session->peer = x;
|
||||||
s->session->verify_result = s->verify_result;
|
s->session->verify_result = s->verify_result;
|
||||||
|
/* Ensure there is no RPK */
|
||||||
|
EVP_PKEY_free(s->session->peer_rpk);
|
||||||
|
s->session->peer_rpk = NULL;
|
||||||
|
|
||||||
/* Save the current hash state for when we receive the CertificateVerify */
|
/* Save the current hash state for when we receive the CertificateVerify */
|
||||||
if (SSL_CONNECTION_IS_TLS13(s)
|
if (SSL_CONNECTION_IS_TLS13(s)
|
||||||
@ -2111,7 +2212,7 @@ static int tls_process_ske_srp(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **pkey)
|
|||||||
|
|
||||||
/* We must check if there is a certificate */
|
/* We must check if there is a certificate */
|
||||||
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
|
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
|
||||||
*pkey = X509_get0_pubkey(s->session->peer);
|
*pkey = tls_get_peer_pkey(s);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
@ -2200,7 +2301,7 @@ static int tls_process_ske_dhe(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **pkey)
|
|||||||
* public keys. We should have a less ad-hoc way of doing this
|
* public keys. We should have a less ad-hoc way of doing this
|
||||||
*/
|
*/
|
||||||
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
|
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
|
||||||
*pkey = X509_get0_pubkey(s->session->peer);
|
*pkey = tls_get_peer_pkey(s);
|
||||||
/* else anonymous DH, so no certificate or pkey. */
|
/* else anonymous DH, so no certificate or pkey. */
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -2265,9 +2366,9 @@ static int tls_process_ske_ecdhe(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **pkey
|
|||||||
* and ECDSA.
|
* and ECDSA.
|
||||||
*/
|
*/
|
||||||
if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aECDSA)
|
if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aECDSA)
|
||||||
*pkey = X509_get0_pubkey(s->session->peer);
|
*pkey = tls_get_peer_pkey(s);
|
||||||
else if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aRSA)
|
else if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aRSA)
|
||||||
*pkey = X509_get0_pubkey(s->session->peer);
|
*pkey = tls_get_peer_pkey(s);
|
||||||
/* else anonymous ECDH, so no certificate or pkey. */
|
/* else anonymous ECDH, so no certificate or pkey. */
|
||||||
|
|
||||||
/* Cache the agreed upon group in the SSL_SESSION */
|
/* Cache the agreed upon group in the SSL_SESSION */
|
||||||
@ -2945,7 +3046,7 @@ static int tls_construct_cke_rsa(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
size_t pmslen = 0;
|
size_t pmslen = 0;
|
||||||
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
||||||
|
|
||||||
if (s->session->peer == NULL) {
|
if (!received_server_cert(s)) {
|
||||||
/*
|
/*
|
||||||
* We should always have a server certificate with SSL_kRSA.
|
* We should always have a server certificate with SSL_kRSA.
|
||||||
*/
|
*/
|
||||||
@ -2953,7 +3054,11 @@ static int tls_construct_cke_rsa(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey = X509_get0_pubkey(s->session->peer);
|
if ((pkey = tls_get_peer_pkey(s)) == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!EVP_PKEY_is_a(pkey, "RSA")) {
|
if (!EVP_PKEY_is_a(pkey, "RSA")) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
@ -3128,7 +3233,7 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
#ifndef OPENSSL_NO_GOST
|
#ifndef OPENSSL_NO_GOST
|
||||||
/* GOST key exchange message creation */
|
/* GOST key exchange message creation */
|
||||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||||
X509 *peer_cert;
|
EVP_PKEY *pkey = NULL;
|
||||||
size_t msglen;
|
size_t msglen;
|
||||||
unsigned int md_len;
|
unsigned int md_len;
|
||||||
unsigned char shared_ukm[32], tmp[256];
|
unsigned char shared_ukm[32], tmp[256];
|
||||||
@ -3144,15 +3249,14 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
/*
|
/*
|
||||||
* Get server certificate PKEY and create ctx from it
|
* Get server certificate PKEY and create ctx from it
|
||||||
*/
|
*/
|
||||||
peer_cert = s->session->peer;
|
if ((pkey = tls_get_peer_pkey(s)) == NULL) {
|
||||||
if (peer_cert == NULL) {
|
|
||||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
||||||
X509_get0_pubkey(peer_cert),
|
pkey,
|
||||||
sctx->propq);
|
sctx->propq);
|
||||||
if (pkey_ctx == NULL) {
|
if (pkey_ctx == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
||||||
@ -3279,7 +3383,7 @@ static int tls_construct_cke_gost18(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
unsigned char rnd_dgst[32];
|
unsigned char rnd_dgst[32];
|
||||||
unsigned char *encdata = NULL;
|
unsigned char *encdata = NULL;
|
||||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||||
X509 *peer_cert;
|
EVP_PKEY *pkey;
|
||||||
unsigned char *pms = NULL;
|
unsigned char *pms = NULL;
|
||||||
size_t pmslen = 0;
|
size_t pmslen = 0;
|
||||||
size_t msglen;
|
size_t msglen;
|
||||||
@ -3310,15 +3414,14 @@ static int tls_construct_cke_gost18(SSL_CONNECTION *s, WPACKET *pkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get server certificate PKEY and create ctx from it */
|
/* Get server certificate PKEY and create ctx from it */
|
||||||
peer_cert = s->session->peer;
|
if ((pkey = tls_get_peer_pkey(s)) == NULL) {
|
||||||
if (peer_cert == NULL) {
|
|
||||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
||||||
X509_get0_pubkey(peer_cert),
|
pkey,
|
||||||
sctx->propq);
|
sctx->propq);
|
||||||
if (pkey_ctx == NULL) {
|
if (pkey_ctx == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
||||||
@ -3629,6 +3732,7 @@ WORK_STATE tls_prepare_client_certificate(SSL_CONNECTION *s, WORK_STATE wst)
|
|||||||
CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
|
CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
|
||||||
WPACKET *pkt)
|
WPACKET *pkt)
|
||||||
{
|
{
|
||||||
|
CERT_PKEY *cpk = NULL;
|
||||||
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
|
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
|
||||||
|
|
||||||
if (SSL_CONNECTION_IS_TLS13(s)) {
|
if (SSL_CONNECTION_IS_TLS13(s)) {
|
||||||
@ -3643,12 +3747,25 @@ CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
|
|||||||
return CON_FUNC_ERROR;
|
return CON_FUNC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ssl3_output_cert_chain(s, pkt,
|
if (s->s3.tmp.cert_req != 2)
|
||||||
(s->s3.tmp.cert_req == 2) ? NULL
|
cpk = s->cert->key;
|
||||||
: s->cert->key, 0)) {
|
switch (s->ext.client_cert_type) {
|
||||||
|
case TLSEXT_cert_type_rpk:
|
||||||
|
if (!tls_output_rpk(s, pkt, cpk)) {
|
||||||
/* SSLfatal() already called */
|
/* SSLfatal() already called */
|
||||||
return CON_FUNC_ERROR;
|
return CON_FUNC_ERROR;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case TLSEXT_cert_type_x509:
|
||||||
|
if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
return CON_FUNC_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return CON_FUNC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (SSL_CONNECTION_IS_TLS13(s)
|
if (SSL_CONNECTION_IS_TLS13(s)
|
||||||
&& SSL_IS_FIRST_HANDSHAKE(s)
|
&& SSL_IS_FIRST_HANDSHAKE(s)
|
||||||
@ -3764,6 +3881,7 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
|||||||
const SSL_CERT_LOOKUP *clu;
|
const SSL_CERT_LOOKUP *clu;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
long alg_k, alg_a;
|
long alg_k, alg_a;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
|
alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
|
||||||
alg_a = s->s3.tmp.new_cipher->algorithm_auth;
|
alg_a = s->s3.tmp.new_cipher->algorithm_auth;
|
||||||
@ -3773,8 +3891,8 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* This is the passed certificate */
|
/* This is the passed certificate */
|
||||||
clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx,
|
pkey = tls_get_peer_pkey(s);
|
||||||
SSL_CONNECTION_GET_CTX(s));
|
clu = ssl_cert_lookup_by_pkey(pkey, &idx, SSL_CONNECTION_GET_CTX(s));
|
||||||
|
|
||||||
/* Check certificate is recognised and suitable for cipher */
|
/* Check certificate is recognised and suitable for cipher */
|
||||||
if (clu == NULL || (alg_a & clu->amask) == 0) {
|
if (clu == NULL || (alg_a & clu->amask) == 0) {
|
||||||
@ -3782,13 +3900,6 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clu->amask & SSL_aECDSA) {
|
|
||||||
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
|
|
||||||
return 1;
|
|
||||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
|
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
|
||||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
||||||
@ -3800,6 +3911,17 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Early out to skip the checks below */
|
||||||
|
if (s->session->peer_rpk != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (clu->amask & SSL_aECDSA) {
|
||||||
|
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
|
||||||
|
return 1;
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/trace.h>
|
#include <openssl/trace.h>
|
||||||
|
#include <openssl/encoder.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map error codes to TLS/SSL alart types.
|
* Map error codes to TLS/SSL alart types.
|
||||||
@ -447,7 +448,6 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL_CONNECTION *s, PACKET *pkt)
|
|||||||
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
||||||
int j;
|
int j;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
X509 *peer;
|
|
||||||
const EVP_MD *md = NULL;
|
const EVP_MD *md = NULL;
|
||||||
size_t hdatalen = 0;
|
size_t hdatalen = 0;
|
||||||
void *hdata;
|
void *hdata;
|
||||||
@ -461,8 +461,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL_CONNECTION *s, PACKET *pkt)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer = s->session->peer;
|
pkey = tls_get_peer_pkey(s);
|
||||||
pkey = X509_get0_pubkey(peer);
|
|
||||||
if (pkey == NULL) {
|
if (pkey == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
@ -1092,6 +1091,291 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVP_PKEY* tls_get_peer_pkey(const SSL_CONNECTION *sc)
|
||||||
|
{
|
||||||
|
if (sc->session->peer_rpk != NULL)
|
||||||
|
return sc->session->peer_rpk;
|
||||||
|
if (sc->session->peer != NULL)
|
||||||
|
return X509_get0_pubkey(sc->session->peer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls_process_rpk(SSL_CONNECTION *sc, PACKET *pkt, EVP_PKEY **peer_rpk)
|
||||||
|
{
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
RAW_EXTENSION *rawexts = NULL;
|
||||||
|
PACKET extensions;
|
||||||
|
PACKET context;
|
||||||
|
unsigned long cert_len = 0, spki_len = 0;
|
||||||
|
const unsigned char *spki, *spkistart;
|
||||||
|
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(sc);
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* ----------------------------
|
||||||
|
* TLS 1.3 Certificate message:
|
||||||
|
* ----------------------------
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2
|
||||||
|
*
|
||||||
|
* enum {
|
||||||
|
* X509(0),
|
||||||
|
* RawPublicKey(2),
|
||||||
|
* (255)
|
||||||
|
* } CertificateType;
|
||||||
|
*
|
||||||
|
* struct {
|
||||||
|
* select (certificate_type) {
|
||||||
|
* case RawPublicKey:
|
||||||
|
* // From RFC 7250 ASN.1_subjectPublicKeyInfo
|
||||||
|
* opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
|
||||||
|
*
|
||||||
|
* case X509:
|
||||||
|
* opaque cert_data<1..2^24-1>;
|
||||||
|
* };
|
||||||
|
* Extension extensions<0..2^16-1>;
|
||||||
|
* } CertificateEntry;
|
||||||
|
*
|
||||||
|
* struct {
|
||||||
|
* opaque certificate_request_context<0..2^8-1>;
|
||||||
|
* CertificateEntry certificate_list<0..2^24-1>;
|
||||||
|
* } Certificate;
|
||||||
|
*
|
||||||
|
* The client MUST send a Certificate message if and only if the server
|
||||||
|
* has requested client authentication via a CertificateRequest message
|
||||||
|
* (Section 4.3.2). If the server requests client authentication but no
|
||||||
|
* suitable certificate is available, the client MUST send a Certificate
|
||||||
|
* message containing no certificates (i.e., with the "certificate_list"
|
||||||
|
* field having length 0).
|
||||||
|
*
|
||||||
|
* ----------------------------
|
||||||
|
* TLS 1.2 Certificate message:
|
||||||
|
* ----------------------------
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc7250#section-3
|
||||||
|
*
|
||||||
|
* opaque ASN.1Cert<1..2^24-1>;
|
||||||
|
*
|
||||||
|
* struct {
|
||||||
|
* select(certificate_type){
|
||||||
|
*
|
||||||
|
* // certificate type defined in this document.
|
||||||
|
* case RawPublicKey:
|
||||||
|
* opaque ASN.1_subjectPublicKeyInfo<1..2^24-1>;
|
||||||
|
*
|
||||||
|
* // X.509 certificate defined in RFC 5246
|
||||||
|
* case X.509:
|
||||||
|
* ASN.1Cert certificate_list<0..2^24-1>;
|
||||||
|
*
|
||||||
|
* // Additional certificate type based on
|
||||||
|
* // "TLS Certificate Types" subregistry
|
||||||
|
* };
|
||||||
|
* } Certificate;
|
||||||
|
*
|
||||||
|
* -------------
|
||||||
|
* Consequently:
|
||||||
|
* -------------
|
||||||
|
* After the (TLS 1.3 only) context octet string (1 byte length + data) the
|
||||||
|
* Certificate message has a 3-byte length that is zero in the client to
|
||||||
|
* server message when the client has no RPK to send. In that case, there
|
||||||
|
* are no (TLS 1.3 only) per-certificate extensions either, because the
|
||||||
|
* [CertificateEntry] list is empty.
|
||||||
|
*
|
||||||
|
* In the server to client direction, or when the client had an RPK to send,
|
||||||
|
* the TLS 1.3 message just prepends the length of the RPK+extensions,
|
||||||
|
* while TLS <= 1.2 sends just the RPK (octet-string).
|
||||||
|
*
|
||||||
|
* The context must be zero-length in the server to client direction, and
|
||||||
|
* must match the value recorded in the certificate request in the client
|
||||||
|
* to server direction.
|
||||||
|
*/
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
if (!PACKET_get_length_prefixed_1(pkt, &context)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (sc->server) {
|
||||||
|
if (sc->pha_context == NULL) {
|
||||||
|
if (PACKET_remaining(&context) != 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!PACKET_equal(&context, sc->pha_context, sc->pha_context_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (PACKET_remaining(&context) != 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PACKET_get_net_3(pkt, &cert_len)
|
||||||
|
|| PACKET_remaining(pkt) != cert_len) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The list length may be zero when there is no RPK. In the case of TLS
|
||||||
|
* 1.2 this is actually the RPK length, which cannot be zero as specified,
|
||||||
|
* but that breaks the ability of the client to decline client auth. We
|
||||||
|
* overload the 0 RPK length to mean "no RPK". This interpretation is
|
||||||
|
* also used some other (reference?) implementations, but is not supported
|
||||||
|
* by the verbatim RFC7250 text.
|
||||||
|
*/
|
||||||
|
if (cert_len == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
/*
|
||||||
|
* With TLS 1.3, a non-empty explicit-length RPK octet-string followed
|
||||||
|
* by a possibly empty extension block.
|
||||||
|
*/
|
||||||
|
if (!PACKET_get_net_3(pkt, &spki_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (spki_len == 0) {
|
||||||
|
/* empty RPK */
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_EMPTY_RAW_PUBLIC_KEY);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spki_len = cert_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PACKET_get_bytes(pkt, &spki, spki_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
spkistart = spki;
|
||||||
|
if ((pkey = d2i_PUBKEY_ex(NULL, &spki, spki_len, sctx->libctx, sctx->propq)) == NULL
|
||||||
|
|| spki != (spkistart + spki_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (EVP_PKEY_missing_parameters(pkey)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR,
|
||||||
|
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the Extensions block */
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
if (PACKET_remaining(pkt) != (cert_len - 3 - spki_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!PACKET_as_length_prefixed_2(pkt, &extensions)
|
||||||
|
|| PACKET_remaining(pkt) != 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!tls_collect_extensions(sc, &extensions, SSL_EXT_TLS1_3_RAW_PUBLIC_KEY,
|
||||||
|
&rawexts, NULL, 1)) {
|
||||||
|
/* SSLfatal already called */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* chain index is always zero and fin always 1 for RPK */
|
||||||
|
if (!tls_parse_all_extensions(sc, SSL_EXT_TLS1_3_RAW_PUBLIC_KEY,
|
||||||
|
rawexts, NULL, 0, 1)) {
|
||||||
|
/* SSLfatal already called */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
if (peer_rpk != NULL) {
|
||||||
|
*peer_rpk = pkey;
|
||||||
|
pkey = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
OPENSSL_free(rawexts);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long tls_output_rpk(SSL_CONNECTION *sc, WPACKET *pkt, CERT_PKEY *cpk)
|
||||||
|
{
|
||||||
|
int pdata_len = 0;
|
||||||
|
unsigned char *pdata = NULL;
|
||||||
|
X509_PUBKEY *xpk = NULL;
|
||||||
|
unsigned long ret = 0;
|
||||||
|
X509 *x509 = NULL;
|
||||||
|
|
||||||
|
if (cpk != NULL && cpk->x509 != NULL) {
|
||||||
|
x509 = cpk->x509;
|
||||||
|
/* Get the RPK from the certificate */
|
||||||
|
xpk = X509_get_X509_PUBKEY(cpk->x509);
|
||||||
|
if (xpk == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
pdata_len = i2d_X509_PUBKEY(xpk, &pdata);
|
||||||
|
} else if (cpk != NULL && cpk->privatekey != NULL) {
|
||||||
|
/* Get the RPK from the private key */
|
||||||
|
pdata_len = i2d_PUBKEY(cpk->privatekey, &pdata);
|
||||||
|
} else {
|
||||||
|
/* The server RPK is not optional */
|
||||||
|
if (sc->server) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* The client can send a zero length certificate list */
|
||||||
|
if (!WPACKET_sub_memcpy_u24(pkt, pdata, pdata_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata_len <= 0) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLSv1.2 is _just_ the raw public key
|
||||||
|
* TLSv1.3 includes extensions, so there's a length wrapper
|
||||||
|
*/
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
if (!WPACKET_start_sub_packet_u24(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WPACKET_sub_memcpy_u24(pkt, pdata, pdata_len)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
/*
|
||||||
|
* Only send extensions relevent to raw public keys. Until such
|
||||||
|
* extensions are defined, this will be an empty set of extensions.
|
||||||
|
* |x509| may be NULL, which raw public-key extensions need to handle.
|
||||||
|
*/
|
||||||
|
if (!tls_construct_extensions(sc, pkt, SSL_EXT_TLS1_3_RAW_PUBLIC_KEY,
|
||||||
|
x509, 0)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!WPACKET_close(pkt)) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
err:
|
||||||
|
OPENSSL_free(pdata);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long ssl3_output_cert_chain(SSL_CONNECTION *s, WPACKET *pkt,
|
unsigned long ssl3_output_cert_chain(SSL_CONNECTION *s, WPACKET *pkt,
|
||||||
CERT_PKEY *cpk, int for_comp)
|
CERT_PKEY *cpk, int for_comp)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -173,6 +173,13 @@ __owur CON_FUNC_RETURN tls_construct_cert_status(SSL_CONNECTION *s,
|
|||||||
WPACKET *pkt);
|
WPACKET *pkt);
|
||||||
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL_CONNECTION *s,
|
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL_CONNECTION *s,
|
||||||
PACKET *pkt);
|
PACKET *pkt);
|
||||||
|
__owur MSG_PROCESS_RETURN tls_process_server_rpk(SSL_CONNECTION *sc,
|
||||||
|
PACKET *pkt);
|
||||||
|
__owur MSG_PROCESS_RETURN tls_process_client_rpk(SSL_CONNECTION *sc,
|
||||||
|
PACKET *pkt);
|
||||||
|
__owur unsigned long tls_output_rpk(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
CERT_PKEY *cpk);
|
||||||
|
__owur int tls_process_rpk(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **peer_rpk);
|
||||||
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
||||||
PACKET *pkt);
|
PACKET *pkt);
|
||||||
__owur WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s,
|
__owur WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s,
|
||||||
@ -536,3 +543,30 @@ int tls_handle_alpn(SSL_CONNECTION *s);
|
|||||||
|
|
||||||
int tls13_save_handshake_digest_for_pha(SSL_CONNECTION *s);
|
int tls13_save_handshake_digest_for_pha(SSL_CONNECTION *s);
|
||||||
int tls13_restore_handshake_digest_for_pha(SSL_CONNECTION *s);
|
int tls13_restore_handshake_digest_for_pha(SSL_CONNECTION *s);
|
||||||
|
|
||||||
|
__owur EVP_PKEY* tls_get_peer_pkey(const SSL_CONNECTION *sc);
|
||||||
|
/* RFC7250 */
|
||||||
|
EXT_RETURN tls_construct_ctos_client_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
EXT_RETURN tls_construct_stoc_client_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
int tls_parse_ctos_client_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
int tls_parse_stoc_client_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
EXT_RETURN tls_construct_ctos_server_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
EXT_RETURN tls_construct_stoc_server_cert_type(SSL_CONNECTION *sc, WPACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
int tls_parse_ctos_server_cert_type(SSL_CONNECTION *sc, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
int tls_parse_stoc_server_cert_type(SSL_CONNECTION *s, PACKET *pkt,
|
||||||
|
unsigned int context,
|
||||||
|
X509 *x, size_t chainidx);
|
||||||
|
@ -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 (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
* Copyright 2005 Nokia. All rights reserved.
|
* Copyright 2005 Nokia. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -47,6 +47,11 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
|
|||||||
static CON_FUNC_RETURN tls_construct_encrypted_extensions(SSL_CONNECTION *s,
|
static CON_FUNC_RETURN tls_construct_encrypted_extensions(SSL_CONNECTION *s,
|
||||||
WPACKET *pkt);
|
WPACKET *pkt);
|
||||||
|
|
||||||
|
static ossl_inline int received_client_cert(const SSL_CONNECTION *sc)
|
||||||
|
{
|
||||||
|
return sc->session->peer_rpk != NULL || sc->session->peer != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ossl_statem_server13_read_transition() encapsulates the logic for the allowed
|
* ossl_statem_server13_read_transition() encapsulates the logic for the allowed
|
||||||
* handshake state transitions when a TLSv1.3 server is reading messages from
|
* handshake state transitions when a TLSv1.3 server is reading messages from
|
||||||
@ -109,7 +114,7 @@ static int ossl_statem_server13_read_transition(SSL_CONNECTION *s, int mt)
|
|||||||
|
|
||||||
case TLS_ST_SR_COMP_CERT:
|
case TLS_ST_SR_COMP_CERT:
|
||||||
case TLS_ST_SR_CERT:
|
case TLS_ST_SR_CERT:
|
||||||
if (s->session->peer == NULL) {
|
if (!received_client_cert(s)) {
|
||||||
if (mt == SSL3_MT_FINISHED) {
|
if (mt == SSL3_MT_FINISHED) {
|
||||||
st->hand_state = TLS_ST_SR_FINISHED;
|
st->hand_state = TLS_ST_SR_FINISHED;
|
||||||
return 1;
|
return 1;
|
||||||
@ -250,7 +255,7 @@ int ossl_statem_server_read_transition(SSL_CONNECTION *s, int mt)
|
|||||||
* the case of static DH). In that case |st->no_cert_verify| should be
|
* the case of static DH). In that case |st->no_cert_verify| should be
|
||||||
* set.
|
* set.
|
||||||
*/
|
*/
|
||||||
if (s->session->peer == NULL || st->no_cert_verify) {
|
if (!received_client_cert(s) || st->no_cert_verify) {
|
||||||
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||||
/*
|
/*
|
||||||
* For the ECDH ciphersuites when the client sends its ECDH
|
* For the ECDH ciphersuites when the client sends its ECDH
|
||||||
@ -444,6 +449,13 @@ int send_certificate_request(SSL_CONNECTION *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_compressed_cert(SSL_CONNECTION *sc)
|
||||||
|
{
|
||||||
|
/* If we negotiated RPK, we won't attempt to compress it */
|
||||||
|
return sc->ext.server_cert_type == TLSEXT_cert_type_x509
|
||||||
|
&& get_compressed_certificate_alg(sc) != TLSEXT_comp_cert_none;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ossl_statem_server13_write_transition() works out what handshake state to
|
* ossl_statem_server13_write_transition() works out what handshake state to
|
||||||
* move to next when a TLSv1.3 server is writing messages to be sent to the
|
* move to next when a TLSv1.3 server is writing messages to be sent to the
|
||||||
@ -506,7 +518,7 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL_CONNECTION *s)
|
|||||||
st->hand_state = TLS_ST_SW_FINISHED;
|
st->hand_state = TLS_ST_SW_FINISHED;
|
||||||
else if (send_certificate_request(s))
|
else if (send_certificate_request(s))
|
||||||
st->hand_state = TLS_ST_SW_CERT_REQ;
|
st->hand_state = TLS_ST_SW_CERT_REQ;
|
||||||
else if (get_compressed_certificate_alg(s) != TLSEXT_comp_cert_none)
|
else if (do_compressed_cert(s))
|
||||||
st->hand_state = TLS_ST_SW_COMP_CERT;
|
st->hand_state = TLS_ST_SW_COMP_CERT;
|
||||||
else
|
else
|
||||||
st->hand_state = TLS_ST_SW_CERT;
|
st->hand_state = TLS_ST_SW_CERT;
|
||||||
@ -517,7 +529,7 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL_CONNECTION *s)
|
|||||||
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
||||||
s->post_handshake_auth = SSL_PHA_REQUESTED;
|
s->post_handshake_auth = SSL_PHA_REQUESTED;
|
||||||
st->hand_state = TLS_ST_OK;
|
st->hand_state = TLS_ST_OK;
|
||||||
} else if (get_compressed_certificate_alg(s) != TLSEXT_comp_cert_none) {
|
} else if (do_compressed_cert(s)) {
|
||||||
st->hand_state = TLS_ST_SW_COMP_CERT;
|
st->hand_state = TLS_ST_SW_COMP_CERT;
|
||||||
} else {
|
} else {
|
||||||
st->hand_state = TLS_ST_SW_CERT;
|
st->hand_state = TLS_ST_SW_CERT;
|
||||||
@ -3243,7 +3255,7 @@ static int tls_process_cke_gost(SSL_CONNECTION *s, PACKET *pkt)
|
|||||||
* EVP_PKEY_derive_set_peer, because it is completely valid to use a
|
* EVP_PKEY_derive_set_peer, because it is completely valid to use a
|
||||||
* client certificate for authorization only.
|
* client certificate for authorization only.
|
||||||
*/
|
*/
|
||||||
client_pub_pkey = X509_get0_pubkey(s->session->peer);
|
client_pub_pkey = tls_get_peer_pkey(s);
|
||||||
if (client_pub_pkey) {
|
if (client_pub_pkey) {
|
||||||
if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
@ -3485,7 +3497,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL_CONNECTION *s,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (s->statem.no_cert_verify || !s->session->peer) {
|
if (s->statem.no_cert_verify || !received_client_cert(s)) {
|
||||||
/*
|
/*
|
||||||
* No certificate verify or no peer certificate so we no longer need
|
* No certificate verify or no peer certificate so we no longer need
|
||||||
* the handshake_buffer
|
* the handshake_buffer
|
||||||
@ -3513,6 +3525,91 @@ WORK_STATE tls_post_process_client_key_exchange(SSL_CONNECTION *s,
|
|||||||
return WORK_FINISHED_CONTINUE;
|
return WORK_FINISHED_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MSG_PROCESS_RETURN tls_process_client_rpk(SSL_CONNECTION *sc, PACKET *pkt)
|
||||||
|
{
|
||||||
|
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
||||||
|
SSL_SESSION *new_sess = NULL;
|
||||||
|
EVP_PKEY *peer_rpk = NULL;
|
||||||
|
|
||||||
|
if (!tls_process_rpk(sc, pkt, &peer_rpk)) {
|
||||||
|
/* SSLfatal already called */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_rpk == NULL) {
|
||||||
|
if ((sc->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
|
||||||
|
&& (sc->verify_mode & SSL_VERIFY_PEER)) {
|
||||||
|
SSLfatal(sc, SSL_AD_CERTIFICATE_REQUIRED,
|
||||||
|
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ssl_verify_rpk(sc, peer_rpk) <= 0) {
|
||||||
|
SSLfatal(sc, ssl_x509err2alert(sc->verify_result),
|
||||||
|
SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sessions must be immutable once they go into the session cache. Otherwise
|
||||||
|
* we can get multi-thread problems. Therefore we don't "update" sessions,
|
||||||
|
* we replace them with a duplicate. Here, we need to do this every time
|
||||||
|
* a new RPK (or certificate) is received via post-handshake authentication,
|
||||||
|
* as the session may have already gone into the session cache.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sc->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||||
|
if ((new_sess = ssl_session_dup(sc->session, 0)) == NULL) {
|
||||||
|
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_SESSION_free(sc->session);
|
||||||
|
sc->session = new_sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure there is no peer/peer_chain */
|
||||||
|
X509_free(sc->session->peer);
|
||||||
|
sc->session->peer = NULL;
|
||||||
|
sk_X509_pop_free(sc->session->peer_chain, X509_free);
|
||||||
|
sc->session->peer_chain = NULL;
|
||||||
|
/* Save RPK */
|
||||||
|
EVP_PKEY_free(sc->session->peer_rpk);
|
||||||
|
sc->session->peer_rpk = peer_rpk;
|
||||||
|
peer_rpk = NULL;
|
||||||
|
|
||||||
|
sc->session->verify_result = sc->verify_result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
|
||||||
|
* message
|
||||||
|
*/
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)) {
|
||||||
|
if (!ssl3_digest_cached_records(sc, 1)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the current hash state for when we receive the CertificateVerify */
|
||||||
|
if (!ssl_handshake_hash(sc, sc->cert_verify_hash,
|
||||||
|
sizeof(sc->cert_verify_hash),
|
||||||
|
&sc->cert_verify_hash_len)) {
|
||||||
|
/* SSLfatal() already called */;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resend session tickets */
|
||||||
|
sc->sent_tickets = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = MSG_PROCESS_CONTINUE_READING;
|
||||||
|
|
||||||
|
err:
|
||||||
|
EVP_PKEY_free(peer_rpk);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
|
MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
|
||||||
PACKET *pkt)
|
PACKET *pkt)
|
||||||
{
|
{
|
||||||
@ -3534,6 +3631,15 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
|
|||||||
if (s->rlayer.rrlmethod->set_plain_alerts != NULL)
|
if (s->rlayer.rrlmethod->set_plain_alerts != NULL)
|
||||||
s->rlayer.rrlmethod->set_plain_alerts(s->rlayer.rrl, 0);
|
s->rlayer.rrlmethod->set_plain_alerts(s->rlayer.rrl, 0);
|
||||||
|
|
||||||
|
if (s->ext.client_cert_type == TLSEXT_cert_type_rpk)
|
||||||
|
return tls_process_client_rpk(s, pkt);
|
||||||
|
|
||||||
|
if (s->ext.client_cert_type != TLSEXT_cert_type_x509) {
|
||||||
|
SSLfatal(s, SSL_AD_UNSUPPORTED_CERTIFICATE,
|
||||||
|
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if ((sk = sk_X509_new_null()) == NULL) {
|
if ((sk = sk_X509_new_null()) == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
@ -3665,6 +3771,9 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
|
|||||||
OSSL_STACK_OF_X509_free(s->session->peer_chain);
|
OSSL_STACK_OF_X509_free(s->session->peer_chain);
|
||||||
s->session->peer_chain = sk;
|
s->session->peer_chain = sk;
|
||||||
sk = NULL;
|
sk = NULL;
|
||||||
|
/* Ensure there is no RPK */
|
||||||
|
EVP_PKEY_free(s->session->peer_rpk);
|
||||||
|
s->session->peer_rpk = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
|
* Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
|
||||||
@ -3733,9 +3842,22 @@ CON_FUNC_RETURN tls_construct_server_certificate(SSL_CONNECTION *s, WPACKET *pkt
|
|||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
return CON_FUNC_ERROR;
|
return CON_FUNC_ERROR;
|
||||||
}
|
}
|
||||||
|
switch (s->ext.server_cert_type) {
|
||||||
|
case TLSEXT_cert_type_rpk:
|
||||||
|
if (!tls_output_rpk(s, pkt, cpk)) {
|
||||||
|
/* SSLfatal() already called */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TLSEXT_cert_type_x509:
|
||||||
if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
|
if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
|
||||||
/* SSLfatal() already called */
|
/* SSLfatal() already called */
|
||||||
return CON_FUNC_ERROR;
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CON_FUNC_SUCCESS;
|
return CON_FUNC_SUCCESS;
|
||||||
@ -3869,7 +3991,8 @@ static CON_FUNC_RETURN construct_stateless_ticket(SSL_CONNECTION *s,
|
|||||||
* create a fresh copy (not shared with other threads) to clean up
|
* create a fresh copy (not shared with other threads) to clean up
|
||||||
*/
|
*/
|
||||||
const_p = senc;
|
const_p = senc;
|
||||||
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
|
sess = d2i_SSL_SESSION_ex(NULL, &const_p, slen_full, sctx->libctx,
|
||||||
|
sctx->propq);
|
||||||
if (sess == NULL) {
|
if (sess == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
|
30
ssl/t1_lib.c
30
ssl/t1_lib.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
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -2192,6 +2192,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s,
|
|||||||
SSL_HMAC *hctx = NULL;
|
SSL_HMAC *hctx = NULL;
|
||||||
EVP_CIPHER_CTX *ctx = NULL;
|
EVP_CIPHER_CTX *ctx = NULL;
|
||||||
SSL_CTX *tctx = s->session_ctx;
|
SSL_CTX *tctx = s->session_ctx;
|
||||||
|
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
||||||
|
|
||||||
if (eticklen == 0) {
|
if (eticklen == 0) {
|
||||||
/*
|
/*
|
||||||
@ -2263,7 +2264,6 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s,
|
|||||||
renew_ticket = 1;
|
renew_ticket = 1;
|
||||||
} else {
|
} else {
|
||||||
EVP_CIPHER *aes256cbc = NULL;
|
EVP_CIPHER *aes256cbc = NULL;
|
||||||
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
|
||||||
|
|
||||||
/* Check key name matches */
|
/* Check key name matches */
|
||||||
if (memcmp(etick, tctx->ext.tick_key_name,
|
if (memcmp(etick, tctx->ext.tick_key_name,
|
||||||
@ -2341,7 +2341,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s,
|
|||||||
slen += declen;
|
slen += declen;
|
||||||
p = sdec;
|
p = sdec;
|
||||||
|
|
||||||
sess = d2i_SSL_SESSION(NULL, &p, slen);
|
sess = d2i_SSL_SESSION_ex(NULL, &p, slen, sctx->libctx, sctx->propq);
|
||||||
slen -= p - sdec;
|
slen -= p - sdec;
|
||||||
OPENSSL_free(sdec);
|
OPENSSL_free(sdec);
|
||||||
if (sess) {
|
if (sess) {
|
||||||
@ -3048,9 +3048,15 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
|
|||||||
uint32_t *pvalid;
|
uint32_t *pvalid;
|
||||||
unsigned int suiteb_flags = tls1_suiteb(s);
|
unsigned int suiteb_flags = tls1_suiteb(s);
|
||||||
|
|
||||||
/* idx == -1 means checking server chains */
|
/*
|
||||||
|
* Meaning of idx:
|
||||||
|
* idx == -1 means SSL_check_chain() invocation
|
||||||
|
* idx == -2 means checking client certificate chains
|
||||||
|
* idx >= 0 means checking SSL_PKEY index
|
||||||
|
*
|
||||||
|
* For RPK, where there may be no cert, we ignore -1
|
||||||
|
*/
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
/* idx == -2 means checking client certificate chains */
|
|
||||||
if (idx == -2) {
|
if (idx == -2) {
|
||||||
cpk = c->key;
|
cpk = c->key;
|
||||||
idx = (int)(cpk - c->pkeys);
|
idx = (int)(cpk - c->pkeys);
|
||||||
@ -3061,13 +3067,19 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
|
|||||||
pk = cpk->privatekey;
|
pk = cpk->privatekey;
|
||||||
chain = cpk->chain;
|
chain = cpk->chain;
|
||||||
strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
|
strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
|
||||||
|
if (tls12_rpk_and_privkey(s, idx)) {
|
||||||
|
if (EVP_PKEY_is_a(pk, "EC") && !tls1_check_pkey_comp(s, pk))
|
||||||
|
return 0;
|
||||||
|
*pvalid = rv = CERT_PKEY_RPK;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
/* If no cert or key, forget it */
|
/* If no cert or key, forget it */
|
||||||
if (!x || !pk)
|
if (x == NULL || pk == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
} else {
|
} else {
|
||||||
size_t certidx;
|
size_t certidx;
|
||||||
|
|
||||||
if (!x || !pk)
|
if (x == NULL || pk == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ssl_cert_lookup_by_pkey(pk, &certidx,
|
if (ssl_cert_lookup_by_pkey(pk, &certidx,
|
||||||
@ -3487,6 +3499,10 @@ static int tls12_get_cert_sigalg_idx(const SSL_CONNECTION *s,
|
|||||||
&& (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
|
&& (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* If doing RPK, the CERT_PKEY won't be "valid" */
|
||||||
|
if (tls12_rpk_and_privkey(s, sig_idx))
|
||||||
|
return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_RPK ? sig_idx : -1;
|
||||||
|
|
||||||
return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
|
return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2012-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@ -477,6 +477,8 @@ static const ssl_trace_tbl ssl_exts_tbl[] = {
|
|||||||
{TLSEXT_TYPE_application_layer_protocol_negotiation,
|
{TLSEXT_TYPE_application_layer_protocol_negotiation,
|
||||||
"application_layer_protocol_negotiation"},
|
"application_layer_protocol_negotiation"},
|
||||||
{TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
|
{TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
|
||||||
|
{TLSEXT_TYPE_client_cert_type, "client_cert_type"},
|
||||||
|
{TLSEXT_TYPE_server_cert_type, "server_cert_type"},
|
||||||
{TLSEXT_TYPE_padding, "padding"},
|
{TLSEXT_TYPE_padding, "padding"},
|
||||||
{TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
|
{TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
|
||||||
{TLSEXT_TYPE_extended_master_secret, "extended_master_secret"},
|
{TLSEXT_TYPE_extended_master_secret, "extended_master_secret"},
|
||||||
@ -627,6 +629,18 @@ static const ssl_trace_tbl ssl_comp_cert_tbl[] = {
|
|||||||
{TLSEXT_comp_cert_zstd, "zstd"}
|
{TLSEXT_comp_cert_zstd, "zstd"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "pgp" and "1609dot2" are defined in RFC7250,
|
||||||
|
* although OpenSSL doesn't support them, it can
|
||||||
|
* at least report them in traces
|
||||||
|
*/
|
||||||
|
static const ssl_trace_tbl ssl_cert_type_tbl[] = {
|
||||||
|
{TLSEXT_cert_type_x509, "x509"},
|
||||||
|
{TLSEXT_cert_type_pgp, "pgp"},
|
||||||
|
{TLSEXT_cert_type_rpk, "rpk"},
|
||||||
|
{TLSEXT_cert_type_1609dot2, "1609dot2"}
|
||||||
|
};
|
||||||
|
|
||||||
static void ssl_print_hex(BIO *bio, int indent, const char *name,
|
static void ssl_print_hex(BIO *bio, int indent, const char *name,
|
||||||
const unsigned char *msg, size_t msglen)
|
const unsigned char *msg, size_t msglen)
|
||||||
{
|
{
|
||||||
@ -910,6 +924,20 @@ static int ssl_print_extension(BIO *bio, int indent, int server,
|
|||||||
BIO_printf(bio, "max_early_data=%u\n", (unsigned int)max_early_data);
|
BIO_printf(bio, "max_early_data=%u\n", (unsigned int)max_early_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TLSEXT_TYPE_server_cert_type:
|
||||||
|
case TLSEXT_TYPE_client_cert_type:
|
||||||
|
if (server) {
|
||||||
|
if (extlen != 1)
|
||||||
|
return 0;
|
||||||
|
return ssl_trace_list(bio, indent + 2, ext, 1, 1, ssl_cert_type_tbl);
|
||||||
|
}
|
||||||
|
if (extlen < 1)
|
||||||
|
return 0;
|
||||||
|
xlen = ext[0];
|
||||||
|
if (extlen != xlen + 1)
|
||||||
|
return 0;
|
||||||
|
return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1, ssl_cert_type_tbl);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
|
BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
|
||||||
}
|
}
|
||||||
@ -1275,6 +1303,36 @@ static int ssl_print_certificate(BIO *bio, int indent,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ssl_print_raw_public_key(BIO *bio, const SSL *ssl, int server,
|
||||||
|
int indent, const unsigned char **pmsg,
|
||||||
|
size_t *pmsglen)
|
||||||
|
{
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
size_t clen;
|
||||||
|
const unsigned char *msg = *pmsg;
|
||||||
|
size_t msglen = *pmsglen;
|
||||||
|
|
||||||
|
if (msglen < 3)
|
||||||
|
return 0;
|
||||||
|
clen = (msg[0] << 16) | (msg[1] << 8) | msg[2];
|
||||||
|
if (msglen < clen + 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
msg += 3;
|
||||||
|
|
||||||
|
BIO_indent(bio, indent, 80);
|
||||||
|
BIO_printf(bio, "raw_public_key, length=%d\n", (int)clen);
|
||||||
|
|
||||||
|
pkey = d2i_PUBKEY_ex(NULL, &msg, clen, ssl->ctx->libctx, ssl->ctx->propq);
|
||||||
|
if (pkey == NULL)
|
||||||
|
return 0;
|
||||||
|
EVP_PKEY_print_public(bio, pkey, indent + 2, NULL);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
*pmsg += clen + 3;
|
||||||
|
*pmsglen -= clen + 3;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int ssl_print_certificates(BIO *bio, const SSL_CONNECTION *sc, int server,
|
static int ssl_print_certificates(BIO *bio, const SSL_CONNECTION *sc, int server,
|
||||||
int indent, const unsigned char *msg,
|
int indent, const unsigned char *msg,
|
||||||
size_t msglen)
|
size_t msglen)
|
||||||
@ -1291,6 +1349,16 @@ static int ssl_print_certificates(BIO *bio, const SSL_CONNECTION *sc, int server
|
|||||||
if (msglen != clen + 3)
|
if (msglen != clen + 3)
|
||||||
return 0;
|
return 0;
|
||||||
msg += 3;
|
msg += 3;
|
||||||
|
if ((server && sc->ext.server_cert_type == TLSEXT_cert_type_rpk)
|
||||||
|
|| (!server && sc->ext.client_cert_type == TLSEXT_cert_type_rpk)) {
|
||||||
|
if (!ssl_print_raw_public_key(bio, &sc->ssl, server, indent, &msg, &clen))
|
||||||
|
return 0;
|
||||||
|
if (SSL_CONNECTION_IS_TLS13(sc)
|
||||||
|
&& !ssl_print_extensions(bio, indent + 2, server,
|
||||||
|
SSL3_MT_CERTIFICATE, &msg, &clen))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
BIO_indent(bio, indent, 80);
|
BIO_indent(bio, indent, 80);
|
||||||
BIO_printf(bio, "certificate_list, length=%d\n", (int)clen);
|
BIO_printf(bio, "certificate_list, length=%d\n", (int)clen);
|
||||||
while (clen > 0) {
|
while (clen > 0) {
|
||||||
|
@ -66,6 +66,10 @@ IF[{- !$disabled{tests} -}]
|
|||||||
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \
|
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \
|
||||||
x509_test hpke_test pairwise_fail_test nodefltctxtest
|
x509_test hpke_test pairwise_fail_test nodefltctxtest
|
||||||
|
|
||||||
|
IF[{- !$disabled{'rpk'} -}]
|
||||||
|
PROGRAMS{noinst}=rpktest
|
||||||
|
ENDIF
|
||||||
|
|
||||||
IF[{- !$disabled{'deprecated-3.0'} -}]
|
IF[{- !$disabled{'deprecated-3.0'} -}]
|
||||||
PROGRAMS{noinst}=enginetest
|
PROGRAMS{noinst}=enginetest
|
||||||
ENDIF
|
ENDIF
|
||||||
@ -485,6 +489,10 @@ IF[{- !$disabled{tests} -}]
|
|||||||
INCLUDE[sslapitest]=../include ../apps/include ..
|
INCLUDE[sslapitest]=../include ../apps/include ..
|
||||||
DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a
|
DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a
|
||||||
|
|
||||||
|
SOURCE[rpktest]=rpktest.c helpers/ssltestlib.c
|
||||||
|
INCLUDE[rpktest]=../include ../apps/include ..
|
||||||
|
DEPEND[rpktest]=../libcrypto ../libssl libtestutil.a
|
||||||
|
|
||||||
SOURCE[defltfips_test]=defltfips_test.c
|
SOURCE[defltfips_test]=defltfips_test.c
|
||||||
INCLUDE[defltfips_test]=../include ../apps/include
|
INCLUDE[defltfips_test]=../include ../apps/include
|
||||||
DEPEND[defltfips_test]=../libcrypto libtestutil.a
|
DEPEND[defltfips_test]=../libcrypto libtestutil.a
|
||||||
|
@ -61,6 +61,8 @@ static EXT_LIST ext_list[] = {
|
|||||||
EXT_ENTRY(extended_master_secret),
|
EXT_ENTRY(extended_master_secret),
|
||||||
EXT_ENTRY(signature_algorithms_cert),
|
EXT_ENTRY(signature_algorithms_cert),
|
||||||
EXT_ENTRY(post_handshake_auth),
|
EXT_ENTRY(post_handshake_auth),
|
||||||
|
EXT_ENTRY(client_cert_type),
|
||||||
|
EXT_ENTRY(server_cert_type),
|
||||||
EXT_ENTRY(signature_algorithms),
|
EXT_ENTRY(signature_algorithms),
|
||||||
EXT_ENTRY(supported_versions),
|
EXT_ENTRY(supported_versions),
|
||||||
EXT_ENTRY(psk_kex_modes),
|
EXT_ENTRY(psk_kex_modes),
|
||||||
|
96
test/recipes/70-test_certtypeext.t
Normal file
96
test/recipes/70-test_certtypeext.t
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#! /usr/bin/env perl
|
||||||
|
# Copyright 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
|
||||||
|
# in the file LICENSE in the source distribution or at
|
||||||
|
# https://www.openssl.org/source/license.html
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
|
||||||
|
use OpenSSL::Test::Utils;
|
||||||
|
use TLSProxy::Proxy;
|
||||||
|
|
||||||
|
my $test_name = "test_certtypeext";
|
||||||
|
setup($test_name);
|
||||||
|
|
||||||
|
plan skip_all => "TLSProxy isn't usable on $^O"
|
||||||
|
if $^O =~ /^(VMS)$/;
|
||||||
|
|
||||||
|
plan skip_all => "$test_name needs the dynamic engine feature enabled"
|
||||||
|
if disabled("engine") || disabled("dynamic-engine");
|
||||||
|
|
||||||
|
plan skip_all => "$test_name needs the sock feature enabled"
|
||||||
|
if disabled("sock");
|
||||||
|
|
||||||
|
plan skip_all => "$test_name needs TLSv1.2 enabled"
|
||||||
|
if disabled("tls1_2");
|
||||||
|
|
||||||
|
my $proxy = TLSProxy::Proxy->new(
|
||||||
|
\&certtype_filter,
|
||||||
|
cmdstr(app(["openssl"]), display => 1),
|
||||||
|
srctop_file("apps", "server.pem"),
|
||||||
|
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
||||||
|
);
|
||||||
|
|
||||||
|
use constant {
|
||||||
|
SERVER_CERT_TYPE => 0,
|
||||||
|
CLIENT_CERT_TYPE => 1,
|
||||||
|
NO_CERT_TYPE => 2
|
||||||
|
};
|
||||||
|
my $testtype;
|
||||||
|
|
||||||
|
# Test 1: Just do a verify without cert type
|
||||||
|
$proxy->clear();
|
||||||
|
$proxy->clientflags("-tls1_2 -cert ".srctop_file("apps", "server.pem"));
|
||||||
|
$proxy->serverflags("-verify 4");
|
||||||
|
$testtype = NO_CERT_TYPE;
|
||||||
|
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
||||||
|
plan tests => 4;
|
||||||
|
ok(TLSProxy::Message->success, "Simple verify");
|
||||||
|
|
||||||
|
# Test 2: Set a bogus server cert type
|
||||||
|
$proxy->clear();
|
||||||
|
$proxy->serverflags("-enable_server_rpk");
|
||||||
|
$testtype = SERVER_CERT_TYPE;
|
||||||
|
$proxy->start();
|
||||||
|
ok(TLSProxy::Message->fail, "Unsupported server cert type");
|
||||||
|
|
||||||
|
# Test 3: Set a bogus client cert type
|
||||||
|
$proxy->clear();
|
||||||
|
$proxy->serverflags("-enable_client_rpk");
|
||||||
|
$testtype = CLIENT_CERT_TYPE;
|
||||||
|
$proxy->start();
|
||||||
|
ok(TLSProxy::Message->success, "Unsupported client cert type, no verify");
|
||||||
|
|
||||||
|
# Test 4: Set a bogus server cert type with verify
|
||||||
|
$proxy->clear();
|
||||||
|
$testtype = CLIENT_CERT_TYPE;
|
||||||
|
$proxy->clientflags("-tls1_2 -cert ".srctop_file("apps", "server.pem"));
|
||||||
|
$proxy->serverflags("-verify 4 -enable_client_rpk");
|
||||||
|
$proxy->start();
|
||||||
|
ok(TLSProxy::Message->fail, "Unsupported client cert type with verify");
|
||||||
|
|
||||||
|
sub certtype_filter
|
||||||
|
{
|
||||||
|
my $proxy = shift;
|
||||||
|
my $message;
|
||||||
|
|
||||||
|
# We're only interested in the initial ClientHello
|
||||||
|
return if $proxy->flight != 0;
|
||||||
|
|
||||||
|
$message = ${$proxy->message_list}[0];
|
||||||
|
|
||||||
|
# Add unsupported and bogus client and server cert type to the client hello.
|
||||||
|
my $ct = pack "C5", 0x04, 0x01, 0x03, 0x55, 0x66;
|
||||||
|
if ($testtype == CLIENT_CERT_TYPE) {
|
||||||
|
print "SETTING CLIENT CERT TYPE\n";
|
||||||
|
$message->set_extension(TLSProxy::Message::EXT_CLIENT_CERT_TYPE, $ct);
|
||||||
|
}
|
||||||
|
if ($testtype == SERVER_CERT_TYPE) {
|
||||||
|
print "SETTING SERVER CERT TYPE\n";
|
||||||
|
$message->set_extension(TLSProxy::Message::EXT_SERVER_CERT_TYPE, $ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
$message->repack();
|
||||||
|
}
|
23
test/recipes/90-test_rpk.t
Normal file
23
test/recipes/90-test_rpk.t
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#! /usr/bin/env perl
|
||||||
|
# Copyright 2016-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
|
||||||
|
# in the file LICENSE in the source distribution or at
|
||||||
|
# https://www.openssl.org/source/license.html
|
||||||
|
|
||||||
|
use OpenSSL::Test::Utils;
|
||||||
|
use OpenSSL::Test qw/:DEFAULT srctop_dir bldtop_dir/;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
setup("test_rpk");
|
||||||
|
}
|
||||||
|
|
||||||
|
use lib srctop_dir('Configurations');
|
||||||
|
use lib bldtop_dir('.');
|
||||||
|
|
||||||
|
plan skip_all => "RPK is disabled in this OpenSSL build" if disabled("tls1_2") && disabled("tls1_3");
|
||||||
|
|
||||||
|
plan tests => 1;
|
||||||
|
|
||||||
|
ok(run(test(["rpktest", srctop_dir("test", "certs")])), "running rpktest");
|
759
test/rpktest.c
Normal file
759
test/rpktest.c
Normal file
@ -0,0 +1,759 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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
|
||||||
|
* in the file LICENSE in the source distribution or at
|
||||||
|
* https://www.openssl.org/source/license.html
|
||||||
|
*/
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#include "helpers/ssltestlib.h"
|
||||||
|
#include "internal/dane.h"
|
||||||
|
#include "testutil.h"
|
||||||
|
|
||||||
|
#undef OSSL_NO_USABLE_TLS1_3
|
||||||
|
#if defined(OPENSSL_NO_TLS1_3) \
|
||||||
|
|| (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
|
||||||
|
/*
|
||||||
|
* If we don't have ec or dh then there are no built-in groups that are usable
|
||||||
|
* with TLSv1.3
|
||||||
|
*/
|
||||||
|
# define OSSL_NO_USABLE_TLS1_3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char *certsdir = NULL;
|
||||||
|
static char *rootcert = NULL;
|
||||||
|
static char *cert = NULL;
|
||||||
|
static char *privkey = NULL;
|
||||||
|
static char *cert2 = NULL;
|
||||||
|
static char *privkey2 = NULL;
|
||||||
|
static char *cert448 = NULL;
|
||||||
|
static char *privkey448 = NULL;
|
||||||
|
static char *cert25519 = NULL;
|
||||||
|
static char *privkey25519 = NULL;
|
||||||
|
static OSSL_LIB_CTX *libctx = NULL;
|
||||||
|
static OSSL_PROVIDER *defctxnull = NULL;
|
||||||
|
|
||||||
|
static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||||
|
static const unsigned char SID_CTX[] = { 'r', 'p', 'k' };
|
||||||
|
|
||||||
|
static int rpk_verify_client_cb(int ok, X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
int err = X509_STORE_CTX_get_error(ctx);
|
||||||
|
|
||||||
|
if (X509_STORE_CTX_get0_rpk(ctx) != NULL) {
|
||||||
|
if (err != X509_V_OK) {
|
||||||
|
TEST_info("rpk_verify_client_cb: ok=%d err=%d", ok, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int rpk_verify_server_cb(int ok, X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
int err = X509_STORE_CTX_get_error(ctx);
|
||||||
|
|
||||||
|
if (X509_STORE_CTX_get0_rpk(ctx) != NULL) {
|
||||||
|
if (err != X509_V_OK) {
|
||||||
|
TEST_info("rpk_verify_server_cb: ok=%d err=%d", ok, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test dimensions:
|
||||||
|
* (2) server_cert_type RPK off/on for server
|
||||||
|
* (2) client_cert_type RPK off/on for server
|
||||||
|
* (2) server_cert_type RPK off/on for client
|
||||||
|
* (2) client_cert_type RPK off/on for client
|
||||||
|
* (4) RSA vs ECDSA vs Ed25519 vs Ed448 certificates
|
||||||
|
* (2) TLSv1.2 vs TLSv1.3
|
||||||
|
*
|
||||||
|
* Tests:
|
||||||
|
* idx = 0 - is the normal success case, certificate, single peer key
|
||||||
|
* idx = 1 - only a private key
|
||||||
|
* idx = 2 - add client authentication
|
||||||
|
* idx = 3 - add second peer key (rootcert.pem)
|
||||||
|
* idx = 4 - add second peer key (different, RSA or ECDSA)
|
||||||
|
* idx = 5 - reverse peer keys (rootcert.pem, different order)
|
||||||
|
* idx = 6 - reverse peer keys (RSA or ECDSA, different order)
|
||||||
|
* idx = 7 - expects failure due to mismatched key (RSA or ECDSA)
|
||||||
|
* idx = 8 - expects failure due to no configured key on client
|
||||||
|
* idx = 9 - add client authentication (PHA)
|
||||||
|
* idx = 10 - add client authentication (privake key only)
|
||||||
|
* idx = 11 - simple resumption
|
||||||
|
* idx = 12 - simple resumption, no ticket
|
||||||
|
* idx = 13 - resumption with client authentication
|
||||||
|
* idx = 14 - resumption with client authentication, no ticket
|
||||||
|
* idx = 15 - like 0, but use non-default libctx
|
||||||
|
*
|
||||||
|
* 16 * 2 * 4 * 2 * 2 * 2 * 2 = 2048 tests
|
||||||
|
*/
|
||||||
|
static int test_rpk(int idx)
|
||||||
|
{
|
||||||
|
# define RPK_TESTS 16
|
||||||
|
# define RPK_DIMS (2 * 4 * 2 * 2 * 2 * 2)
|
||||||
|
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||||
|
SSL *clientssl = NULL, *serverssl = NULL;
|
||||||
|
EVP_PKEY *pkey = NULL, *other_pkey = NULL, *root_pkey = NULL;
|
||||||
|
X509 *x509 = NULL, *other_x509 = NULL, *root_x509 = NULL;
|
||||||
|
int testresult = 0, ret, expected = 1;
|
||||||
|
int client_expected = X509_V_OK;
|
||||||
|
int verify;
|
||||||
|
int tls_version;
|
||||||
|
char *cert_file = NULL;
|
||||||
|
char *privkey_file = NULL;
|
||||||
|
char *other_cert_file = NULL;
|
||||||
|
SSL_SESSION *client_sess = NULL;
|
||||||
|
SSL_SESSION *server_sess = NULL;
|
||||||
|
int idx_server_server_rpk, idx_server_client_rpk;
|
||||||
|
int idx_client_server_rpk, idx_client_client_rpk;
|
||||||
|
int idx_cert, idx_prot;
|
||||||
|
int client_auth = 0;
|
||||||
|
int resumption = 0;
|
||||||
|
long server_verify_result = 0;
|
||||||
|
long client_verify_result = 0;
|
||||||
|
OSSL_LIB_CTX *test_libctx = NULL;
|
||||||
|
|
||||||
|
if (!TEST_int_le(idx, RPK_TESTS * RPK_DIMS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
idx_server_server_rpk = idx / (RPK_TESTS * 2 * 4 * 2 * 2 * 2);
|
||||||
|
idx %= RPK_TESTS * 2 * 4 * 2 * 2 * 2;
|
||||||
|
idx_server_client_rpk = idx / (RPK_TESTS * 2 * 4 * 2 * 2);
|
||||||
|
idx %= RPK_TESTS * 2 * 4 * 2 * 2;
|
||||||
|
idx_client_server_rpk = idx / (RPK_TESTS * 2 * 4 * 2);
|
||||||
|
idx %= RPK_TESTS * 2 * 4 * 2;
|
||||||
|
idx_client_client_rpk = idx / (RPK_TESTS * 2 * 4);
|
||||||
|
idx %= RPK_TESTS * 2 * 4;
|
||||||
|
idx_cert = idx / (RPK_TESTS * 2);
|
||||||
|
idx %= RPK_TESTS * 2;
|
||||||
|
idx_prot = idx / RPK_TESTS;
|
||||||
|
idx %= RPK_TESTS;
|
||||||
|
|
||||||
|
/* Load "root" cert/pubkey */
|
||||||
|
root_x509 = load_cert_pem(rootcert, NULL);
|
||||||
|
if (!TEST_ptr(root_x509))
|
||||||
|
goto end;
|
||||||
|
root_pkey = X509_get0_pubkey(root_x509);
|
||||||
|
if (!TEST_ptr(root_pkey))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
switch (idx_cert) {
|
||||||
|
case 0:
|
||||||
|
/* use RSA */
|
||||||
|
cert_file = cert;
|
||||||
|
privkey_file = privkey;
|
||||||
|
other_cert_file = cert2;
|
||||||
|
break;
|
||||||
|
#ifndef OPENSSL_NO_ECDSA
|
||||||
|
case 1:
|
||||||
|
/* use ECDSA */
|
||||||
|
cert_file = cert2;
|
||||||
|
privkey_file = privkey2;
|
||||||
|
other_cert_file = cert;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* use Ed448 */
|
||||||
|
cert_file = cert448;
|
||||||
|
privkey_file = privkey448;
|
||||||
|
other_cert_file = cert;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* use Ed25519 */
|
||||||
|
cert_file = cert25519;
|
||||||
|
privkey_file = privkey25519;
|
||||||
|
other_cert_file = cert;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
testresult = TEST_skip("EDCSA disabled");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
/* Load primary cert */
|
||||||
|
x509 = load_cert_pem(cert_file, NULL);
|
||||||
|
if (!TEST_ptr(x509))
|
||||||
|
goto end;
|
||||||
|
pkey = X509_get0_pubkey(x509);
|
||||||
|
/* load other cert */
|
||||||
|
other_x509 = load_cert_pem(other_cert_file, NULL);
|
||||||
|
if (!TEST_ptr(other_x509))
|
||||||
|
goto end;
|
||||||
|
other_pkey = X509_get0_pubkey(other_x509);
|
||||||
|
#ifdef OPENSSL_NO_ECDSA
|
||||||
|
/* Can't get other_key if it's ECDSA */
|
||||||
|
if (other_pkey == NULL && idx_cert == 0
|
||||||
|
&& (idx == 4 || idx == 6 || idx == 7)) {
|
||||||
|
testresult = TEST_skip("EDCSA disabled");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (idx_prot) {
|
||||||
|
case 0:
|
||||||
|
#ifdef OSSL_NO_USABLE_TLS1_3
|
||||||
|
testresult = TEST_skip("TLSv1.3 disabled");
|
||||||
|
goto end;
|
||||||
|
#else
|
||||||
|
tls_version = TLS1_3_VERSION;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 1:
|
||||||
|
#ifdef OPENSSL_NO_TLS1_2
|
||||||
|
testresult = TEST_skip("TLSv1.2 disabled");
|
||||||
|
goto end;
|
||||||
|
#else
|
||||||
|
tls_version = TLS1_2_VERSION;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == 15) {
|
||||||
|
test_libctx = libctx;
|
||||||
|
defctxnull = OSSL_PROVIDER_load(NULL, "null");
|
||||||
|
if (!TEST_ptr(defctxnull))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(create_ssl_ctx_pair(test_libctx,
|
||||||
|
TLS_server_method(), TLS_client_method(),
|
||||||
|
tls_version, tls_version,
|
||||||
|
&sctx, &cctx, NULL, NULL)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (idx_server_server_rpk)
|
||||||
|
if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_rpk, sizeof(cert_type_rpk))))
|
||||||
|
goto end;
|
||||||
|
if (idx_server_client_rpk)
|
||||||
|
if (!TEST_true(SSL_CTX_set1_client_cert_type(sctx, cert_type_rpk, sizeof(cert_type_rpk))))
|
||||||
|
goto end;
|
||||||
|
if (idx_client_server_rpk)
|
||||||
|
if (!TEST_true(SSL_CTX_set1_server_cert_type(cctx, cert_type_rpk, sizeof(cert_type_rpk))))
|
||||||
|
goto end;
|
||||||
|
if (idx_client_client_rpk)
|
||||||
|
if (!TEST_true(SSL_CTX_set1_client_cert_type(cctx, cert_type_rpk, sizeof(cert_type_rpk))))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_CTX_set_session_id_context(sctx, SID_CTX, sizeof(SID_CTX))))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_CTX_set_session_id_context(cctx, SID_CTX, sizeof(SID_CTX))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_int_gt(SSL_CTX_dane_enable(sctx), 0))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_gt(SSL_CTX_dane_enable(cctx), 0))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* NEW */
|
||||||
|
SSL_CTX_set_verify(cctx, SSL_VERIFY_PEER, rpk_verify_client_cb);
|
||||||
|
|
||||||
|
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||||
|
NULL, NULL)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_int_gt(SSL_dane_enable(serverssl, NULL), 0))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Set private key and certificate */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
/* Only a private key */
|
||||||
|
if (idx == 1) {
|
||||||
|
if (idx_server_server_rpk == 0 || idx_client_server_rpk == 0)
|
||||||
|
expected = 0;
|
||||||
|
} else {
|
||||||
|
/* Add certificate */
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(serverssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(serverssl), 1))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
default:
|
||||||
|
if (!TEST_true(idx < RPK_TESTS))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
client_auth = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, root_pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, root_pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
if (idx_server_server_rpk == 1 && idx_client_server_rpk == 1)
|
||||||
|
client_expected = -1;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
|
||||||
|
goto end;
|
||||||
|
client_verify_result = X509_V_ERR_DANE_NO_MATCH;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if (idx_server_server_rpk == 1 && idx_client_server_rpk == 1)
|
||||||
|
client_expected = -1;
|
||||||
|
/* no peer keys */
|
||||||
|
client_verify_result = X509_V_ERR_RPK_UNTRUSTED;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
if (tls_version != TLS1_3_VERSION) {
|
||||||
|
testresult = TEST_skip("PHA requires TLSv1.3");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_POST_HANDSHAKE, rpk_verify_server_cb);
|
||||||
|
SSL_set_post_handshake_auth(clientssl, 1);
|
||||||
|
client_auth = 1;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
/* Since there's no cert, this is expected to fail without RPK support */
|
||||||
|
if (!idx_server_client_rpk || !idx_client_client_rpk)
|
||||||
|
expected = 0;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
client_auth = 1;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
if (!idx_server_server_rpk || !idx_client_server_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing resumption with server RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
resumption = 1;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
if (!idx_server_server_rpk || !idx_client_server_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing resumption with server RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
SSL_set_options(serverssl, SSL_OP_NO_TICKET);
|
||||||
|
SSL_set_options(clientssl, SSL_OP_NO_TICKET);
|
||||||
|
resumption = 1;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
if (!idx_server_server_rpk || !idx_client_server_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing resumption with server RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!idx_server_client_rpk || !idx_client_client_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing client authentication resumption with client RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
client_auth = 1;
|
||||||
|
resumption = 1;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
if (!idx_server_server_rpk || !idx_client_server_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing resumption with server RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!idx_server_client_rpk || !idx_client_client_rpk) {
|
||||||
|
testresult = TEST_skip("Only testing client authentication resumption with client RPK");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
SSL_set_options(serverssl, SSL_OP_NO_TICKET);
|
||||||
|
SSL_set_options(clientssl, SSL_OP_NO_TICKET);
|
||||||
|
client_auth = 1;
|
||||||
|
resumption = 1;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
|
||||||
|
if (!TEST_int_eq(expected, ret))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Make sure client gets RPK or certificate as configured */
|
||||||
|
if (expected == 1) {
|
||||||
|
if (idx_server_server_rpk && idx_client_server_rpk) {
|
||||||
|
if (!TEST_long_eq(SSL_get_verify_result(clientssl), client_verify_result))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_ptr(SSL_get0_peer_rpk(clientssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
} else {
|
||||||
|
if (!TEST_ptr(SSL_get0_peer_certificate(clientssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_x509))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_x509))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == 9) {
|
||||||
|
/* Make PHA happen... */
|
||||||
|
if (!TEST_true(SSL_verify_client_post_handshake(serverssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_do_handshake(serverssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_le(SSL_read(clientssl, NULL, 0), 0))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_le(SSL_read(serverssl, NULL, 0), 0))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure server gets an RPK or certificate as configured */
|
||||||
|
if (client_auth) {
|
||||||
|
if (idx_server_client_rpk && idx_client_client_rpk) {
|
||||||
|
if (!TEST_long_eq(SSL_get_verify_result(serverssl), server_verify_result))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_ptr(SSL_get0_peer_rpk(serverssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
} else {
|
||||||
|
/* only if connection is expected to succeed */
|
||||||
|
if (expected == 1 && !TEST_ptr(SSL_get0_peer_certificate(serverssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_x509))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_x509))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resumption) {
|
||||||
|
EVP_PKEY *client_pkey = NULL;
|
||||||
|
EVP_PKEY *server_pkey = NULL;
|
||||||
|
|
||||||
|
if (!TEST_ptr((client_sess = SSL_get1_session(clientssl)))
|
||||||
|
|| !TEST_ptr((client_pkey = SSL_SESSION_get0_peer_rpk(client_sess))))
|
||||||
|
goto end;
|
||||||
|
if (client_auth) {
|
||||||
|
if (!TEST_ptr((server_sess = SSL_get1_session(serverssl)))
|
||||||
|
|| !TEST_ptr((server_pkey = SSL_SESSION_get0_peer_rpk(server_sess))))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
SSL_shutdown(clientssl);
|
||||||
|
SSL_shutdown(serverssl);
|
||||||
|
SSL_free(clientssl);
|
||||||
|
SSL_free(serverssl);
|
||||||
|
serverssl = clientssl = NULL;
|
||||||
|
|
||||||
|
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||||
|
NULL, NULL))
|
||||||
|
|| !TEST_true(SSL_set_session(clientssl, client_sess)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Set private key (and maybe certificate) */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(serverssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(serverssl), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_gt(SSL_dane_enable(serverssl, "example.com"), 0))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
|
||||||
|
goto end;
|
||||||
|
SSL_set_options(clientssl, SSL_OP_NO_TICKET);
|
||||||
|
SSL_set_options(serverssl, SSL_OP_NO_TICKET);
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, server_pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_add_expected_rpk(serverssl, server_pkey)))
|
||||||
|
goto end;
|
||||||
|
/* Use the same key for client auth */
|
||||||
|
if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
|
||||||
|
goto end;
|
||||||
|
SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
|
||||||
|
SSL_set_options(serverssl, SSL_OP_NO_TICKET);
|
||||||
|
SSL_set_options(clientssl, SSL_OP_NO_TICKET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
|
||||||
|
if (!TEST_int_eq(expected, ret))
|
||||||
|
goto end;
|
||||||
|
verify = SSL_get_verify_result(clientssl);
|
||||||
|
if (!TEST_int_eq(client_expected, verify))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_true(SSL_session_reused(clientssl)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_ptr(SSL_get0_peer_rpk(clientssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (client_auth) {
|
||||||
|
if (!TEST_ptr(SSL_get0_peer_rpk(serverssl)))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_rpk))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testresult = 1;
|
||||||
|
|
||||||
|
end:
|
||||||
|
OSSL_PROVIDER_unload(defctxnull);
|
||||||
|
defctxnull = NULL;
|
||||||
|
SSL_SESSION_free(client_sess);
|
||||||
|
SSL_SESSION_free(server_sess);
|
||||||
|
SSL_free(serverssl);
|
||||||
|
SSL_free(clientssl);
|
||||||
|
SSL_CTX_free(sctx);
|
||||||
|
SSL_CTX_free(cctx);
|
||||||
|
X509_free(x509);
|
||||||
|
X509_free(other_x509);
|
||||||
|
X509_free(root_x509);
|
||||||
|
|
||||||
|
if (testresult == 0) {
|
||||||
|
TEST_info("idx_ss_rpk=%d, idx_sc_rpk=%d, idx_cs_rpk=%d, idx_cc_rpk=%d, idx_cert=%d, idx_prot=%d, idx=%d",
|
||||||
|
idx_server_server_rpk, idx_server_client_rpk,
|
||||||
|
idx_client_server_rpk, idx_client_client_rpk,
|
||||||
|
idx_cert, idx_prot, idx);
|
||||||
|
}
|
||||||
|
return testresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_rpk_api(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||||
|
unsigned char cert_type_dups[] = { TLSEXT_cert_type_rpk,
|
||||||
|
TLSEXT_cert_type_x509,
|
||||||
|
TLSEXT_cert_type_x509 };
|
||||||
|
unsigned char cert_type_bad[] = { 0xFF };
|
||||||
|
unsigned char cert_type_extra[] = { TLSEXT_cert_type_rpk,
|
||||||
|
TLSEXT_cert_type_x509,
|
||||||
|
0xFF };
|
||||||
|
unsigned char cert_type_unsup[] = { TLSEXT_cert_type_pgp,
|
||||||
|
TLSEXT_cert_type_1609dot2 };
|
||||||
|
unsigned char cert_type_just_x509[] = { TLSEXT_cert_type_x509 };
|
||||||
|
unsigned char cert_type_just_rpk[] = { TLSEXT_cert_type_rpk };
|
||||||
|
|
||||||
|
if (!TEST_true(create_ssl_ctx_pair(NULL,
|
||||||
|
TLS_server_method(), TLS_client_method(),
|
||||||
|
TLS1_2_VERSION, TLS1_2_VERSION,
|
||||||
|
&sctx, &cctx, NULL, NULL)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_dups, sizeof(cert_type_dups))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_bad, sizeof(cert_type_bad))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_extra, sizeof(cert_type_extra))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_unsup, sizeof(cert_type_unsup))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_just_x509, sizeof(cert_type_just_x509))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_just_rpk, sizeof(cert_type_just_rpk))))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
SSL_CTX_free(sctx);
|
||||||
|
SSL_CTX_free(cctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
OPT_TEST_DECLARE_USAGE("certdir\n")
|
||||||
|
|
||||||
|
int setup_tests(void)
|
||||||
|
{
|
||||||
|
if (!test_skip_common_options()) {
|
||||||
|
TEST_error("Error parsing test options\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TEST_ptr(certsdir = test_get_argument(0)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rootcert = test_mk_file_path(certsdir, "rootcert.pem");
|
||||||
|
if (rootcert == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cert = test_mk_file_path(certsdir, "servercert.pem");
|
||||||
|
if (cert == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
privkey = test_mk_file_path(certsdir, "serverkey.pem");
|
||||||
|
if (privkey == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cert2 = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
|
||||||
|
if (cert2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
privkey2 = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
|
||||||
|
if (privkey2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cert448 = test_mk_file_path(certsdir, "server-ed448-cert.pem");
|
||||||
|
if (cert2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
privkey448 = test_mk_file_path(certsdir, "server-ed448-key.pem");
|
||||||
|
if (privkey2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cert25519 = test_mk_file_path(certsdir, "server-ed25519-cert.pem");
|
||||||
|
if (cert2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
privkey25519 = test_mk_file_path(certsdir, "server-ed25519-key.pem");
|
||||||
|
if (privkey2 == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
libctx = OSSL_LIB_CTX_new();
|
||||||
|
if (libctx == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ADD_TEST(test_rpk_api);
|
||||||
|
ADD_ALL_TESTS(test_rpk, RPK_TESTS * RPK_DIMS);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_tests(void)
|
||||||
|
{
|
||||||
|
OPENSSL_free(rootcert);
|
||||||
|
OPENSSL_free(cert);
|
||||||
|
OPENSSL_free(privkey);
|
||||||
|
OPENSSL_free(cert2);
|
||||||
|
OPENSSL_free(privkey2);
|
||||||
|
OPENSSL_free(cert448);
|
||||||
|
OPENSSL_free(privkey448);
|
||||||
|
OPENSSL_free(cert25519);
|
||||||
|
OPENSSL_free(privkey25519);
|
||||||
|
OSSL_LIB_CTX_free(libctx);
|
||||||
|
}
|
@ -9558,9 +9558,12 @@ static int create_cert_key(int idx, char *certfilename, char *privkeyfilename)
|
|||||||
* correctly establish a TLS (1.3) connection.
|
* correctly establish a TLS (1.3) connection.
|
||||||
* Test 0: Signature algorithm with built-in hashing functionality: "xorhmacsig"
|
* Test 0: Signature algorithm with built-in hashing functionality: "xorhmacsig"
|
||||||
* Test 1: Signature algorithm using external SHA2 hashing: "xorhmacsha2sig"
|
* Test 1: Signature algorithm using external SHA2 hashing: "xorhmacsha2sig"
|
||||||
|
* Test 2: Test 0 using RPK
|
||||||
|
* Test 3: Test 1 using RPK
|
||||||
*/
|
*/
|
||||||
static int test_pluggable_signature(int idx)
|
static int test_pluggable_signature(int idx)
|
||||||
{
|
{
|
||||||
|
static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||||
SSL_CTX *cctx = NULL, *sctx = NULL;
|
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||||
SSL *clientssl = NULL, *serverssl = NULL;
|
SSL *clientssl = NULL, *serverssl = NULL;
|
||||||
int testresult = 0;
|
int testresult = 0;
|
||||||
@ -9568,10 +9571,12 @@ static int test_pluggable_signature(int idx)
|
|||||||
OSSL_PROVIDER *defaultprov = OSSL_PROVIDER_load(libctx, "default");
|
OSSL_PROVIDER *defaultprov = OSSL_PROVIDER_load(libctx, "default");
|
||||||
char *certfilename = "tls-prov-cert.pem";
|
char *certfilename = "tls-prov-cert.pem";
|
||||||
char *privkeyfilename = "tls-prov-key.pem";
|
char *privkeyfilename = "tls-prov-key.pem";
|
||||||
|
int sigidx = idx % 2;
|
||||||
|
int rpkidx = idx / 2;
|
||||||
|
|
||||||
/* create key and certificate for the different algorithm types */
|
/* create key and certificate for the different algorithm types */
|
||||||
if (!TEST_ptr(tlsprov)
|
if (!TEST_ptr(tlsprov)
|
||||||
|| !TEST_true(create_cert_key(idx, certfilename, privkeyfilename)))
|
|| !TEST_true(create_cert_key(sigidx, certfilename, privkeyfilename)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
|
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
|
||||||
@ -9583,6 +9588,13 @@ static int test_pluggable_signature(int idx)
|
|||||||
NULL, NULL)))
|
NULL, NULL)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
/* Enable RPK for server cert */
|
||||||
|
if (rpkidx) {
|
||||||
|
if (!TEST_true(SSL_set1_server_cert_type(serverssl, cert_type_rpk, sizeof(cert_type_rpk)))
|
||||||
|
|| !TEST_true(SSL_set1_server_cert_type(clientssl, cert_type_rpk, sizeof(cert_type_rpk))))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is necessary to pass minimal setup w/o other groups configured */
|
/* This is necessary to pass minimal setup w/o other groups configured */
|
||||||
if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup"))
|
if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup"))
|
||||||
|| !TEST_true(SSL_set1_groups_list(clientssl, "xorgroup")))
|
|| !TEST_true(SSL_set1_groups_list(clientssl, "xorgroup")))
|
||||||
@ -9596,6 +9608,10 @@ static int test_pluggable_signature(int idx)
|
|||||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
|
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
/* If using RPK, make sure we got one */
|
||||||
|
if (rpkidx && !TEST_long_eq(SSL_get_verify_result(clientssl), X509_V_ERR_RPK_UNTRUSTED))
|
||||||
|
goto end;
|
||||||
|
|
||||||
testresult = 1;
|
testresult = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -11083,7 +11099,7 @@ int setup_tests(void)
|
|||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_TLS1_3
|
#ifndef OPENSSL_NO_TLS1_3
|
||||||
ADD_ALL_TESTS(test_pluggable_group, 2);
|
ADD_ALL_TESTS(test_pluggable_group, 2);
|
||||||
ADD_ALL_TESTS(test_pluggable_signature, 2);
|
ADD_ALL_TESTS(test_pluggable_signature, 4);
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_TLS1_2
|
#ifndef OPENSSL_NO_TLS1_2
|
||||||
ADD_TEST(test_ssl_dup);
|
ADD_TEST(test_ssl_dup);
|
||||||
|
@ -5514,3 +5514,6 @@ ASN1_item_unpack_ex ? 3_2_0 EXIST::FUNCTION:
|
|||||||
PKCS12_SAFEBAG_get1_cert_ex ? 3_2_0 EXIST::FUNCTION:
|
PKCS12_SAFEBAG_get1_cert_ex ? 3_2_0 EXIST::FUNCTION:
|
||||||
PKCS12_SAFEBAG_get1_crl_ex ? 3_2_0 EXIST::FUNCTION:
|
PKCS12_SAFEBAG_get1_crl_ex ? 3_2_0 EXIST::FUNCTION:
|
||||||
EC_GROUP_to_params ? 3_2_0 EXIST::FUNCTION:EC
|
EC_GROUP_to_params ? 3_2_0 EXIST::FUNCTION:EC
|
||||||
|
X509_STORE_CTX_init_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
X509_STORE_CTX_get0_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
X509_STORE_CTX_set0_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
@ -544,3 +544,17 @@ SSL_net_write_desired ? 3_2_0 EXIST::FUNCTION:
|
|||||||
SSL_shutdown_ex ? 3_2_0 EXIST::FUNCTION:
|
SSL_shutdown_ex ? 3_2_0 EXIST::FUNCTION:
|
||||||
SSL_stream_conclude ? 3_2_0 EXIST::FUNCTION:
|
SSL_stream_conclude ? 3_2_0 EXIST::FUNCTION:
|
||||||
SSL_inject_net_dgram ? 3_2_0 EXIST::FUNCTION:QUIC
|
SSL_inject_net_dgram ? 3_2_0 EXIST::FUNCTION:QUIC
|
||||||
|
SSL_get0_peer_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_SESSION_get0_peer_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_set1_client_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_get0_client_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_set1_server_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_get0_server_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_set1_client_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_get0_client_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_set1_server_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_get0_server_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_get_negotiated_client_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_get_negotiated_server_cert_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_add_expected_rpk ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
d2i_SSL_SESSION_ex ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
@ -75,6 +75,8 @@ use constant {
|
|||||||
EXT_USE_SRTP => 14,
|
EXT_USE_SRTP => 14,
|
||||||
EXT_ALPN => 16,
|
EXT_ALPN => 16,
|
||||||
EXT_SCT => 18,
|
EXT_SCT => 18,
|
||||||
|
EXT_CLIENT_CERT_TYPE => 19,
|
||||||
|
EXT_SERVER_CERT_TYPE => 20,
|
||||||
EXT_PADDING => 21,
|
EXT_PADDING => 21,
|
||||||
EXT_ENCRYPT_THEN_MAC => 22,
|
EXT_ENCRYPT_THEN_MAC => 22,
|
||||||
EXT_EXTENDED_MASTER_SECRET => 23,
|
EXT_EXTENDED_MASTER_SECRET => 23,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user