From 58301e24f66aa74b13b85a171dd14e6088c35662 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Sat, 1 Jun 2024 19:23:25 +0000 Subject: [PATCH] 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 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22206) --- crypto/x509/build.info | 2 +- crypto/x509/ext_dat.h | 1 + crypto/x509/standard_exts.h | 1 + crypto/x509/v3_ac_tgt.c | 239 ++++++++++++++++++++++++ crypto/x509/v3_crld.c | 16 +- crypto/x509/v3_utl.c | 13 ++ doc/build.info | 6 + doc/man3/OSSL_GENERAL_NAMES_print.pod | 36 ++++ doc/man3/X509_dup.pod | 12 ++ doc/man3/d2i_X509.pod | 12 ++ fuzz/asn1.c | 2 + include/crypto/x509_acert.h | 4 + include/openssl/x509_acert.h.in | 36 ++++ include/openssl/x509v3.h.in | 2 + test/certs/ext-targetingInformation.pem | 14 ++ test/recipes/25-test_x509.t | 31 ++- util/libcrypto.num | 16 ++ 17 files changed, 427 insertions(+), 16 deletions(-) create mode 100644 crypto/x509/v3_ac_tgt.c create mode 100644 doc/man3/OSSL_GENERAL_NAMES_print.pod create mode 100644 test/certs/ext-targetingInformation.pem 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 +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#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 + + 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 to BIO I. Each line is indented by I 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. + +=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 #include #include +#include #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 +#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: