8#include <botan/asn1_obj.h>
9#include <botan/der_enc.h>
10#include <botan/ber_dec.h>
11#include <botan/exceptn.h>
12#include <botan/parsing.h>
13#include <botan/calendar.h>
41 "ASN1_Time: Bad encoding tag");
58 uint32_t full_year = m_year;
62 if(m_year < 1950 || m_year >= 2050)
64 " cannot be encoded as a UTCTime");
66 full_year = (m_year >= 2000) ? (m_year - 2000) : (m_year - 1900);
69 const uint64_t YEAR_FACTOR = 10000000000ULL;
70 const uint64_t MON_FACTOR = 100000000;
71 const uint64_t DAY_FACTOR = 1000000;
72 const uint64_t HOUR_FACTOR = 10000;
73 const uint64_t MIN_FACTOR = 100;
75 const uint64_t int_repr =
76 YEAR_FACTOR * full_year +
77 MON_FACTOR * m_month +
79 HOUR_FACTOR * m_hour +
80 MIN_FACTOR * m_minute +
85 uint32_t desired_size = (m_tag ==
UTC_TIME) ? 13 : 15;
87 while(repr.size() < desired_size)
96 throw Invalid_State(
"ASN1_Time::readable_string: No time set");
99 std::stringstream output;
100 output << std::setfill(
'0')
101 << std::setw(4) << m_year <<
"/"
102 << std::setw(2) << m_month <<
"/"
103 << std::setw(2) << m_day
105 << std::setw(2) << m_hour <<
":"
106 << std::setw(2) << m_minute <<
":"
107 << std::setw(2) << m_second
115 return (m_year != 0);
123 const int32_t EARLIER = -1, LATER = 1, SAME_TIME = 0;
125 if(m_year < other.m_year)
return EARLIER;
126 if(m_year > other.m_year)
return LATER;
127 if(m_month < other.m_month)
return EARLIER;
128 if(m_month > other.m_month)
return LATER;
129 if(m_day < other.m_day)
return EARLIER;
130 if(m_day > other.m_day)
return LATER;
131 if(m_hour < other.m_hour)
return EARLIER;
132 if(m_hour > other.m_hour)
return LATER;
133 if(m_minute < other.m_minute)
return EARLIER;
134 if(m_minute > other.m_minute)
return LATER;
135 if(m_second < other.m_second)
return EARLIER;
136 if(m_second > other.m_second)
return LATER;
141void ASN1_Time::set_to(
const std::string& t_spec,
ASN1_Tag spec_tag)
150 catch(Invalid_Argument&) {}
157 catch(Invalid_Argument&) {}
159 throw Invalid_Argument(
"Time string could not be parsed as GeneralizedTime or UTCTime.");
166 BOTAN_ARG_CHECK(t_spec.back() ==
'Z',
"Botan does not support times with timezones other than Z");
170 BOTAN_ARG_CHECK(t_spec.size() == 15,
"Invalid GeneralizedTime string");
177 const size_t YEAR_SIZE = (spec_tag ==
UTC_TIME) ? 2 : 4;
179 std::vector<std::string> params;
182 for(
size_t j = 0; j != YEAR_SIZE; ++j)
183 current += t_spec[j];
184 params.push_back(current);
187 for(
size_t j = YEAR_SIZE; j != t_spec.size() - 1; ++j)
189 current += t_spec[j];
190 if(current.size() == 2)
192 params.push_back(current);
202 m_second = (params.size() == 6) ?
to_u32bit(params[5]) : 0;
207 if(m_year >= 50) m_year += 1900;
211 if(!passes_sanity_check())
212 throw Invalid_Argument(
"Time " + t_spec +
" does not seem to be valid");
218bool ASN1_Time::passes_sanity_check()
const
221 if(m_year < 1950 || m_year > 3100)
223 if(m_month == 0 || m_month > 12)
226 const uint32_t days_in_month[12] = { 31, 28+1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
228 if(m_day == 0 || m_day > days_in_month[m_month-1])
231 if(m_month == 2 && m_day == 29)
236 if(m_year % 100 == 0 && m_year % 400 != 0)
240 if(m_hour >= 24 || m_minute >= 60 || m_second > 60)
269 return std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
276 {
return (t1.
cmp(t2) == 0); }
278 {
return (t1.
cmp(t2) != 0); }
281 {
return (t1.
cmp(t2) <= 0); }
283 {
return (t1.
cmp(t2) >= 0); }
286 {
return (t1.
cmp(t2) < 0); }
288 {
return (t1.
cmp(t2) > 0); }
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
uint64_t time_since_epoch() const
Return time since epoch.
std::chrono::system_clock::time_point to_std_timepoint() const
Returns a STL timepoint object.
std::string to_string() const
Return an internal string representation of the time.
void decode_from(BER_Decoder &) override
ASN1_Time()=default
Create an invalid ASN1_Time.
bool time_is_set() const
Return if the time has been set somehow.
int32_t cmp(const ASN1_Time &other) const
Compare this time against another.
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
void encode_into(DER_Encoder &) const override
DER encode a ASN1_Time.
BER_Object get_next_object()
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
uint32_t get_minutes() const
std::chrono::system_clock::time_point to_std_timepoint() const
uint32_t get_month() const
uint32_t get_seconds() const
uint32_t get_hour() const
uint32_t get_year() const
std::string to_string(const BER_Object &obj)
bool operator>=(const ASN1_Time &, const ASN1_Time &)
bool operator<=(const ASN1_Time &, const ASN1_Time &)
bool operator<(const OID &a, const OID &b)
bool operator>(const ASN1_Time &, const ASN1_Time &)
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
@ UTC_OR_GENERALIZED_TIME
uint32_t to_u32bit(const std::string &str)
calendar_point calendar_value(const std::chrono::system_clock::time_point &time_point)