Botan  1.10.9
asn1_eac_tm.cpp
Go to the documentation of this file.
1 /*
2 * EAC Time Types
3 * (C) 2007 FlexSecure GmbH
4 * 2008 Jack Lloyd
5 *
6 * Distributed under the terms of the Botan license
7 */
8 
9 #include <botan/eac_asn_obj.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/charset.h>
13 #include <botan/parsing.h>
14 #include <botan/internal/rounding.h>
15 #include <botan/time.h>
16 
17 namespace Botan {
18 
19 namespace {
20 
21 SecureVector<byte> enc_two_digit(u32bit in)
22  {
23  SecureVector<byte> result;
24  in %= 100;
25  if (in < 10)
26  result.push_back(0x00);
27  else
28  {
29  u32bit y_first_pos = round_down<u32bit>(in, 10) / 10;
30  result.push_back(static_cast<byte>(y_first_pos));
31  }
32 
33  u32bit y_sec_pos = in % 10;
34  result.push_back(static_cast<byte>(y_sec_pos));
35  return result;
36  }
37 
38 u32bit dec_two_digit(byte b1, byte b2)
39  {
40  u32bit upper = b1;
41  u32bit lower = b2;
42 
43  if(upper > 9 || lower > 9)
44  throw Invalid_Argument("CVC dec_two_digit value too large");
45 
46  return upper*10 + lower;
47  }
48 
49 }
50 
51 /*
52 * Create an EAC_Time
53 */
55  {
56  calendar_point cal = calendar_value(timer);
57 
58  year = cal.year;
59  month = cal.month;
60  day = cal.day;
61  }
62 
63 /*
64 * Create an EAC_Time
65 */
66 EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : tag(t)
67  {
68  set_to(t_spec);
69  }
70 /*
71 * Create an EAC_Time
72 */
74  year(y), month(m), day(d), tag(t)
75  {
76  }
77 
78 /*
79 * Set the time with a human readable string
80 */
81 void EAC_Time::set_to(const std::string& time_str)
82  {
83  if (time_str == "")
84  {
85  year = month = day = 0;
86  return;
87  }
88 
89  std::vector<std::string> params;
90  std::string current;
91 
92  for (u32bit j = 0; j != time_str.size(); ++j)
93  {
94  if (Charset::is_digit(time_str[j]))
95  current += time_str[j];
96  else
97  {
98  if (current != "")
99  params.push_back(current);
100  current.clear();
101  }
102  }
103  if (current != "")
104  params.push_back(current);
105 
106  if (params.size() != 3)
107  throw Invalid_Argument("Invalid time specification " + time_str);
108 
109  year = to_u32bit(params[0]);
110  month = to_u32bit(params[1]);
111  day = to_u32bit(params[2]);
112 
113  if (!passes_sanity_check())
114  throw Invalid_Argument("Invalid time specification " + time_str);
115  }
116 
117 
118 /*
119 * DER encode a EAC_Time
120 */
122  {
123  der.add_object(tag, APPLICATION,
124  encoded_eac_time());
125  }
126 
127 /*
128 * Return a string representation of the time
129 */
130 std::string EAC_Time::as_string() const
131  {
132  if (time_is_set() == false)
133  throw Invalid_State("EAC_Time::as_string: No time set");
134 
135  std::string asn1rep;
136  asn1rep = to_string(year, 2);
137 
138  asn1rep += to_string(month, 2) + to_string(day, 2);
139 
140  return asn1rep;
141  }
142 
143 /*
144 * Return if the time has been set somehow
145 */
147  {
148  return (year != 0);
149  }
150 
151 /*
152 * Return a human readable string representation
153 */
154 std::string EAC_Time::readable_string() const
155  {
156  if (time_is_set() == false)
157  throw Invalid_State("EAC_Time::readable_string: No time set");
158 
159  std::string readable;
160  readable += to_string(year, 2) + "/";
161  readable += to_string(month, 2) + "/";
162  readable += to_string(day, 2) + " ";
163 
164  return readable;
165  }
166 
167 /*
168 * Do a general sanity check on the time
169 */
170 bool EAC_Time::passes_sanity_check() const
171  {
172  if (year < 2000 || year > 2099)
173  return false;
174  if (month == 0 || month > 12)
175  return false;
176  if (day == 0 || day > 31)
177  return false;
178 
179  return true;
180  }
181 
182 /*
183 * modification functions
184 */
185 
187  {
188  year += years;
189  }
191  {
192  year += months/12;
193  month += months % 12;
194  if(month > 12)
195  {
196  year += 1;
197  month -= 12;
198  }
199  }
200 
201 
202 /*
203 * Compare this time against another
204 */
205 s32bit EAC_Time::cmp(const EAC_Time& other) const
206  {
207  if (time_is_set() == false)
208  throw Invalid_State("EAC_Time::cmp: No time set");
209 
210  const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
211 
212  if (year < other.year) return EARLIER;
213  if (year > other.year) return LATER;
214  if (month < other.month) return EARLIER;
215  if (month > other.month) return LATER;
216  if (day < other.day) return EARLIER;
217  if (day > other.day) return LATER;
218 
219  return SAME_TIME;
220  }
221 
222 /*
223 * Compare two EAC_Times for in various ways
224 */
225 bool operator==(const EAC_Time& t1, const EAC_Time& t2)
226  {
227  return (t1.cmp(t2) == 0);
228  }
229 
230 bool operator!=(const EAC_Time& t1, const EAC_Time& t2)
231  {
232  return (t1.cmp(t2) != 0);
233  }
234 
235 bool operator<=(const EAC_Time& t1, const EAC_Time& t2)
236  {
237  return (t1.cmp(t2) <= 0);
238  }
239 
240 bool operator>=(const EAC_Time& t1, const EAC_Time& t2)
241  {
242  return (t1.cmp(t2) >= 0);
243  }
244 
245 bool operator>(const EAC_Time& t1, const EAC_Time& t2)
246  {
247  return (t1.cmp(t2) > 0);
248  }
249 
250 bool operator<(const EAC_Time& t1, const EAC_Time& t2)
251  {
252  return (t1.cmp(t2) < 0);
253  }
254 
255 /*
256 * Decode a BER encoded EAC_Time
257 */
259  {
260  BER_Object obj = source.get_next_object();
261 
262  if(obj.type_tag != this->tag)
263  throw BER_Decoding_Error("Tag mismatch when decoding");
264 
265  if(obj.value.size() != 6)
266  {
267  throw Decoding_Error("EAC_Time decoding failed");
268  }
269 
270  try
271  {
272  u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]);
273  u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]);
274  u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]);
275  year = tmp_year + 2000;
276  month = tmp_mon;
277  day = tmp_day;
278  }
279  catch (Invalid_Argument)
280  {
281  throw Decoding_Error("EAC_Time decoding failed");
282  }
283 
284  }
285 
287  {
288  return year;
289  }
290 
292  {
293  return month;
294  }
295 
297  {
298  return day;
299  }
300 
301 /*
302 * make the value an octet string for encoding
303 */
304 SecureVector<byte> EAC_Time::encoded_eac_time() const
305  {
306  SecureVector<byte> result;
307  result += enc_two_digit(year);
308  result += enc_two_digit(month);
309  result += enc_two_digit(day);
310  return result;
311  }
312 
313 ASN1_Ced::ASN1_Ced(std::string const& str) :
314  EAC_Time(str, ASN1_Tag(37))
315  {}
316 
318  EAC_Time(val, ASN1_Tag(37))
319  {}
320 
322  EAC_Time(other.get_year(),
323  other.get_month(),
324  other.get_day(),
325  ASN1_Tag(37))
326  {}
327 
328 ASN1_Cex::ASN1_Cex(std::string const& str) :
329  EAC_Time(str, ASN1_Tag(36))
330  {}
331 
333  EAC_Time(val, ASN1_Tag(36))
334  {}
335 
337  EAC_Time(other.get_year(),
338  other.get_month(),
339  other.get_day(),
340  ASN1_Tag(36))
341  {}
342 
343 }
void encode_into(class DER_Encoder &) const
u32bit get_day() const
bool operator!=(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:106
bool BOTAN_DLL operator>=(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:283
bool time_is_set() const
u32bit get_year() const
bool operator==(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:98
ASN1_Cex(std::string const &str="")
EAC_Time(u64bit, ASN1_Tag t=ASN1_Tag(0))
Definition: asn1_eac_tm.cpp:54
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
void decode_from(class BER_Decoder &)
u32bit get_month() const
calendar_point calendar_value(u64bit a_time_t)
Definition: time.cpp:81
void add_years(u32bit years)
signed int s32bit
Definition: types.h:37
unsigned char byte
Definition: types.h:22
unsigned long long u64bit
Definition: types.h:49
void add_months(u32bit months)
bool BOTAN_DLL operator>(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:288
std::string readable_string() const
ASN1_Tag
Definition: asn1_int.h:19
s32bit cmp(const EAC_Time &other) const
ASN1_Ced(std::string const &str="")
std::string as_string() const
size_t size() const
Definition: secmem.h:29
SecureVector< byte > value
Definition: asn1_int.h:83
bool is_digit(char c)
Definition: charset.cpp:128
BER_Object get_next_object()
Definition: ber_dec.cpp:193
ASN1_Tag type_tag
Definition: asn1_int.h:82
bool BOTAN_DLL operator<(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:286
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
bool BOTAN_DLL operator<=(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:281
u32bit to_u32bit(const std::string &number)
Definition: parsing.cpp:18
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const byte rep[], size_t length)
Definition: der_enc.cpp:346
unsigned int u32bit
Definition: types.h:32
void set_to(const std::string &str)
Definition: asn1_eac_tm.cpp:81