Document a batch of extension-related functions in x509.h. Change-Id: Iaa5971f6a09a4267be95ea1820b72f7b619b53e1 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48366 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 7484000..e7e6227 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c
@@ -74,12 +74,15 @@ int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, int lastpos) { - const ASN1_OBJECT *obj; - - obj = OBJ_nid2obj(nid); - if (obj == NULL) - return (-2); - return (X509at_get_attr_by_OBJ(x, obj, lastpos)); + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + /* TODO(davidben): Return -1 here. Callers often check the result + * against -1 without handling a theoretical -2 output. Reporting a + * different result should not be necessary because invalid NIDs are + * almost always a programmer error. */ + return -2; + } + return X509at_get_attr_by_OBJ(x, obj, lastpos); } int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 91bf024..d2a51c0 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c
@@ -72,12 +72,15 @@ int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, int lastpos) { - const ASN1_OBJECT *obj; - - obj = OBJ_nid2obj(nid); - if (obj == NULL) - return (-2); - return (X509v3_get_ext_by_OBJ(x, obj, lastpos)); + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + /* TODO(davidben): Return -1 here. Callers often check the result + * against -1 without handling a theoretical -2 output. Reporting a + * different result should not be necessary because invalid NIDs are + * almost always a programmer error. */ + return -2; + } + return X509v3_get_ext_by_OBJ(x, obj, lastpos); } int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, @@ -172,11 +175,9 @@ err: OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); err2: - if (new_ex != NULL) - X509_EXTENSION_free(new_ex); - if (sk != NULL) - sk_X509_EXTENSION_free(sk); - return (NULL); + X509_EXTENSION_free(new_ex); + sk_X509_EXTENSION_free(sk); + return NULL; } X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
diff --git a/include/openssl/x509.h b/include/openssl/x509.h index beeed91..564d102 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h
@@ -1480,28 +1480,90 @@ const X509_NAME_ENTRY *ne); OPENSSL_EXPORT ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne); +// X509v3_get_ext_count returns the number of extensions in |x|. OPENSSL_EXPORT int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); + +// X509v3_get_ext_by_NID returns the index of the first extension in |x| with +// type |nid|, or a negative number if not found. If found, callers can use +// |X509v3_get_ext| to look up the extension by index. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching extensions by first passing -1 and then +// passing the previously-returned value until no match is returned. OPENSSL_EXPORT int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, int lastpos); + +// X509v3_get_ext_by_OBJ behaves like |X509v3_get_ext_by_NID| but looks for +// extensions matching |obj|. OPENSSL_EXPORT int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, const ASN1_OBJECT *obj, int lastpos); + +// X509v3_get_ext_by_critical returns the index of the first extension in |x| +// whose critical bit matches |crit|, or a negative number if no such extension +// was found. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching extensions by first passing -1 and then +// passing the previously-returned value until no match is returned. OPENSSL_EXPORT int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, int crit, int lastpos); + +// X509v3_get_ext returns the extension in |x| at index |loc|, or NULL if |loc| +// is out of bounds. OPENSSL_EXPORT X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); + +// X509v3_delete_ext removes the extension in |x| at index |loc| and returns the +// removed extension, or NULL if |loc| was out of bounds. If an extension was +// returned, the caller must release it with |X509_EXTENSION_free|. OPENSSL_EXPORT X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); + +// X509v3_add_ext adds a copy of |ex| to the extension list in |*x|. If |*x| is +// NULL, it allocates a new |STACK_OF(X509_EXTENSION)| to hold the copy and sets +// |*x| to the new list. It returns |*x| on success and NULL on error. The +// caller retains ownership of |ex| and can release it independently of |*x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509v3_add_ext( STACK_OF(X509_EXTENSION) **x, X509_EXTENSION *ex, int loc); +// X509_get_ext_count returns the number of extensions in |x|. OPENSSL_EXPORT int X509_get_ext_count(const X509 *x); + +// X509_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches for +// extensions in |x|. OPENSSL_EXPORT int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); + +// X509_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches for +// extensions in |x|. OPENSSL_EXPORT int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos); + +// X509_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| but +// searches for extensions in |x|. OPENSSL_EXPORT int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos); + +// X509_get_ext returns the extension in |x| at index |loc|, or NULL if |loc| is +// out of bounds. OPENSSL_EXPORT X509_EXTENSION *X509_get_ext(const X509 *x, int loc); + +// X509_delete_ext removes the extension in |x| at index |loc| and returns the +// removed extension, or NULL if |loc| was out of bounds. If non-NULL, the +// caller must release the result with |X509_EXTENSION_free|. It is also safe, +// but not necessary, to call |X509_EXTENSION_free| if the result is NULL. OPENSSL_EXPORT X509_EXTENSION *X509_delete_ext(X509 *x, int loc); + +// X509_add_ext adds a copy of |ex| to |x|. It returns one on success and zero +// on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. OPENSSL_EXPORT int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); // X509_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the extension in @@ -1521,15 +1583,41 @@ OPENSSL_EXPORT int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags); +// X509_CRL_get_ext_count returns the number of extensions in |x|. OPENSSL_EXPORT int X509_CRL_get_ext_count(const X509_CRL *x); + +// X509_CRL_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches for +// extensions in |x|. OPENSSL_EXPORT int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos); + +// X509_CRL_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches for +// extensions in |x|. OPENSSL_EXPORT int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, int lastpos); + +// X509_CRL_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| but +// searches for extensions in |x|. OPENSSL_EXPORT int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos); + +// X509_CRL_get_ext returns the extension in |x| at index |loc|, or NULL if +// |loc| is out of bounds. OPENSSL_EXPORT X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); + +// X509_CRL_delete_ext removes the extension in |x| at index |loc| and returns +// the removed extension, or NULL if |loc| was out of bounds. If non-NULL, the +// caller must release the result with |X509_EXTENSION_free|. It is also safe, +// but not necessary, to call |X509_EXTENSION_free| if the result is NULL. OPENSSL_EXPORT X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); + +// X509_CRL_add_ext adds a copy of |ex| to |x|. It returns one on success and +// zero on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. OPENSSL_EXPORT int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); // X509_CRL_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the @@ -1549,18 +1637,45 @@ OPENSSL_EXPORT int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, unsigned long flags); +// X509_REVOKED_get_ext_count returns the number of extensions in |x|. OPENSSL_EXPORT int X509_REVOKED_get_ext_count(const X509_REVOKED *x); + +// X509_REVOKED_get_ext_by_NID behaves like |X509v3_get_ext_by_NID| but searches +// for extensions in |x|. OPENSSL_EXPORT int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos); + +// X509_REVOKED_get_ext_by_OBJ behaves like |X509v3_get_ext_by_OBJ| but searches +// for extensions in |x|. OPENSSL_EXPORT int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, int lastpos); + +// X509_REVOKED_get_ext_by_critical behaves like |X509v3_get_ext_by_critical| +// but searches for extensions in |x|. OPENSSL_EXPORT int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos); + +// X509_REVOKED_get_ext returns the extension in |x| at index |loc|, or NULL if +// |loc| is out of bounds. OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc); + +// X509_REVOKED_delete_ext removes the extension in |x| at index |loc| and +// returns the removed extension, or NULL if |loc| was out of bounds. If +// non-NULL, the caller must release the result with |X509_EXTENSION_free|. It +// is also safe, but not necessary, to call |X509_EXTENSION_free| if the result +// is NULL. OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); + +// X509_REVOKED_add_ext adds a copy of |ex| to |x|. It returns one on success +// and zero on failure. The caller retains ownership of |ex| and can release it +// independently of |x|. +// +// The new extension is inserted at index |loc|, shifting extensions to the +// right. If |loc| is -1 or out of bounds, the new extension is appended to the +// list. OPENSSL_EXPORT int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); @@ -1583,40 +1698,106 @@ void *value, int crit, unsigned long flags); +// X509_EXTENSION_create_by_NID creates a new |X509_EXTENSION| with type |nid|, +// value |data|, and critical bit |crit|. It returns the newly-allocated +// |X509_EXTENSION| on success, and false on error. |nid| should be a |NID_*| +// constant. +// +// If |ex| and |*ex| are both non-NULL, it modifies and returns |*ex| instead of +// creating a new object. If |ex| is non-NULL, but |*ex| is NULL, it sets |*ex| +// to the new |X509_EXTENSION|, in addition to returning the result. OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_NID( X509_EXTENSION **ex, int nid, int crit, const ASN1_OCTET_STRING *data); + +// X509_EXTENSION_create_by_OBJ behaves like |X509_EXTENSION_create_by_NID|, but +// the extension type is determined by an |ASN1_OBJECT|. OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_OBJ( X509_EXTENSION **ex, const ASN1_OBJECT *obj, int crit, const ASN1_OCTET_STRING *data); + +// X509_EXTENSION_set_object sets |ex|'s extension type to |obj|. It returns one +// on success and zero on error. OPENSSL_EXPORT int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj); + +// X509_EXTENSION_set_critical sets |ex| to critical if |crit| is non-zero and +// to non-critical if |crit| is zero. OPENSSL_EXPORT int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); + +// X509_EXTENSION_set_data set's |ex|'s extension value to a copy of |data|. It +// returns one on success and zero on error. OPENSSL_EXPORT int X509_EXTENSION_set_data(X509_EXTENSION *ex, const ASN1_OCTET_STRING *data); + +// X509_EXTENSION_get_object returns |ex|'s extension type. OPENSSL_EXPORT ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); + +// X509_EXTENSION_get_data returns |ne|'s extension value. OPENSSL_EXPORT ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); + +// X509_EXTENSION_get_critical returns one if |ex| is critical and zero +// otherwise. OPENSSL_EXPORT int X509_EXTENSION_get_critical(X509_EXTENSION *ex); +// X509at_get_attr_count returns the number of attributes in |x|. OPENSSL_EXPORT int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); + +// X509at_get_attr_by_NID returns the index of the attribute in |x| of type +// |nid|, or a negative number if not found. If found, callers can use +// |X509at_get_attr| to look up the attribute by index. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching attributes by first passing -1 and then +// passing the previously-returned value until no match is returned. OPENSSL_EXPORT int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, int lastpos); + +// X509at_get_attr_by_OBJ behaves like |X509at_get_attr_by_NID| but looks for +// attributes of type |obj|. OPENSSL_EXPORT int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj, int lastpos); + +// X509at_get_attr returns the attribute at index |loc| in |x|, or NULL if +// out of bounds. OPENSSL_EXPORT X509_ATTRIBUTE *X509at_get_attr( const STACK_OF(X509_ATTRIBUTE) *x, int loc); + +// X509at_delete_attr removes the attribute at index |loc| in |x|. It returns +// the removed attribute to the caller, or NULL if |loc| was out of bounds. If +// non-NULL, the caller must release the result with |X509_ATTRIBUTE_free| when +// done. It is also safe, but not necessary, to call |X509_ATTRIBUTE_free| if +// the result is NULL. OPENSSL_EXPORT X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); + +// X509at_add1_attr appends a copy of |attr| to the attribute list in |*x|. If +// |*x| is NULL, it allocates a new |STACK_OF(X509_ATTRIBUTE)| to hold the copy +// and sets |*x| to the new list. It returns |*x| on success and NULL on error. +// The caller retains ownership of |attr| and can release it independently of +// |*x|. OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr( STACK_OF(X509_ATTRIBUTE) **x, X509_ATTRIBUTE *attr); + +// X509at_add1_attr_by_OBJ behaves like |X509at_add1_attr|, but adds an +// attribute created by |X509_ATTRIBUTE_create_by_OBJ|. OPENSSL_EXPORT 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); + +// X509at_add1_attr_by_NID behaves like |X509at_add1_attr|, but adds an +// attribute created by |X509_ATTRIBUTE_create_by_NID|. OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID( STACK_OF(X509_ATTRIBUTE) **x, int nid, int type, const unsigned char *bytes, int len); + +// X509at_add1_attr_by_txt behaves like |X509at_add1_attr|, but adds an +// attribute created by |X509_ATTRIBUTE_create_by_txt|. OPENSSL_EXPORT 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); + +// TODO(davidben): Document or remove this function. The behavior of |lastpos| +// is complex. OPENSSL_EXPORT void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, ASN1_OBJECT *obj, int lastpos, int type);