From 116d9250a996c6627bda53b7f1e4cba503785b86 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sun, 1 Aug 2021 15:10:08 -0400 Subject: 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 Commit-Queue: Adam Langley --- include/openssl/asn1.h | 157 ++++++++++++++++++++++++++++++++++++++++--------- include/openssl/x509.h | 39 +++++++++++- 2 files changed, 166 insertions(+), 30 deletions(-) (limited to 'include') 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 @@ OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, // 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 @@ OPENSSL_EXPORT ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x); 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_UTCTIME) 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_ENTRY_set(const X509_NAME_ENTRY *ne); 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_VAL) 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_ENTRY) 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) -- cgit v1.1