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