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