monotone

monotone Mtn Source Tree

Root/botan/asn1_tm.cpp

1/*************************************************
2* X.509 Time Types Source File *
3* (C) 1999-2005 The Botan Project *
4*************************************************/
5
6#include <botan/asn1_obj.h>
7#include <botan/charset.h>
8#include <botan/parsing.h>
9#include <botan/conf.h>
10#include <ctime>
11
12namespace Botan {
13
14namespace {
15
16/*************************************************
17* Convert a time_t to a struct tm *
18*************************************************/
19std::tm get_tm(u64bit timer)
20 {
21 std::time_t time_val = (std::time_t)timer;
22
23 if((u64bit)time_val != timer)
24 throw Encoding_Error("X509_Time: time_t overflow with time value " +
25 to_string(timer));
26
27 std::tm* tm_p = std::gmtime(&time_val);
28 if(tm_p == 0)
29 throw Encoding_Error("X509_Time: gmtime could not encode " +
30 to_string(timer));
31 return (*tm_p);
32 }
33
34}
35
36/*************************************************
37* Create an X509_Time *
38*************************************************/
39X509_Time::X509_Time(const std::string& time_str)
40 {
41 if(time_str == "")
42 {
43 year = month = day = hour = minute = second = 0;
44 return;
45 }
46
47 std::vector<std::string> params;
48 std::string current;
49
50 for(u32bit j = 0; j != time_str.size(); j++)
51 {
52 if(is_digit(time_str[j]))
53 current += time_str[j];
54 else
55 {
56 if(current != "")
57 params.push_back(current);
58 current = "";
59 }
60 }
61 if(current != "")
62 params.push_back(current);
63
64 if(params.size() < 3 || params.size() > 6)
65 throw Invalid_Argument("Invalid time specification " + time_str);
66
67 year = to_u32bit(params[0]);
68 month = to_u32bit(params[1]);
69 day = to_u32bit(params[2]);
70 hour = (params.size() >= 4) ? to_u32bit(params[3]) : 0;
71 minute = (params.size() >= 5) ? to_u32bit(params[4]) : 0;
72 second = (params.size() == 6) ? to_u32bit(params[5]) : 0;
73
74 if(year >= 2050)
75 tag = GENERALIZED_TIME;
76 else
77 tag = UTC_TIME;
78
79 if(!passes_sanity_check())
80 throw Invalid_Argument("Invalid time specification " + time_str);
81 }
82
83/*************************************************
84* Create an X509_Time *
85*************************************************/
86X509_Time::X509_Time(u64bit timer)
87 {
88 std::tm time_info = get_tm(timer);
89
90 year = time_info.tm_year + 1900;
91 month = time_info.tm_mon + 1;
92 day = time_info.tm_mday;
93 hour = time_info.tm_hour;
94 minute = time_info.tm_min;
95 second = time_info.tm_sec;
96
97 if(year >= 2050)
98 tag = GENERALIZED_TIME;
99 else
100 tag = UTC_TIME;
101 }
102
103/*************************************************
104* Create an X509_Time *
105*************************************************/
106X509_Time::X509_Time(const std::string& t_spec, ASN1_Tag t) : tag(t)
107 {
108 if(tag != GENERALIZED_TIME && tag != UTC_TIME)
109 throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag));
110 if(tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15)
111 throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec);
112 if(tag == UTC_TIME && t_spec.size() != 11 && t_spec.size() != 13)
113 throw Invalid_Argument("Invalid UTCTime: " + t_spec);
114 if(t_spec[t_spec.size()-1] != 'Z')
115 throw Invalid_Argument("Invalid time encoding: " + t_spec);
116
117 const u32bit YEAR_SIZE = (tag == UTC_TIME) ? 2 : 4;
118
119 std::vector<std::string> params;
120 std::string current;
121
122 for(u32bit j = 0; j != YEAR_SIZE; j++)
123 current += t_spec[j];
124 params.push_back(current);
125 current = "";
126
127 for(u32bit j = YEAR_SIZE; j != t_spec.size() - 1; j++)
128 {
129 current += t_spec[j];
130 if(current.size() == 2)
131 {
132 params.push_back(current);
133 current = "";
134 }
135 }
136
137 year = to_u32bit(params[0]);
138 month = to_u32bit(params[1]);
139 day = to_u32bit(params[2]);
140 hour = to_u32bit(params[3]);
141 minute = to_u32bit(params[4]);
142 second = (params.size() == 6) ? to_u32bit(params[5]) : 0;
143
144 if(tag == UTC_TIME)
145 {
146 if(year >= 50) year += 1900;
147 else year += 2000;
148 }
149
150 if(!passes_sanity_check())
151 throw Invalid_Argument("Invalid time specification " + t_spec);
152 }
153
154/*************************************************
155* Return a string representation of the time *
156*************************************************/
157std::string X509_Time::as_string() const
158 {
159 if(time_is_set() == false)
160 throw Invalid_State("X509_Time::as_string: No time set");
161
162 std::string asn1rep;
163 if(tag == GENERALIZED_TIME)
164 asn1rep = to_string(year, 4);
165 else
166 {
167 if(year < 1950 || year >= 2050)
168 throw Encoding_Error("X509_Time: The time " + readable_string() +
169 " cannot be encoded as a UTCTime");
170 u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900);
171 asn1rep = to_string(asn1year, 2);
172 }
173 asn1rep += to_string(month, 2) + to_string(day, 2);
174 asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2);
175 asn1rep += "Z";
176 return asn1rep;
177 }
178
179/*************************************************
180* Return if the time has been set somehow *
181*************************************************/
182bool X509_Time::time_is_set() const
183 {
184 return (year != 0);
185 }
186
187/*************************************************
188* Return a human readable string representation *
189*************************************************/
190std::string X509_Time::readable_string() const
191 {
192 if(time_is_set() == false)
193 throw Invalid_State("X509_Time::readable_string: No time set");
194
195 std::string readable;
196 readable += to_string(year, 4) + "/";
197 readable += to_string(month ) + "/";
198 readable += to_string(day ) + " ";
199 readable += to_string(hour ) + ":";
200 readable += to_string(minute, 2) + ":";
201 readable += to_string(second, 2) + " UTC";
202 return readable;
203 }
204
205/*************************************************
206* Do a general sanity check on the time *
207*************************************************/
208bool X509_Time::passes_sanity_check() const
209 {
210 if(year < 1950 || year > 2100)
211 return false;
212 if(month == 0 || month > 12)
213 return false;
214 if(day == 0 || day > 31)
215 return false;
216 if(hour >= 24 || minute > 60 || second > 60)
217 return false;
218 return true;
219 }
220
221/*************************************************
222* Return the type of this Time object *
223*************************************************/
224ASN1_Tag X509_Time::tagging() const
225 {
226 return tag;
227 }
228
229/*************************************************
230* Compare this time against another *
231*************************************************/
232s32bit X509_Time::cmp(const X509_Time& other) const
233 {
234 if(time_is_set() == false)
235 throw Invalid_State("X509_Time::cmp: No time set");
236
237 const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
238
239 if(year < other.year) return EARLIER;
240 if(year > other.year) return LATER;
241 if(month < other.month) return EARLIER;
242 if(month > other.month) return LATER;
243 if(day < other.day) return EARLIER;
244 if(day > other.day) return LATER;
245 if(hour < other.hour) return EARLIER;
246 if(hour > other.hour) return LATER;
247 if(minute < other.minute) return EARLIER;
248 if(minute > other.minute) return LATER;
249 if(second < other.second) return EARLIER;
250 if(second > other.second) return LATER;
251
252 return SAME_TIME;
253 }
254
255/*************************************************
256* Compare this time against another *
257*************************************************/
258s32bit X509_Time::cmp(u64bit seconds) const
259 {
260 return cmp(X509_Time(seconds));
261 }
262
263/*************************************************
264* Compare two X509_Times for in various ways *
265*************************************************/
266bool operator==(const X509_Time& t1, const X509_Time& t2)
267 { return (t1.cmp(t2) == 0); }
268bool operator!=(const X509_Time& t1, const X509_Time& t2)
269 { return (t1.cmp(t2) != 0); }
270bool operator<=(const X509_Time& t1, const X509_Time& t2)
271 { return (t1.cmp(t2) <= 0); }
272bool operator>=(const X509_Time& t1, const X509_Time& t2)
273 { return (t1.cmp(t2) >= 0); }
274
275/*************************************************
276* Do a validity check *
277*************************************************/
278s32bit validity_check(const X509_Time& start, const X509_Time& end,
279 u64bit current_time)
280 {
281 const u32bit ALLOWABLE_SLIP = Config::get_time("x509/validity_slack");
282 const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1;
283
284 if(start.cmp(current_time + ALLOWABLE_SLIP) > 0)
285 return NOT_YET_VALID;
286 if(end.cmp(current_time - ALLOWABLE_SLIP) < 0)
287 return EXPIRED;
288 return VALID_TIME;
289 }
290
291namespace DER {
292
293/*************************************************
294* DER encode an X509_Time *
295*************************************************/
296void encode(DER_Encoder& encoder, const X509_Time& obj, ASN1_Tag tagging)
297 {
298 if(tagging != GENERALIZED_TIME && tagging != UTC_TIME)
299 throw Invalid_Argument("DER::encode: Bad encoding tag for time value");
300 encoder.add_object(tagging, UNIVERSAL, local2iso(obj.as_string()));
301 }
302
303/*************************************************
304* DER encode an X509_Time *
305*************************************************/
306void encode(DER_Encoder& encoder, const X509_Time& obj)
307 {
308 DER::encode(encoder, obj, obj.tagging());
309 }
310
311}
312
313namespace BER {
314
315/*************************************************
316* Decode a BER encoded X509_Time *
317*************************************************/
318void decode(BER_Decoder& source, X509_Time& obj)
319 {
320 BER_Object ber_obj = source.get_next_object();
321 obj = X509_Time(iso2local(BER::to_string(ber_obj)), ber_obj.type_tag);
322 }
323
324}
325
326}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status