x509_acert: Load attributes from config file section
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>
Thu, 3 Jun 2021 06:41:27 +0000 (15:41 +0900)
committerMatt Caswell <matt@openssl.org>
Wed, 24 Apr 2024 13:08:05 +0000 (14:08 +0100)
Several of the attribute values defined for use by attribute certificates
use multi-valued data in an ASN.1 SEQUENCE. Allow reading of these values
from a configuration file, similar to how generic X.509 extensions are
handled.

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

crypto/x509/x509_acert.c
doc/build.info
doc/man3/X509_ACERT_add_attr_nconf.pod [new file with mode: 0644]
include/openssl/x509_acert.h.in
util/libcrypto.num

index 9499a14cc0bb1d68069c7bd02725b939984fb3da..a3c894636339ef16acb5897608b802ef006ef00b 100644 (file)
@@ -7,7 +7,10 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h>
+#include <crypto/ctype.h>
 #include <openssl/asn1t.h>
+#include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include "x509_acert.h"
@@ -243,6 +246,71 @@ int X509_ACERT_add1_attr_by_txt(X509_ACERT *x, const char *attrname, int type,
     return X509at_add1_attr_by_txt(attrs, attrname, type, bytes, len) != NULL;
 }
 
+static int check_asn1_attribute(const char **value)
+{
+    const char *p = *value;
+
+    if (strncmp(p, "ASN1:", 5) != 0)
+        return 0;
+
+    p += 5;
+    while (ossl_isspace(*p))
+        p++;
+
+    *value = p;
+    return 1;
+}
+
+int X509_ACERT_add_attr_nconf(CONF *conf, const char *section,
+                              X509_ACERT *acert)
+{
+    int ret = 0, i;
+    STACK_OF(CONF_VALUE) *attr_sk = NCONF_get_section(conf, section);
+
+    if (attr_sk == NULL)
+        goto err;
+
+    for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
+        CONF_VALUE *v = sk_CONF_VALUE_value(attr_sk, i);
+        const char *value = v->value;
+
+        if (value == NULL) {
+            ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES,
+                           "name=%s,section=%s",v->name, section);
+            goto err;
+        }
+
+        if (check_asn1_attribute(&value) == 1) {
+            int att_len;
+            unsigned char *att_data = NULL;
+            ASN1_TYPE *asn1 = ASN1_generate_nconf(value, conf);
+
+            if (asn1 == NULL)
+                goto err;
+
+            att_len = i2d_ASN1_TYPE(asn1, &att_data);
+
+            ret = X509_ACERT_add1_attr_by_txt(acert, v->name, V_ASN1_SEQUENCE,
+                                              att_data, att_len);
+            OPENSSL_free(att_data);
+            ASN1_TYPE_free(asn1);
+
+            if (!ret)
+                goto err;
+        } else {
+            ret = X509_ACERT_add1_attr_by_txt(acert, v->name,
+                                              V_ASN1_OCTET_STRING,
+                                              (unsigned char *)value,
+                                              strlen(value));
+            if (!ret)
+                goto err;
+        }
+    }
+    ret = 1;
+err:
+    return ret;
+}
+
 void *X509_ACERT_get_ext_d2i(const X509_ACERT *x, int nid, int *crit, int *idx)
 {
     return X509V3_get_d2i(x->acinfo->extensions, nid, crit, idx);
index 373f61476e348d3ddb7d77589babbebbb751943d..c7cb6d5d4fb3ed2b17debfeebfe16142a9d26cbb 100644 (file)
@@ -2811,6 +2811,10 @@ DEPEND[html/man3/X509_ACERT_add1_attr.html]=man3/X509_ACERT_add1_attr.pod
 GENERATE[html/man3/X509_ACERT_add1_attr.html]=man3/X509_ACERT_add1_attr.pod
 DEPEND[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod
 GENERATE[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod
+DEPEND[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod
+GENERATE[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod
+DEPEND[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.pod
+GENERATE[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.pod
 DEPEND[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod
 GENERATE[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod
 DEPEND[man/man3/X509_ACERT_get0_holder_baseCertId.3]=man3/X509_ACERT_get0_holder_baseCertId.pod
@@ -3658,6 +3662,7 @@ html/man3/UI_new.html \
 html/man3/X509V3_get_d2i.html \
 html/man3/X509V3_set_ctx.html \
 html/man3/X509_ACERT_add1_attr.html \
+html/man3/X509_ACERT_add_attr_nconf.html \
 html/man3/X509_ACERT_get0_holder_baseCertId.html \
 html/man3/X509_ACERT_get_attr.html \
 html/man3/X509_ACERT_print_ex.html \
@@ -4309,6 +4314,7 @@ man/man3/UI_new.3 \
 man/man3/X509V3_get_d2i.3 \
 man/man3/X509V3_set_ctx.3 \
 man/man3/X509_ACERT_add1_attr.3 \
+man/man3/X509_ACERT_add_attr_nconf.3 \
 man/man3/X509_ACERT_get0_holder_baseCertId.3 \
 man/man3/X509_ACERT_get_attr.3 \
 man/man3/X509_ACERT_print_ex.3 \
diff --git a/doc/man3/X509_ACERT_add_attr_nconf.pod b/doc/man3/X509_ACERT_add_attr_nconf.pod
new file mode 100644 (file)
index 0000000..a16d31c
--- /dev/null
@@ -0,0 +1,63 @@
+=pod
+
+=head1 NAME
+
+X509_ACERT_add_attr_nconf
+- Add attributes to X509_ACERT from configuration section
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509_acert.h>
+
+ int X509_ACERT_add_attr_nconf(CONF *conf, const char *section,
+                               X509_ACERT *acert);
+
+=head1 DESCRIPTION
+
+X509_ACERT_add_attr_nconf() adds one or more B<X509_ATTRIBUTE>s to the
+existing B<X509_ACERT> structure I<acert>. The attributes are read
+from a I<section> of the I<conf> object.
+
+The give I<section> of the configuration should contain attribute
+descriptions of the form:
+
+  attribute_name = value
+
+The format of B<value> will vary depending on the B<attribute_name>.
+B<value> can either be a string value or an B<ASN1_TYPE>
+object.
+
+To encode an B<ASN1_TYPE> object, use the prefix "ASN1:" followed by
+the object description that uses the same syntax as L<ASN1_generate_nconf(3)>.
+For example:
+
+ id-aca-group = ASN1:SEQUENCE:ietfattr
+
+ [ietfattr]
+ values = SEQUENCE:groups
+
+ [groups]
+ 1.string = UTF8:mygroup1
+
+=head1 RETURN VALUES
+
+X509_ACERT_add_attr_nconf() returns 1 for success and 0 for failure.
+
+=head1 SEE ALSO
+
+L<ASN1_generate_nconf(3)>.
+
+=head1 HISTORY
+
+The function X509_ACERT_add_attr_nconf() was added in OpenSSL 3.4.
+
+=head1 COPYRIGHT
+
+Copyright 2023 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 a1e6704c0d92fded0247eb0558a4fe43197e8985..42376a6cb763efee73bf6abd0410f8b4afa2526f 100644 (file)
@@ -98,6 +98,8 @@ int X509_ACERT_add1_attr_by_NID(X509_ACERT *x, int nid, int type,
                                 const void *bytes, int len);
 int X509_ACERT_add1_attr_by_txt(X509_ACERT *x, const char *attrname, int type,
                                 const unsigned char *bytes, int len);
+int X509_ACERT_add_attr_nconf(CONF *conf, const char *section,
+                              X509_ACERT *acert);
 
 int X509_ACERT_set1_issuerName(X509_ACERT *x, const X509_NAME *name);
 int X509_ACERT_set1_serialNumber(X509_ACERT *x, const ASN1_INTEGER *serial);
index 70e5871fb5a7d231e9fe280c890ff16137eacfb3..77b66ee2725c9982b6ef1b1bc00f72de01a882bc 100644 (file)
@@ -5632,3 +5632,4 @@ OSSL_IETF_ATTR_SYNTAX_get_value_num     ? 3_4_0   EXIST::FUNCTION:
 OSSL_IETF_ATTR_SYNTAX_get0_value        ?      3_4_0   EXIST::FUNCTION:
 OSSL_IETF_ATTR_SYNTAX_add1_value        ?      3_4_0   EXIST::FUNCTION:
 OSSL_IETF_ATTR_SYNTAX_print             ?      3_4_0   EXIST::FUNCTION:
+X509_ACERT_add_attr_nconf               ?      3_4_0   EXIST::FUNCTION: