Botan
1.11.15
|
00001 /* 00002 * EAC Time Types 00003 * (C) 2007 FlexSecure GmbH 00004 * 2008-2009 Jack Lloyd 00005 * 00006 * Botan is released under the Simplified BSD License (see license.txt) 00007 */ 00008 00009 #include <botan/eac_asn_obj.h> 00010 #include <botan/der_enc.h> 00011 #include <botan/ber_dec.h> 00012 #include <botan/charset.h> 00013 #include <botan/parsing.h> 00014 #include <botan/internal/rounding.h> 00015 #include <botan/calendar.h> 00016 00017 namespace Botan { 00018 00019 namespace { 00020 00021 std::vector<byte> enc_two_digit(u32bit in) 00022 { 00023 std::vector<byte> result; 00024 in %= 100; 00025 if(in < 10) 00026 result.push_back(0x00); 00027 else 00028 { 00029 u32bit y_first_pos = round_down<u32bit>(in, 10) / 10; 00030 result.push_back(static_cast<byte>(y_first_pos)); 00031 } 00032 00033 u32bit y_sec_pos = in % 10; 00034 result.push_back(static_cast<byte>(y_sec_pos)); 00035 return result; 00036 } 00037 00038 u32bit dec_two_digit(byte b1, byte b2) 00039 { 00040 u32bit upper = b1; 00041 u32bit lower = b2; 00042 00043 if(upper > 9 || lower > 9) 00044 throw Invalid_Argument("CVC dec_two_digit value too large"); 00045 00046 return upper*10 + lower; 00047 } 00048 00049 } 00050 00051 /* 00052 * Create an EAC_Time 00053 */ 00054 EAC_Time::EAC_Time(const std::chrono::system_clock::time_point& time, 00055 ASN1_Tag t) : tag(t) 00056 { 00057 calendar_point cal = calendar_value(time); 00058 00059 year = cal.year; 00060 month = cal.month; 00061 day = cal.day; 00062 } 00063 00064 /* 00065 * Create an EAC_Time 00066 */ 00067 EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : tag(t) 00068 { 00069 set_to(t_spec); 00070 } 00071 00072 /* 00073 * Create an EAC_Time 00074 */ 00075 EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) : 00076 year(y), month(m), day(d), tag(t) 00077 { 00078 } 00079 00080 /* 00081 * Set the time with a human readable string 00082 */ 00083 void EAC_Time::set_to(const std::string& time_str) 00084 { 00085 if(time_str == "") 00086 { 00087 year = month = day = 0; 00088 return; 00089 } 00090 00091 std::vector<std::string> params; 00092 std::string current; 00093 00094 for(u32bit j = 0; j != time_str.size(); ++j) 00095 { 00096 if(Charset::is_digit(time_str[j])) 00097 current += time_str[j]; 00098 else 00099 { 00100 if(current != "") 00101 params.push_back(current); 00102 current.clear(); 00103 } 00104 } 00105 if(current != "") 00106 params.push_back(current); 00107 00108 if(params.size() != 3) 00109 throw Invalid_Argument("Invalid time specification " + time_str); 00110 00111 year = to_u32bit(params[0]); 00112 month = to_u32bit(params[1]); 00113 day = to_u32bit(params[2]); 00114 00115 if(!passes_sanity_check()) 00116 throw Invalid_Argument("Invalid time specification " + time_str); 00117 } 00118 00119 00120 /* 00121 * DER encode a EAC_Time 00122 */ 00123 void EAC_Time::encode_into(DER_Encoder& der) const 00124 { 00125 der.add_object(tag, APPLICATION, 00126 encoded_eac_time()); 00127 } 00128 00129 /* 00130 * Return a string representation of the time 00131 */ 00132 std::string EAC_Time::as_string() const 00133 { 00134 if(time_is_set() == false) 00135 throw Invalid_State("EAC_Time::as_string: No time set"); 00136 00137 return std::to_string(year * 10000 + month * 100 + day); 00138 } 00139 00140 /* 00141 * Return if the time has been set somehow 00142 */ 00143 bool EAC_Time::time_is_set() const 00144 { 00145 return (year != 0); 00146 } 00147 00148 /* 00149 * Return a human readable string representation 00150 */ 00151 std::string EAC_Time::readable_string() const 00152 { 00153 if(time_is_set() == false) 00154 throw Invalid_State("EAC_Time::readable_string: No time set"); 00155 00156 std::string output(11, 0); 00157 00158 std::sprintf(&output[0], "%04d/%02d/%02d", year, month, day); 00159 00160 return output; 00161 } 00162 00163 /* 00164 * Do a general sanity check on the time 00165 */ 00166 bool EAC_Time::passes_sanity_check() const 00167 { 00168 if(year < 2000 || year > 2099) 00169 return false; 00170 if(month == 0 || month > 12) 00171 return false; 00172 if(day == 0 || day > 31) 00173 return false; 00174 00175 return true; 00176 } 00177 00178 /* 00179 * modification functions 00180 */ 00181 void EAC_Time::add_years(u32bit years) 00182 { 00183 year += years; 00184 } 00185 00186 void EAC_Time::add_months(u32bit months) 00187 { 00188 year += months/12; 00189 month += months % 12; 00190 if(month > 12) 00191 { 00192 year += 1; 00193 month -= 12; 00194 } 00195 } 00196 00197 /* 00198 * Compare this time against another 00199 */ 00200 s32bit EAC_Time::cmp(const EAC_Time& other) const 00201 { 00202 if(time_is_set() == false) 00203 throw Invalid_State("EAC_Time::cmp: No time set"); 00204 00205 const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; 00206 00207 if(year < other.year) return EARLIER; 00208 if(year > other.year) return LATER; 00209 if(month < other.month) return EARLIER; 00210 if(month > other.month) return LATER; 00211 if(day < other.day) return EARLIER; 00212 if(day > other.day) return LATER; 00213 00214 return SAME_TIME; 00215 } 00216 00217 /* 00218 * Compare two EAC_Times for in various ways 00219 */ 00220 bool operator==(const EAC_Time& t1, const EAC_Time& t2) 00221 { 00222 return (t1.cmp(t2) == 0); 00223 } 00224 00225 bool operator!=(const EAC_Time& t1, const EAC_Time& t2) 00226 { 00227 return (t1.cmp(t2) != 0); 00228 } 00229 00230 bool operator<=(const EAC_Time& t1, const EAC_Time& t2) 00231 { 00232 return (t1.cmp(t2) <= 0); 00233 } 00234 00235 bool operator>=(const EAC_Time& t1, const EAC_Time& t2) 00236 { 00237 return (t1.cmp(t2) >= 0); 00238 } 00239 00240 bool operator>(const EAC_Time& t1, const EAC_Time& t2) 00241 { 00242 return (t1.cmp(t2) > 0); 00243 } 00244 00245 bool operator<(const EAC_Time& t1, const EAC_Time& t2) 00246 { 00247 return (t1.cmp(t2) < 0); 00248 } 00249 00250 /* 00251 * Decode a BER encoded EAC_Time 00252 */ 00253 void EAC_Time::decode_from(BER_Decoder& source) 00254 { 00255 BER_Object obj = source.get_next_object(); 00256 00257 if(obj.type_tag != this->tag) 00258 throw BER_Decoding_Error("Tag mismatch when decoding"); 00259 00260 if(obj.value.size() != 6) 00261 { 00262 throw Decoding_Error("EAC_Time decoding failed"); 00263 } 00264 00265 try 00266 { 00267 u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]); 00268 u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]); 00269 u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]); 00270 year = tmp_year + 2000; 00271 month = tmp_mon; 00272 day = tmp_day; 00273 } 00274 catch (Invalid_Argument) 00275 { 00276 throw Decoding_Error("EAC_Time decoding failed"); 00277 } 00278 00279 } 00280 00281 /* 00282 * make the value an octet string for encoding 00283 */ 00284 std::vector<byte> EAC_Time::encoded_eac_time() const 00285 { 00286 std::vector<byte> result; 00287 result += enc_two_digit(year); 00288 result += enc_two_digit(month); 00289 result += enc_two_digit(day); 00290 return result; 00291 } 00292 00293 }