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);