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]
|
||||
|
||||
* 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
|
||||
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]
|
||||
|
||||
* Add Raw Public Key (RFC7250) support.
|
||||
* Added support for certificate compression (RFC8879), including
|
||||
library support for Brotli and Zstandard compression.
|
||||
* 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
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@ -673,6 +673,8 @@ static STRINT_PAIR tlsext_types[] = {
|
||||
{"session ticket", TLSEXT_TYPE_session_ticket},
|
||||
{"renegotiation info", TLSEXT_TYPE_renegotiate},
|
||||
{"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
|
||||
{"client cert type", TLSEXT_TYPE_client_cert_type},
|
||||
{"server cert type", TLSEXT_TYPE_server_cert_type},
|
||||
{"TLS padding", TLSEXT_TYPE_padding},
|
||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||
{"next protocol", TLSEXT_TYPE_next_proto_neg},
|
||||
@ -1171,7 +1173,7 @@ static char *hexencode(const unsigned char *data, size_t len)
|
||||
void print_verify_detail(SSL *s, BIO *bio)
|
||||
{
|
||||
int mdpth;
|
||||
EVP_PKEY *mspki;
|
||||
EVP_PKEY *mspki = NULL;
|
||||
long verify_err = SSL_get_verify_result(s);
|
||||
|
||||
if (verify_err == X509_V_OK) {
|
||||
@ -1206,12 +1208,15 @@ void print_verify_detail(SSL *s, BIO *bio)
|
||||
hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
|
||||
else
|
||||
hexdata = hexencode(data, dlen);
|
||||
BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
|
||||
BIO_printf(bio, "DANE TLSA %d %d %d %s%s ",
|
||||
usage, selector, mtype,
|
||||
(dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
|
||||
(mspki != NULL) ? "signed the certificate" :
|
||||
mdpth ? "matched TA certificate" : "matched EE certificate",
|
||||
mdpth);
|
||||
(dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata);
|
||||
if (SSL_get0_peer_rpk(s) == NULL)
|
||||
BIO_printf(bio, "%s certificate at depth %d\n",
|
||||
(mspki != NULL) ? "signed the peer" :
|
||||
mdpth ? "matched the TA" : "matched the EE", mdpth);
|
||||
else
|
||||
BIO_printf(bio, "matched the peer raw public key\n");
|
||||
OPENSSL_free(hexdata);
|
||||
}
|
||||
}
|
||||
@ -1219,17 +1224,16 @@ void print_verify_detail(SSL *s, BIO *bio)
|
||||
void print_ssl_summary(SSL *s)
|
||||
{
|
||||
const SSL_CIPHER *c;
|
||||
X509 *peer;
|
||||
X509 *peer = SSL_get0_peer_certificate(s);
|
||||
EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s);
|
||||
int nid;
|
||||
|
||||
BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
|
||||
print_raw_cipherlist(s);
|
||||
c = SSL_get_current_cipher(s);
|
||||
BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
|
||||
do_print_sigalgs(bio_err, s, 0);
|
||||
peer = SSL_get0_peer_certificate(s);
|
||||
if (peer != NULL) {
|
||||
int nid;
|
||||
|
||||
BIO_puts(bio_err, "Peer certificate: ");
|
||||
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
|
||||
0, get_nameopt());
|
||||
@ -1239,8 +1243,13 @@ void print_ssl_summary(SSL *s)
|
||||
if (SSL_get_peer_signature_type_nid(s, &nid))
|
||||
BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
|
||||
print_verify_detail(s, bio_err);
|
||||
} else if (peer_rpk != NULL) {
|
||||
BIO_printf(bio_err, "Peer used raw public key\n");
|
||||
if (SSL_get_peer_signature_type_nid(s, &nid))
|
||||
BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
|
||||
print_verify_detail(s, bio_err);
|
||||
} else {
|
||||
BIO_puts(bio_err, "No peer certificate\n");
|
||||
BIO_puts(bio_err, "No peer certificate or raw public key\n");
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC
|
||||
ssl_print_point_formats(bio_err, s);
|
||||
@ -1595,4 +1604,3 @@ int progress_cb(EVP_PKEY_CTX *ctx)
|
||||
(void)BIO_flush(b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
@ -75,6 +75,9 @@ static int ocsp_resp_cb(SSL *s, void *arg);
|
||||
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
|
||||
static int is_dNS_name(const char *host);
|
||||
|
||||
static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||
static int enable_server_rpk = 0;
|
||||
|
||||
static int saved_errno;
|
||||
|
||||
static void save_errno(void)
|
||||
@ -468,6 +471,8 @@ typedef enum OPTION_choice {
|
||||
#endif
|
||||
OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
|
||||
OPT_ENABLE_PHA,
|
||||
OPT_ENABLE_SERVER_RPK,
|
||||
OPT_ENABLE_CLIENT_RPK,
|
||||
OPT_SCTP_LABEL_BUG,
|
||||
OPT_KTLS,
|
||||
OPT_R_ENUM, OPT_PROV_ENUM
|
||||
@ -658,6 +663,8 @@ const OPTIONS s_client_options[] = {
|
||||
#endif
|
||||
{"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
|
||||
{"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
|
||||
{"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"},
|
||||
{"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"},
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
{"use_srtp", OPT_USE_SRTP, 's',
|
||||
"Offer SRTP key management with a colon-separated profile list"},
|
||||
@ -896,6 +903,7 @@ int s_client_main(int argc, char **argv)
|
||||
#endif
|
||||
char *psksessf = NULL;
|
||||
int enable_pha = 0;
|
||||
int enable_client_rpk = 0;
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
int sctp_label_bug = 0;
|
||||
#endif
|
||||
@ -1489,6 +1497,12 @@ int s_client_main(int argc, char **argv)
|
||||
enable_ktls = 1;
|
||||
#endif
|
||||
break;
|
||||
case OPT_ENABLE_SERVER_RPK:
|
||||
enable_server_rpk = 1;
|
||||
break;
|
||||
case OPT_ENABLE_CLIENT_RPK:
|
||||
enable_client_rpk = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1980,6 +1994,18 @@ int s_client_main(int argc, char **argv)
|
||||
if (enable_pha)
|
||||
SSL_set_post_handshake_auth(con, 1);
|
||||
|
||||
if (enable_client_rpk)
|
||||
if (!SSL_set1_client_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) {
|
||||
BIO_printf(bio_err, "Error setting client certificate types\n");
|
||||
goto end;
|
||||
}
|
||||
if (enable_server_rpk) {
|
||||
if (!SSL_set1_server_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) {
|
||||
BIO_printf(bio_err, "Error setting server certificate types\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (sess_in != NULL) {
|
||||
SSL_SESSION *sess;
|
||||
BIO *stmp = BIO_new_file(sess_in, "r");
|
||||
@ -3254,6 +3280,23 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
||||
} else {
|
||||
BIO_printf(bio, "no peer certificate available\n");
|
||||
}
|
||||
|
||||
/* Only display RPK information if configured */
|
||||
if (SSL_get_negotiated_client_cert_type(s) == TLSEXT_cert_type_rpk)
|
||||
BIO_printf(bio, "Client-to-server raw public key negotiated\n");
|
||||
if (SSL_get_negotiated_server_cert_type(s) == TLSEXT_cert_type_rpk)
|
||||
BIO_printf(bio, "Server-to-client raw public key negotiated\n");
|
||||
if (enable_server_rpk) {
|
||||
EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s);
|
||||
|
||||
if (peer_rpk != NULL) {
|
||||
BIO_printf(bio, "Server raw public key\n");
|
||||
EVP_PKEY_print_public(bio, peer_rpk, 2, NULL);
|
||||
} else {
|
||||
BIO_printf(bio, "no peer rpk available\n");
|
||||
}
|
||||
}
|
||||
|
||||
print_ca_names(bio, s);
|
||||
|
||||
ssl_print_sigalgs(bio, s);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
@ -100,6 +100,9 @@ static int use_zc_sendfile = 0;
|
||||
|
||||
static const char *session_id_prefix = NULL;
|
||||
|
||||
static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||
static int enable_client_rpk = 0;
|
||||
|
||||
#ifndef OPENSSL_NO_DTLS
|
||||
static int enable_timeouts = 0;
|
||||
static long socket_mtu;
|
||||
@ -720,6 +723,8 @@ typedef enum OPTION_choice {
|
||||
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_KTLS,
|
||||
OPT_USE_ZC_SENDFILE,
|
||||
OPT_TFO, OPT_CERT_COMP,
|
||||
OPT_ENABLE_SERVER_RPK,
|
||||
OPT_ENABLE_CLIENT_RPK,
|
||||
OPT_R_ENUM,
|
||||
OPT_S_ENUM,
|
||||
OPT_V_ENUM,
|
||||
@ -971,7 +976,8 @@ const OPTIONS s_server_options[] = {
|
||||
{"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
|
||||
{"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"},
|
||||
#endif
|
||||
|
||||
{"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"},
|
||||
{"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"},
|
||||
OPT_R_OPTIONS,
|
||||
OPT_S_OPTIONS,
|
||||
OPT_V_OPTIONS,
|
||||
@ -1069,6 +1075,7 @@ int s_server_main(int argc, char *argv[])
|
||||
#endif
|
||||
int tfo = 0;
|
||||
int cert_comp = 0;
|
||||
int enable_server_rpk = 0;
|
||||
|
||||
/* Init of few remaining global variables */
|
||||
local_argc = argc;
|
||||
@ -1675,6 +1682,12 @@ int s_server_main(int argc, char *argv[])
|
||||
case OPT_CERT_COMP:
|
||||
cert_comp = 1;
|
||||
break;
|
||||
case OPT_ENABLE_SERVER_RPK:
|
||||
enable_server_rpk = 1;
|
||||
break;
|
||||
case OPT_ENABLE_CLIENT_RPK:
|
||||
enable_client_rpk = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2274,6 +2287,16 @@ int s_server_main(int argc, char *argv[])
|
||||
if (ctx2 != NULL && !SSL_CTX_compress_certs(ctx2, 0))
|
||||
BIO_printf(bio_s_out, "Error compressing certs on ctx2\n");
|
||||
}
|
||||
if (enable_server_rpk)
|
||||
if (!SSL_CTX_set1_server_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) {
|
||||
BIO_printf(bio_s_out, "Error setting server certificate types\n");
|
||||
goto end;
|
||||
}
|
||||
if (enable_client_rpk)
|
||||
if (!SSL_CTX_set1_client_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) {
|
||||
BIO_printf(bio_s_out, "Error setting server certificate types\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (rev)
|
||||
server_cb = rev_body;
|
||||
@ -3025,6 +3048,19 @@ static void print_connection_info(SSL *con)
|
||||
dump_cert_text(bio_s_out, peer);
|
||||
peer = NULL;
|
||||
}
|
||||
/* Only display RPK information if configured */
|
||||
if (SSL_get_negotiated_server_cert_type(con) == TLSEXT_cert_type_rpk)
|
||||
BIO_printf(bio_s_out, "Server-to-client raw public key negotiated\n");
|
||||
if (SSL_get_negotiated_client_cert_type(con) == TLSEXT_cert_type_rpk)
|
||||
BIO_printf(bio_s_out, "Client-to-server raw public key negotiated\n");
|
||||
if (enable_client_rpk) {
|
||||
EVP_PKEY *client_rpk = SSL_get0_peer_rpk(con);
|
||||
|
||||
if (client_rpk != NULL) {
|
||||
BIO_printf(bio_s_out, "Client raw public key\n");
|
||||
EVP_PKEY_print_public(bio_s_out, client_rpk, 2, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL)
|
||||
BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
|
||||
@ -3792,7 +3828,8 @@ static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen,
|
||||
if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
|
||||
const unsigned char *p = sess->der;
|
||||
BIO_printf(bio_err, "Lookup session: cache hit\n");
|
||||
return d2i_SSL_SESSION(NULL, &p, sess->derlen);
|
||||
return d2i_SSL_SESSION_ex(NULL, &p, sess->derlen, app_get0_libctx(),
|
||||
app_get0_propq());
|
||||
}
|
||||
}
|
||||
BIO_printf(bio_err, "Lookup session: cache miss\n");
|
||||
|
@ -1280,6 +1280,7 @@ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
|
||||
attempt to reuse session in different context
|
||||
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
|
||||
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_CIPHER:186:bad cipher
|
||||
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_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode
|
||||
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_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long
|
||||
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_MAX_EARLY_DATA:174:invalid max early data
|
||||
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_SEQUENCE_NUMBER:402:invalid sequence number
|
||||
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_CIPHER_RETURNED:261:wrong cipher returned
|
||||
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_SIZE:265:wrong signature size
|
||||
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
|
||||
* 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";
|
||||
case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS:
|
||||
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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@ -41,9 +41,13 @@
|
||||
#define CRL_SCORE_AKID 0x004 /* CRL issuer matches CRL AKID */
|
||||
#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 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_rpk(X509_STORE_CTX *ctx);
|
||||
static int null_callback(int ok, X509_STORE_CTX *e);
|
||||
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);
|
||||
@ -56,7 +60,8 @@ static int check_cert(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 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_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
|
||||
* 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);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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);
|
||||
return -1;
|
||||
}
|
||||
if (ctx->rpk != NULL)
|
||||
return x509_verify_rpk(ctx);
|
||||
if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1)
|
||||
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.
|
||||
* 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;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
if (ctx->cert == NULL) {
|
||||
ERR_raise(ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
|
||||
ctx->error = X509_V_ERR_INVALID_CALL;
|
||||
@ -298,7 +352,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
ctx->num_untrusted = 1;
|
||||
|
||||
/* 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);
|
||||
|
||||
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)
|
||||
{
|
||||
int n = sk_X509_num(ctx->chain) - 1;
|
||||
X509 *xi = sk_X509_value(ctx->chain, n);
|
||||
X509 *xs = xi;
|
||||
int n;
|
||||
X509 *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;
|
||||
if (ctx->bare_ta_signed) {
|
||||
@ -2227,6 +2291,11 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *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)
|
||||
{
|
||||
ctx->crls = sk;
|
||||
@ -2348,6 +2417,15 @@ void X509_STORE_CTX_free(X509_STORE_CTX *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,
|
||||
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->dane = NULL;
|
||||
ctx->bare_ta_signed = 0;
|
||||
ctx->rpk = NULL;
|
||||
/* Zero ex_data to make sure we're cleanup-safe */
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return ctx->untrusted;
|
||||
@ -2712,7 +2796,7 @@ static unsigned char *dane_i2d(X509 *cert, uint8_t selector,
|
||||
#define DANETLS_NONE 256 /* impossible uint8_t */
|
||||
|
||||
/* 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;
|
||||
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).
|
||||
*/
|
||||
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;
|
||||
if (matched > 0) {
|
||||
ctx->num_untrusted = depth - 1;
|
||||
@ -2917,6 +3001,62 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -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];
|
||||
}
|
||||
|
||||
/*-
|
||||
* 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
|
||||
* 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
|
||||
DEPEND[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
|
||||
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
|
||||
@ -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
|
||||
DEPEND[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
|
||||
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
|
||||
@ -3468,6 +3476,7 @@ html/man3/SSL_do_handshake.html \
|
||||
html/man3/SSL_export_keying_material.html \
|
||||
html/man3/SSL_extension_supported.html \
|
||||
html/man3/SSL_free.html \
|
||||
html/man3/SSL_get0_peer_rpk.html \
|
||||
html/man3/SSL_get0_peer_scts.html \
|
||||
html/man3/SSL_get_SSL_CTX.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_session_reused.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_bio.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_extension_supported.3 \
|
||||
man/man3/SSL_free.3 \
|
||||
man/man3/SSL_get0_peer_rpk.3 \
|
||||
man/man3/SSL_get0_peer_scts.3 \
|
||||
man/man3/SSL_get_SSL_CTX.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_session_reused.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_bio.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_engine_synopsis -}[B<-ssl_client_engine> I<id>]
|
||||
{- $OpenSSL::safe::opt_v_synopsis -}
|
||||
[B<-enable_server_rpk>]
|
||||
[B<-enable_client_rpk>]
|
||||
[I<host>:I<port>]
|
||||
|
||||
=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
|
||||
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>
|
||||
|
||||
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<-tfo>, B<-no_tx_cert_comp>, and B<-no_rx_cert_comp> options were added
|
||||
in OpenSSL 3.2.
|
||||
The
|
||||
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
|
||||
|
||||
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
|
||||
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_r_synopsis -}
|
||||
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
|
||||
[B<-enable_server_rpk>]
|
||||
[B<-enable_client_rpk>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@ -867,6 +869,26 @@ If the server requests a client certificate, then
|
||||
verification errors are displayed, for debugging, but the command will
|
||||
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
|
||||
|
||||
=head1 CONNECTED COMMANDS
|
||||
@ -971,12 +993,17 @@ The
|
||||
The B<-srpvfile>, B<-srpuserseed>, and B<-engine>
|
||||
option were deprecated in OpenSSL 3.0.
|
||||
|
||||
The B<-tfo>, B<-no_tx_cert_comp>, and B<-no_rx_cert_comp> options were added
|
||||
in OpenSSL 3.2.
|
||||
The
|
||||
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
|
||||
|
||||
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
|
||||
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);
|
||||
if (depth >= 0) {
|
||||
(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,
|
||||
(mspki != NULL) ? "TA public key verified certificate" :
|
||||
depth ? "matched TA certificate" : "matched EE certificate",
|
||||
depth);
|
||||
printf("DANE TLSA %d %d %d ", usage, selector, mtype);
|
||||
if (SSL_get0_peer_rpk(ssl) == NULL)
|
||||
printf("%s certificate at depth %d\n",
|
||||
(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) {
|
||||
/* 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)>.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
=head1 NOTES
|
||||
@ -490,7 +496,7 @@ L<X509_free(3)>.
|
||||
|
||||
=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
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
|
@ -3,12 +3,16 @@
|
||||
=head1 NAME
|
||||
|
||||
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_set0_rpk,
|
||||
X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
|
||||
X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted,
|
||||
X509_STORE_CTX_get_num_untrusted,
|
||||
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_verify,
|
||||
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,
|
||||
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_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_rpk(X509_STORE_CTX *ctx, EVP_PKEY *target);
|
||||
|
||||
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);
|
||||
@ -43,6 +50,7 @@ X509_STORE_CTX_purpose_inherit
|
||||
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);
|
||||
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);
|
||||
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>,
|
||||
and a list of additional certificates may be provided in I<untrusted>,
|
||||
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.
|
||||
Yet note that L<X509_verify_cert(3)> and L<X509_STORE_CTX_verify(3)>
|
||||
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,
|
||||
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
|
||||
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
|
||||
@ -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>
|
||||
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>.
|
||||
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
|
||||
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
|
||||
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
|
||||
@ -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
|
||||
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>
|
||||
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_set0_trusted_stack(),
|
||||
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_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_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.
|
||||
|
||||
=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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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)>
|
||||
|
||||
=head1 HISTORY
|
||||
@ -89,7 +102,7 @@ X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0.
|
||||
|
||||
=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
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
=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
|
||||
|
||||
@ -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,
|
||||
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);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@ -25,8 +28,9 @@ from this SSL_CTX object).
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
d2i_SSL_SESSION() returns a pointer to the newly allocated SSL_SESSION
|
||||
object. In case of failure the NULL-pointer is returned and the error message
|
||||
d2i_SSL_SESSION() and d2i_SSL_SESSION_ex() return a pointer to the newly
|
||||
allocated SSL_SESSION object.
|
||||
In case of failure the NULL-pointer is returned and the error message
|
||||
can be retrieved from the error stack.
|
||||
|
||||
i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes.
|
||||
@ -40,7 +44,7 @@ L<d2i_X509(3)>
|
||||
|
||||
=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
|
||||
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
|
||||
* 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;
|
||||
/* signed via bare TA public key, rather than CA certificate */
|
||||
int bare_ta_signed;
|
||||
/* Raw Public Key */
|
||||
EVP_PKEY *rpk;
|
||||
|
||||
OSSL_LIB_CTX *libctx;
|
||||
char *propq;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* {- 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 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 */
|
||||
/* 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 */
|
||||
#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 */
|
||||
#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 */
|
||||
#define SSL_EXT_SSL3_ALLOWED 0x0008
|
||||
#define SSL_EXT_SSL3_ALLOWED 0x00008
|
||||
/* 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 */
|
||||
#define SSL_EXT_TLS1_3_ONLY 0x0020
|
||||
#define SSL_EXT_TLS1_3_ONLY 0x00020
|
||||
/* Ignore this extension during parsing if we are resuming */
|
||||
#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040
|
||||
#define SSL_EXT_CLIENT_HELLO 0x0080
|
||||
#define SSL_EXT_IGNORE_ON_RESUMPTION 0x00040
|
||||
#define SSL_EXT_CLIENT_HELLO 0x00080
|
||||
/* Really means TLS1.2 or below */
|
||||
#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100
|
||||
#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200
|
||||
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400
|
||||
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800
|
||||
#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
|
||||
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
|
||||
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
|
||||
#define SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION 0x8000
|
||||
#define SSL_EXT_TLS1_2_SERVER_HELLO 0x00100
|
||||
#define SSL_EXT_TLS1_3_SERVER_HELLO 0x00200
|
||||
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x00400
|
||||
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x00800
|
||||
#define SSL_EXT_TLS1_3_CERTIFICATE 0x01000
|
||||
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x02000
|
||||
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x04000
|
||||
#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 */
|
||||
|
||||
@ -566,6 +568,8 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
|
||||
# define CERT_PKEY_CERT_TYPE 0x400
|
||||
/* Cert chain suitable to Suite B */
|
||||
# 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_FILE 0x2
|
||||
@ -1734,6 +1738,9 @@ __owur int SSL_has_matching_session_id(const SSL *s,
|
||||
unsigned int id_len);
|
||||
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||
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
|
||||
__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_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
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
# 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_BAD_CERTIFICATE 348
|
||||
# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
|
||||
# define SSL_R_BAD_CIPHER 186
|
||||
# define SSL_R_BAD_COMPRESSION_ALGORITHM 326
|
||||
@ -111,6 +112,7 @@
|
||||
# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318
|
||||
# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374
|
||||
# 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_ENCRYPTED_LENGTH_TOO_LONG 150
|
||||
# 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_MAX_EARLY_DATA 174
|
||||
# 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_SEQUENCE_NUMBER 402
|
||||
# define SSL_R_INVALID_SERVERINFO_DATA 388
|
||||
@ -342,6 +345,7 @@
|
||||
# define SSL_R_WRONG_CERTIFICATE_TYPE 383
|
||||
# define SSL_R_WRONG_CIPHER_RETURNED 261
|
||||
# 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_SIZE 265
|
||||
# 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 2005 Nokia. All rights reserved.
|
||||
*
|
||||
@ -122,6 +122,14 @@ extern "C" {
|
||||
*/
|
||||
# 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.
|
||||
* 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_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_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* {- 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
|
||||
* 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_EXTENSIONS_REQUIRE_VERSION_3 93
|
||||
# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94
|
||||
# define X509_V_ERR_RPK_UNTRUSTED 95
|
||||
|
||||
/* Certificate verify flags */
|
||||
# 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);
|
||||
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store,
|
||||
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_cleanup(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);
|
||||
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);
|
||||
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,
|
||||
@ -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_get1_chain(const X509_STORE_CTX *ctx);
|
||||
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_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
||||
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.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
@ -12,6 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "ssl_local.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/encoder.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
typedef struct {
|
||||
@ -44,6 +45,7 @@ typedef struct {
|
||||
uint32_t tlsext_max_fragment_len_mode;
|
||||
ASN1_OCTET_STRING *ticket_appdata;
|
||||
uint32_t kex_group;
|
||||
ASN1_OCTET_STRING *peer_rpk;
|
||||
} 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_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_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)
|
||||
|
||||
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
|
||||
@ -125,8 +128,10 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
||||
#endif
|
||||
ASN1_OCTET_STRING alpn_selected;
|
||||
ASN1_OCTET_STRING ticket_appdata;
|
||||
ASN1_OCTET_STRING peer_rpk;
|
||||
|
||||
long l;
|
||||
int ret;
|
||||
|
||||
if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
|
||||
return 0;
|
||||
@ -169,6 +174,14 @@ int i2d_SSL_SESSION(const SSL_SESSION *in, unsigned char **pp)
|
||||
|
||||
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,
|
||||
in->ext.hostname);
|
||||
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,
|
||||
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 */
|
||||
@ -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,
|
||||
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;
|
||||
size_t tmpl;
|
||||
@ -316,6 +336,19 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||
ret->peer = as->peer;
|
||||
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,
|
||||
as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
|
||||
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
|
||||
*
|
||||
* 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:
|
||||
* 1: Verify success
|
||||
* 0: Verify failure or error
|
||||
* -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;
|
||||
int i = 0;
|
||||
@ -429,7 +429,12 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
||||
X509_VERIFY_PARAM *param;
|
||||
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;
|
||||
|
||||
sctx = SSL_CONNECTION_GET_CTX(s);
|
||||
@ -444,10 +449,17 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
x = sk_X509_value(sk, 0);
|
||||
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
|
||||
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
||||
goto end;
|
||||
if (sk != NULL) {
|
||||
x = sk_X509_value(sk, 0);
|
||||
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
|
||||
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
|
||||
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);
|
||||
/*
|
||||
@ -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);
|
||||
OSSL_STACK_OF_X509_free(s->verified_chain);
|
||||
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);
|
||||
if (s->verified_chain == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
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"},
|
||||
{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"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CERTIFICATE), "bad certificate"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC),
|
||||
"bad change cipher spec"},
|
||||
{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),
|
||||
"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_EMPTY_RAW_PUBLIC_KEY),
|
||||
"empty raw public key"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST),
|
||||
"empty srtp protection profile list"},
|
||||
{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"},
|
||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_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_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),
|
||||
"wrong cipher returned"},
|
||||
{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),
|
||||
"wrong signature length"},
|
||||
{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 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
|
||||
memcpy(s->cert_comp_prefs, ctx->cert_comp_prefs, sizeof(s->cert_comp_prefs));
|
||||
#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
|
||||
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->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);
|
||||
|
||||
if (ssl->method != NULL)
|
||||
@ -4099,6 +4116,9 @@ void SSL_CTX_free(SSL_CTX *a)
|
||||
OPENSSL_free(a->sigalg_lookup_cache);
|
||||
OPENSSL_free(a->tls12_sigalgs);
|
||||
|
||||
OPENSSL_free(a->client_cert_type);
|
||||
OPENSSL_free(a->server_cert_type);
|
||||
|
||||
CRYPTO_THREAD_lock_free(a->lock);
|
||||
#ifdef TSAN_REQUIRES_LOCKING
|
||||
CRYPTO_THREAD_lock_free(a->tsan_lock);
|
||||
@ -4266,6 +4286,24 @@ void ssl_set_masks(SSL_CONNECTION *s)
|
||||
|
||||
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
|
||||
* depending on the key usage extension.
|
||||
@ -7254,3 +7292,175 @@ int SSL_stream_conclude(SSL *ssl, uint64_t flags)
|
||||
return 0;
|
||||
#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 2005 Nokia. All rights reserved.
|
||||
*
|
||||
@ -371,6 +371,11 @@
|
||||
#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 */
|
||||
typedef enum {
|
||||
SSL_PHA_NONE = 0,
|
||||
@ -510,6 +515,8 @@ struct ssl_session_st {
|
||||
* to disable session caching and tickets.
|
||||
*/
|
||||
int not_resumable;
|
||||
/* Peer raw public key, if available */
|
||||
EVP_PKEY *peer_rpk;
|
||||
/* This is the cert and type for the other end. */
|
||||
X509 *peer;
|
||||
/* Certificate chain peer sent. */
|
||||
@ -684,6 +691,8 @@ typedef enum tlsext_index_en {
|
||||
TLSEXT_IDX_extended_master_secret,
|
||||
TLSEXT_IDX_signature_algorithms_cert,
|
||||
TLSEXT_IDX_post_handshake_auth,
|
||||
TLSEXT_IDX_client_cert_type,
|
||||
TLSEXT_IDX_server_cert_type,
|
||||
TLSEXT_IDX_signature_algorithms,
|
||||
TLSEXT_IDX_supported_versions,
|
||||
TLSEXT_IDX_psk_kex_modes,
|
||||
@ -1170,6 +1179,12 @@ struct ssl_ctx_st {
|
||||
/* certificate compression preferences */
|
||||
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
||||
#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;
|
||||
@ -1651,6 +1666,11 @@ struct ssl_connection_st {
|
||||
int compress_certificate_from_peer[TLSEXT_comp_cert_limit];
|
||||
/* indicate that we sent the extension, so we'll accept it */
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -1771,6 +1791,12 @@ struct ssl_connection_st {
|
||||
/* certificate compression preferences */
|
||||
int cert_comp_prefs[TLSEXT_comp_cert_limit];
|
||||
#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) \
|
||||
@ -2380,11 +2406,47 @@ struct openssl_ssl_test_functions {
|
||||
|
||||
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 */
|
||||
static ossl_inline int ssl_has_cert(const SSL_CONNECTION *s, int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= (int)s->ssl_pkey_num)
|
||||
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
|
||||
&& 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);
|
||||
|
||||
__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_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
dest->peer_chain = NULL;
|
||||
dest->peer = NULL;
|
||||
dest->peer_rpk = NULL;
|
||||
dest->ticket_appdata = NULL;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
if (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->session_id, sizeof(ss->session_id));
|
||||
X509_free(ss->peer);
|
||||
EVP_PKEY_free(ss->peer_rpk);
|
||||
OSSL_STACK_OF_X509_free(ss->peer_chain);
|
||||
OPENSSL_free(ss->ext.hostname);
|
||||
OPENSSL_free(ss->ext.tick);
|
||||
@ -1042,6 +1051,11 @@ X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
|
||||
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,
|
||||
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
|
||||
* 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 init_sig_algs_cert(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,
|
||||
unsigned int context);
|
||||
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,
|
||||
},
|
||||
{
|
||||
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,
|
||||
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))
|
||||
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 */
|
||||
if ((sc->options & SSL_OP_NO_RX_CERTIFICATE_COMPRESSION) != 0)
|
||||
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))
|
||||
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 */
|
||||
if ((sc->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
|
||||
return 1;
|
||||
@ -1869,3 +1907,23 @@ int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt, unsigned int
|
||||
#endif
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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
|
||||
* 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_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE
|
||||
| SSL_EXT_TLS1_3_RAW_PUBLIC_KEY
|
||||
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
|
||||
/* Only send extensions present in ClientHello/CertificateRequest */
|
||||
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_post_handshake_auth:
|
||||
case TLSEXT_TYPE_compress_certificate:
|
||||
case TLSEXT_TYPE_client_cert_type:
|
||||
case TLSEXT_TYPE_server_cert_type:
|
||||
return 1;
|
||||
default:
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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 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,
|
||||
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?
|
||||
*
|
||||
@ -419,6 +424,13 @@ int ossl_statem_client_read_transition(SSL_CONNECTION *s, int mt)
|
||||
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
|
||||
* 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:
|
||||
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;
|
||||
else
|
||||
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;
|
||||
else if (s->s3.tmp.cert_req == 0)
|
||||
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;
|
||||
else
|
||||
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:
|
||||
if (s->s3.tmp.cert_req == 0)
|
||||
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;
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
||||
PACKET *pkt)
|
||||
@ -1860,6 +1947,14 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
|
||||
unsigned int context = 0;
|
||||
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) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||
goto err;
|
||||
@ -1947,6 +2042,9 @@ WORK_STATE tls_post_process_server_certificate(SSL_CONNECTION *s,
|
||||
size_t certidx;
|
||||
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)
|
||||
s->rwstate = SSL_NOTHING;
|
||||
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);
|
||||
s->session->peer = x;
|
||||
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 */
|
||||
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 */
|
||||
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;
|
||||
#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
|
||||
*/
|
||||
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. */
|
||||
|
||||
ret = 1;
|
||||
@ -2265,9 +2366,9 @@ static int tls_process_ske_ecdhe(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **pkey
|
||||
* and ECDSA.
|
||||
*/
|
||||
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)
|
||||
*pkey = X509_get0_pubkey(s->session->peer);
|
||||
*pkey = tls_get_peer_pkey(s);
|
||||
/* else anonymous ECDH, so no certificate or pkey. */
|
||||
|
||||
/* 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;
|
||||
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.
|
||||
*/
|
||||
@ -2953,7 +3054,11 @@ static int tls_construct_cke_rsa(SSL_CONNECTION *s, WPACKET *pkt)
|
||||
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")) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
@ -3128,7 +3233,7 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
/* GOST key exchange message creation */
|
||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||
X509 *peer_cert;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t msglen;
|
||||
unsigned int md_len;
|
||||
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
|
||||
*/
|
||||
peer_cert = s->session->peer;
|
||||
if (peer_cert == NULL) {
|
||||
if ((pkey = tls_get_peer_pkey(s)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
||||
X509_get0_pubkey(peer_cert),
|
||||
pkey,
|
||||
sctx->propq);
|
||||
if (pkey_ctx == NULL) {
|
||||
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 *encdata = NULL;
|
||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||
X509 *peer_cert;
|
||||
EVP_PKEY *pkey;
|
||||
unsigned char *pms = NULL;
|
||||
size_t pmslen = 0;
|
||||
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 */
|
||||
peer_cert = s->session->peer;
|
||||
if (peer_cert == NULL) {
|
||||
if ((pkey = tls_get_peer_pkey(s)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
|
||||
X509_get0_pubkey(peer_cert),
|
||||
pkey,
|
||||
sctx->propq);
|
||||
if (pkey_ctx == NULL) {
|
||||
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,
|
||||
WPACKET *pkt)
|
||||
{
|
||||
CERT_PKEY *cpk = NULL;
|
||||
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
|
||||
|
||||
if (SSL_CONNECTION_IS_TLS13(s)) {
|
||||
@ -3643,10 +3747,23 @@ CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
|
||||
return CON_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
if (!ssl3_output_cert_chain(s, pkt,
|
||||
(s->s3.tmp.cert_req == 2) ? NULL
|
||||
: s->cert->key, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
if (s->s3.tmp.cert_req != 2)
|
||||
cpk = s->cert->key;
|
||||
switch (s->ext.client_cert_type) {
|
||||
case TLSEXT_cert_type_rpk:
|
||||
if (!tls_output_rpk(s, pkt, cpk)) {
|
||||
/* SSLfatal() already called */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3764,6 +3881,7 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
||||
const SSL_CERT_LOOKUP *clu;
|
||||
size_t idx;
|
||||
long alg_k, alg_a;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
|
||||
alg_a = s->s3.tmp.new_cipher->algorithm_auth;
|
||||
@ -3773,8 +3891,8 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
||||
return 1;
|
||||
|
||||
/* This is the passed certificate */
|
||||
clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx,
|
||||
SSL_CONNECTION_GET_CTX(s));
|
||||
pkey = tls_get_peer_pkey(s);
|
||||
clu = ssl_cert_lookup_by_pkey(pkey, &idx, SSL_CONNECTION_GET_CTX(s));
|
||||
|
||||
/* Check certificate is recognised and suitable for cipher */
|
||||
if (clu == NULL || (alg_a & clu->amask) == 0) {
|
||||
@ -3782,13 +3900,6 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
||||
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) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
||||
@ -3800,6 +3911,17 @@ int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
@ -20,6 +20,7 @@
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/trace.h>
|
||||
#include <openssl/encoder.h>
|
||||
|
||||
/*
|
||||
* 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;
|
||||
int j;
|
||||
unsigned int len;
|
||||
X509 *peer;
|
||||
const EVP_MD *md = NULL;
|
||||
size_t hdatalen = 0;
|
||||
void *hdata;
|
||||
@ -461,8 +461,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL_CONNECTION *s, PACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
peer = s->session->peer;
|
||||
pkey = X509_get0_pubkey(peer);
|
||||
pkey = tls_get_peer_pkey(s);
|
||||
if (pkey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
@ -1092,6 +1091,291 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i
|
||||
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,
|
||||
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
|
||||
* 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);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL_CONNECTION *s,
|
||||
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,
|
||||
PACKET *pkt);
|
||||
__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_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 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,
|
||||
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
|
||||
* 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_CERT:
|
||||
if (s->session->peer == NULL) {
|
||||
if (!received_client_cert(s)) {
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_SR_FINISHED;
|
||||
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
|
||||
* 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) {
|
||||
/*
|
||||
* For the ECDH ciphersuites when the client sends its ECDH
|
||||
@ -444,6 +449,13 @@ int send_certificate_request(SSL_CONNECTION *s)
|
||||
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
|
||||
* 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;
|
||||
else if (send_certificate_request(s))
|
||||
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;
|
||||
else
|
||||
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) {
|
||||
s->post_handshake_auth = SSL_PHA_REQUESTED;
|
||||
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;
|
||||
} else {
|
||||
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
|
||||
* 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 (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
||||
ERR_clear_error();
|
||||
@ -3485,7 +3497,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL_CONNECTION *s,
|
||||
}
|
||||
#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
|
||||
* the handshake_buffer
|
||||
@ -3513,6 +3525,91 @@ WORK_STATE tls_post_process_client_key_exchange(SSL_CONNECTION *s,
|
||||
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,
|
||||
PACKET *pkt)
|
||||
{
|
||||
@ -3534,6 +3631,15 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
|
||||
if (s->rlayer.rrlmethod->set_plain_alerts != NULL)
|
||||
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) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||
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);
|
||||
s->session->peer_chain = sk;
|
||||
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
|
||||
@ -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);
|
||||
return CON_FUNC_ERROR;
|
||||
}
|
||||
if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
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)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
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
|
||||
* 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;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
SSL_CTX *tctx = s->session_ctx;
|
||||
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
||||
|
||||
if (eticklen == 0) {
|
||||
/*
|
||||
@ -2263,7 +2264,6 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s,
|
||||
renew_ticket = 1;
|
||||
} else {
|
||||
EVP_CIPHER *aes256cbc = NULL;
|
||||
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
|
||||
|
||||
/* Check key name matches */
|
||||
if (memcmp(etick, tctx->ext.tick_key_name,
|
||||
@ -2341,7 +2341,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s,
|
||||
slen += declen;
|
||||
p = sdec;
|
||||
|
||||
sess = d2i_SSL_SESSION(NULL, &p, slen);
|
||||
sess = d2i_SSL_SESSION_ex(NULL, &p, slen, sctx->libctx, sctx->propq);
|
||||
slen -= p - sdec;
|
||||
OPENSSL_free(sdec);
|
||||
if (sess) {
|
||||
@ -3048,9 +3048,15 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
|
||||
uint32_t *pvalid;
|
||||
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) {
|
||||
/* idx == -2 means checking client certificate chains */
|
||||
if (idx == -2) {
|
||||
cpk = c->key;
|
||||
idx = (int)(cpk - c->pkeys);
|
||||
@ -3061,13 +3067,19 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
|
||||
pk = cpk->privatekey;
|
||||
chain = cpk->chain;
|
||||
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 (!x || !pk)
|
||||
if (x == NULL || pk == NULL)
|
||||
goto end;
|
||||
} else {
|
||||
size_t certidx;
|
||||
|
||||
if (!x || !pk)
|
||||
if (x == NULL || pk == NULL)
|
||||
return 0;
|
||||
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
* 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,
|
||||
"application_layer_protocol_negotiation"},
|
||||
{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_encrypt_then_mac, "encrypt_then_mac"},
|
||||
{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"}
|
||||
};
|
||||
|
||||
/*
|
||||
* "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,
|
||||
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);
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
int indent, const unsigned char *msg,
|
||||
size_t msglen)
|
||||
@ -1291,6 +1349,16 @@ static int ssl_print_certificates(BIO *bio, const SSL_CONNECTION *sc, int server
|
||||
if (msglen != clen + 3)
|
||||
return 0;
|
||||
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_printf(bio, "certificate_list, length=%d\n", (int)clen);
|
||||
while (clen > 0) {
|
||||
|
@ -66,6 +66,10 @@ IF[{- !$disabled{tests} -}]
|
||||
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \
|
||||
x509_test hpke_test pairwise_fail_test nodefltctxtest
|
||||
|
||||
IF[{- !$disabled{'rpk'} -}]
|
||||
PROGRAMS{noinst}=rpktest
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{'deprecated-3.0'} -}]
|
||||
PROGRAMS{noinst}=enginetest
|
||||
ENDIF
|
||||
@ -485,6 +489,10 @@ IF[{- !$disabled{tests} -}]
|
||||
INCLUDE[sslapitest]=../include ../apps/include ..
|
||||
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
|
||||
INCLUDE[defltfips_test]=../include ../apps/include
|
||||
DEPEND[defltfips_test]=../libcrypto libtestutil.a
|
||||
|
@ -61,6 +61,8 @@ static EXT_LIST ext_list[] = {
|
||||
EXT_ENTRY(extended_master_secret),
|
||||
EXT_ENTRY(signature_algorithms_cert),
|
||||
EXT_ENTRY(post_handshake_auth),
|
||||
EXT_ENTRY(client_cert_type),
|
||||
EXT_ENTRY(server_cert_type),
|
||||
EXT_ENTRY(signature_algorithms),
|
||||
EXT_ENTRY(supported_versions),
|
||||
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.
|
||||
* Test 0: Signature algorithm with built-in hashing functionality: "xorhmacsig"
|
||||
* 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 const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
|
||||
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||
SSL *clientssl = NULL, *serverssl = NULL;
|
||||
int testresult = 0;
|
||||
@ -9568,10 +9571,12 @@ static int test_pluggable_signature(int idx)
|
||||
OSSL_PROVIDER *defaultprov = OSSL_PROVIDER_load(libctx, "default");
|
||||
char *certfilename = "tls-prov-cert.pem";
|
||||
char *privkeyfilename = "tls-prov-key.pem";
|
||||
int sigidx = idx % 2;
|
||||
int rpkidx = idx / 2;
|
||||
|
||||
/* create key and certificate for the different algorithm types */
|
||||
if (!TEST_ptr(tlsprov)
|
||||
|| !TEST_true(create_cert_key(idx, certfilename, privkeyfilename)))
|
||||
|| !TEST_true(create_cert_key(sigidx, certfilename, privkeyfilename)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
|
||||
@ -9583,6 +9588,13 @@ static int test_pluggable_signature(int idx)
|
||||
NULL, NULL)))
|
||||
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 */
|
||||
if (!TEST_true(SSL_set1_groups_list(serverssl, "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)))
|
||||
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;
|
||||
|
||||
end:
|
||||
@ -11083,7 +11099,7 @@ int setup_tests(void)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
ADD_ALL_TESTS(test_pluggable_group, 2);
|
||||
ADD_ALL_TESTS(test_pluggable_signature, 2);
|
||||
ADD_ALL_TESTS(test_pluggable_signature, 4);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_2
|
||||
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_crl_ex ? 3_2_0 EXIST::FUNCTION:
|
||||
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_stream_conclude ? 3_2_0 EXIST::FUNCTION:
|
||||
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_ALPN => 16,
|
||||
EXT_SCT => 18,
|
||||
EXT_CLIENT_CERT_TYPE => 19,
|
||||
EXT_SERVER_CERT_TYPE => 20,
|
||||
EXT_PADDING => 21,
|
||||
EXT_ENCRYPT_THEN_MAC => 22,
|
||||
EXT_EXTENDED_MASTER_SECRET => 23,
|
||||
|
Loading…
x
Reference in New Issue
Block a user