X509_ATTRIBUTE(3SSL)
β¨ X509_ATTRIBUTE β¨
okay bestie so this is part of the OpenSSL manual, section 3SSL, and it's literally all about the X509_ATTRIBUTE family of functions π we're talking attributes, the ASN.1 kind, the ones hiding inside X509, X509_REQ, PKCS12, PKCS8, PKCS7 and CMS. them. no cap.
π NAME π
X509_ATTRIBUTE, X509at_get_attr, X509at_get_attr_count, X509at_get_attr_by_NID, X509at_get_attr_by_OBJ, X509at_delete_attr, X509at_add1_attr, X509at_add1_attr_by_OBJ, X509at_add1_attr_by_NID, X509at_add1_attr_by_txt, X509at_get0_data_by_OBJ, X509_ATTRIBUTE_create, X509_ATTRIBUTE_create_by_NID, X509_ATTRIBUTE_create_by_OBJ, X509_ATTRIBUTE_create_by_txt, X509_ATTRIBUTE_set1_object, X509_ATTRIBUTE_set1_data, X509_ATTRIBUTE_count, X509_ATTRIBUTE_get0_data, X509_ATTRIBUTE_get0_object, X509_ATTRIBUTE_get0_type β a whole friend group of X509 attribute functions π«Ά
πΈ SYNOPSIS πΈ
#include <openssl/x509.h>
typedef struct x509_attributes_st X509_ATTRIBUTE;
int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
int lastpos);
int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
const ASN1_OBJECT *obj, int lastpos);
X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
X509_ATTRIBUTE *attr);
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
**x, const ASN1_OBJECT *obj,
int type,
const unsigned char *bytes,
int len);
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
**x, int nid, int type,
const unsigned char *bytes,
int len);
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
**x, const char *attrname,
int type,
const unsigned char *bytes,
int len);
void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x,
const ASN1_OBJECT *obj, int lastpos, int type);
X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
int atrtype, const void *data,
int len);
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
const ASN1_OBJECT *obj,
int atrtype, const void *data,
int len);
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
const char *atrname, int type,
const unsigned char *bytes,
int len);
int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
const void *data, int len);
const void *X509_ATTRIBUTE_get0_data(const X509_ATTRIBUTE *attr, int idx,
int atrtype, void *data);
int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr);
const ASN1_OBJECT *X509_ATTRIBUTE_get0_object(const X509_ATTRIBUTE *attr);
const ASN1_TYPE *X509_ATTRIBUTE_get0_type(const X509_ATTRIBUTE *attr, int idx);
π DESCRIPTION π
X509_ATTRIBUTE objects get used by SO many standards bestie, like X509, X509_REQ, PKCS12, PKCS8, PKCS7 and CMS. it's giving universal.
so the X509_ATTRIBUTE object is the glow-up of the ASN.1 Attribute, exactly as defined in RFC 5280, which is literally:
Attribute ::= SEQUENCE {
type AttributeType,
values SET OF AttributeValue }
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY -- DEFINED BY AttributeType
and for the vibe check, CMS defines the signing-time attribute like this:
id-signingTime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
us(840) rsadsi(113549) pkcs(1) pkcs9(9) 5 }
SigningTime ::= Time
Time ::= CHOICE {
utcTime UTCTime,
generalizedTime GeneralizedTime }
in OpenSSL, AttributeType maps to an ASN1_OBJECT object and AttributeValue maps to a list of ASN1_TYPE objects. that's the whole lore. π€
the following functions are the ones that serve X509_ATTRIBUTE objects. let's go, one by one, no skips. π
X509at_get_attr_by_OBJ()β finds the location of the first matching objectobjin a list of attributesskπ the search starts at the position afterlastpos. if what you get back is positive, you can totally feed it into the next call toX509at_get_attr_by_OBJ()as the value oflastposso you can iterate through all the remaining attributes, slay. andlastposcan be set to any negative value on that first call, which makes the search start from the very beginning of the list. main character search energy β¨X509at_get_attr_by_NID()β same situation asX509at_get_attr_by_OBJ()except it passes the numerical identifier (NID)nidthat's associated with the object π« see<openssl/obj_mac.h>for the list ofNID_*.X509at_get_attr()β returns theX509_ATTRIBUTEobject sitting at indexlocin the list of attributesxπlocshould be in the range from0toX509at_get_attr_count() - 1.X509at_delete_attr()β removes theX509_ATTRIBUTEobject at indexlocin the list of attributesxποΈ bye bestie.X509at_add1_attr()β pushes a copy of theX509_ATTRIBUTEobject you pass in onto the listxπ«Ά bothxandattrmust be non NULL or an error will occur, so like, don't be messy. if*xis NULL then a brand new list gets created, otherwise it uses the list you passed in. and heads up: an error will occur if an existing attribute (with the same attribute type) already exists in the attribute list πX509at_add1_attr_by_OBJ()β creates a newX509_ATTRIBUTEusingX509_ATTRIBUTE_set1_object()andX509_ATTRIBUTE_set1_data()to assign a newobjwith typetypeand databytesof lengthlen, and then pushes it onto the attribute listxπ bothxandattrmust be non NULL or an error will occur. if*xis NULL then a new attribute list is created. ifobjalready exists in the attribute list then an error occurs, periodt. πX509at_add1_attr_by_NID()β same asX509at_add1_attr_by_OBJ()except it passes the numerical identifier (NID)nidassociated with the object. see<openssl/obj_mac.h>for a list ofNID_*π¦X509at_add1_attr_by_txt()β same asX509at_add1_attr_by_OBJ()except it passes a nameattrnameassociated with the object. see<openssl/obj_mac.h>for a list ofSN_*names πΈX509_ATTRIBUTE_set1_object()β assigns anASN1_OBJECTobjto the attributeattrπ ifattralready contained an existingASN1_OBJECTthen that one gets freed, rip. an error occurs if eitherattrorobjare NULL, or if theobjyou passed in cannot be duplicated.X509_ATTRIBUTE_set1_data()β pushes a newASN1_TYPEobject onto theattrattributes list π₯ the new object is assigned a copy of the data indataof sizelen. okay so ifattrtypehas the flagMBSTRING_FLAGset, then a table lookup using theattrattributes NID is used to set anASN1_STRINGusingASN1_STRING_set_by_NID(), and thedatayou passed in must be in the format required for that object type or an error will occur β no improvising. iflenis not-1then internallyASN1_STRING_type_new()is used with theattrtypeyou passed in. and ifattrtypeis0, the call does literally nothing except return1πX509_ATTRIBUTE_create()β creates a newX509_ATTRIBUTEusingnidto set theASN1_OBJECTOID and theatrtypeandvalueto set theASN1_TYPEβ¨X509_ATTRIBUTE_create_by_OBJ()β usesX509_ATTRIBUTE_set1_object()andX509_ATTRIBUTE_set1_data()to assign a newobjwith typeatrtypeand datadataof lengthlenπ«Ά if the attribute you passed in,attrOR*attr, is NULL then a newX509_ATTRIBUTEwill be returned, otherwise theX509_ATTRIBUTEyou passed in gets used. and note this bestie: theASN1_OBJECTobjis pushed onto the attributes existing list of objects, which could be an issue if the attributes<ASN1_OBJECT>was different π¬ lowkey a trap.X509_ATTRIBUTE_create_by_NID()β same asX509_ATTRIBUTE_create_by_OBJ()except that it passes the numerical identifier (NID)nidassociated with the object. see<openssl/obj_mac.h>for a list ofNID_*πX509_ATTRIBUTE_create_by_txt()β same asX509_ATTRIBUTE_create_by_OBJ()except that it passes a nameatrnameassociated with the object. see<openssl/obj_mac.h>for a list ofSN_*names π§X509_ATTRIBUTE_count()β returns the number ofASN1_TYPEobjects in an attributeattrπ’ count 'em.X509_ATTRIBUTE_get0_type()β returns theASN1_TYPEobject at indexidxin the attribute listattrπidxshould be in the range of0toX509_ATTRIBUTE_count() - 1or an error will occur, so stay in your lane.X509_ATTRIBUTE_get0_data()β returns the data of anASN1_TYPEobject at indexidxin the attributeattrπdatais unused and can be set to NULL, it's just there for the vibes. an error will occur if the attribute typeatrtypedoes not match the type of theASN1_TYPEobject at indexidxOR ifatrtypeis eitherV_ASN1_BOOLEANorV_ASN1_NULLOR if theidxis not in the range0toX509_ATTRIBUTE_count() - 1. three ways to fail, pick your fighter πX509at_get0_data_by_OBJ()β finds the first attribute in an attribute listxthat matches theobj, starting at indexlastpos, and returns the data retrieved from the found attribute's firstASN1_TYPEobject π₯ an error will occur if the attribute typetypedoes not match the type of theASN1_TYPEobject OR iftypeis eitherV_ASN1_BOOLEANorV_ASN1_NULLOR if the attribute is not found. also iflastposis less than-1then an error will occur if there are multiple objects in the listxthat matchobj. and iflastposis less than-2then an error will occur if there is more than oneASN1_TYPEobject in the found attribute. so like, very strict. very demure. very mindful. π
okay warning bestie: thoseV_ASN1_BOOLEANandV_ASN1_NULLcases are real and they will bite you. it's not a maybe. π
π RETURN VALUES π
okay bestie, this is the part where we find out what you actually get back from each of these, so pay attention, this is giving important π
X509at_get_attr_count()β hands you the number of attributes chillin' in the listx, or-1ifxisNULL. like if you passed nothing, you get nothing back, but with a minus sign for drama πX509at_get_attr_by_OBJ()β returns-1if the list is empty OR the object just isn't in there (rude, honestly). otherwise it returns the location of the object in the list. so-1means "nope, not here" twice over, and you literally cannot tell which one it was, that's just the vibe π«ΆX509at_get_attr_by_NID()β same energy asX509at_get_attr_by_OBJ(), except it returns-2if thenidisn't even known by OpenSSL. so like,-2is "girl what nid is that, never heard of her" πX509at_get_attr()β returns either anX509_ATTRIBUTEorNULLif there's an error. simple. clean. iconic.X509at_delete_attr()β returns either the removedX509_ATTRIBUTEorNULLif there's an error. it hands you the thing it just deleted, which is lowkey iconic behavior β¨X509_ATTRIBUTE_count()β returns-1on error, otherwise the number ofASN1_TYPEelements. yes bestie,-1is the error girl again, she's everywhere πX509_ATTRIBUTE_get0_type()β returnsNULLon error, otherwise anASN1_TYPEobject.NULL= something went wrong, no cap.X509_ATTRIBUTE_get0_data()β returnsNULLif an error occurs, otherwise it gives you the data associated with anASN1_TYPEobject. the actual payload, the juicy part πX509_ATTRIBUTE_set1_object()andX509_ATTRIBUTE_set1_data()β return1on success, or0otherwise. classic 1-or-0 binary situation, no in-between, no nuance πΈX509_ATTRIBUTE_create(),X509_ATTRIBUTE_create_by_OBJ(),X509_ATTRIBUTE_create_by_NID()andX509_ATTRIBUTE_create_by_txt()β return either anX509_ATTRIBUTEon success, orNULLif there's an error. make it, or don't π¦X509at_add1_attr(),X509at_add1_attr_by_OBJ(),X509at_add1_attr_by_NID()andX509at_add1_attr_by_txt()β returnNULLon error, otherwise you get back a list ofX509_ATTRIBUTE. note theNULLhere means error, not "empty", don't get it twisted πX509at_get0_data_by_OBJ()β returns the data retrieved from the found attribute's firstASN1_TYPEobject, orNULLif an error occurs. first one, bestie, not all of them, just the first π
pro tip from me to you: the negative numbers in this section are not vibes, they're error codes.-1and-2are doing a lot of heavy lifting here and you gotta know which function returns which. memorize the chart, slay the day π
π₯ SEE ALSO π₯
go read these next, they're all in the group chat:
ASN1_TYPE_get(3)ASN1_INTEGER_get(3)ASN1_ENUMERATED_get(3)ASN1_STRING_get0_data(3)ASN1_STRING_length(3)ASN1_STRING_type(3)X509_REQ_get_attr(3)EVP_PKEY_get_attr(3)CMS_signed_get_attr(3)PKCS8_pkey_get0_attrs(3)
π COPYRIGHT π
Copyright 2023-2026 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>.
and that's a wrap on X509_ATTRIBUTE(3SSL) bestie!! this whole thing was 4.0.3, dated 2026-09-29, and you absolutely ate reading all of it πβ¨π go forth and get your attribute data, you main character π«Άπβ
π¦ where this page comes from
- ubuntu stonking: libssl-doc 4.0.3-1ubuntu1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms