xref: /openssl/crypto/x509/x_ietfatt.c (revision 7ed6de99)
1 /*
2  * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/err.h>
11 #include <openssl/asn1t.h>
12 #include <openssl/x509_acert.h>
13 
14 /*-
15  * Definition of IetfAttrSyntax from RFC 5755 4.4
16  *
17  * IetfAttrSyntax ::= SEQUENCE {
18  *   policyAuthority [0] GeneralNames    OPTIONAL,
19  *   values          SEQUENCE OF CHOICE {
20  *                     octets    OCTET STRING,
21  *                     oid       OBJECT IDENTIFIER,
22  *                     string    UTF8String
23  *                   }
24  * }
25  *
26  * Section 4.4.2 states that all values in the sequence MUST use the
27  * same choice of value (octet, oid or string).
28  */
29 
30 struct OSSL_IETF_ATTR_SYNTAX_VALUE_st {
31     int type;
32     union {
33         ASN1_OCTET_STRING *octets;
34         ASN1_OBJECT *oid;
35         ASN1_UTF8STRING *string;
36     } u;
37 };
38 
39 struct OSSL_IETF_ATTR_SYNTAX_st {
40     GENERAL_NAMES *policyAuthority;
41     int type;
42     STACK_OF(OSSL_IETF_ATTR_SYNTAX_VALUE) *values;
43 };
44 
45 ASN1_CHOICE(OSSL_IETF_ATTR_SYNTAX_VALUE) = {
46     ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.octets, ASN1_OCTET_STRING),
47     ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.oid, ASN1_OBJECT),
48     ASN1_SIMPLE(OSSL_IETF_ATTR_SYNTAX_VALUE, u.string, ASN1_UTF8STRING),
49 } ASN1_CHOICE_END(OSSL_IETF_ATTR_SYNTAX_VALUE)
50 
51 ASN1_SEQUENCE(OSSL_IETF_ATTR_SYNTAX) = {
52     ASN1_IMP_SEQUENCE_OF_OPT(OSSL_IETF_ATTR_SYNTAX, policyAuthority, GENERAL_NAME, 0),
53     ASN1_SEQUENCE_OF(OSSL_IETF_ATTR_SYNTAX, values, OSSL_IETF_ATTR_SYNTAX_VALUE),
54 } ASN1_SEQUENCE_END(OSSL_IETF_ATTR_SYNTAX)
55 
56 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX)
57 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OSSL_IETF_ATTR_SYNTAX_VALUE)
58 
59 OSSL_IETF_ATTR_SYNTAX *d2i_OSSL_IETF_ATTR_SYNTAX (OSSL_IETF_ATTR_SYNTAX **a,
60                                                   const unsigned char **in,
61                                                   long len)
62 {
63     OSSL_IETF_ATTR_SYNTAX *ias;
64     int i;
65 
66     ias = (OSSL_IETF_ATTR_SYNTAX *) ASN1_item_d2i((ASN1_VALUE **)a, in, len,
67                                                   OSSL_IETF_ATTR_SYNTAX_it());
68     if (ias == NULL)
69         return ias;
70 
71     for (i = 0; i < sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(ias->values); i++)
72     {
73         OSSL_IETF_ATTR_SYNTAX_VALUE *val;
74 
75         val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(ias->values, i);
76         if (i == 0)
77             ias->type = val->type;
78         else if (val->type != ias->type)
79             goto invalid_types;
80     }
81 
82     return ias;
83 
84 invalid_types:
85     OSSL_IETF_ATTR_SYNTAX_free(ias);
86     if (a)
87         *a = NULL;
88     ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
89     return NULL;
90 }
91 
i2d_OSSL_IETF_ATTR_SYNTAX(const OSSL_IETF_ATTR_SYNTAX * a,unsigned char ** out)92 int i2d_OSSL_IETF_ATTR_SYNTAX (const OSSL_IETF_ATTR_SYNTAX *a,
93                                unsigned char **out)
94 {
95     return ASN1_item_i2d((const ASN1_VALUE *)a, out, OSSL_IETF_ATTR_SYNTAX_it());
96 }
97 
OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX * a)98 int OSSL_IETF_ATTR_SYNTAX_get_value_num(const OSSL_IETF_ATTR_SYNTAX *a)
99 {
100     if (a->values == NULL)
101         return 0;
102 
103     return sk_OSSL_IETF_ATTR_SYNTAX_VALUE_num(a->values);
104 }
105 
106 const GENERAL_NAMES *
OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX * a)107 OSSL_IETF_ATTR_SYNTAX_get0_policyAuthority(const OSSL_IETF_ATTR_SYNTAX *a)
108 {
109     return a->policyAuthority;
110 }
111 
OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX * a,GENERAL_NAMES * names)112 void OSSL_IETF_ATTR_SYNTAX_set0_policyAuthority(OSSL_IETF_ATTR_SYNTAX *a,
113                                                 GENERAL_NAMES *names)
114 {
115     GENERAL_NAMES_free(a->policyAuthority);
116     a->policyAuthority = names;
117 }
118 
OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX * a,int ind,int * type)119 void *OSSL_IETF_ATTR_SYNTAX_get0_value(const OSSL_IETF_ATTR_SYNTAX *a,
120                                        int ind, int *type)
121 {
122     OSSL_IETF_ATTR_SYNTAX_VALUE *val;
123 
124     val = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_value(a->values, ind);
125     if (val == NULL)
126         return NULL;
127 
128     if (type != NULL)
129         *type = val->type;
130 
131     switch (val->type) {
132     case OSSL_IETFAS_OCTETS:
133         return val->u.octets;
134     case OSSL_IETFAS_OID:
135         return val->u.oid;
136     case OSSL_IETFAS_STRING:
137         return val->u.string;
138     }
139 
140     return NULL;
141 }
142 
OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX * a,int type,void * data)143 int OSSL_IETF_ATTR_SYNTAX_add1_value(OSSL_IETF_ATTR_SYNTAX *a, int type,
144                                      void *data)
145 {
146     OSSL_IETF_ATTR_SYNTAX_VALUE *val;
147 
148     if (data == NULL)
149         return 0;
150 
151     if (a->values == NULL) {
152         if ((a->values = sk_OSSL_IETF_ATTR_SYNTAX_VALUE_new_null()) == NULL)
153             goto err;
154         a->type = type;
155     }
156 
157     if (type != a->type) {
158         ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
159         return 0;
160     }
161 
162     if ((val = OSSL_IETF_ATTR_SYNTAX_VALUE_new()) == NULL)
163         goto err;
164 
165     val->type = type;
166     switch (type) {
167     case OSSL_IETFAS_OCTETS:
168         val->u.octets = data;
169         break;
170     case OSSL_IETFAS_OID:
171         val->u.oid = data;
172         break;
173     case OSSL_IETFAS_STRING:
174         val->u.string = data;
175         break;
176     default:
177         OSSL_IETF_ATTR_SYNTAX_VALUE_free(val);
178         ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
179         return 0;
180     }
181 
182     if (sk_OSSL_IETF_ATTR_SYNTAX_VALUE_push(a->values, val) <= 0) {
183         OSSL_IETF_ATTR_SYNTAX_VALUE_free(val);
184         return 0;
185     }
186 
187     return 1;
188 
189 err:
190     ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
191     return 0;
192 }
193 
OSSL_IETF_ATTR_SYNTAX_print(BIO * bp,OSSL_IETF_ATTR_SYNTAX * a,int indent)194 int OSSL_IETF_ATTR_SYNTAX_print(BIO *bp, OSSL_IETF_ATTR_SYNTAX *a, int indent)
195 {
196     int i;
197 
198     if (a->policyAuthority != NULL) {
199         for (i = 0; i < sk_GENERAL_NAME_num(a->policyAuthority); i++) {
200             if (BIO_printf(bp, "%*s", indent, "") <= 0)
201                 goto err;
202 
203             if (GENERAL_NAME_print(bp, sk_GENERAL_NAME_value(a->policyAuthority,
204                                                              i)) <= 0)
205                 goto err;
206 
207             if (BIO_printf(bp, "\n") <= 0)
208                 goto err;
209         }
210     }
211 
212     for (i = 0; i < OSSL_IETF_ATTR_SYNTAX_get_value_num(a); i++) {
213         char oidstr[80];
214         int ietf_type;
215         void *attr_value = OSSL_IETF_ATTR_SYNTAX_get0_value(a, i, &ietf_type);
216 
217         if (attr_value == NULL)
218             goto err;
219 
220         if (BIO_printf(bp, "%*s", indent, "") <= 0)
221             goto err;
222 
223         switch (ietf_type) {
224         case OSSL_IETFAS_OID:
225             OBJ_obj2txt(oidstr, sizeof(oidstr), attr_value, 0);
226             BIO_printf(bp, "%.*s", (int) sizeof(oidstr), oidstr);
227             break;
228         case OSSL_IETFAS_OCTETS:
229         case OSSL_IETFAS_STRING:
230             ASN1_STRING_print(bp, attr_value);
231             break;
232         }
233     }
234     if (BIO_printf(bp, "\n") <= 0)
235         goto err;
236 
237     return 1;
238 
239 err:
240     return 0;
241 }
242