"RSA+SHA256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha256WithRSAEncryption, NID_undef, 1, 0,
- TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+ TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
{TLSEXT_SIGALG_rsa_pkcs1_sha384_name,
"RSA+SHA384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha384WithRSAEncryption, NID_undef, 1, 0,
- TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+ TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
{TLSEXT_SIGALG_rsa_pkcs1_sha512_name,
"RSA+SHA512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha512WithRSAEncryption, NID_undef, 1, 0,
- TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+ TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
{TLSEXT_SIGALG_rsa_pkcs1_sha224_name,
"RSA+SHA224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
return secbits;
}
+static int tls_sigalg_compat(SSL_CONNECTION *sc, const SIGALG_LOOKUP *lu)
+{
+ int minversion, maxversion;
+ int minproto, maxproto;
+
+ if (!lu->available)
+ return 0;
+
+ if (SSL_CONNECTION_IS_DTLS(sc)) {
+ if (sc->ssl.method->version == DTLS_ANY_VERSION) {
+ minproto = sc->min_proto_version;
+ maxproto = sc->max_proto_version;
+ } else {
+ maxproto = minproto = sc->version;
+ }
+ minversion = lu->mindtls;
+ maxversion = lu->maxdtls;
+ } else {
+ if (sc->ssl.method->version == TLS_ANY_VERSION) {
+ minproto = sc->min_proto_version;
+ maxproto = sc->max_proto_version;
+ } else {
+ maxproto = minproto = sc->version;
+ }
+ minversion = lu->mintls;
+ maxversion = lu->maxtls;
+ }
+ if (minversion == -1 || maxversion == -1
+ || (minversion != 0 && maxproto != 0
+ && ssl_version_cmp(sc, minversion, maxproto) > 0)
+ || (maxversion != 0 && minproto != 0
+ && ssl_version_cmp(sc, maxversion, minproto) < 0)
+ || !tls12_sigalg_allowed(sc, SSL_SECOP_SIGALG_SUPPORTED, lu))
+ return 0;
+ return 1;
+}
+
/*
* Check signature algorithm is consistent with sent supported signature
* algorithms and if so set relevant digest and signature scheme in
int pkeyid = -1;
const SIGALG_LOOKUP *lu;
int secbits = 0;
- int minversion, maxversion;
pkeyid = EVP_PKEY_get_id(pkey);
/* Is this code point available and compatible with the protocol */
lu = tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), sig);
- if (lu == NULL) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
- return 0;
- }
- minversion = SSL_CONNECTION_IS_DTLS(s) ? lu->mindtls : lu->mintls;
- maxversion = SSL_CONNECTION_IS_DTLS(s) ? lu->maxdtls : lu->maxtls;
- if (minversion == -1 || maxversion == -1 || !lu->available
- || (minversion != 0 && s->max_proto_version != 0
- && ssl_version_cmp(s, minversion, s->max_proto_version) > 0)
- || (maxversion != 0 && s->min_proto_version != 0
- && ssl_version_cmp(s, maxversion, s->min_proto_version) < 0)
- || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu)) {
+ if (lu == NULL || !tls_sigalg_compat(s, lu)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
for (i = 0; i < psiglen; i++, psig++) {
const SIGALG_LOOKUP *lu =
tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), *psig);
- int minversion, maxversion;
- if (lu == NULL)
- continue;
- minversion = SSL_CONNECTION_IS_DTLS(s) ? lu->mindtls : lu->mintls;
- maxversion = SSL_CONNECTION_IS_DTLS(s) ? lu->maxdtls : lu->maxtls;
- if (minversion == -1 || maxversion == -1 || !lu->available
- || (minversion != 0 && s->max_proto_version != 0
- && ssl_version_cmp(s, minversion, s->max_proto_version) > 0)
- || (maxversion != 0 && s->min_proto_version != 0
- && ssl_version_cmp(s, maxversion, s->min_proto_version) < 0)
- || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
+ if (lu == NULL || !tls_sigalg_compat(s, lu))
continue;
if (!WPACKET_put_bytes_u16(pkt, *psig))
return 0;
const SIGALG_LOOKUP *sigalg;
size_t sigalgslen;
- if (default_nid == -1)
+ /*-
+ * RFC 8446, section 4.2.3:
+ *
+ * The signatures on certificates that are self-signed or certificates
+ * that are trust anchors are not validated, since they begin a
+ * certification path (see [RFC5280], Section 3.2). A certificate that
+ * begins a certification path MAY use a signature algorithm that is not
+ * advertised as being supported in the "signature_algorithms"
+ * extension.
+ */
+ if (default_nid == -1 || X509_self_signed(x, 0))
return 1;
sig_nid = X509_get_signature_nid(x);
if (default_nid)
sigalgslen = s->shared_sigalgslen;
}
for (i = 0; i < sigalgslen; i++) {
+ int mdnid, pknid;
+
sigalg = use_pc_sigalgs
? tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s),
s->s3.tmp.peer_cert_sigalgs[i])
: s->shared_sigalgs[i];
- if (sigalg != NULL && sig_nid == sigalg->sigandhash)
+ if (sigalg == NULL)
+ continue;
+ if (sig_nid == sigalg->sigandhash)
+ return 1;
+ if (sigalg->sig != EVP_PKEY_RSA_PSS)
+ continue;
+ /*
+ * Accept RSA PKCS#1 signatures in certificates when the signature
+ * algorithms include RSA-PSS with a matching digest algorithm.
+ *
+ * When a TLS 1.3 peer inadvertently omits the legacy RSA PKCS#1 code
+ * points, and we're doing strict checking of the certificate chain (in
+ * a cert_cb via SSL_check_chain()) we may then reject RSA signed
+ * certificates in the chain, but the TLS requirement on PSS should not
+ * extend to certificates. Though the peer can in fact list the legacy
+ * sigalgs for just this purpose, it is not likely that a better chain
+ * signed with RSA-PSS is available.
+ */
+ if (!OBJ_find_sigid_algs(sig_nid, &mdnid, &pknid))
+ continue;
+ if (pknid == EVP_PKEY_RSA && mdnid == sigalg->hash)
return 1;
}
return 0;
/* Look for a shared sigalgs matching possible certificates */
for (i = 0; i < s->shared_sigalgslen; i++) {
- int dtls, minversion, maxversion;
-
/* Skip SHA1, SHA224, DSA and RSA if not PSS */
lu = s->shared_sigalgs[i];
if (lu->hash == NID_sha1
|| lu->hash == NID_sha224
|| lu->sig == EVP_PKEY_DSA
- || lu->sig == EVP_PKEY_RSA)
- continue;
-
- /*
- * By this point the protocol version should already be chosen. Check
- * the sigalg version bounds.
- */
- dtls = SSL_CONNECTION_IS_DTLS(s);
- minversion = dtls ? lu->mindtls : lu->mintls;
- maxversion = dtls ? lu->maxdtls : lu->maxtls;
- if (minversion != 0 && ssl_version_cmp(s, minversion, s->version) > 0)
- continue;
- if (maxversion != 0 && ssl_version_cmp(s, maxversion, s->version) < 0)
+ || lu->sig == EVP_PKEY_RSA
+ || !tls_sigalg_compat(s, lu))
continue;
/* Check that we have a cert, and signature_algorithms_cert */
* cert type
*/
for (i = 0; i < s->shared_sigalgslen; i++) {
- int dtls, minversion, maxversion;
-
/* Check the sigalg version bounds */
lu = s->shared_sigalgs[i];
- dtls = SSL_CONNECTION_IS_DTLS(s);
- minversion = dtls ? lu->mindtls : lu->mintls;
- maxversion = dtls ? lu->maxdtls : lu->maxtls;
- if (minversion != 0
- && ssl_version_cmp(s, minversion, s->version) > 0)
+ if (!tls_sigalg_compat(s, lu))
continue;
- if (maxversion != 0
- && ssl_version_cmp(s, maxversion, s->version) < 0)
- continue;
-
if (s->server) {
if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
continue;
#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
static int cert_cb_cnt;
+static int load_chain(const char *file, EVP_PKEY **pkey, X509 **x509,
+ STACK_OF(X509) *chain)
+{
+ char *path = test_mk_file_path(certsdir, file);
+ BIO *in = NULL;
+ X509 *x = NULL;
+ int ok = 0;
+
+ if (path == NULL)
+ return 0;
+ if ((in = BIO_new(BIO_s_file())) == NULL
+ || BIO_read_filename(in, path) <= 0)
+ goto out;
+ if (pkey == NULL) {
+ if ((x = X509_new_ex(libctx, NULL)) == NULL
+ || PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
+ goto out;
+ if (chain == NULL)
+ *x509 = x;
+ else if (!sk_X509_push(chain, x))
+ goto out;
+ } else if (PEM_read_bio_PrivateKey_ex(in, pkey, NULL, NULL,
+ libctx, NULL) == NULL) {
+ goto out;
+ }
+
+ x = NULL;
+ ok = 1;
+ out:
+ X509_free(x);
+ BIO_free(in);
+ OPENSSL_free(path);
+ return ok;
+}
+
static int cert_cb(SSL *s, void *arg)
{
SSL_CTX *ctx = (SSL_CTX *)arg;
- BIO *in = NULL;
EVP_PKEY *pkey = NULL;
- X509 *x509 = NULL, *rootx = NULL;
+ X509 *x509 = NULL, *x = NULL;
STACK_OF(X509) *chain = NULL;
- char *rootfile = NULL, *ecdsacert = NULL, *ecdsakey = NULL;
int ret = 0;
if (cert_cb_cnt == 0) {
} else if (cert_cb_cnt == 3) {
int rv;
- rootfile = test_mk_file_path(certsdir, "rootcert.pem");
- ecdsacert = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
- ecdsakey = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
- if (!TEST_ptr(rootfile) || !TEST_ptr(ecdsacert) || !TEST_ptr(ecdsakey))
- goto out;
chain = sk_X509_new_null();
- if (!TEST_ptr(chain))
- goto out;
- if (!TEST_ptr(in = BIO_new(BIO_s_file()))
- || !TEST_int_gt(BIO_read_filename(in, rootfile), 0)
- || !TEST_ptr(rootx = X509_new_ex(libctx, NULL))
- || !TEST_ptr(PEM_read_bio_X509(in, &rootx, NULL, NULL))
- || !TEST_true(sk_X509_push(chain, rootx)))
- goto out;
- rootx = NULL;
- BIO_free(in);
- if (!TEST_ptr(in = BIO_new(BIO_s_file()))
- || !TEST_int_gt(BIO_read_filename(in, ecdsacert), 0)
- || !TEST_ptr(x509 = X509_new_ex(libctx, NULL))
- || !TEST_ptr(PEM_read_bio_X509(in, &x509, NULL, NULL)))
- goto out;
- BIO_free(in);
- if (!TEST_ptr(in = BIO_new(BIO_s_file()))
- || !TEST_int_gt(BIO_read_filename(in, ecdsakey), 0)
- || !TEST_ptr(pkey = PEM_read_bio_PrivateKey_ex(in, NULL,
- NULL, NULL,
- libctx, NULL)))
+ if (!TEST_ptr(chain)
+ || !TEST_true(load_chain("ca-cert.pem", NULL, NULL, chain))
+ || !TEST_true(load_chain("root-cert.pem", NULL, NULL, chain))
+ || !TEST_true(load_chain("p256-ee-rsa-ca-cert.pem", NULL,
+ &x509, NULL))
+ || !TEST_true(load_chain("p256-ee-rsa-ca-key.pem", &pkey,
+ NULL, NULL)))
goto out;
rv = SSL_check_chain(s, x509, pkey, chain);
/*
/* Abort the handshake */
out:
- OPENSSL_free(ecdsacert);
- OPENSSL_free(ecdsakey);
- OPENSSL_free(rootfile);
- BIO_free(in);
EVP_PKEY_free(pkey);
X509_free(x509);
- X509_free(rootx);
+ X509_free(x);
OSSL_STACK_OF_X509_free(chain);
return ret;
}
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
- TLS1_VERSION,
+ prot,
prot,
&sctx, &cctx, NULL, NULL)))
goto end;