]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Support subjectDirectoryAttributes and associatedInformation exts
authorJonathan M. Wilbur <jonathan@wilbur.space>
Tue, 18 Jun 2024 09:08:40 +0000 (09:08 +0000)
committerTomas Mraz <tomas@openssl.org>
Mon, 24 Jun 2024 13:33:21 +0000 (15:33 +0200)
Added tests for SDA and AI extensions.
Added internal function ossl_print_attribute_value() with documentation.

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24669)

14 files changed:
crypto/x509/build.info
crypto/x509/ext_dat.h
crypto/x509/standard_exts.h
crypto/x509/v3_sda.c [new file with mode: 0644]
crypto/x509/x_attrib.c
doc/internal/man3/ossl_print_attribute_value.pod [new file with mode: 0644]
doc/man3/X509_dup.pod
doc/man3/d2i_X509.pod
include/crypto/x509.h
include/openssl/x509v3.h.in
test/certs/ext-associatedInformation.pem [new file with mode: 0644]
test/certs/ext-subjectDirectoryAttributes.pem [new file with mode: 0644]
test/recipes/25-test_x509.t
util/libcrypto.num

index 1184329b2052ffcc148895715dec0948939680f0..ff648e99976f5108a7e1a70376db4439d4db5caa 100644 (file)
@@ -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 v3_ac_tgt.c
+        x509_acert.c x509aset.c t_acert.c x_ietfatt.c v3_ac_tgt.c v3_sda.c
 
 IF[{- !$disabled{'deprecated-3.0'} -}]
   SOURCE[../../libcrypto]=x509type.c
index befb8e444aad7aaa6fc76deb69417fea297c6b44..f3ad5afbf054e0eb069b99046e5f4f0b5af5fc2b 100644 (file)
@@ -34,3 +34,5 @@ extern const X509V3_EXT_METHOD ossl_v3_indirect_issuer;
 extern const X509V3_EXT_METHOD ossl_v3_targeting_information;
 extern const X509V3_EXT_METHOD ossl_v3_holder_name_constraints;
 extern const X509V3_EXT_METHOD ossl_v3_delegated_name_constraints;
+extern const X509V3_EXT_METHOD ossl_v3_subj_dir_attrs;
+extern const X509V3_EXT_METHOD ossl_v3_associated_info;
index f399bde8b3c6a93731350073aa9f4b5e4ed89aee..655dd21e1e7aa2e8b425b92b0d9ad591e9cd7d16 100644 (file)
@@ -62,6 +62,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = {
     &ossl_v3_name_constraints,
     &ossl_v3_policy_mappings,
     &ossl_v3_inhibit_anyp,
+    &ossl_v3_subj_dir_attrs,
     &ossl_v3_idp,
     &ossl_v3_alt[2],
     &ossl_v3_freshest_crl,
@@ -81,6 +82,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = {
     &ossl_v3_single_use,
     &ossl_v3_group_ac,
     &ossl_v3_holder_name_constraints,
+    &ossl_v3_associated_info,
 };
 
 /* Number of standard extensions */
diff --git a/crypto/x509/v3_sda.c b/crypto/x509/v3_sda.c
new file mode 100644 (file)
index 0000000..35602fc
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+#include <crypto/x509.h>
+#include "ext_dat.h"
+
+ASN1_ITEM_TEMPLATE(ATTRIBUTES_SYNTAX) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Attributes, X509_ATTRIBUTE)
+ASN1_ITEM_TEMPLATE_END(ATTRIBUTES_SYNTAX)
+
+IMPLEMENT_ASN1_FUNCTIONS(ATTRIBUTES_SYNTAX)
+
+static int i2r_ATTRIBUTES_SYNTAX(X509V3_EXT_METHOD *method,
+                                 ATTRIBUTES_SYNTAX *attrlst,
+                                 BIO *out, int indent)
+{
+    X509_ATTRIBUTE *attr;
+    ASN1_TYPE *av;
+    int i, j, attr_nid;
+
+    if (!attrlst) {
+        if (BIO_printf(out, "<No Attributes>\n") <= 0)
+            return 0;
+        return 1;
+    }
+    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
+        if (BIO_printf(out, "<Empty Attributes>\n") <= 0)
+            return 0;
+        return 1;
+    }
+
+    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
+        ASN1_OBJECT *attr_obj;
+        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
+        attr_obj = X509_ATTRIBUTE_get0_object(attr);
+        attr_nid = OBJ_obj2nid(attr_obj);
+        if (indent && BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        if (attr_nid == NID_undef) {
+            if (i2a_ASN1_OBJECT(out, attr_obj) <= 0)
+                return 0;
+            if (BIO_puts(out, ":\n") <= 0)
+                return 0;
+        } else if (BIO_printf(out, "%s:\n", OBJ_nid2ln(attr_nid)) <= 0) {
+            return 0;
+        }
+
+        if (X509_ATTRIBUTE_count(attr)) {
+            for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
+            {
+                av = X509_ATTRIBUTE_get0_type(attr, j);
+                if (ossl_print_attribute_value(out, attr_nid, av, indent + 4) <= 0)
+                    return 0;
+                if (BIO_puts(out, "\n") <= 0)
+                    return 0;
+            }
+        } else if (BIO_printf(out, "%*s<No Values>\n", indent + 4, "") <= 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+const X509V3_EXT_METHOD ossl_v3_subj_dir_attrs = {
+    NID_subject_directory_attributes, X509V3_EXT_MULTILINE,
+    ASN1_ITEM_ref(ATTRIBUTES_SYNTAX),
+    0, 0, 0, 0,
+    0, 0, 0, 0,
+    (X509V3_EXT_I2R)i2r_ATTRIBUTES_SYNTAX,
+    0,
+    NULL
+};
+
+const X509V3_EXT_METHOD ossl_v3_associated_info = {
+    NID_associated_information, X509V3_EXT_MULTILINE,
+    ASN1_ITEM_ref(ATTRIBUTES_SYNTAX),
+    0, 0, 0, 0,
+    0, 0, 0, 0,
+    (X509V3_EXT_I2R)i2r_ATTRIBUTES_SYNTAX,
+    0,
+    NULL
+};
index 5c7e622d1a0bc4bbd15e04cf30de67f4814bfc54..4bae3779058861ccd50a1b12a8b730622e3f49c2 100644 (file)
@@ -13,6 +13,7 @@
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
 #include "x509_local.h"
+#include <crypto/x509.h>
 
 /*-
  * X509_ATTRIBUTE: this has the following form:
@@ -56,3 +57,228 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
     ASN1_TYPE_free(val);
     return NULL;
 }
+
+static int print_hex(BIO *out, unsigned char *buf, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        if (BIO_printf(out, "%02X ", buf[i]) <= 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static int asn1_integer_print_bio(BIO *bio, const ASN1_INTEGER *num)
+{
+    BIGNUM *num_bn;
+    int result = 0;
+    char *hex;
+
+    num_bn = ASN1_INTEGER_to_BN(num, NULL);
+    if (num_bn == NULL)
+        return -1;
+    if ((hex = BN_bn2hex(num_bn)) != NULL) {
+        result = BIO_write(bio, "0x", 2) > 0;
+        result = result && BIO_write(bio, hex, strlen(hex)) > 0;
+        OPENSSL_free(hex);
+    } else {
+        return -1;
+    }
+    BN_free(num_bn);
+
+    return result;
+}
+
+static int print_oid (BIO *out, ASN1_OBJECT *oid) {
+    const char *ln;
+    char objbuf[80];
+    int rc;
+
+    if (OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1) <= 0)
+        return 0;
+    ln = OBJ_nid2ln(OBJ_obj2nid(oid));
+    rc = (ln != NULL)
+           ? BIO_printf(out, "%s (%s)", objbuf, ln)
+           : BIO_printf(out, "%s", objbuf);
+    if (rc < 0)
+        return 0;
+    return 1;
+}
+
+int ossl_print_attribute_value(BIO *out,
+                               int obj_nid,
+                               const ASN1_TYPE *av,
+                               int indent)
+{
+    ASN1_STRING *str;
+    unsigned char *value;
+    X509_NAME *xn = NULL;
+    int64_t int_val;
+
+    /*
+     * This switch-case is only for syntaxes that are not encoded as a single
+     * primitively-constructed value universal ASN.1 type.
+     */
+    switch (obj_nid) {
+    case NID_undef: /* Unrecognized OID. */
+        break;
+    /* Attribute types with DN syntax. */
+    case NID_member:
+    case NID_roleOccupant:
+    case NID_seeAlso:
+    case NID_manager:
+    case NID_documentAuthor:
+    case NID_secretary:
+    case NID_associatedName:
+    case NID_dITRedirect:
+    case NID_owner:
+        value = av->value.sequence->data;
+        xn = d2i_X509_NAME(NULL,
+                           (const unsigned char**)&(av->value.sequence->data),
+                           av->value.sequence->length);
+        if (xn == NULL) {
+            BIO_puts(out, "(COULD NOT DECODE DISTINGUISHED NAME)\n");
+            return 0;
+        }
+        /*
+         * d2i_ functions increment the ppin pointer. See doc/man3/d2i_X509.pod.
+         * This resets the pointer. We don't want to corrupt this value.
+         */
+        av->value.sequence->data = value;
+        if (X509_NAME_print_ex(out, xn, indent, XN_FLAG_SEP_CPLUS_SPC) <= 0)
+            return 0;
+        X509_NAME_free(xn);
+        return 1;
+
+    default:
+        break;
+    }
+
+    switch (av->type) {
+    case V_ASN1_BOOLEAN:
+        if (av->value.boolean) {
+            return BIO_printf(out, "%*sTRUE", indent, "");
+        } else {
+            return BIO_printf(out, "%*sFALSE", indent, "");
+        }
+
+    case V_ASN1_INTEGER:
+        if (BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        if (ASN1_INTEGER_get_int64(&int_val, av->value.integer) > 0) {
+            return BIO_printf(out, "%lld", (long long int)int_val);
+        } else {
+            str = av->value.integer;
+            return asn1_integer_print_bio(out, str);
+        }
+
+    case V_ASN1_ENUMERATED:
+        if (BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        if (ASN1_ENUMERATED_get_int64(&int_val, av->value.enumerated) > 0) {
+            return BIO_printf(out, "%lld", (long long int)int_val);
+        } else {
+            str = av->value.enumerated;
+            return asn1_integer_print_bio(out, str);
+        }
+
+    case V_ASN1_BIT_STRING:
+        if (BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        return print_hex(out, av->value.bit_string->data,
+                 av->value.bit_string->length);
+
+    case V_ASN1_OCTET_STRING:
+    case V_ASN1_VIDEOTEXSTRING:
+        if (BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        return print_hex(out, av->value.octet_string->data,
+                 av->value.octet_string->length);
+
+    case V_ASN1_NULL:
+        return BIO_printf(out, "%*sNULL", indent, "");
+
+    case V_ASN1_OBJECT:
+        if (BIO_printf(out, "%*s", indent, "") <= 0)
+            return 0;
+        return print_oid(out, av->value.object);
+    
+    /*
+     * ObjectDescriptor is an IMPLICIT GraphicString, but GeneralString is a
+     * superset supported by OpenSSL, so we will use that anywhere a
+     * GraphicString is needed here.
+     */
+    case V_ASN1_GENERALSTRING:
+    case V_ASN1_GRAPHICSTRING:
+    case V_ASN1_OBJECT_DESCRIPTOR:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.generalstring->length,
+                          av->value.generalstring->data);
+
+    /* EXTERNAL would go here. */
+    /* EMBEDDED PDV would go here. */
+
+    case V_ASN1_UTF8STRING:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.utf8string->length,
+                          av->value.utf8string->data);
+
+    case V_ASN1_REAL:
+        return BIO_printf(out, "%*sREAL", indent, "");
+
+    /* RELATIVE-OID would go here. */
+    /* TIME would go here. */
+
+    case V_ASN1_SEQUENCE:
+        return ASN1_parse_dump(out, av->value.sequence->data,
+                        av->value.sequence->length, indent, 1);
+
+    case V_ASN1_SET:
+        return ASN1_parse_dump(out, av->value.set->data,
+                av->value.set->length, indent, 1);
+
+    /*
+     * UTCTime ::= [UNIVERSAL 23] IMPLICIT VisibleString
+     * GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
+     * VisibleString is a superset for NumericString, so it will work for that.
+     */
+    case V_ASN1_VISIBLESTRING:
+    case V_ASN1_UTCTIME:
+    case V_ASN1_GENERALIZEDTIME:
+    case V_ASN1_NUMERICSTRING:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.visiblestring->length,
+                          av->value.visiblestring->data);
+
+    case V_ASN1_PRINTABLESTRING:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.printablestring->length,
+                          av->value.printablestring->data);
+
+    case V_ASN1_T61STRING:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.t61string->length,
+                          av->value.t61string->data);
+
+    case V_ASN1_IA5STRING:
+        return BIO_printf(out, "%*s%.*s", indent, "",
+                          av->value.ia5string->length,
+                          av->value.ia5string->data);
+
+    /* UniversalString would go here. */
+    /* CHARACTER STRING would go here. */
+    /* BMPString would go here. */
+    /* DATE would go here. */
+    /* TIME-OF-DAY would go here. */
+    /* DATE-TIME would go here. */
+    /* DURATION would go here. */
+    /* OID-IRI would go here. */
+    /* RELATIVE-OID-IRI would go here. */
+
+    /* Would it be approriate to just hexdump? */
+    default:
+        return BIO_printf(out, "%*s<Unsupported tag %d>", indent, "", av->type);
+    }
+}
diff --git a/doc/internal/man3/ossl_print_attribute_value.pod b/doc/internal/man3/ossl_print_attribute_value.pod
new file mode 100644 (file)
index 0000000..1816f83
--- /dev/null
@@ -0,0 +1,52 @@
+=pod
+
+=head1 NAME
+
+ossl_print_attribute_value
+- Print an X.500 directory attribute value
+
+=head1 SYNOPSIS
+
+ #include <crypto/x509.h>
+
+ int ossl_print_attribute_value(BIO *out, int obj_nid, const ASN1_TYPE *av, int indent);
+
+=head1 DESCRIPTION
+
+ossl_print_attribute_value() prints an X.500 directory value, which is an
+ASN.1 value and an associated attribute type that informs its interpretation,
+syntax, display characteristics, comparison, sorting, and substring searching
+behaviors, among other things. This attribute type is identified by an ASN.1
+object identifier.
+
+X.500 directory values are used in the relative distinguished names in a
+distinguished name, as seen in the C<subject> and C<issuer> fields of an X.509
+public key certificate. They also appear in the attributes of an X.509
+attribute certificate, as well as in the subjectDirectoryAttributes or
+associatedInformation X.509v3 extensions.
+
+The I<out> argument is a B<BIO> pointer for printing the output. The I<obj_nid>
+argument is the NID of the attribute type object identifier. The ASN.1 value
+itself is passed in I<av> and the level of desired indentation in terms of the
+number of spaces is specified in I<indent>.
+
+This function generally prints values in such a way as to keep them on a single
+line, but this is not always the case. Unrecognized attribute types whose syntax
+is a C<SET> or C<SEQUENCE> will be printed on multiple lines, for instance. Not
+all ASN.1 syntaxes are currently supported, and there is no guarantee for what
+printed values will look like in future versions.
+
+=head1 RETURN VALUES
+
+Returns 1 if it succeeds in printing, and 0 if it failed.
+
+=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
index dc43c46aa9ab9f7888594a6094c0ae477df994ff..f350d74a7196f410b1c355e448a29b563103bb69 100644 (file)
@@ -19,6 +19,9 @@ ASIdentifiers_free,
 ASIdentifiers_new,
 ASRange_free,
 ASRange_new,
+ATTRIBUTES_SYNTAX_free,
+ATTRIBUTES_SYNTAX_it,
+ATTRIBUTES_SYNTAX_new,
 AUTHORITY_INFO_ACCESS_free,
 AUTHORITY_INFO_ACCESS_new,
 AUTHORITY_KEYID_free,
index 38181e764bb4371ef48f599fa5bf2ac61505cfba..86a653ad148ada669774f83c33a3c3a12744038b 100644 (file)
@@ -38,6 +38,7 @@ d2i_ASN1_UTCTIME,
 d2i_ASN1_UTF8STRING,
 d2i_ASN1_VISIBLESTRING,
 d2i_ASRange,
+d2i_ATTRIBUTES_SYNTAX,
 d2i_AUTHORITY_INFO_ACCESS,
 d2i_AUTHORITY_KEYID,
 d2i_BASIC_CONSTRAINTS,
@@ -220,6 +221,7 @@ i2d_ASN1_UTF8STRING,
 i2d_ASN1_VISIBLESTRING,
 i2d_ASN1_bio_stream,
 i2d_ASRange,
+i2d_ATTRIBUTES_SYNTAX,
 i2d_AUTHORITY_INFO_ACCESS,
 i2d_AUTHORITY_KEYID,
 i2d_BASIC_CONSTRAINTS,
index 18eb2f7c63f998200efdf49d507b6d79b55c3f8c..81d543a7a13892eda1fae2d872514d909c151ff4 100644 (file)
@@ -388,4 +388,10 @@ STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
                                                        int type,
                                                        const unsigned char *bytes,
                                                        int len);
+                                            
+int ossl_print_attribute_value(BIO *out,
+                               int obj_nid,
+                               const ASN1_TYPE *av,
+                               int indent);
+
 #endif  /* OSSL_CRYPTO_X509_H */
index 7c2313e424881f388d11a29f6d931cd170c9e956..10fc663e6dc560469d77f9d2a782d0a38a78c027 100644 (file)
@@ -1021,6 +1021,9 @@ void PROFESSION_INFO_set0_registrationNumber(
 
 int OSSL_GENERAL_NAMES_print(BIO *out, GENERAL_NAMES *gens, int indent);
 
+typedef STACK_OF(X509_ATTRIBUTE) ATTRIBUTES_SYNTAX;
+DECLARE_ASN1_FUNCTIONS(ATTRIBUTES_SYNTAX)
+
 # ifdef  __cplusplus
 }
 # endif
diff --git a/test/certs/ext-associatedInformation.pem b/test/certs/ext-associatedInformation.pem
new file mode 100644 (file)
index 0000000..e9278e1
--- /dev/null
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBYzCCAU2gAwIBAgIEDCI4TjANBgkqhkiG9w0BAQEFADARMQ8wDQYDVQQDDAZI
+aSBtb20wIhgPMjAyMjEwMjkwMTIzNDNaGA8yMDIyMTAyOTAxMjM0M1owETEPMA0G
+A1UEAwwGSGkgbW9tMAowBQYDKgMEAwEAo4HaMIHXMIHUBgNVHUsEgcwwgckwgX8G
+A1UEAzF4DAtTdGV2ZSBCcnVsZQwPRHIuIFN0ZXZlIEJydWxlDCJEci4gU3RldmUg
+QnJ1bGUsIGZyb20gQnJ1bGVzIFJ1bGVzDDRUaGUgZ2l2ZW5OYW1lIGF0dHJpYnV0
+ZSBiZWxvdyBpcyBpbnRlbnRpb25hbGx5IGVtcHR5MAwGA1UEajEFBgNVBAMwGgYD
+VQQgMRMwETEPMA0GA1UEAwwGSGkgbW9tMAcGA1UEKjEAMBIGA1UEBzELDAlGdW5r
+eXRvd24wDQYJKoZIhvcNAQEBBQADAQA=
+-----END CERTIFICATE-----
diff --git a/test/certs/ext-subjectDirectoryAttributes.pem b/test/certs/ext-subjectDirectoryAttributes.pem
new file mode 100644 (file)
index 0000000..4dcb43d
--- /dev/null
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBYzCCAU2gAwIBAgIEDCI4TjANBgkqhkiG9w0BAQEFADARMQ8wDQYDVQQDDAZI
+aSBtb20wIhgPMjAyMjEwMjkwMTI0NDlaGA8yMDIyMTAyOTAxMjQ0OVowETEPMA0G
+A1UEAwwGSGkgbW9tMAowBQYDKgMEAwEAo4HaMIHXMIHUBgNVHQkEgcwwgckwgX8G
+A1UEAzF4DAtTdGV2ZSBCcnVsZQwPRHIuIFN0ZXZlIEJydWxlDCJEci4gU3RldmUg
+QnJ1bGUsIGZyb20gQnJ1bGVzIFJ1bGVzDDRUaGUgZ2l2ZW5OYW1lIGF0dHJpYnV0
+ZSBiZWxvdyBpcyBpbnRlbnRpb25hbGx5IGVtcHR5MAwGA1UEajEFBgNVBAMwGgYD
+VQQgMRMwETEPMA0GA1UEAwwGSGkgbW9tMAcGA1UEKjEAMBIGA1UEBzELDAlGdW5r
+eXRvd24wDQYJKoZIhvcNAQEBBQADAQA=
+-----END CERTIFICATE-----
index f5e5919eab9457e3c71235b369bd3246d38860d6..579f90278d160975198d9698cafd4d68f834a03d 100644 (file)
@@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
 
 setup("test_x509");
 
-plan tests => 66;
+plan tests => 82;
 
 # Prevent MSys2 filename munging for arguments that look like file paths but
 # aren't
@@ -193,6 +193,57 @@ cert_contains($dnc_cert,
 cert_contains($dnc_cert,
               "DirName:CN = Wildboar",
               1, 'X.509 Delegated Name Constraint');
+my $sda_cert = srctop_file(@certs, "ext-subjectDirectoryAttributes.pem");
+cert_contains($sda_cert,
+              "Steve Brule",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "CN=Hi mom",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "<No Values>",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "Funkytown",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "commonName",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "owner",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "givenName",
+              1, 'X.509 Subject Directory Attributes');
+cert_contains($sda_cert,
+              "localityName",
+              1, 'X.509 Subject Directory Attributes');
+
+my $ass_info_cert = srctop_file(@certs, "ext-associatedInformation.pem");
+cert_contains($ass_info_cert,
+              "Steve Brule",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "CN=Hi mom",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "<No Values>",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "Funkytown",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "commonName",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "owner",
+              1, 'X509v3 Associated Information');
+cert_contains($sda_cert,
+              "givenName",
+              1, 'X509v3 Associated Information');
+cert_contains($ass_info_cert,
+              "localityName",
+              1, 'X509v3 Associated Information');
 
 sub test_errors { # actually tests diagnostics of OSSL_STORE
     my ($expected, $cert, @opts) = @_;
index 681183a9f4c58e01c9bd3eded0c044b7bcd288b7..2c9292d4abe0a27be4f6c5c76da454f3c9e13749 100644 (file)
@@ -5683,3 +5683,8 @@ 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:
+d2i_ATTRIBUTES_SYNTAX                   ?      3_4_0   EXIST::FUNCTION:
+i2d_ATTRIBUTES_SYNTAX                   ?      3_4_0   EXIST::FUNCTION:
+ATTRIBUTES_SYNTAX_free                  ?      3_4_0   EXIST::FUNCTION:
+ATTRIBUTES_SYNTAX_new                   ?      3_4_0   EXIST::FUNCTION:
+ATTRIBUTES_SYNTAX_it                    ?      3_4_0   EXIST::FUNCTION: