Document another batch of functions.

This covers most of the ASN.1 time functions and a handful more of
x509.h. Also remove some code under #if 0.

I'm running out of a easy ones to do, which is probably a good thing.

Change-Id: I085b1e2a54d191a7a5f18c801b3c135cfda7bd88
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48665
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c
index 15c9409..ad7f784 100644
--- a/crypto/asn1/a_time.c
+++ b/crypto/asn1/a_time.c
@@ -200,7 +200,7 @@
     return 0;
 }
 
-int ASN1_TIME_diff(int *pday, int *psec,
+int ASN1_TIME_diff(int *out_days, int *out_seconds,
                    const ASN1_TIME *from, const ASN1_TIME *to)
 {
     struct tm tm_from, tm_to;
@@ -208,5 +208,5 @@
         return 0;
     if (!asn1_time_to_tm(&tm_to, to))
         return 0;
-    return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
+    return OPENSSL_gmtime_diff(out_days, out_seconds, &tm_from, &tm_to);
 }
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c
index 28f07ac..21ea2cc 100644
--- a/crypto/asn1/a_utctm.c
+++ b/crypto/asn1/a_utctm.c
@@ -262,42 +262,3 @@
         return -1;
     return 0;
 }
-
-#if 0
-time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
-{
-    struct tm tm;
-    int offset;
-
-    OPENSSL_memset(&tm, '\0', sizeof tm);
-
-# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
-    tm.tm_year = g2(s->data);
-    if (tm.tm_year < 50)
-        tm.tm_year += 100;
-    tm.tm_mon = g2(s->data + 2) - 1;
-    tm.tm_mday = g2(s->data + 4);
-    tm.tm_hour = g2(s->data + 6);
-    tm.tm_min = g2(s->data + 8);
-    tm.tm_sec = g2(s->data + 10);
-    if (s->data[12] == 'Z')
-        offset = 0;
-    else {
-        offset = g2(s->data + 13) * 60 + g2(s->data + 15);
-        if (s->data[12] == '-')
-            offset = -offset;
-    }
-# undef g2
-
-    return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
-                                       * timezone instead of UTC, and unless
-                                       * we rewrite OpenSSL in Lisp we cannot
-                                       * locally change the timezone without
-                                       * possibly interfering with other
-                                       * parts of the program. timegm, which
-                                       * uses UTC, is non-standard. Also
-                                       * time_t is inappropriate for general
-                                       * UTC times because it may a 32 bit
-                                       * type. */
-}
-#endif
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 5ed4edd..6aee451 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1976,9 +1976,9 @@
     return ret;
 }
 
-ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
+ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec)
 {
-    return X509_time_adj(s, adj, NULL);
+    return X509_time_adj(s, offset_sec, NULL);
 }
 
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index db467fd..42f24c8 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -452,6 +452,135 @@
 // TODO(davidben): Expand and document function prototypes generated in macros.
 
 
+// Time.
+//
+// GeneralizedTime and UTCTime values are represented as |ASN1_STRING|s. The
+// type field is |V_ASN1_GENERALIZEDTIME| or |V_ASN1_UTCTIME|, respectively. The
+// data field contains the DER encoding of the value. For example, the UNIX
+// epoch would be "19700101000000Z" for a GeneralizedTime and "700101000000Z"
+// for a UTCTime.
+//
+// ASN.1 does not define how to interpret UTCTime's two-digit year. RFC5280
+// defines it as a range from 1950 to 2049 for X.509. The library uses the
+// RFC5280 interpretation. It does not currently enforce the restrictions from
+// BER, and the additional restrictions from RFC5280, but future versions may.
+// Callers should not rely on fractional seconds and non-UTC time zones.
+//
+// The |ASN1_TIME| typedef represents the X.509 Time type, which is a CHOICE of
+// GeneralizedTime and UTCTime, using UTCTime when the value is in range.
+
+// ASN1_UTCTIME_check returns one if |a| is a valid UTCTime and zero otherwise.
+OPENSSL_EXPORT int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
+
+// ASN1_UTCTIME_set represents |t| as a UTCTime and writes the result to |s|. It
+// returns |s| on success and NULL on error. If |s| is NULL, it returns a
+// newly-allocated |ASN1_UTCTIME| instead.
+//
+// Note this function may fail if the time is out of range for UTCTime.
+OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
+
+// ASN1_UTCTIME_adj adds |offset_day| days and |offset_sec| seconds to |t| and
+// writes the result to |s| as a UTCTime. It returns |s| on success and NULL on
+// error. If |s| is NULL, it returns a newly-allocated |ASN1_UTCTIME| instead.
+//
+// Note this function may fail if the time overflows or is out of range for
+// UTCTime.
+OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
+                                              int offset_day, long offset_sec);
+
+// ASN1_UTCTIME_set_string sets |s| to a UTCTime whose contents are a copy of
+// |str|. It returns one on success and zero on error or if |str| is not a valid
+// UTCTime.
+//
+// If |s| is NULL, this function validates |str| without copying it.
+OPENSSL_EXPORT int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+
+// ASN1_UTCTIME_cmp_time_t compares |s| to |t|. It returns -1 if |s| < |t|, 0 if
+// they are equal, 1 if |s| > |t|, and -2 on error.
+OPENSSL_EXPORT int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+
+// ASN1_GENERALIZEDTIME_check returns one if |a| is a valid GeneralizedTime and
+// zero otherwise.
+OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
+
+// ASN1_GENERALIZEDTIME_set represents |t| as a GeneralizedTime and writes the
+// result to |s|. It returns |s| on success and NULL on error. If |s| is NULL,
+// it returns a newly-allocated |ASN1_GENERALIZEDTIME| instead.
+//
+// Note this function may fail if the time is out of range for GeneralizedTime.
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(
+    ASN1_GENERALIZEDTIME *s, time_t t);
+
+// ASN1_GENERALIZEDTIME_adj adds |offset_day| days and |offset_sec| seconds to
+// |t| and writes the result to |s| as a GeneralizedTime. It returns |s| on
+// success and NULL on error. If |s| is NULL, it returns a newly-allocated
+// |ASN1_GENERALIZEDTIME| instead.
+//
+// Note this function may fail if the time overflows or is out of range for
+// GeneralizedTime.
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(
+    ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, long offset_sec);
+
+// ASN1_GENERALIZEDTIME_set_string sets |s| to a GeneralizedTime whose contents
+// are a copy of |str|. It returns one on success and zero on error or if |str|
+// is not a valid GeneralizedTime.
+//
+// If |s| is NULL, this function validates |str| without copying it.
+OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
+                                                   const char *str);
+
+// ASN1_TIME_diff computes |to| - |from|. On success, it sets |*out_days| to the
+// difference in days, rounded towards zero, sets |*out_seconds| to the
+// remainder, and returns one. On error, it returns zero.
+//
+// If |from| is before |to|, both outputs will be <= 0, with at least one
+// negative. If |from| is after |to|, both will be >= 0, with at least one
+// positive. If they are equal, ignoring fractional seconds, both will be zero.
+//
+// Note this function may fail on overflow, or if |from| or |to| cannot be
+// decoded.
+OPENSSL_EXPORT int ASN1_TIME_diff(int *out_days, int *out_seconds,
+                                  const ASN1_TIME *from, const ASN1_TIME *to);
+
+// ASN1_TIME_set represents |t| as a GeneralizedTime or UTCTime and writes
+// the result to |s|. As in RFC5280, section 4.1.2.5, it uses UTCTime when the
+// time fits and GeneralizedTime otherwise. It returns |s| on success and NULL
+// on error. If |s| is NULL, it returns a newly-allocated |ASN1_TIME| instead.
+//
+// Note this function may fail if the time is out of range for GeneralizedTime.
+OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
+
+// ASN1_TIME_adj adds |offset_day| days and |offset_sec| seconds to
+// |t| and writes the result to |s|. As in RFC5280, section 4.1.2.5, it uses
+// UTCTime when the time fits and GeneralizedTime otherwise. It returns |s| on
+// success and NULL on error. If |s| is NULL, it returns a newly-allocated
+// |ASN1_GENERALIZEDTIME| instead.
+//
+// Note this function may fail if the time overflows or is out of range for
+// GeneralizedTime.
+OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day,
+                                        long offset_sec);
+
+// ASN1_TIME_check returns one if |t| is a valid UTCTime or GeneralizedTime, and
+// zero otherwise. |t|'s type determines which check is performed. This
+// function does not enforce that UTCTime was used when possible.
+OPENSSL_EXPORT int ASN1_TIME_check(const ASN1_TIME *t);
+
+// ASN1_TIME_to_generalizedtime converts |t| to a GeneralizedTime. If |out| is
+// NULL, it returns a newly-allocated |ASN1_GENERALIZEDTIME| on success, or NULL
+// on error. If |out| is non-NULL and |*out| is NULL, it additionally sets
+// |*out| to the result. If |out| and |*out| are non-NULL, it instead updates
+// the object pointed by |*out| and returns |*out| on success or NULL on error.
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(
+    const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
+
+// ASN1_TIME_set_string behaves like |ASN1_UTCTIME_set_string| if |str| is a
+// valid UTCTime, and |ASN1_GENERALIZEDTIME_set_string| if |str| is a valid
+// GeneralizedTime. If |str| is neither, it returns zero.
+OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
+
+// TODO(davidben): Expand and document function prototypes generated in macros.
+
 
 // Arbitrary elements.
 
@@ -924,26 +1053,6 @@
 
 DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
 
-OPENSSL_EXPORT int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
-OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
-OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
-                                              int offset_day, long offset_sec);
-OPENSSL_EXPORT int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
-OPENSSL_EXPORT int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
-#if 0
-time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
-#endif
-
-OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
-OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(
-    ASN1_GENERALIZEDTIME *s, time_t t);
-OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(
-    ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, long offset_sec);
-OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
-                                                   const char *str);
-OPENSSL_EXPORT int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
-                                  const ASN1_TIME *to);
-
 DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
 OPENSSL_EXPORT ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(
     const ASN1_OCTET_STRING *a);
@@ -970,14 +1079,6 @@
 DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
 DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
 
-OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
-OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day,
-                                        long offset_sec);
-OPENSSL_EXPORT int ASN1_TIME_check(const ASN1_TIME *t);
-OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(
-    const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
-OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
-
 OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a);
 OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a);
 OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a);
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index dafa677..8c5e471 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -860,12 +860,37 @@
 OPENSSL_EXPORT int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
                                       size_t *pderlen);
 
+// X509_cmp_time compares |s| against |*t|. On success, it returns a negative
+// number if |s| <= |*t| and a positive number if |s| > |*t|. On error, it
+// returns zero. If |t| is NULL, it uses the current time instead of |*t|.
+//
+// WARNING: Unlike most comparison functions, this function returns zero on
+// error, not equality.
 OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t);
+
+// X509_cmp_current_time behaves like |X509_cmp_time| but compares |s| against
+// the current time.
 OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s);
-OPENSSL_EXPORT ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+
+// X509_time_adj calls |X509_time_adj_ex| with |offset_day| equal to zero.
+OPENSSL_EXPORT ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec,
+                                        time_t *t);
+
+// X509_time_adj_ex behaves like |ASN1_TIME_adj|, but adds an offset to |*t|. If
+// |t| is NULL, it uses the current time instead of |*t|.
+//
+// TODO(davidben): This isn't quite right. If |s| is non-NULL and lacks the
+// |ASN1_STRING_FLAG_MSTRING| flag, it tries to preserve |s|'s current time
+// (UTCTime or GeneralizedTime), rather than implementing the RFC5280 CHOICE
+// type. Remove this behavior and then the flag. Whether |s| has the flag is
+// mostly an accident of it was constructed. Meanwhile, callers should use
+// |ASN1_TIME_adj|, which does the same thing without this quirk.
 OPENSSL_EXPORT ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day,
                                            long offset_sec, time_t *t);
-OPENSSL_EXPORT ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+// X509_gmtime_adj behaves like |X509_time_adj_ex| but adds |offset_sec| to the
+// current time.
+OPENSSL_EXPORT ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec);
 
 OPENSSL_EXPORT const char *X509_get_default_cert_area(void);
 OPENSSL_EXPORT const char *X509_get_default_cert_dir(void);
@@ -882,7 +907,15 @@
 
 DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
 
+// X509_PUBKEY_set serializes |pkey| into a newly-allocated |X509_PUBKEY|
+// structure. On success, it frees |*x|, sets |*x| to the new object, and
+// returns one. Otherwise, it returns zero.
 OPENSSL_EXPORT int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+
+// X509_PUBKEY_get decodes the public key in |key| and returns an |EVP_PKEY| on
+// success, or NULL on error. The caller must release the result with
+// |EVP_PKEY_free| when done. The |EVP_PKEY| is cached in |key|, so callers must
+// not mutate the result.
 OPENSSL_EXPORT EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key);
 
 DECLARE_ASN1_FUNCTIONS(X509_SIG)
@@ -904,6 +937,8 @@
 
 DECLARE_ASN1_FUNCTIONS(X509_NAME)
 
+// X509_NAME_set makes a copy of |name|. On success, it frees |*xn|, sets |*xn|
+// to the copy, and returns one. Otherwise, it returns zero.
 OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
 
 DECLARE_ASN1_FUNCTIONS(X509_CINF)