Skip to content

Commit

Permalink
Add support for targetingInformation X.509v3 extension
Browse files Browse the repository at this point in the history
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 openssl#22206)
  • Loading branch information
JonathanWilbur authored and t8m committed Jun 17, 2024
1 parent 40948c4 commit 58301e2
Show file tree
Hide file tree
Showing 17 changed files with 427 additions and 16 deletions.
2 changes: 1 addition & 1 deletion crypto/x509/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions crypto/x509/ext_dat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
1 change: 1 addition & 0 deletions crypto/x509/standard_exts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
239 changes: 239 additions & 0 deletions crypto/x509/v3_ac_tgt.c
Original file line number Diff line number Diff line change
@@ -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
};
16 changes: 2 additions & 14 deletions crypto/x509/v3_crld.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions crypto/x509/v3_utl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 6 additions & 0 deletions doc/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
36 changes: 36 additions & 0 deletions doc/man3/OSSL_GENERAL_NAMES_print.pod
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions doc/man3/X509_dup.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 58301e2

Please sign in to comment.