summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan M. Wilbur <jonathan@wilbur.space>2024-06-01 19:23:25 +0000
committerTomas Mraz <tomas@openssl.org>2024-06-17 14:03:25 +0200
commit58301e24f66aa74b13b85a171dd14e6088c35662 (patch)
treeb6d25e9e26f8dee2bf86c723ee865471897d2b00
parent40948c4c74099ae21843d9265dfe65f13cb9e6c5 (diff)
Add support for targetingInformation X.509v3 extension
Support for the targetingInformation X.509v3 extension defined in ITU-T Recommendation X.509 (2019), Section 17.1.2.2. This extension is used in attribute certificates. Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22206)
-rw-r--r--crypto/x509/build.info2
-rw-r--r--crypto/x509/ext_dat.h1
-rw-r--r--crypto/x509/standard_exts.h1
-rw-r--r--crypto/x509/v3_ac_tgt.c239
-rw-r--r--crypto/x509/v3_crld.c16
-rw-r--r--crypto/x509/v3_utl.c13
-rw-r--r--doc/build.info6
-rw-r--r--doc/man3/OSSL_GENERAL_NAMES_print.pod36
-rw-r--r--doc/man3/X509_dup.pod12
-rw-r--r--doc/man3/d2i_X509.pod12
-rw-r--r--fuzz/asn1.c2
-rw-r--r--include/crypto/x509_acert.h4
-rw-r--r--include/openssl/x509_acert.h.in36
-rw-r--r--include/openssl/x509v3.h.in2
-rw-r--r--test/certs/ext-targetingInformation.pem14
-rw-r--r--test/recipes/25-test_x509.t31
-rw-r--r--util/libcrypto.num16
17 files changed, 427 insertions, 16 deletions
diff --git a/crypto/x509/build.info b/crypto/x509/build.info
index 6cebadea77..1184329b20 100644
--- a/crypto/x509/build.info
+++ b/crypto/x509/build.info
@@ -16,7 +16,7 @@ SOURCE[../../libcrypto]=\
pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \
v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c v3_no_rev_avail.c \
v3_soa_id.c v3_no_ass.c v3_group_ac.c v3_single_use.c v3_ind_iss.c \
- x509_acert.c x509aset.c t_acert.c x_ietfatt.c
+ x509_acert.c x509aset.c t_acert.c x_ietfatt.c v3_ac_tgt.c
IF[{- !$disabled{'deprecated-3.0'} -}]
SOURCE[../../libcrypto]=x509type.c
diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h
index 1ffc816e5e..8d34e829dc 100644
--- a/crypto/x509/ext_dat.h
+++ b/crypto/x509/ext_dat.h
@@ -31,3 +31,4 @@ extern const X509V3_EXT_METHOD ossl_v3_no_assertion;
extern const X509V3_EXT_METHOD ossl_v3_no_rev_avail;
extern const X509V3_EXT_METHOD ossl_v3_single_use;
extern const X509V3_EXT_METHOD ossl_v3_indirect_issuer;
+extern const X509V3_EXT_METHOD ossl_v3_targeting_information;
diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h
index 87a564b238..eba9e31dec 100644
--- a/crypto/x509/standard_exts.h
+++ b/crypto/x509/standard_exts.h
@@ -53,6 +53,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = {
#endif
&ossl_v3_sinfo,
&ossl_v3_policy_constraints,
+ &ossl_v3_targeting_information,
&ossl_v3_no_rev_avail,
#ifndef OPENSSL_NO_OCSP
&ossl_v3_crl_hold,
diff --git a/crypto/x509/v3_ac_tgt.c b/crypto/x509/v3_ac_tgt.c
new file mode 100644
index 0000000000..c6b3701b4e
--- /dev/null
+++ b/crypto/x509/v3_ac_tgt.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright 1999-2024 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 <stdio.h>
+#include <openssl/x509_acert.h>
+#include <crypto/x509_acert.h>
+#include "internal/cryptlib.h"
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include "ext_dat.h"
+#include "x509_local.h"
+#include "crypto/asn1.h"
+
+static int i2r_ISSUER_SERIAL(X509V3_EXT_METHOD *method,
+ OSSL_ISSUER_SERIAL *iss,
+ BIO *out, int indent);
+static int i2r_OBJECT_DIGEST_INFO(X509V3_EXT_METHOD *method,
+ OSSL_OBJECT_DIGEST_INFO *odi,
+ BIO *out, int indent);
+static int i2r_TARGET_CERT(X509V3_EXT_METHOD *method,
+ OSSL_TARGET_CERT *tc,
+ BIO *out, int indent);
+static int i2r_TARGET(X509V3_EXT_METHOD *method,
+ OSSL_TARGET *target,
+ BIO *out, int indent);
+static int i2r_TARGETING_INFORMATION(X509V3_EXT_METHOD *method,
+ OSSL_TARGETING_INFORMATION *tinfo,
+ BIO *out, int indent);
+
+ASN1_SEQUENCE(OSSL_ISSUER_SERIAL) = {
+ ASN1_SEQUENCE_OF(OSSL_ISSUER_SERIAL, issuer, GENERAL_NAME),
+ ASN1_EMBED(OSSL_ISSUER_SERIAL, serial, ASN1_INTEGER),
+ ASN1_OPT(OSSL_ISSUER_SERIAL, issuerUID, ASN1_BIT_STRING),
+} static_ASN1_SEQUENCE_END(OSSL_ISSUER_SERIAL)
+
+ASN1_SEQUENCE(OSSL_OBJECT_DIGEST_INFO) = {
+ ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, digestedObjectType, ASN1_ENUMERATED),
+ ASN1_OPT(OSSL_OBJECT_DIGEST_INFO, otherObjectTypeID, ASN1_OBJECT),
+ ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, digestAlgorithm, X509_ALGOR),
+ ASN1_EMBED(OSSL_OBJECT_DIGEST_INFO, objectDigest, ASN1_BIT_STRING),
+} static_ASN1_SEQUENCE_END(OSSL_OBJECT_DIGEST_INFO)
+
+ASN1_SEQUENCE(OSSL_TARGET_CERT) = {
+ ASN1_SIMPLE(OSSL_TARGET_CERT, targetCertificate, OSSL_ISSUER_SERIAL),
+ ASN1_OPT(OSSL_TARGET_CERT, targetName, GENERAL_NAME),
+ ASN1_OPT(OSSL_TARGET_CERT, certDigestInfo, OSSL_OBJECT_DIGEST_INFO),
+} static_ASN1_SEQUENCE_END(OSSL_TARGET_CERT)
+
+ASN1_CHOICE(OSSL_TARGET) = {
+ ASN1_EXP(OSSL_TARGET, choice.targetName, GENERAL_NAME, 0),
+ ASN1_EXP(OSSL_TARGET, choice.targetGroup, GENERAL_NAME, 1),
+ ASN1_IMP(OSSL_TARGET, choice.targetCert, OSSL_TARGET_CERT, 2),
+} ASN1_CHOICE_END(OSSL_TARGET)
+
+ASN1_ITEM_TEMPLATE(OSSL_TARGETS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Targets, OSSL_TARGET)
+ASN1_ITEM_TEMPLATE_END(OSSL_TARGETS)
+
+ASN1_ITEM_TEMPLATE(OSSL_TARGETING_INFORMATION) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, TargetingInformation, OSSL_TARGETS)
+ASN1_ITEM_TEMPLATE_END(OSSL_TARGETING_INFORMATION)
+
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_TARGET)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_TARGETS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_TARGETING_INFORMATION)
+
+static int i2r_ISSUER_SERIAL(X509V3_EXT_METHOD *method,
+ OSSL_ISSUER_SERIAL *iss,
+ BIO *out, int indent)
+{
+ if (iss->issuer != NULL) {
+ BIO_printf(out, "%*sIssuer Names:\n", indent, "");
+ OSSL_GENERAL_NAMES_print(out, iss->issuer, indent);
+ BIO_puts(out, "\n");
+ }
+ BIO_printf(out, "%*sIssuer Serial: ", indent, "");
+ if (i2a_ASN1_INTEGER(out, &(iss->serial)) <= 0)
+ return 0;
+ BIO_puts(out, "\n");
+ if (iss->issuerUID != NULL) {
+ BIO_printf(out, "%*sIssuer UID: ", indent, "");
+ if (i2a_ASN1_STRING(out, iss->issuerUID, V_ASN1_BIT_STRING) <= 0)
+ return 0;
+ BIO_puts(out, "\n");
+ }
+ return 1;
+}
+
+static int i2r_OBJECT_DIGEST_INFO(X509V3_EXT_METHOD *method,
+ OSSL_OBJECT_DIGEST_INFO *odi,
+ BIO *out, int indent)
+{
+ int64_t dot = 0;
+ int sig_nid;
+ X509_ALGOR *digalg;
+ ASN1_STRING *sig;
+
+ if (odi == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ digalg = &odi->digestAlgorithm;
+ sig = &odi->objectDigest;
+ if (!ASN1_ENUMERATED_get_int64(&dot, &odi->digestedObjectType)) {
+ return 0;
+ }
+ switch (dot) {
+ case OSSL_ODI_TYPE_PUBLIC_KEY:
+ BIO_printf(out, "%*sDigest Type: Public Key\n", indent, "");
+ break;
+ case OSSL_ODI_TYPE_PUBLIC_KEY_CERT:
+ BIO_printf(out, "%*sDigest Type: Public Key Certificate\n", indent, "");
+ break;
+ case OSSL_ODI_TYPE_OTHER:
+ BIO_printf(out, "%*sDigest Type: Other\n", indent, "");
+ break;
+ }
+ if (odi->otherObjectTypeID != NULL) {
+ BIO_printf(out, "%*sDigest Type Identifier: ", indent, "");
+ i2a_ASN1_OBJECT(out, odi->otherObjectTypeID);
+ BIO_puts(out, "\n");
+ }
+ if (BIO_printf(out, "%*sSignature Algorithm: ", indent, "") <= 0)
+ return 0;
+ if (i2a_ASN1_OBJECT(out, odi->digestAlgorithm.algorithm) <= 0)
+ return 0;
+ BIO_puts(out, "\n");
+ if (BIO_printf(out, "\n%*sSignature Value: ", indent, "") <= 0)
+ return 0;
+ sig_nid = OBJ_obj2nid(odi->digestAlgorithm.algorithm);
+ if (sig_nid != NID_undef) {
+ int pkey_nid, dig_nid;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
+ ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
+ if (ameth && ameth->sig_print)
+ return ameth->sig_print(out, digalg, sig, indent + 4, 0);
+ }
+ }
+ if (BIO_write(out, "\n", 1) != 1)
+ return 0;
+ if (sig)
+ return X509_signature_dump(out, sig, indent + 4);
+ return 1;
+}
+
+static int i2r_TARGET_CERT(X509V3_EXT_METHOD *method,
+ OSSL_TARGET_CERT *tc,
+ BIO *out, int indent)
+{
+ BIO_printf(out, "%*s", indent, "");
+ if (tc->targetCertificate != NULL) {
+ BIO_puts(out, "Target Certificate:\n");
+ i2r_ISSUER_SERIAL(method, tc->targetCertificate, out, indent + 2);
+ }
+ if (tc->targetName != NULL) {
+ BIO_printf(out, "%*sTarget Name: ", indent, "");
+ GENERAL_NAME_print(out, tc->targetName);
+ BIO_puts(out, "\n");
+ }
+ if (tc->certDigestInfo != NULL) {
+ BIO_printf(out, "%*sCertificate Digest Info:\n", indent, "");
+ i2r_OBJECT_DIGEST_INFO(method, tc->certDigestInfo, out, indent + 2);
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+static int i2r_TARGET(X509V3_EXT_METHOD *method,
+ OSSL_TARGET *target,
+ BIO *out, int indent)
+{
+ switch (target->type) {
+ case OSSL_TGT_TARGET_NAME:
+ BIO_printf(out, "%*sTarget Name: ", indent, "");
+ GENERAL_NAME_print(out, target->choice.targetName);
+ BIO_puts(out, "\n");
+ break;
+ case OSSL_TGT_TARGET_GROUP:
+ BIO_printf(out, "%*sTarget Group: ", indent, "");
+ GENERAL_NAME_print(out, target->choice.targetGroup);
+ BIO_puts(out, "\n");
+ break;
+ case OSSL_TGT_TARGET_CERT:
+ BIO_printf(out, "%*sTarget Cert:\n", indent, "");
+ i2r_TARGET_CERT(method, target->choice.targetCert, out, indent + 2);
+ break;
+ }
+ return 1;
+}
+
+static int i2r_TARGETS(X509V3_EXT_METHOD *method,
+ OSSL_TARGETS *targets,
+ BIO *out, int indent)
+{
+ int i;
+ OSSL_TARGET *target;
+
+ for (i = 0; i < sk_OSSL_TARGET_num(targets); i++) {
+ BIO_printf(out, "%*sTarget:\n", indent, "");
+ target = sk_OSSL_TARGET_value(targets, i);
+ i2r_TARGET(method, target, out, indent + 2);
+ }
+ return 1;
+}
+
+static int i2r_TARGETING_INFORMATION(X509V3_EXT_METHOD *method,
+ OSSL_TARGETING_INFORMATION *tinfo,
+ BIO *out, int indent)
+{
+ int i;
+ OSSL_TARGETS *targets;
+
+ for (i = 0; i < sk_OSSL_TARGETS_num(tinfo); i++) {
+ BIO_printf(out, "%*sTargets:\n", indent, "");
+ targets = sk_OSSL_TARGETS_value(tinfo, i);
+ i2r_TARGETS(method, targets, out, indent + 2);
+ }
+ return 1;
+}
+
+const X509V3_EXT_METHOD ossl_v3_targeting_information = {
+ NID_target_information, 0, ASN1_ITEM_ref(OSSL_TARGETING_INFORMATION),
+ 0, 0, 0, 0,
+ 0,
+ 0,
+ 0, 0,
+ (X509V3_EXT_I2R)i2r_TARGETING_INFORMATION,
+ 0,
+ NULL
+};
diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c
index 839b2c1afe..ae772cdd80 100644
--- a/crypto/x509/v3_crld.c
+++ b/crypto/x509/v3_crld.c
@@ -419,23 +419,11 @@ static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
return NULL;
}
-static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
-{
- int i;
- for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
- if (i > 0)
- BIO_puts(out, "\n");
- BIO_printf(out, "%*s", indent + 2, "");
- GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
- }
- return 1;
-}
-
static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
{
if (dpn->type == 0) {
BIO_printf(out, "%*sFull Name:\n", indent, "");
- print_gens(out, dpn->name.fullname, indent);
+ OSSL_GENERAL_NAMES_print(out, dpn->name.fullname, indent);
} else {
X509_NAME ntmp;
ntmp.entries = dpn->name.relativename;
@@ -486,7 +474,7 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
print_reasons(out, "Reasons", point->reasons, indent);
if (point->CRLissuer) {
BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
- print_gens(out, point->CRLissuer, indent);
+ OSSL_GENERAL_NAMES_print(out, point->CRLissuer, indent);
}
}
return 1;
diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c
index 1a18174995..a036e9e9ad 100644
--- a/crypto/x509/v3_utl.c
+++ b/crypto/x509/v3_utl.c
@@ -1356,3 +1356,16 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
}
return 1;
}
+
+int OSSL_GENERAL_NAMES_print(BIO *out, GENERAL_NAMES *gens, int indent)
+{
+ int i;
+
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ if (i > 0)
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*s", indent + 2, "");
+ GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
+ }
+ return 1;
+}
diff --git a/doc/build.info b/doc/build.info
index bff96a8a90..cb9c76b6a3 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -1711,6 +1711,10 @@ DEPEND[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_
GENERATE[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_certs.pod
DEPEND[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
GENERATE[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
+DEPEND[html/man3/OSSL_GENERAL_NAMES_print.html]=man3/OSSL_GENERAL_NAMES_print.pod
+GENERATE[html/man3/OSSL_GENERAL_NAMES_print.html]=man3/OSSL_GENERAL_NAMES_print.pod
+DEPEND[man/man3/OSSL_GENERAL_NAMES_print.3]=man3/OSSL_GENERAL_NAMES_print.pod
+GENERATE[man/man3/OSSL_GENERAL_NAMES_print.3]=man3/OSSL_GENERAL_NAMES_print.pod
DEPEND[html/man3/OSSL_HPKE_CTX_new.html]=man3/OSSL_HPKE_CTX_new.pod
GENERATE[html/man3/OSSL_HPKE_CTX_new.html]=man3/OSSL_HPKE_CTX_new.pod
DEPEND[man/man3/OSSL_HPKE_CTX_new.3]=man3/OSSL_HPKE_CTX_new.pod
@@ -3403,6 +3407,7 @@ html/man3/OSSL_ENCODER_CTX_new_for_pkey.html \
html/man3/OSSL_ENCODER_to_bio.html \
html/man3/OSSL_ERR_STATE_save.html \
html/man3/OSSL_ESS_check_signing_certs.html \
+html/man3/OSSL_GENERAL_NAMES_print.html \
html/man3/OSSL_HPKE_CTX_new.html \
html/man3/OSSL_HTTP_REQ_CTX.html \
html/man3/OSSL_HTTP_parse_url.html \
@@ -4059,6 +4064,7 @@ man/man3/OSSL_ENCODER_CTX_new_for_pkey.3 \
man/man3/OSSL_ENCODER_to_bio.3 \
man/man3/OSSL_ERR_STATE_save.3 \
man/man3/OSSL_ESS_check_signing_certs.3 \
+man/man3/OSSL_GENERAL_NAMES_print.3 \
man/man3/OSSL_HPKE_CTX_new.3 \
man/man3/OSSL_HTTP_REQ_CTX.3 \
man/man3/OSSL_HTTP_parse_url.3 \
diff --git a/doc/man3/OSSL_GENERAL_NAMES_print.pod b/doc/man3/OSSL_GENERAL_NAMES_print.pod
new file mode 100644
index 0000000000..84282ee71d
--- /dev/null
+++ b/doc/man3/OSSL_GENERAL_NAMES_print.pod
@@ -0,0 +1,36 @@
+=pod
+
+=head1 NAME
+
+OSSL_GENERAL_NAMES_print - print GeneralNames in a human-friendly, multi-line
+string
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ int OSSL_GENERAL_NAMES_print(BIO *out, GENERAL_NAMES *gens, int indent);
+
+=head1 DESCRIPTION
+
+OSSL_GENERAL_NAMES_print() prints a human readable version of the GeneralNames
+I<gens> to BIO I<out>. Each line is indented by I<indent> spaces.
+
+=head1 RETURN VALUES
+
+OSSL_GENERAL_NAMES_print() always returns 1.
+
+=head1 HISTORY
+
+The functions described here were all added in OpenSSL 3.4.
+
+=head1 COPYRIGHT
+
+Copyright 2024 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
index 17100a45ff..6333ba6985 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -176,6 +176,18 @@ OSSL_CRMF_PKIPUBLICATIONINFO_new,
OSSL_CRMF_SINGLEPUBINFO_free,
OSSL_CRMF_SINGLEPUBINFO_it,
OSSL_CRMF_SINGLEPUBINFO_new,
+OSSL_TARGET_CERT_free,
+OSSL_TARGET_CERT_it,
+OSSL_TARGET_CERT_new,
+OSSL_TARGET_free,
+OSSL_TARGET_it,
+OSSL_TARGET_new,
+OSSL_TARGETING_INFORMATION_free,
+OSSL_TARGETING_INFORMATION_it,
+OSSL_TARGETING_INFORMATION_new,
+OSSL_TARGETS_free,
+OSSL_TARGETS_it,
+OSSL_TARGETS_new,
OSSL_IETF_ATTR_SYNTAX_VALUE_free,
OSSL_IETF_ATTR_SYNTAX_VALUE_it,
OSSL_IETF_ATTR_SYNTAX_VALUE_new,
diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod
index 1c0b5bf625..373962e135 100644
--- a/doc/man3/d2i_X509.pod
+++ b/doc/man3/d2i_X509.pod
@@ -101,6 +101,12 @@ d2i_OSSL_CRMF_PBMPARAMETER,
d2i_OSSL_CRMF_PKIPUBLICATIONINFO,
d2i_OSSL_CRMF_SINGLEPUBINFO,
d2i_OSSL_IETF_ATTR_SYNTAX,
+d2i_OSSL_ISSUER_SERIAL,
+d2i_OSSL_OBJECT_DIGEST_INFO,
+d2i_OSSL_TARGET_CERT,
+d2i_OSSL_TARGET,
+d2i_OSSL_TARGETING_INFORMATION,
+d2i_OSSL_TARGETS,
d2i_OTHERNAME,
d2i_PBE2PARAM,
d2i_PBEPARAM,
@@ -276,6 +282,12 @@ i2d_OSSL_CRMF_PBMPARAMETER,
i2d_OSSL_CRMF_PKIPUBLICATIONINFO,
i2d_OSSL_CRMF_SINGLEPUBINFO,
i2d_OSSL_IETF_ATTR_SYNTAX,
+i2d_OSSL_ISSUER_SERIAL,
+i2d_OSSL_OBJECT_DIGEST_INFO,
+i2d_OSSL_TARGET_CERT,
+i2d_OSSL_TARGET,
+i2d_OSSL_TARGETING_INFORMATION,
+i2d_OSSL_TARGETS,
i2d_OTHERNAME,
i2d_PBE2PARAM,
i2d_PBEPARAM,
diff --git a/fuzz/asn1.c b/fuzz/asn1.c
index f7a019774b..febb296ce9 100644
--- a/fuzz/asn1.c
+++ b/fuzz/asn1.c
@@ -37,6 +37,7 @@
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
+#include <openssl/x509_acert.h>
#include "internal/nelem.h"
#include "fuzzer.h"
@@ -174,6 +175,7 @@ static ASN1_ITEM_EXP *item_type[] = {
#endif
ASN1_ITEM_ref(SXNET),
ASN1_ITEM_ref(SXNETID),
+ ASN1_ITEM_ref(OSSL_TARGETING_INFORMATION),
ASN1_ITEM_ref(USERNOTICE),
ASN1_ITEM_ref(X509),
ASN1_ITEM_ref(X509_ALGOR),
diff --git a/include/crypto/x509_acert.h b/include/crypto/x509_acert.h
index 3223bf6234..faf6bf50e9 100644
--- a/include/crypto/x509_acert.h
+++ b/include/crypto/x509_acert.h
@@ -13,6 +13,10 @@
# include <openssl/x509_acert.h>
+#define OSSL_ODI_TYPE_PUBLIC_KEY 0
+#define OSSL_ODI_TYPE_PUBLIC_KEY_CERT 1
+#define OSSL_ODI_TYPE_OTHER 2
+
struct ossl_object_digest_info_st {
ASN1_ENUMERATED digestedObjectType;
ASN1_OBJECT *otherObjectTypeID;
diff --git a/include/openssl/x509_acert.h.in b/include/openssl/x509_acert.h.in
index 42376a6cb7..70facf8ecc 100644
--- a/include/openssl/x509_acert.h.in
+++ b/include/openssl/x509_acert.h.in
@@ -153,4 +153,40 @@ int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type,
void *data);
int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, int indent);
+struct TARGET_CERT_st {
+ OSSL_ISSUER_SERIAL *targetCertificate;
+ GENERAL_NAME *targetName;
+ OSSL_OBJECT_DIGEST_INFO *certDigestInfo;
+};
+
+typedef struct TARGET_CERT_st OSSL_TARGET_CERT;
+
+# define OSSL_TGT_TARGET_NAME 0
+# define OSSL_TGT_TARGET_GROUP 1
+# define OSSL_TGT_TARGET_CERT 2
+
+typedef struct TARGET_st {
+ int type;
+ union {
+ GENERAL_NAME *targetName;
+ GENERAL_NAME *targetGroup;
+ OSSL_TARGET_CERT *targetCert;
+ } choice;
+} OSSL_TARGET;
+
+typedef STACK_OF(OSSL_TARGET) OSSL_TARGETS;
+typedef STACK_OF(OSSL_TARGETS) OSSL_TARGETING_INFORMATION;
+
+{-
+ generate_stack_macros("OSSL_TARGET");
+-}
+
+{-
+ generate_stack_macros("OSSL_TARGETS");
+-}
+
+DECLARE_ASN1_FUNCTIONS(OSSL_TARGET)
+DECLARE_ASN1_FUNCTIONS(OSSL_TARGETS)
+DECLARE_ASN1_FUNCTIONS(OSSL_TARGETING_INFORMATION)
+
#endif
diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in
index a967064f4c..7c2313e424 100644
--- a/include/openssl/x509v3.h.in
+++ b/include/openssl/x509v3.h.in
@@ -1019,6 +1019,8 @@ const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(
void PROFESSION_INFO_set0_registrationNumber(
PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn);
+int OSSL_GENERAL_NAMES_print(BIO *out, GENERAL_NAMES *gens, int indent);
+
# ifdef __cplusplus
}
# endif
diff --git a/test/certs/ext-targetingInformation.pem b/test/certs/ext-targetingInformation.pem
new file mode 100644
index 0000000000..0ce3998ab2
--- /dev/null
+++ b/test/certs/ext-targetingInformation.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKzCCAhegAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMwMTI1
+NDEzWhgPMjAyMTA4MzAxMjU0MTNaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB
+CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq
+nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir
+Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI
+qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06
+GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus
+pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABo4GxMIGuMIGrBgNVHTcEgaMwgaAw
+OqAgpB4wHDEaMBgGA1UEAwwRV2lsZGJvYXIgU29mdHdhcmWhFoIUd2lsZGJvYXJz
+b2Z0d2FyZS5jb20wYqJgMDEwJaQeMBwxGjAYBgNVBAMMEVdpbGRib2FyIFNvZnR3
+YXJliANVBAMCBAECAwQDAgOwgRVqb25hdGhhbkB3aWxidXIuc3BhY2UwFAoBADAL
+BgkqhkiG9w0BAQUDAgIkMAsGCSqGSIb3DQEBBQMBAA==
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
index c727e5cdb3..2ae13df615 100644
--- a/test/recipes/25-test_x509.t
+++ b/test/recipes/25-test_x509.t
@@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_x509");
-plan tests => 51;
+plan tests => 60;
# Prevent MSys2 filename munging for arguments that look like file paths but
# aren't
@@ -143,6 +143,35 @@ cert_contains(srctop_file(@certs, "ext-indirectIssuer.pem"),
"Indirect Issuer",
1, 'X.509 Indirect Issuer');
+my $tgt_info_cert = srctop_file(@certs, "ext-targetingInformation.pem");
+cert_contains($tgt_info_cert,
+ "AC Targeting",
+ 1, 'X.509 Targeting Information Extension');
+cert_contains($tgt_info_cert,
+ "Targets:",
+ 1, 'X.509 Targeting Information Targets');
+cert_contains($tgt_info_cert,
+ "Target:",
+ 1, 'X.509 Targeting Information Target');
+cert_contains($tgt_info_cert,
+ "Target Name: DirName:CN = W",
+ 1, 'X.509 Targeting Information Target Name');
+cert_contains($tgt_info_cert,
+ "Target Group: DNS:wildboarsoftware.com",
+ 1, 'X.509 Targeting Information Target Name');
+cert_contains($tgt_info_cert,
+ "Issuer Names:",
+ 1, 'X.509 Targeting Information Issuer Names');
+cert_contains($tgt_info_cert,
+ "Issuer Serial: 01020304",
+ 1, 'X.509 Targeting Information Issuer Serial');
+cert_contains($tgt_info_cert,
+ "Issuer UID: B0",
+ 1, 'X.509 Targeting Information Issuer UID');
+cert_contains($tgt_info_cert,
+ "Digest Type: Public Key",
+ 1, 'X.509 Targeting Information Object Digest Type');
+
sub test_errors { # actually tests diagnostics of OSSL_STORE
my ($expected, $cert, @opts) = @_;
my $infile = srctop_file(@certs, $cert);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index e0474a0021..526cc59355 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5647,3 +5647,19 @@ X509_ACERT_add_attr_nconf ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_get_conf_diagnostics ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_set_conf_diagnostics ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_get_data ? 3_4_0 EXIST::FUNCTION:
+d2i_OSSL_TARGET ? 3_4_0 EXIST::FUNCTION:
+i2d_OSSL_TARGET ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGET_free ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGET_new ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGET_it ? 3_4_0 EXIST::FUNCTION:
+d2i_OSSL_TARGETS ? 3_4_0 EXIST::FUNCTION:
+i2d_OSSL_TARGETS ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETS_free ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETS_new ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETS_it ? 3_4_0 EXIST::FUNCTION:
+d2i_OSSL_TARGETING_INFORMATION ? 3_4_0 EXIST::FUNCTION:
+i2d_OSSL_TARGETING_INFORMATION ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETING_INFORMATION_free ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETING_INFORMATION_new ? 3_4_0 EXIST::FUNCTION:
+OSSL_TARGETING_INFORMATION_it ? 3_4_0 EXIST::FUNCTION:
+OSSL_GENERAL_NAMES_print ? 3_4_0 EXIST::FUNCTION: