diff options
Diffstat (limited to 'crypto/asn1/a_time.c')
-rw-r--r-- | crypto/asn1/a_time.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 27f9bc6808..12b1ff5890 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -107,7 +107,6 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, return NULL; } - int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) { ASN1_TIME t; @@ -130,6 +129,65 @@ int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) return 1; } +int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str) +{ + ASN1_TIME t; + struct tm tm; + int rv = 0; + + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = ASN1_STRING_FLAG_X509_TIME; + + t.type = V_ASN1_UTCTIME; + + if (!ASN1_TIME_check(&t)) { + t.type = V_ASN1_GENERALIZEDTIME; + if (!ASN1_TIME_check(&t)) + goto out; + } + + /* + * Per RFC 5280 (section 4.1.2.5.), the valid input time + * strings should be encoded with the following rules: + * + * 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ + * 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ + * 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ + * 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ + * + * Only strings of the 4th rule should be reformatted, but since a + * UTC can only present [1950, 2050), so if the given time string + * is less than 1950 (e.g. 19230419000000Z), we do nothing... + */ + + if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) { + if (!asn1_generalizedtime_to_tm(&tm, &t)) + goto out; + if (tm.tm_year >= 50 && tm.tm_year < 150) { + t.length -= 2; + /* + * it's OK to let original t.data go since that's assigned + * to a piece of memory allocated outside of this function. + * new t.data would be freed after ASN1_STRING_copy is done. + */ + t.data = OPENSSL_zalloc(t.length + 1); + if (t.data == NULL) + goto out; + memcpy(t.data, str + 2, t.length); + t.type = V_ASN1_UTCTIME; + } + } + + if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) + rv = 1; + + if (t.data != (unsigned char *)str) + OPENSSL_free(t.data); +out: + return rv; +} + int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm) { if (s == NULL) { |