diff options
-rw-r--r-- | crypto/asn1/a_time.c | 4 | ||||
-rw-r--r-- | crypto/asn1/a_utctm.c | 39 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.c | 4 | ||||
-rw-r--r-- | include/openssl/asn1.h | 157 | ||||
-rw-r--r-- | include/openssl/x509.h | 39 |
5 files changed, 170 insertions, 73 deletions
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 @@ static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) 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 @@ int ASN1_TIME_diff(int *pday, int *psec, 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 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) 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 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) 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 @@ 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) |