| /* |
| * Copyright 2021-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/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: |
| OSSL_IETF_ATTR_SYNTAX_VALUE_free(val); |
| 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; |
| } |