diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h index 482de09662304..807c7af2862fd 100644 --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -47,6 +47,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = { ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), ASN1_ITEM_ref(AUTHORITY_KEYID), ASN1_ITEM_ref(BASIC_CONSTRAINTS), + ASN1_ITEM_ref(BASIC_ATTR_CONSTRAINTS), ASN1_ITEM_ref(BIGNUM), ASN1_ITEM_ref(CBIGNUM), ASN1_ITEM_ref(CERTIFICATEPOLICIES), diff --git a/crypto/x509/build.info b/crypto/x509/build.info index ace5ea5ea1317..dda4fc88e94db 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -17,7 +17,7 @@ SOURCE[../../libcrypto]=\ v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c \ x509_acert.c t_acert.c x509aset.c x_ietfatt.c \ v3_no_rev_avail.c v3_soa_id.c v3_no_ass.c v3_group_ac.c \ - v3_single_use.c v3_ac_tgt.c v3_audit_id.c + v3_single_use.c v3_ac_tgt.c v3_audit_id.c v3_bacons.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 7258fca263963..f9ec85fc825f3 100644 --- a/crypto/x509/ext_dat.h +++ b/crypto/x509/ext_dat.h @@ -32,3 +32,4 @@ 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_targeting_information; extern const X509V3_EXT_METHOD ossl_v3_audit_identity; +extern const X509V3_EXT_METHOD ossl_v3_bacons; diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h index ca3712986f379..729bad949bb4e 100644 --- a/crypto/x509/standard_exts.h +++ b/crypto/x509/standard_exts.h @@ -75,6 +75,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &ossl_v3_issuer_sign_tool, &ossl_v3_tls_feature, &ossl_v3_ext_admission, + &ossl_v3_bacons, &ossl_v3_soa_identifier, &ossl_v3_no_assertion, &ossl_v3_single_use, diff --git a/crypto/x509/v3_bacons.c b/crypto/x509/v3_bacons.c new file mode 100644 index 0000000000000..d55065c23a69c --- /dev/null +++ b/crypto/x509/v3_bacons.c @@ -0,0 +1,85 @@ +/* + * Copyright 1999-2021 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 "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" +#include "x509_local.h" + +static STACK_OF(CONF_VALUE) *i2v_BASIC_ATTR_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_ATTR_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist); +static BASIC_ATTR_CONSTRAINTS *v2i_BASIC_ATTR_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD ossl_v3_bacons = { + NID_basic_att_constraints, 0, + ASN1_ITEM_ref(BASIC_ATTR_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V)i2v_BASIC_ATTR_CONSTRAINTS, + (X509V3_EXT_V2I)v2i_BASIC_ATTR_CONSTRAINTS, + NULL, NULL, + NULL +}; + +ASN1_SEQUENCE(BASIC_ATTR_CONSTRAINTS) = { + ASN1_OPT(BASIC_ATTR_CONSTRAINTS, authority, ASN1_FBOOLEAN), + ASN1_OPT(BASIC_ATTR_CONSTRAINTS, pathlen, ASN1_INTEGER) +} ASN1_SEQUENCE_END(BASIC_ATTR_CONSTRAINTS) + +IMPLEMENT_ASN1_FUNCTIONS(BASIC_ATTR_CONSTRAINTS) + +static STACK_OF(CONF_VALUE) *i2v_BASIC_ATTR_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_ATTR_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist) +{ + X509V3_add_value_bool("authority", bcons->authority, &extlist); + X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); + return extlist; +} + +static BASIC_ATTR_CONSTRAINTS *v2i_BASIC_ATTR_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + BASIC_ATTR_CONSTRAINTS *bcons = NULL; + CONF_VALUE *val; + int i; + + if ((bcons = BASIC_ATTR_CONSTRAINTS_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (strcmp(val->name, "authority") == 0) { + if (!X509V3_get_value_bool(val, &bcons->authority)) + goto err; + } else if (strcmp(val->name, "pathlen") == 0) { + if (!X509V3_get_value_int(val, &bcons->pathlen)) + goto err; + } else { + ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_add_error_name_value(val); + goto err; + } + } + return bcons; + err: + BASIC_ATTR_CONSTRAINTS_free(bcons); + return NULL; +} diff --git a/fuzz/asn1.c b/fuzz/asn1.c index 6659205bc0f84..8d84764b0ec60 100644 --- a/fuzz/asn1.c +++ b/fuzz/asn1.c @@ -80,6 +80,7 @@ static ASN1_ITEM_EXP *item_type[] = { ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), ASN1_ITEM_ref(AUTHORITY_KEYID), ASN1_ITEM_ref(BASIC_CONSTRAINTS), + ASN1_ITEM_ref(BASIC_ATTR_CONSTRAINTS), ASN1_ITEM_ref(BIGNUM), ASN1_ITEM_ref(CBIGNUM), ASN1_ITEM_ref(CERTIFICATEPOLICIES), diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in index 0b5c568b564a1..2edccc5b86031 100644 --- a/include/openssl/x509v3.h.in +++ b/include/openssl/x509v3.h.in @@ -126,6 +126,11 @@ typedef struct BASIC_CONSTRAINTS_st { ASN1_INTEGER *pathlen; } BASIC_CONSTRAINTS; +typedef struct BASIC_ATTR_CONSTRAINTS_st { + int authority; + ASN1_INTEGER *pathlen; +} BASIC_ATTR_CONSTRAINTS; + typedef struct PKEY_USAGE_PERIOD_st { ASN1_GENERALIZEDTIME *notBefore; ASN1_GENERALIZEDTIME *notAfter; @@ -507,6 +512,7 @@ typedef struct x509_purpose_st { # define X509V3_ADD_SILENT 0x10 DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) +DECLARE_ASN1_FUNCTIONS(BASIC_ATTR_CONSTRAINTS) DECLARE_ASN1_FUNCTIONS(SXNET) DECLARE_ASN1_FUNCTIONS(SXNETID) diff --git a/test/certs/ext-basicAttConstraints.pem b/test/certs/ext-basicAttConstraints.pem new file mode 100644 index 0000000000000..9d3a25bd2e8bf --- /dev/null +++ b/test/certs/ext-basicAttConstraints.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCCAXigAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMxMDIx +MjQ5WhgPMjAyMTA4MzEwMjEyNDlaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABoxMwETAPBgNVHSkECDAGAQH/AgED +MAsGCSqGSIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t index 5a757405d884f..eeac77006649b 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 => 43; +plan tests => 45; # Prevent MSys2 filename munging for arguments that look like file paths but # aren't @@ -154,6 +154,14 @@ cert_contains($tgt_info_cert, "Digest Type: Public Key", 1, 'X.509 Targeting Information Object Digest Type'); +my $basic_att_constraints_cert = srctop_file(@certs, "ext-basicAttConstraints.pem"); +cert_contains($basic_att_constraints_cert, + "authority:TRUE", + 1, 'X.509 Basic Attribute Constraints Authority'); +cert_contains($basic_att_constraints_cert, + "pathlen:3", + 1, 'X.509 Basic Attribute Constraints Path Length'); + sub test_errors { # actually tests diagnostics of OSSL_STORE my ($expected, $cert, @opts) = @_; my $infile = srctop_file(@certs, $cert); diff --git a/util/indent.pro b/util/indent.pro index 928218c5d37db..0e46e8eacd4ad 100644 --- a/util/indent.pro +++ b/util/indent.pro @@ -80,6 +80,7 @@ -T AUTHORITY_INFO_ACCESS -T AUTHORITY_KEYID -T BASIC_CONSTRAINTS +-T BASIC_ATTR_CONSTRAINTS -T BF_KEY -T BF_LONG -T BIGNUM diff --git a/util/libcrypto.num b/util/libcrypto.num index 9661e006f6fa5..c5daade1dc9e9 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5583,3 +5583,8 @@ TARGETING_INFORMATION_free ? 3_1_0 EXIST::FUNCTION: TARGETING_INFORMATION_new ? 3_1_0 EXIST::FUNCTION: TARGETING_INFORMATION_it ? 3_1_0 EXIST::FUNCTION: ossl_print_gens ? 3_1_0 EXIST::FUNCTION: +d2i_BASIC_ATTR_CONSTRAINTS ? 3_1_0 EXIST::FUNCTION: +i2d_BASIC_ATTR_CONSTRAINTS ? 3_1_0 EXIST::FUNCTION: +BASIC_ATTR_CONSTRAINTS_free ? 3_1_0 EXIST::FUNCTION: +BASIC_ATTR_CONSTRAINTS_new ? 3_1_0 EXIST::FUNCTION: +BASIC_ATTR_CONSTRAINTS_it ? 3_1_0 EXIST::FUNCTION: