ASN1_TIME_SET(3)

πŸ“¦
version 4.1.0 Β· 3 versions
, in opensuse-leap 16.0

✨ NAME ✨

okay so this is the ASN1_TIME_SET(3) page, and it's literally the whole squad of ASN.1 Time functions. we're talking ASN1_TIME_set, ASN1_UTCTIME_set, ASN1_GENERALIZEDTIME_set, ASN1_TIME_adj, ASN1_UTCTIME_adj, ASN1_GENERALIZEDTIME_adj, ASN1_TIME_set_string, ASN1_TIME_set_string_X509, ASN1_UTCTIME_set_string, ASN1_GENERALIZEDTIME_set_string, ASN1_TIME_normalize, ASN1_TIME_check, ASN1_UTCTIME_check, ASN1_GENERALIZEDTIME_check, ASN1_TIME_print, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print, ASN1_TIME_to_tm, ASN1_TIME_diff, ASN1_TIME_cmp_time_t, ASN1_UTCTIME_cmp_time_t, ASN1_TIME_compare, ASN1_TIME_to_generalizedtime, OPENSSL_gmtime, OPENSSL_timegm, OPENSSL_posix_to_tm, OPENSSL_tm_to_posix β€” all the ASN.1 Time functions. iykyk πŸ’…

🌈 SYNOPSIS 🌈

bestie, here's the whole signature lineup, copy-paste exact, no cap:

       #include <openssl/asn1.h>

       ASN1_TIME *
       ASN1_TIME_set(ASN1_TIME *s, time_t t);

       ASN1_UTCTIME *
       ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);

       ASN1_GENERALIZEDTIME *
       ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t);

       ASN1_TIME *
       ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec);

       ASN1_UTCTIME *
       ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day,
           long offset_sec);

       ASN1_GENERALIZEDTIME *
       ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t,
           int offset_day, long offset_sec);

       int
       ASN1_TIME_set_string(ASN1_TIME *s, const char *str);

       int
       ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);

       int
       ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);

       int
       ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
           const char *str);

       int
       ASN1_TIME_normalize(ASN1_TIME *s);

       int
       ASN1_TIME_check(const ASN1_TIME *t);

       int
       ASN1_UTCTIME_check(const ASN1_UTCTIME *t);

       int
       ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *t);

       int
       ASN1_TIME_print(BIO *b, const ASN1_TIME *s);

       int
       ASN1_UTCTIME_print(BIO *b, const ASN1_UTCTIME *s);

       int
       ASN1_GENERALIZEDTIME_print(BIO *b, const ASN1_GENERALIZEDTIME *s);

       int
       ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);

       int
       ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
           const ASN1_TIME *to);

       int
       ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);

       int
       ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);

       int
       ASN1_TIME_compare(const ASN1_TIME *s, const ASN1_TIME *t);

       ASN1_GENERALIZEDTIME *
       ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
           ASN1_GENERALIZEDTIME **out);

and then the crypto/posix besties:

       #include <openssl/crypto.h>

       struct tm *
       OPENSSL_gmtime(const time_t *time, struct tm *out_tm);
       #include <openssl/posix_time.h>

       int
       OPENSSL_timegm(const struct tm *tm, time_t *out_time);

       int
       OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm);

       int
       OPENSSL_tm_to_posix(struct tm *t_tm, int64_t *out);

πŸ’– DESCRIPTION πŸ’–

okay so picture this: an ASN1_TIME object is basically a shallow wrapper around a string that holds an ASN.1 Time value in the restricted format that's valid in X.509 certificates. it's giving "string but make it cert-legal" πŸ’…

so an ASN1_TIME object is either an ASN1_UTCTIME object containing a string of the format YYMMDDHHMMSSZ which is valid for the years 1950 to 2049, or an ASN1_GENERALIZEDTIME object containing a string of the format YYYYMMDDHHMMSSZ which is valid for the years 0000 to 1949 and 2050 to 9999. in both cases, the mandatory suffix Z represents the GMT time zone.

LibreSSL by design does not support the full syntax of ASN.1 times. in particular, it neither supports fractional seconds nor any other time zone. so don't come for her with your fancy nanoseconds, bestie 😭

now the functions, let's go:

  • ASN1_TIME_set(), ASN1_UTCTIME_set(), and ASN1_GENERALIZEDTIME_set() β€” set the time object s to the time represented by the time_t value t. if s is NULL, a new time object is allocated and returned. iconic.
  • ASN1_TIME_adj(), ASN1_UTCTIME_adj(), and ASN1_GENERALIZEDTIME_adj() β€” set the time object s to the time represented by the time offset_day and offset_sec after the time_t value t. the values of offset_day or offset_sec can be negative to set a time before t. the offset_sec value can also exceed the number of seconds in a day. if s is NULL, a new time object is allocated and returned. flexible queen.
  • ASN1_TIME_adj() may change the type from ASN1_GENERALIZEDTIME to ASN1_UTCTIME or vice versa depending on the resulting year. the functions ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_adj() do not modify the type of the return object. so know the difference, bestie.
  • ASN1_TIME_set_string(), ASN1_TIME_set_string_X509(), ASN1_UTCTIME_set_string(), and ASN1_GENERALIZEDTIME_set_string() β€” set the time object s to the time string str, which must be in appropriate ASN.1 time format: YYMMDDHHMMSSZ for ASN1_UTCTIME, YYYYMMDDHHMMSSZ for ASN1_GENERALIZEDTIME, or either of the two for ASN1_TIME. the string str is copied into s. if s is NULL, these functions only perform a format check on str.
  • in LibreSSL, ASN1_TIME_set_string() and ASN1_TIME_set_string_X509() behave identically and always set the time object to a valid value to use in an X.509 certificate. ASN1_GENERALIZEDTIME_set_string() may encode a time string that is not valid in an X.509 certificate. so watch out for that one πŸ‘€
  • ASN1_TIME_normalize() β€” converts an ASN1_GENERALIZEDTIME into a time value that can be used in a certificate by changing it to an ASN1_UTCTIME if possible. it has no effect on an ASN1_UTCTIME. glow-up function.
  • ASN1_TIME_check(), ASN1_UTCTIME_check(), and ASN1_GENERALIZEDTIME_check() β€” check the syntax of the time string contained in the object s. vibe check but for time strings ✨
  • ASN1_TIME_print(), ASN1_UTCTIME_print(), and ASN1_GENERALIZEDTIME_print() β€” print out the time s to BIO b in human readable format. it will be of the format MMM DD HH:MM:SS YYYY [GMT], for example "Feb 3 00:55:52 2015 GMT". it does not include a newline. if the time string has an invalid format, it prints out "Bad time value" and returns an error. no cap.
  • ASN1_TIME_to_tm() β€” converts the time s to the standard tm structure. if s is NULL, then the current time is converted. the output time is always in the GMT time zone. the tm_sec, tm_min, tm_hour, tm_mday, tm_mon, and tm_year fields of the tm structure are set to the proper values, whereas all other fields are set to 0. if tm is NULL, this function performs a format check on s only. main character energy.
  • ASN1_TIME_diff() β€” sets *pday and *psec to the time difference between from and to. if to represents a time later than from, then one or both (depending on the time difference) of *pday and *psec will be positive. if to represents a time earlier than from, then one or both of *pday and *psec will be negative. if to and from represent the same time, then *pday and *psec will both be zero. if both *pday and *psec are nonzero, they will always have the same sign. the value of *psec will always be less than the number of seconds in a day. if from or to is NULL, the current time is used. math but make it cute.
  • ASN1_TIME_cmp_time_t(), ASN1_UTCTIME_cmp_time_t(), and ASN1_TIME_compare() β€” compare the two times represented by s and t. who's earlier, who's later, we stan a comparison.
  • ASN1_TIME_to_generalizedtime() β€” converts the ASN1_TIME t to an ASN1_GENERALIZEDTIME, regardless of year. if either out or *out is NULL, then a new object is allocated and must be freed after use. don't forget to free, bestie, or it's a leak 😭
  • the ASN1_TIME, ASN1_UTCTIME, and ASN1_GENERALIZEDTIME objects are represented as ASN1_STRING objects internally and can be freed using ASN1_STRING_free(3). periodt.
  • it is recommended that ASN1_TIME functions be used instead of ASN1_UTCTIME or ASN1_GENERALIZEDTIME functions because the ASN1_UTCTIME and ASN1_GENERALIZEDTIME functions act only on that specific time format, while the ASN1_TIME functions operate on either format. so use the flexible one, bestie.
  • OPENSSL_gmtime() β€” converts a time_t value in time to a struct tm in out_tm and also returns the struct passed in on success. slay.
  • OPENSSL_timegm() β€” converts a time structure in UTC time in tm to a time_t value in out_time. iconic.
  • OPENSSL_posix_to_tm() β€” converts an int64_t POSIX time value in time, which must be in the range of year 0 to 9999, to a broken out time value in tm. no pressure.
  • OPENSSL_tm_to_posix() β€” converts a time value between the years 0 and 9999 in tm to a POSIX time value in out. reverse uno card.

πŸ’€ RETURN VALUES πŸ’€

okay so what do these functions give back? let's break it down:

  • ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(), ASN1_TIME_adj(), ASN1_UTCTIME_adj(), ASN1_GENERALIZEDTIME_adj(), and ASN1_TIME_to_generalizedtime() return a pointer to a time object or NULL if an error occurred. no vibes on error.
  • ASN1_TIME_set_string(), ASN1_TIME_set_string_X509(), ASN1_UTCTIME_set_string(), and ASN1_GENERALIZEDTIME_set_string() return 1 if the time value is successfully set or 0 otherwise. simple.
  • ASN1_TIME_normalize() returns 1 on success or 0 on error. glow-up successful or not.
  • ASN1_TIME_check(), ASN1_UTCTIME_check(), and ASN1_GENERALIZEDTIME_check() return 1 if the time string contained in the object is syntactically correct or 0 otherwise. vibe check passed or failed.
  • ASN1_TIME_print(), ASN1_UTCTIME_print(), and ASN1_GENERALIZEDTIME_print() return 1 if the time is successfully printed or 0 if an error occurred (I/O error or invalid time format). so if it says "Bad time value", you already know it's a 0.
  • ASN1_TIME_to_tm() returns 1 if the time is successfully parsed or 0 if an error occurred, usually due to an invalid time format. bestie, format matters.
  • ASN1_TIME_diff() returns 1 for success or 0 for failure. it can for example fail if a time string passed in has invalid syntax. math can fail, apparently.
  • ASN1_TIME_cmp_time_t(), ASN1_UTCTIME_cmp_time_t(), and ASN1_TIME_compare() return -1 if s is earlier than t, 0 if both are equal, 1 if s is later than t, or -2 on error. so -2 is the error vibe.
  • OPENSSL_timegm() returns 1 for success or 0 for failure. it can fail if the time is not representable in a time_t, or falls outside the range allowed in RFC 5280 times. tragic.
  • OPENSSL_gmtime() returns out_tm on success or NULL for failure. it can fail if the time is not representable in a struct tm, or falls outside the range allowed in RFC 5280 times. same energy.
  • OPENSSL_posix_to_tm() and OPENSSL_tm_to_posix() return 1 for success or 0 on failure. it is a failure if the year is less than 0 or more than 9999. so keep it in range, bestie.

πŸ¦‹ EXAMPLES πŸ¦‹

set a time object to one hour after the current time and print it out, periodt:

             #include <time.h>
             #include <openssl/asn1.h>

             ASN1_TIME *asn1_time;
             time_t t;
             BIO *b;

             t = time(NULL);
             asn1_time = ASN1_TIME_adj(NULL, t, 0, 60 * 60);
             b = BIO_new_fp(stdout, BIO_NOCLOSE);
             if (asn1_time != NULL) {
                     ASN1_TIME_print(b, asn1_time);
                     BIO_printf(b, "\n");
             } else {
                     BIO_printf(b, "Time out of range or un-representable\n");
             }
             ASN1_STRING_free(asn1_time);
             BIO_free(b);

🌸 SEE ALSO 🌸

πŸ‘‘ STANDARDS πŸ‘‘

the usage of the ASN.1 Time, UTCTime, and GeneralizedTime data types in X.509 certificates is specified in RFC 5280, Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, section 4.1.2.5 (TBS Certificate Validity). that's the standard, bestie ✨

πŸ•°οΈ HISTORY πŸ•°οΈ

okay bestie, storytime πŸ“–βœ¨ β€” this is literally the family tree of every function on this page and it goes way back. Buckle up πŸ’…

  • ASN1_UTCTIME_check() and ASN1_UTCTIME_print() β€” the OGs πŸ§“ first showed up in SSLeay 0.5.1.
  • ASN1_UTCTIME_set() β€” debuted in SSLeay 0.6.0.
  • ASN1_UTCTIME_set_string() β€” arrived in SSLeay 0.9.0.
  • and all of those geriatric icons πŸ’€ have been available since OpenBSD 2.4.

  • ASN1_TIME_set(), ASN1_GENERALIZEDTIME_set(), ASN1_GENERALIZEDTIME_set_string(), ASN1_GENERALIZEDTIME_check(), ASN1_TIME_print(), and ASN1_GENERALIZEDTIME_print() β€” this whole friend group 🫢 first appeared in OpenSSL 0.9.2b and has been available since OpenBSD 2.6.
  • ASN1_UTCTIME_cmp_time_t() β€” first appeared in OpenSSL 0.9.6, available since OpenBSD 2.9.
  • ASN1_TIME_check() and ASN1_TIME_to_generalizedtime() β€” first appeared in OpenSSL 0.9.7, available since OpenBSD 3.2.
  • ASN1_TIME_adj(), ASN1_UTCTIME_adj(), ASN1_GENERALIZEDTIME_adj(), and ASN1_TIME_set_string() β€” first appeared in OpenSSL 1.0.0, available since OpenBSD 4.9.
  • ASN1_TIME_diff() β€” first appeared in OpenSSL 1.0.2, available since OpenBSD 7.1.
  • ASN1_TIME_set_string_X509(), ASN1_TIME_normalize(), ASN1_TIME_to_tm(), ASN1_TIME_cmp_time_t(), and ASN1_TIME_compare() β€” first appeared in OpenSSL 1.1.1, available since OpenBSD 7.2. (newer gen, still iconic πŸ‘‘)
  • OPENSSL_gmtime() β€” first appeared in OpenSSL 0.9.7. Then OPENSSL_timegm(), OPENSSL_posix_to_tm(), and OPENSSL_tm_to_posix() first appeared in BoringSSL 🌈 β€” and all these functions have been available since OpenBSD 7.5.

⚠️ CAVEATS ⚠️

okay this is the part where you listen πŸ‘‚πŸ’… no playing on your phone.

Some applications out here doing the absolute most 😭 β€” they add offset times directly to a time_t value and then pass the results to ASN1_TIME_set() (or equivalent). And yeah… that can cause problems, because the time_t value can overflow on some systems, resulting in unexpected results. πŸ’€ Not the vibe!

New applications should use ASN1_TIME_adj() instead 🫢 β€” pass the offset value in the offset_sec and offset_day parameters instead of directly manipulating a time_t value. fr fr, do it this way. 🌸

that's the whole page bestie, you ate it up πŸ’–βœ¨ go forth and set those times responsibly πŸŽ€

🌸 this one's from Debian, dated March 5, 2024 β€” and the page is literally called ASN1_TIME_SET(3). periodt. πŸ’…πŸ‘‘

πŸ“¦ where this page comes from
  • opensuse-leap 16.0: libressl-devel-doc 4.1.0-bp160.1.1 Β· OpenSSL
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms