]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509/x509_att.c
Implement EVP_PKEY_dup() function
[thirdparty/openssl.git] / crypto / x509 / x509_att.c
CommitLineData
b1322259 1/*
454afd98 2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
b38f9f66 3 *
3e4b43b9 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
b38f9f66
DSH
8 */
9
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
1f5e0f92 12#include <openssl/safestack.h>
b38f9f66
DSH
13#include <openssl/asn1.h>
14#include <openssl/objects.h>
15#include <openssl/evp.h>
16#include <openssl/x509.h>
17#include <openssl/x509v3.h>
2145ba5e 18#include "crypto/x509.h"
706457b7 19#include "x509_local.h"
b38f9f66 20
77b47b90 21int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
b38f9f66 22{
0f113f3e 23 return sk_X509_ATTRIBUTE_num(x);
b38f9f66
DSH
24}
25
77b47b90 26int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
0f113f3e 27 int lastpos)
b38f9f66 28{
c47ba4e9 29 const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
b38f9f66 30
0f113f3e 31 if (obj == NULL)
26a7d938
K
32 return -2;
33 return X509at_get_attr_by_OBJ(x, obj, lastpos);
b38f9f66
DSH
34}
35
0f113f3e 36int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
c47ba4e9 37 const ASN1_OBJECT *obj, int lastpos)
b38f9f66 38{
0f113f3e
MC
39 int n;
40 X509_ATTRIBUTE *ex;
b38f9f66 41
0f113f3e 42 if (sk == NULL)
26a7d938 43 return -1;
0f113f3e
MC
44 lastpos++;
45 if (lastpos < 0)
46 lastpos = 0;
47 n = sk_X509_ATTRIBUTE_num(sk);
48 for (; lastpos < n; lastpos++) {
49 ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
50 if (OBJ_cmp(ex->object, obj) == 0)
26a7d938 51 return lastpos;
0f113f3e 52 }
26a7d938 53 return -1;
b38f9f66
DSH
54}
55
77b47b90 56X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
b38f9f66 57{
0f113f3e
MC
58 if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
59 return NULL;
d2a56999
F
60
61 return sk_X509_ATTRIBUTE_value(x, loc);
b38f9f66
DSH
62}
63
77b47b90 64X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
b38f9f66 65{
0f113f3e 66 X509_ATTRIBUTE *ret;
b38f9f66 67
0f113f3e 68 if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
26a7d938 69 return NULL;
0f113f3e 70 ret = sk_X509_ATTRIBUTE_delete(x, loc);
26a7d938 71 return ret;
b38f9f66
DSH
72}
73
c7cb16a8 74STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
0f113f3e 75 X509_ATTRIBUTE *attr)
b38f9f66 76{
0f113f3e
MC
77 X509_ATTRIBUTE *new_attr = NULL;
78 STACK_OF(X509_ATTRIBUTE) *sk = NULL;
b38f9f66 79
0f113f3e 80 if (x == NULL) {
9311d0c4 81 ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
0f113f3e
MC
82 goto err2;
83 }
c755c5fd 84
0f113f3e
MC
85 if (*x == NULL) {
86 if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
87 goto err;
2145ba5e 88 } else {
0f113f3e 89 sk = *x;
2145ba5e 90 }
b38f9f66 91
0f113f3e
MC
92 if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
93 goto err2;
94 if (!sk_X509_ATTRIBUTE_push(sk, new_attr))
95 goto err;
96 if (*x == NULL)
97 *x = sk;
26a7d938 98 return sk;
0f113f3e 99 err:
9311d0c4 100 ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
0f113f3e 101 err2:
222561fe 102 X509_ATTRIBUTE_free(new_attr);
2145ba5e
TM
103 if (*x == NULL)
104 sk_X509_ATTRIBUTE_free(sk);
26a7d938 105 return NULL;
b38f9f66
DSH
106}
107
0f113f3e
MC
108STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
109 **x, const ASN1_OBJECT *obj,
110 int type,
111 const unsigned char *bytes,
112 int len)
77b47b90 113{
0f113f3e
MC
114 X509_ATTRIBUTE *attr;
115 STACK_OF(X509_ATTRIBUTE) *ret;
116 attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
117 if (!attr)
118 return 0;
119 ret = X509at_add1_attr(x, attr);
120 X509_ATTRIBUTE_free(attr);
121 return ret;
77b47b90
DSH
122}
123
0f113f3e
MC
124STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
125 **x, int nid, int type,
126 const unsigned char *bytes,
127 int len)
77b47b90 128{
0f113f3e
MC
129 X509_ATTRIBUTE *attr;
130 STACK_OF(X509_ATTRIBUTE) *ret;
131 attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
132 if (!attr)
133 return 0;
134 ret = X509at_add1_attr(x, attr);
135 X509_ATTRIBUTE_free(attr);
136 return ret;
77b47b90
DSH
137}
138
0f113f3e
MC
139STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
140 **x, const char *attrname,
141 int type,
142 const unsigned char *bytes,
143 int len)
77b47b90 144{
0f113f3e
MC
145 X509_ATTRIBUTE *attr;
146 STACK_OF(X509_ATTRIBUTE) *ret;
147 attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
148 if (!attr)
149 return 0;
150 ret = X509at_add1_attr(x, attr);
151 X509_ATTRIBUTE_free(attr);
152 return ret;
77b47b90
DSH
153}
154
796948cd 155void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x,
c47ba4e9 156 const ASN1_OBJECT *obj, int lastpos, int type)
4d318c79 157{
0f113f3e
MC
158 int i;
159 X509_ATTRIBUTE *at;
160 i = X509at_get_attr_by_OBJ(x, obj, lastpos);
161 if (i == -1)
162 return NULL;
163 if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
164 return NULL;
165 at = X509at_get_attr(x, i);
166 if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
167 return NULL;
168 return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
4d318c79
DSH
169}
170
2145ba5e
TM
171STACK_OF(X509_ATTRIBUTE) *ossl_x509at_dup(const STACK_OF(X509_ATTRIBUTE) *x)
172{
173 int i, n;
174 STACK_OF(X509_ATTRIBUTE) *sk = NULL;
175
176 n = sk_X509_ATTRIBUTE_num(x);
177 for (i = 0; i < n; ++i) {
178 X509_ATTRIBUTE *attr = sk_X509_ATTRIBUTE_value(x, i);
179
180 if (X509at_add1_attr(&sk, attr) == NULL) {
181 sk_X509_ATTRIBUTE_pop_free(sk, X509_ATTRIBUTE_free);
182 return NULL;
183 }
184 }
185 return sk;
186}
187
b38f9f66 188X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
0f113f3e
MC
189 int atrtype, const void *data,
190 int len)
b38f9f66 191{
0f113f3e
MC
192 ASN1_OBJECT *obj;
193 X509_ATTRIBUTE *ret;
b38f9f66 194
0f113f3e
MC
195 obj = OBJ_nid2obj(nid);
196 if (obj == NULL) {
9311d0c4 197 ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
26a7d938 198 return NULL;
0f113f3e
MC
199 }
200 ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
201 if (ret == NULL)
202 ASN1_OBJECT_free(obj);
26a7d938 203 return ret;
b38f9f66
DSH
204}
205
206X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
0f113f3e
MC
207 const ASN1_OBJECT *obj,
208 int atrtype, const void *data,
209 int len)
b38f9f66 210{
0f113f3e 211 X509_ATTRIBUTE *ret;
b38f9f66 212
0f113f3e
MC
213 if ((attr == NULL) || (*attr == NULL)) {
214 if ((ret = X509_ATTRIBUTE_new()) == NULL) {
9311d0c4 215 ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
26a7d938 216 return NULL;
0f113f3e
MC
217 }
218 } else
219 ret = *attr;
b38f9f66 220
0f113f3e
MC
221 if (!X509_ATTRIBUTE_set1_object(ret, obj))
222 goto err;
223 if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len))
224 goto err;
8528128b 225
0f113f3e
MC
226 if ((attr != NULL) && (*attr == NULL))
227 *attr = ret;
26a7d938 228 return ret;
0f113f3e
MC
229 err:
230 if ((attr == NULL) || (ret != *attr))
231 X509_ATTRIBUTE_free(ret);
26a7d938 232 return NULL;
b38f9f66
DSH
233}
234
77b47b90 235X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
0f113f3e
MC
236 const char *atrname, int type,
237 const unsigned char *bytes,
238 int len)
239{
240 ASN1_OBJECT *obj;
241 X509_ATTRIBUTE *nattr;
77b47b90 242
0f113f3e
MC
243 obj = OBJ_txt2obj(atrname, 0);
244 if (obj == NULL) {
a150f8e1
RL
245 ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
246 "name=%s", atrname);
26a7d938 247 return NULL;
0f113f3e
MC
248 }
249 nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
250 ASN1_OBJECT_free(obj);
251 return nattr;
252}
77b47b90 253
f2a253e0 254int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
b38f9f66 255{
0f113f3e 256 if ((attr == NULL) || (obj == NULL))
26a7d938 257 return 0;
0f113f3e
MC
258 ASN1_OBJECT_free(attr->object);
259 attr->object = OBJ_dup(obj);
4e0e4d29 260 return attr->object != NULL;
b38f9f66
DSH
261}
262
0f113f3e
MC
263int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
264 const void *data, int len)
b38f9f66 265{
5000a6d1 266 ASN1_TYPE *ttmp = NULL;
0f113f3e
MC
267 ASN1_STRING *stmp = NULL;
268 int atype = 0;
269 if (!attr)
270 return 0;
271 if (attrtype & MBSTRING_FLAG) {
272 stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
273 OBJ_obj2nid(attr->object));
274 if (!stmp) {
9311d0c4 275 ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
0f113f3e
MC
276 return 0;
277 }
278 atype = stmp->type;
279 } else if (len != -1) {
75ebbd9a 280 if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL)
0f113f3e
MC
281 goto err;
282 if (!ASN1_STRING_set(stmp, data, len))
283 goto err;
284 atype = attrtype;
285 }
0f113f3e
MC
286 /*
287 * This is a bit naughty because the attribute should really have at
288 * least one value but some types use and zero length SET and require
289 * this.
290 */
5000a6d1
MC
291 if (attrtype == 0) {
292 ASN1_STRING_free(stmp);
0f113f3e 293 return 1;
5000a6d1 294 }
75ebbd9a 295 if ((ttmp = ASN1_TYPE_new()) == NULL)
0f113f3e
MC
296 goto err;
297 if ((len == -1) && !(attrtype & MBSTRING_FLAG)) {
298 if (!ASN1_TYPE_set1(ttmp, attrtype, data))
299 goto err;
5000a6d1 300 } else {
0f113f3e 301 ASN1_TYPE_set(ttmp, atype, stmp);
5000a6d1
MC
302 stmp = NULL;
303 }
e20b5727 304 if (!sk_ASN1_TYPE_push(attr->set, ttmp))
0f113f3e
MC
305 goto err;
306 return 1;
307 err:
9311d0c4 308 ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
5000a6d1
MC
309 ASN1_TYPE_free(ttmp);
310 ASN1_STRING_free(stmp);
0f113f3e 311 return 0;
b38f9f66
DSH
312}
313
333ed02c 314int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr)
b38f9f66 315{
e20b5727
DSH
316 if (attr == NULL)
317 return 0;
318 return sk_ASN1_TYPE_num(attr->set);
b38f9f66
DSH
319}
320
c7cb16a8 321ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
b38f9f66 322{
0f113f3e 323 if (attr == NULL)
26a7d938
K
324 return NULL;
325 return attr->object;
b38f9f66
DSH
326}
327
c7cb16a8 328void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
0f113f3e 329 int atrtype, void *data)
b38f9f66 330{
0f113f3e
MC
331 ASN1_TYPE *ttmp;
332 ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
333 if (!ttmp)
334 return NULL;
94f4d58a
BE
335 if (atrtype == V_ASN1_BOOLEAN
336 || atrtype == V_ASN1_NULL
337 || atrtype != ASN1_TYPE_get(ttmp)) {
9311d0c4 338 ERR_raise(ERR_LIB_X509, X509_R_WRONG_TYPE);
0f113f3e
MC
339 return NULL;
340 }
341 return ttmp->value.ptr;
b38f9f66
DSH
342}
343
c7cb16a8 344ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
b38f9f66 345{
0f113f3e 346 if (attr == NULL)
0f113f3e 347 return NULL;
e20b5727 348 return sk_ASN1_TYPE_value(attr->set, idx);
b38f9f66 349}