/*
- * 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.
*
#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,
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)
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);
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.
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;
+}