aboutsummaryrefslogtreecommitdiffstats
path: root/src/cert/cvc/asn1_eac_tm.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-10-08 20:40:40 +0000
committerlloyd <[email protected]>2008-10-08 20:40:40 +0000
commit0ffb4257258df236dc469ef086b1871fe7b5afba (patch)
tree8cad23bb8bdf1db1f4d7e6a19eb23d6c1ef2e4ae /src/cert/cvc/asn1_eac_tm.cpp
parentfa7aa7f8dc857bae547fe6981fa6fc2b065b2004 (diff)
Many improvements towards getting the CVC implementation from InSiTo
compiling against mainline. Add several missing classes extracted from other files inside InSiTo. Add dependency note for ecdsa and asn1
Diffstat (limited to 'src/cert/cvc/asn1_eac_tm.cpp')
-rw-r--r--src/cert/cvc/asn1_eac_tm.cpp375
1 files changed, 375 insertions, 0 deletions
diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp
new file mode 100644
index 000000000..81c99f190
--- /dev/null
+++ b/src/cert/cvc/asn1_eac_tm.cpp
@@ -0,0 +1,375 @@
+/*************************************************
+* EAC Time Types Source File *
+* (C) 2007 FlexSecure GmbH *
+* 2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/eac_asn_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <ctime>
+#include <sstream>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Convert a time_t to a struct tm *
+*************************************************/
+std::tm get_tm(u64bit timer)
+ {
+ std::time_t time_val = static_cast<std::time_t>(timer);
+
+ std::tm* tm_p = std::gmtime(&time_val);
+ if (tm_p == 0)
+ throw Encoding_Error("EAC_Time: gmtime could not encode " +
+ to_string(timer));
+ return (*tm_p);
+ }
+SecureVector<byte> enc_two_digit(u32bit in)
+ {
+ SecureVector<byte> result;
+ in %= 100;
+ if (in < 10)
+ {
+ result.append(0x00);
+ }
+ else
+ {
+ u32bit y_first_pos = (in - (in%10))/10;
+ result.append(static_cast<byte>(y_first_pos));
+ }
+ u32bit y_sec_pos = in%10;
+ result.append(static_cast<byte>(y_sec_pos));
+ return result;
+ }
+u32bit dec_two_digit(byte b1, byte b2)
+ {
+ u32bit upper = (u32bit)b1;
+ u32bit lower = (u32bit)b2;
+ if (upper > 9 || lower > 9)
+ {
+ throw Invalid_Argument("u32bit dec_two_digit(byte b1, byte b2): value too large");
+ }
+ return upper*10 + lower;
+
+ }
+}
+
+/*************************************************
+* Create an EAC_Time *
+*************************************************/
+EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t)
+ :tag(t)
+ {
+ std::tm time_info = get_tm(timer);
+
+ year = time_info.tm_year + 1900;
+ month = time_info.tm_mon + 1;
+ day = time_info.tm_mday;
+
+ }
+
+/*************************************************
+* Create an EAC_Time *
+*************************************************/
+EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t)
+ :tag(t)
+ {
+ set_to(t_spec);
+ }
+/*************************************************
+* Create an EAC_Time *
+*************************************************/
+EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t)
+ : year(y),
+ month(m),
+ day(d),
+ tag(t)
+ {
+ }
+
+/*************************************************
+* Set the time with a human readable string *
+*************************************************/
+void EAC_Time::set_to(const std::string& time_str)
+ {
+ if (time_str == "")
+ {
+ year = month = day = 0;
+ return;
+ }
+
+ std::vector<std::string> params;
+ std::string current;
+
+ for (u32bit j = 0; j != time_str.size(); ++j)
+ {
+ if (Charset::is_digit(time_str[j]))
+ current += time_str[j];
+ else
+ {
+ if (current != "")
+ params.push_back(current);
+ current.clear();
+ }
+ }
+ if (current != "")
+ params.push_back(current);
+
+ if (params.size() != 3)
+ throw Invalid_Argument("Invalid time specification " + time_str);
+
+ year = to_u32bit(params[0]);
+ month = to_u32bit(params[1]);
+ day = to_u32bit(params[2]);
+
+ if (!passes_sanity_check())
+ throw Invalid_Argument("Invalid time specification " + time_str);
+ }
+
+
+/*************************************************
+* DER encode a EAC_Time *
+*************************************************/
+void EAC_Time::encode_into(DER_Encoder& der) const
+ {
+ der.add_object(tag, APPLICATION,
+ encoded_eac_time());
+ }
+
+/*************************************************
+* Return a string representation of the time *
+*************************************************/
+std::string EAC_Time::as_string() const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::as_string: No time set");
+
+ std::string asn1rep;
+ asn1rep = to_string(year, 2);
+
+ asn1rep += to_string(month, 2) + to_string(day, 2);
+
+ return asn1rep;
+ }
+
+/*************************************************
+* Return if the time has been set somehow *
+*************************************************/
+bool EAC_Time::time_is_set() const
+ {
+ return (year != 0);
+ }
+
+/*************************************************
+* Return a human readable string representation *
+*************************************************/
+std::string EAC_Time::readable_string() const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::readable_string: No time set");
+
+ std::string readable;
+ readable += to_string(year, 2) + "/";
+ readable += to_string(month, 2) + "/";
+ readable += to_string(day, 2) + " ";
+
+ return readable;
+ }
+
+/*************************************************
+* Do a general sanity check on the time *
+*************************************************/
+bool EAC_Time::passes_sanity_check() const
+ {
+ if (year < 2000 || year > 2099)
+ return false;
+ if (month == 0 || month > 12)
+ return false;
+ if (day == 0 || day > 31)
+ return false;
+
+ return true;
+ }
+
+/******************************************
+* modification functions *
+******************************************/
+
+void EAC_Time::add_years(u32bit years)
+ {
+ year += years;
+ }
+void EAC_Time::add_months(u32bit months)
+ {
+ year += months/12;
+ month += months % 12;
+ if(month > 12)
+ {
+ year += 1;
+ month -= 12;
+ }
+ }
+
+
+/*************************************************
+* Compare this time against another *
+*************************************************/
+s32bit EAC_Time::cmp(const EAC_Time& other) const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::cmp: No time set");
+
+ const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
+
+ if (year < other.year) return EARLIER;
+ if (year > other.year) return LATER;
+ if (month < other.month) return EARLIER;
+ if (month > other.month) return LATER;
+ if (day < other.day) return EARLIER;
+ if (day > other.day) return LATER;
+
+ return SAME_TIME;
+ }
+
+/*************************************************
+* Compare two EAC_Times for in various ways *
+*************************************************/
+bool operator==(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) == 0);
+ }
+bool operator!=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) != 0);
+ }
+bool operator<=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) <= 0);
+ }
+bool operator>=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) >= 0);
+ }
+bool operator>(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) > 0);
+ }
+bool operator<(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) < 0);
+ }
+
+/*************************************************
+* Do a validity check *
+*************************************************/
+s32bit validity_check(const EAC_Time& start, const EAC_Time& end,
+ u64bit current_time)
+ {
+
+ const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1;
+
+ if (start.cmp(current_time) > 0)
+ return NOT_YET_VALID;
+ if (end.cmp(current_time) < 0)
+ return EXPIRED;
+ return VALID_TIME;
+ }
+
+/*************************************************
+* Decode a BER encoded EAC_Time *
+*************************************************/
+void EAC_Time::decode_from(BER_Decoder& source)
+ {
+ BER_Object obj = source.get_next_object();
+ if (obj.type_tag != this->tag)
+ {
+ std::string message("decoding type mismatch for EAC_Time, tag is ");
+ std::stringstream ss;
+ std::string str_is;
+ ss << std::hex << obj.type_tag;
+ ss >> str_is;
+ message.append(str_is);
+ message.append(", while it should be ");
+ std::stringstream ss2;
+ std::string str_should;
+ ss2 << std::hex << this->tag;
+ ss2 >> str_should;
+ message.append(str_should);
+ throw Decoding_Error(message);
+
+ }
+ if (obj.value.size() != 6)
+ {
+ throw Decoding_Error("EAC_Time decoding failed");
+ }
+ try
+ {
+ u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]);
+ u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]);
+ u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]);
+ year = tmp_year + 2000;
+ month = tmp_mon;
+ day = tmp_day;
+ }
+ catch (Invalid_Argument)
+ {
+ throw Decoding_Error("EAC_Time decoding failed");
+ }
+
+ }
+
+u32bit EAC_Time::get_year() const
+ {
+ return year;
+ }
+u32bit EAC_Time::get_month() const
+ {
+ return month;
+ }
+u32bit EAC_Time::get_day() const
+ {
+ return day;
+ }
+
+/*************************************************
+* make the value an octet string for encoding *
+*************************************************/
+SecureVector<byte> EAC_Time::encoded_eac_time() const
+ {
+ SecureVector<byte> result;
+ result.append(enc_two_digit(year));
+ result.append(enc_two_digit(month));
+ result.append(enc_two_digit(day));
+ return result;
+ }
+
+ASN1_Ced::ASN1_Ced(std::string const& str)
+ : EAC_Time(str, ASN1_Tag(37))
+ {}
+
+ASN1_Ced::ASN1_Ced(u64bit val)
+ : EAC_Time(val, ASN1_Tag(37))
+ {}
+
+ASN1_Ced::ASN1_Ced(EAC_Time const& other)
+ : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(37))
+ {}
+
+ASN1_Cex::ASN1_Cex(std::string const& str)
+ : EAC_Time(str, ASN1_Tag(36))
+ {}
+
+ASN1_Cex::ASN1_Cex(u64bit val)
+ : EAC_Time(val, ASN1_Tag(36))
+ {}
+
+ASN1_Cex::ASN1_Cex(EAC_Time const& other)
+ : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(36))
+ {}
+
+}