8 #include <botan/asn1_time.h>
9 #include <botan/der_enc.h>
10 #include <botan/ber_dec.h>
11 #include <botan/charset.h>
12 #include <botan/exceptn.h>
13 #include <botan/parsing.h>
14 #include <botan/calendar.h>
65 uint32_t full_year = m_year;
69 if(m_year < 1950 || m_year >= 2050)
71 " cannot be encoded as a UTCTime");
73 full_year = (m_year >= 2000) ? (m_year - 2000) : (m_year - 1900);
76 const auto factor_y = uint64_t{10000000000ull};
77 const auto factor_m = uint64_t{100000000ull};
78 const auto factor_d = uint64_t{1000000ull};
79 const auto factor_h = uint64_t{10000ull};
80 const auto factor_i = uint64_t{100ull};
89 uint32_t desired_size = (m_tag ==
UTC_TIME) ? 13 : 15;
91 while(repr.size() < desired_size)
100 throw Invalid_State(
"X509_Time::readable_string: No time set");
103 std::stringstream output;
106 output << setfill(
'0')
107 << setw(4) << m_year <<
"/" << setw(2) << m_month <<
"/" << setw(2) << m_day
109 << setw(2) << m_hour <<
":" << setw(2) << m_minute <<
":" << setw(2) << m_second
117 return (m_year != 0);
125 const int32_t EARLIER = -1, LATER = 1, SAME_TIME = 0;
127 if(m_year < other.m_year)
return EARLIER;
128 if(m_year > other.m_year)
return LATER;
129 if(m_month < other.m_month)
return EARLIER;
130 if(m_month > other.m_month)
return LATER;
131 if(m_day < other.m_day)
return EARLIER;
132 if(m_day > other.m_day)
return LATER;
133 if(m_hour < other.m_hour)
return EARLIER;
134 if(m_hour > other.m_hour)
return LATER;
135 if(m_minute < other.m_minute)
return EARLIER;
136 if(m_minute > other.m_minute)
return LATER;
137 if(m_second < other.m_second)
return EARLIER;
138 if(m_second > other.m_second)
return LATER;
143 void X509_Time::set_to(
const std::string& t_spec,
ASN1_Tag spec_tag)
152 catch(Invalid_Argument&) {}
159 catch(Invalid_Argument&) {}
161 throw Invalid_Argument(
"Time string could not be parsed as GeneralizedTime or UTCTime.");
167 throw Invalid_Argument(
"Time string must not be empty.");
169 if(t_spec.back() !=
'Z')
170 throw Unsupported_Argument(
"Botan does not support times with timezones other than Z: " + t_spec);
174 if(t_spec.size() != 15)
175 throw Invalid_Argument(
"Invalid GeneralizedTime string: '" + t_spec +
"'");
179 if(t_spec.size() != 13)
180 throw Invalid_Argument(
"Invalid UTCTime string: '" + t_spec +
"'");
183 const size_t YEAR_SIZE = (spec_tag ==
UTC_TIME) ? 2 : 4;
185 std::vector<std::string> params;
188 for(
size_t j = 0; j != YEAR_SIZE; ++j)
189 current += t_spec[j];
190 params.push_back(current);
193 for(
size_t j = YEAR_SIZE; j != t_spec.size() - 1; ++j)
195 current += t_spec[j];
196 if(current.size() == 2)
198 params.push_back(current);
208 m_second = (params.size() == 6) ?
to_u32bit(params[5]) : 0;
213 if(m_year >= 50) m_year += 1900;
217 if(!passes_sanity_check())
218 throw Invalid_Argument(
"Time did not pass sanity check: " + t_spec);
224 bool X509_Time::passes_sanity_check()
const
226 if(m_year < 1950 || m_year > 2100)
228 if(m_month == 0 || m_month > 12)
230 if(m_day == 0 || m_day > 31)
232 if(m_hour >= 24 || m_minute > 60 || m_second > 60)
244 if (m_hour > 23 || m_minute > 59 || m_second > 59)
262 {
return (t1.
cmp(t2) == 0); }
264 {
return (t1.
cmp(t2) != 0); }
267 {
return (t1.
cmp(t2) <= 0); }
269 {
return (t1.
cmp(t2) >= 0); }
272 {
return (t1.
cmp(t2) < 0); }
274 {
return (t1.
cmp(t2) > 0); }
uint32_t to_u32bit(const std::string &str)
std::chrono::system_clock::time_point to_std_timepoint() const
bool operator>=(const X509_Time &t1, const X509_Time &t2)
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
bool operator>(const X509_Time &t1, const X509_Time &t2)
int32_t cmp(const X509_Time &other) const
Compare this time against another.
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
void decode_from(BER_Decoder &) override
std::string to_string(const BER_Object &obj)
bool operator<(const OID &a, const OID &b)
X509_Time()=default
Create an invalid X509_Time.
void encode_into(DER_Encoder &) const override
DER encode a X509_Time.
#define BOTAN_ASSERT(expr, assertion_made)
std::chrono::system_clock::time_point to_std_timepoint() const
Returns a STL timepoint object.
std::string transcode(const std::string &str, Character_Set to, Character_Set from)
bool time_is_set() const
Return if the time has been set somehow.
BER_Object get_next_object()
std::string to_string() const
Return an internal string representation of the time.
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
bool operator<=(const X509_Time &t1, const X509_Time &t2)
calendar_point calendar_value(const std::chrono::system_clock::time_point &time_point)