summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>2021-06-08 17:31:57 +0900
committerMatt Caswell <matt@openssl.org>2024-04-24 14:05:35 +0100
commit0e8020a45b2f24e85769cd2c66c41f0b7ffa21e4 (patch)
tree80e3c06a6d1fcc4adf19734242f95ec14d9c45ac /crypto
parent1eeec94f1fd7de60248d1093d5552dc1f05c2fc9 (diff)
Add IETFAttrSyntax type support
The IETFAtrrSyntax type is used for the values of several attributes defined in RFC 5755 for use with attribute certificates. Specifically this type is used with the "Charging Identity" and "Group" attributes. Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Neil Horman <nhorman@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15857)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/x509/build.info2
-rw-r--r--crypto/x509/x_ietfatt.c240
2 files changed, 241 insertions, 1 deletions
diff --git a/crypto/x509/build.info b/crypto/x509/build.info
index 873a9838b5..6cebadea77 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
+ x509_acert.c x509aset.c t_acert.c x_ietfatt.c
IF[{- !$disabled{'deprecated-3.0'} -}]
SOURCE[../../libcrypto]=x509type.c
diff --git a/crypto/x509/x_ietfatt.c b/crypto/x509/x_ietfatt.c
new file mode 100644
index 0000000000..08db0bafc7
--- /dev/null
+++ b/crypto/x509/x_ietfatt.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright 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 <openssl/err.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509_acert.h>
+
+/*-
+ * Definition of IetfAttrSyntax from RFC 5755 4.4
+ *
+ * IetfAttrSyntax ::= SEQUENCE {
+ * policyAuthority [0] GeneralNames OPTIONAL,
+ * values SEQUENCE OF CHOICE {
+ * octets OCTET STRING,
+ * oid OBJECT IDENTIFIER,
+ * string UTF8String
+ * }
+ * }
+ *
+ * Section 4.4.2 states that all values in the sequence MUST use the
+ * same choice of value (octet, oid or string).
+ */
+
+struct OSSL_IETF_ATTR_SYNTAX_VALUE_st {
+ int type;
+ union {
+ ASN1_OCTET_STRING *octets;
+ ASN1_OBJECT *oid;
+ ASN1_UTF8STRING *string;
+ } u;
+};
+
+struct OSSL_IETF_ATTR_SYNTAX_st {
+ GENERAL_NAMES *policyAuthority;
+ int type;
+ STACK_OF(OSSL_IETF_ATTR_SYNTAX_VALUE) *values;
+};
+
+ASN1_CHOICE(OSSL_IETF_ATTR_SYNTAX_VALUE) = {
+ ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.octets, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.oid, ASN1_OBJECT),
+ ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.string, ASN1_UTF8STRING),
+} ASN1_CHOICE_END(OSSL_IETF_ATTR_SYNTAX_VALUE)
+
+ASN1_SEQUENCE(OSSL_IETF_ATTR_SYNTAX) = {
+ ASN1_IMP_SEQUENCE_OF_OPT(OSSL_IETF_ATTR_SYNTAX, policyAuthority, GENERAL_NAME, 0),
+ ASN1_SEQUENCE_OF(OSSL_IETF_ATTR_SYNTAX, values, OSSL_IETF_ATTR_SYNTAX_VALUE),
+} ASN1_SEQUENCE_END(OSSL_IETF_ATTR_SYNTAX)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX_VALUE)
+
+OSSL_IETF_ATTR_SYNTAX *d2i_OSSL_IETF_ATTR_SYNTAX (OSSL_IETF_ATTR_SYNTAX **a,
+ const unsigned char **in,
+ long len)
+{
+ OSSL_IETF_ATTR_SYNTAX *ias;
+ int i;
+
+ ias = (OSSL_IETF_ATTR_SYNTAX *) ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+ OSSL_IETF_ATTR_SYNTAX_it());
+ if (ias == NULL)
+ return ias;
+
+ for (i = 0; i < sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(ias->values); i++)
+ {
+ OSSL_IETF_ATTR_SYNTAX_VALUE *val;
+
+ val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(ias->values, i);
+ if (i == 0)
+ ias->type = val->type;
+ else if (val->type != ias->type)
+ goto invalid_types;
+ }
+
+ return ias;
+
+invalid_types:
+ OSSL_IETF_ATTR_SYNTAX_free(ias);
+ if (a)
+ *a = NULL;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+}
+
+int i2d_OSSL_IETF_ATTR_SYNTAX (const OSSL_IETF_ATTR_SYNTAX *a,
+ unsigned char **out)
+{
+ return ASN1_item_i2d((const ASN1_VALUE *)a, out, OSSL_IETF_ATTR_SYNTAX_it());
+}
+
+int OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX *a)
+{
+ if (a->values == NULL)
+ return 0;
+
+ return sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(a->values);
+}
+
+const GENERAL_NAMES *
+OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX *a)
+{
+ return a->policyAuthority;
+}
+
+void OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX *a,
+ GENERAL_NAMES *names)
+{
+ GENERAL_NAMES_free(a->policyAuthority);
+ a->policyAuthority = names;
+}
+
+void *OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX *a,
+ int ind, int *type)
+{
+ OSSL_IETF_ATTR_SYNTAX_VALUE *val;
+
+ val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(a->values, ind);
+ if (val == NULL)
+ return NULL;
+
+ if (type != NULL)
+ *type = val->type;
+
+ switch (val->type) {
+ case OSSL_IETFAS_OCTETS:
+ return val->u.octets;
+ case OSSL_IETFAS_OID:
+ return val->u.oid;
+ case OSSL_IETFAS_STRING:
+ return val->u.string;
+ }
+
+ return NULL;
+}
+
+int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type,
+ void *data)
+{
+ OSSL_IETF_ATTR_SYNTAX_VALUE *val;
+
+ if (data == NULL)
+ return 0;
+
+ if (a->values == NULL) {
+ if ((a->values = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_new_null()) == NULL)
+ goto err;
+ a->type = type;
+ }
+
+ if (type != a->type) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if ((val = OSSL_IETF_ATTR_SYNTAX_VALUE_new()) == NULL)
+ goto err;
+
+ val->type = type;
+ switch (type) {
+ case OSSL_IETFAS_OCTETS:
+ val->u.octets = data;
+ break;
+ case OSSL_IETFAS_OID:
+ val->u.oid = data;
+ break;
+ case OSSL_IETFAS_STRING:
+ val->u.string = data;
+ break;
+ default:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if (sk_OSSL_IETF_ATTR_SYNTAX_VALUE_push(a->values, val) <= 0) {
+ OSSL_IETF_ATTR_SYNTAX_VALUE_free(val);
+ return 0;
+ }
+
+ return 1;
+
+err:
+ ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
+ return 0;
+}
+
+int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, int indent)
+{
+ int i;
+
+ if (a->policyAuthority != NULL) {
+ for (i = 0; i < sk_GENERAL_NAME_num(a->policyAuthority); i++) {
+ if (BIO_printf(bp, "%*s", indent, "") <= 0)
+ goto err;
+
+ if (GENERAL_NAME_print(bp, sk_GENERAL_NAME_value(a->policyAuthority,
+ i)) <= 0)
+ goto err;
+
+ if (BIO_printf(bp, "\n") <= 0)
+ goto err;
+ }
+ }
+
+ for (i = 0; i < OSSL_IETF_ATTR_SYNTAX_get_value_num(a); i++) {
+ char oidstr[80];
+ int ietf_type;
+ void *attr_value = OSSL_IETF_ATTR_SYNTAX_get0_value(a, i, &ietf_type);
+
+ if (attr_value == NULL)
+ goto err;
+
+ if (BIO_printf(bp, "%*s", indent, "") <= 0)
+ goto err;
+
+ switch (ietf_type) {
+ case OSSL_IETFAS_OID:
+ OBJ_obj2txt(oidstr, sizeof(oidstr), attr_value, 0);
+ BIO_printf(bp, "%.*s", (int) sizeof(oidstr), oidstr);
+ break;
+ case OSSL_IETFAS_OCTETS:
+ case OSSL_IETFAS_STRING:
+ ASN1_STRING_print(bp, attr_value);
+ break;
+ }
+ }
+ if (BIO_printf(bp, "\n") <= 0)
+ goto err;
+
+ return 1;
+
+err:
+ return 0;
+}