////////////////////////////////////////////////////////////////////////////////// // Name: actUtility.h // Product: cv act library // Purpose: useful global functions // // Copyright: (c) 2000-2001 cv cryptovision GmbH // all rights reserved // Licence: The conditions for the use of this software are regulated // in the cv act library licence agreement. ////////////////////////////////////////////////////////////////////////////////// #ifndef ACT_Utility_h #define ACT_Utility_h #include "actBlob.h" #include "actBasics.h" #include "actException.h" #include #include #include #include #include #include #if defined(__GNUC__) && (__GNUC__ < 4) namespace act { typedef std::basic_string wstring; } #else namespace act { using std::wstring; } #endif namespace act { class IParam; // // Const Values // extern const size_t sizeof_uuid; // // Prototypes // const char* get_string_param(paramid_t id, IParam* owner); // Converts an unsigned hexadecimal number (independent of prefix "0x") // into a Blob and backwards. // - for blob2hex: the user has to allocate hexnumber Blob& hex2blob(const char* hexnumber, Blob& b); inline Blob& hex2blob(const std::string& hexnumber, Blob& b) { return hex2blob(hexnumber.c_str(), b); } inline Blob hex2blob(const char* hexnumber) { Blob b; return move(hex2blob(hexnumber, b)); } void blob2hex(const Blob& b, char* hexnumber); std::string blob2hex(const Blob& b); // file i/o for act::Blob bool file2blob(const char* filename, Blob &blob); bool blob2file(const char* filename, const act::Blob &blob); // Create an ISO 9834-8 / RFC 4122 version 4 (pseudo random) UUID. // Output string format is "xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx", where // x is random hex char 0 <= x <= f and v an element of { 8, 9, a, b}. void createPseudoRandomUUID(Blob& uuid, bool network_byte_order = true); std::string createPseudoRandomUUID(); std::string uuid2string(const Blob& uuid, bool is_network_byte_order = true); void swapTimeFields(Blob& uuid); std::string serno2string(const act::Blob& serno); std::string id2string(const act::Blob& id, bool is_network_byte_order = true); // CBCMAC with ISO padding void iCBCMAC(const char* cipher, const Blob& iv, const Blob& mac_key, const Blob& mac_data, Blob& mac); void SetDESKeyParity(Blob &key); bool CheckDESKeyParity(const Blob &key); void get_string_seq(const std::string& s, const std::string start, const std::string end, std::string& result, bool case_sens); bool wstr2utf8(const wchar_t* str, std::string& utf8); bool utf82wstr(const char* utf8, act::wstring& wstr); void ASN1ToSequenceOf(Blob& asn1_data); Blob GetASN1SequenceOf(const Blob& asn1_data); Blob GetASN1EncodedLength(size_t length); size_t SkipTagLength(byte tag, const byte* tlv_data, size_t tlv_data_len); size_t SkipTLVElement(byte tag, const byte* tlv_data, size_t tlv_data_len, bool skip_value = true); int FindTlvTemplate(Blob& contentb, const Blob& inb, int intag, int counts); // // Implementation // // // -------------------------------------------------------------------- template const Blob SafeGetName(TypeT* instance) { Blob name; if(instance != 0) { const char* cname = RegistryT::GetName(instance->GetCreatePointer()); if(cname != 0) ConverterT(cname).swap(name); } return move(name); } // --------------------------------------------------------------------------- template struct is_whitespace : is_whitespace { typedef typename TypeT::value_type argument_type; using is_whitespace::operator(); }; template<> struct is_whitespace { typedef char argument_type; bool operator()(unsigned char value) const { return std::isspace(value) != 0; } }; template<> struct is_whitespace { typedef wchar_t argument_type; bool operator()(wchar_t value) const { return std::iswspace(value) != 0; } }; // --------------------------------------------------------------------------- template inline TypeT& erase_right(const PredicateT& predicate, TypeT& value) { value.erase(std::find_if(value.rbegin(), value.rend(), predicate).base(), value.end()); return value; } // --------------------------------------------------------------------------- template inline void fill(TypeT* begin, size_t length, byte value) { ACT_ASSERT(begin != 0); std::fill(reinterpret_cast(begin), reinterpret_cast(begin) + length, value); } // // scoped_delete // --------------------------------------------------------------------------- template struct scoped_delete { PointerT _ptr; explicit scoped_delete(PointerT ptr) : _ptr(ptr) { } ~scoped_delete() { delete _ptr; } PointerT operator->() const { if(_ptr == 0) throw NullPointerException(); return _ptr; } }; // --------------------------------------------------------------------------- template scoped_delete checked_delete(PointerT& ptr_ref) { PointerT ptr = ptr_ref; ptr_ref = 0; return scoped_delete(ptr); } // // scoped_delete // --------------------------------------------------------------------------- template < template class AutoPtrT, class TypeT > struct scoped_delete, void, 1> { AutoPtrT _ptr; explicit scoped_delete(AutoPtrT& ptr) : _ptr(ptr) { } ~scoped_delete() { AutoPtrT(_ptr); } TypeT* operator->() const { TypeT* ptr = _ptr.get(); if(ptr == 0) throw NullPointerException(); return ptr; } }; // --------------------------------------------------------------------------- template < template class AutoPtrT, class TypeT > scoped_delete, void, 1> checked_delete(AutoPtrT& ptr_ref) { return scoped_delete, void, 1>(ptr_ref); } // // scoped_delete > // --------------------------------------------------------------------------- template < template class ArrayT, class TypeT, class AllocatorT, typename DestructF > struct scoped_delete, DestructF, 3> { typedef ArrayT container_type; typedef DestructF destruct_func; explicit scoped_delete(container_type& _container, const destruct_func& _destruct) : destruct(_destruct) { container.swap(_container); } ~scoped_delete() { release(container, destruct); } static void release(container_type& container, const destruct_func& destruct) { if(container.empty() == true) return; container_type failed; typedef typename container_type::const_iterator const_iterator; for(const_iterator i(container.begin()), end(container.end()); i != end; ++i) try { destruct(*i); } catch(Exception&) { failed.push_back(*i); } container.swap(failed); } destruct_func destruct; container_type container; }; // // checked_delete(array_of_ptr_to_type, std::mem_fun(&type::destruct)); // --------------------------------------------------------------------------- template < template class ArrayT, class TypeT, class AllocatorT, typename DestructF > scoped_delete, DestructF, 3> checked_delete(ArrayT& container, const DestructF& destruct) { return scoped_delete, DestructF, 3>(container, destruct); } // // scoped_delete > // --------------------------------------------------------------------------- template < template class MapT, class KeyT, class TypeT, class PredT, class AllocatorT, typename DestructF > struct scoped_delete, DestructF, 4> { typedef MapT container_type; typedef DestructF destruct_func; explicit scoped_delete(container_type& _container, const destruct_func& _destruct) : destruct(_destruct) { container.swap(_container); } ~scoped_delete() { release(container, destruct); } static void release(container_type& container, const destruct_func& destruct) { if(container.empty() == true) return; container_type failed; typedef typename container_type::const_iterator const_iterator; for(const_iterator i(container.begin()), end(container.end()); i != end; ++i) try { destruct(i->second); } catch(Exception&) { failed.insert(*i); } container.swap(failed); } destruct_func destruct; container_type container; }; // // checked_delete_map(map_of_ptr_to_type, std::mem_fun(&type::destruct)); // --------------------------------------------------------------------------- template < template class MapT, class KeyT, class TypeT, class PredT, class AllocatorT, typename DestructF > scoped_delete, DestructF, 4> checked_delete_map(MapT& map_ref, const DestructF& destruct) { return scoped_delete, DestructF, 4>(map_ref, destruct); } // // scoped_delete<> // --------------------------------------------------------------------------- template struct scoped_delete { scoped_delete(const DestructF& _destruct) : destruct(_destruct) { } ~scoped_delete() { if(value.empty() == false) checked_delete(value, destruct); } DestructF destruct; TypeT value; }; // // checked_static_cast<> // --------------------------------------------------------------------------- template inline U checked_static_cast(V p) { ACT_ASSERT(p != 0); ACT_ASSERT(dynamic_cast(p) != 0); return static_cast(p); } // --------------------------------------------------------------------------- template inline TypeT& byref(const TypeT& e) { return const_cast(e); } // --------------------------------------------------------------------------- inline int max_int() { return int((unsigned(1) << (8 * sizeof(int) - 1)) - 1); } // --------------------------------------------------------------------------- inline void OS2IP(Blob& number) { // octet string to integer presentation if((number.at(0) & byte(0x80)) != 0) number.insert(number.begin(), 0); } // --------------------------------------------------------------------------- inline void I2OSP(Blob& number) { // integer to octet string presentation if(number.at(0) == byte(0)) number.erase(number.begin()); } // --------------------------------------------------------------------------- inline void byte2long(const byte *in, size_t input_len, uint32 *out) { size_t i, output_len = input_len / 4; for(i = 0; i < output_len; i++) out[i]= in[i*4] | (in[i*4+1] << 8) | (in[i*4+2] << 16) | (in[i*4+3] << 24); } // --------------------------------------------------------------------------- inline void long2byte(const uint32 *in, size_t input_len, byte *out) { size_t i, output_len = input_len * 4; for(i = 0; i < output_len; i++) out[i] = byte(in[i/4] >> (8*(i%4))); } // --------------------------------------------------------------------------- inline void sweep(void* Mem,size_t l) { std::fill_n(reinterpret_cast(Mem), l, byte(0)); } // --------------------------------------------------------------------------- template inline const TypeT Min(const TypeT& a, const TypeT& b) { return (a < b) ? a : b; } // --------------------------------------------------------------------------- template inline const TypeT& Max(const TypeT& a, const TypeT& b) { return (a inline void xor_n(T1 a, T2 len, T3 b) { for(T2 i = 0; i < len; i++) b[i] ^= a[i]; } // --------------------------------------------------------------------------- template inline void Xor (T1 a, T1 a_end, T3 b) { while(a < a_end) *b++ ^= *a++; } // --------------------------------------------------------------------------- inline const char* blob2char(Blob& b) { b.push_back(byte(0)); return reinterpret_cast(&b[0]); } // --------------------------------------------------------------------------- inline std::string blob2string(const Blob& value) { return value.empty() == false ? std::string(reinterpret_cast(&value.at(0)), reinterpret_cast(&value[0] + value.size())) : std::string(); } // --------------------------------------------------------------------------- inline std::string byte2hex(const byte i) { char tmp[3]; sprintf(tmp, "%02x", i); return tmp; } // --------------------------------------------------------------------------- inline bool isHex(const byte c) { if((c < byte('0') || c > byte('9')) && (c < byte('a') || c > byte('f')) && (c < byte('A') || c > byte('F'))) return false; return true; } // --------------------------------------------------------------------------- inline bool isHex(const Blob& b) { size_t i, b_len = b.size(); for(i = 0; i < b_len; ++i) if(!isHex(b[i])) return false; return true; } // --------------------------------------------------------------------------- inline bool isAlphanumeric(const byte c) { if((c < byte('0') || c > byte('9')) && (c < byte('a') || c > byte('z')) && (c < byte('A') || c > byte('Z'))) return false; return true; } // --------------------------------------------------------------------------- inline bool isAlphanumeric(const Blob& b) { size_t i, b_len = b.size(); for(i = 0; i < b_len; ++i) if(!isAlphanumeric(b[i])) return false; return true; } // --------------------------------------------------------------------------- inline bool isPrintable(const Blob& b) { size_t i, b_len = b.size(); for(i = 0; i < b_len; ++i) if(isprint(int(b[i])) == 0) return false; return true; } // --------------------------------------------------------------------------- inline bool isUUIDFormat(const Blob& b) { size_t b_len = b.size(); if(b_len != sizeof_uuid) return false; // check if the Blob contains only hexadecimal characters, // separated by '-' (UUID string representation) for(size_t i = 0; i < b_len; ++i) if(!isHex(b[i]) && (b[i] != byte('-'))) return false; return true; } // --------------------------------------------------------------------------- inline std::string short2hex(const unsigned short i) { char tmp[5]; sprintf(tmp,"%04x",i); return tmp; } // --------------------------------------------------------------------------- inline std::string long2hex(const unsigned long i) { char tmp[9]; sprintf(tmp,"%08lx",i); return tmp; } // --------------------------------------------------------------------------- inline unsigned long blob2long(const Blob& b) { if(b.size() == 0) throw LogicalException("bad size","blob2long"); Blob tmp(b); while(tmp[0] == 0 && tmp.size() > sizeof(long)) tmp.erase(tmp.begin()); if(tmp.size() > sizeof(long)) throw LogicalException("bad size", "blob2long"); unsigned long n = tmp[0]; for(unsigned int i = 1; i < tmp.size(); ++i) { n <<= 8; n |= tmp[i]; } return n; } // --------------------------------------------------------------------------- inline Blob& long2blob(unsigned long n, Blob& value) { value.resize(sizeof(long)); for(size_t i = sizeof(long) - 1, j = 0; j < sizeof(long); --i, ++j) value[j] = byte((n >> (8 * i)) & 0xff); return value; } // --------------------------------------------------------------------------- inline Blob long2blob(unsigned long n) { Blob value; return move(long2blob(n, value)); } // --------------------------------------------------------------------------- inline Blob size2blob(size_t size) { Blob tmp; tmp.reserve(8); if(size == 0) { tmp.resize(1); return move(tmp); } size_t remaining = size; while(remaining > 0) { tmp.insert(tmp.begin(), byte(remaining & 0xFF)); remaining >>= 8; } return move(tmp); } // --------------------------------------------------------------------------- inline unsigned short blob2short(const Blob& b) { if(b.size() != sizeof(short)) throw LogicalException("bad size", "blob2short"); unsigned short n = b[1]; n += (b[0] << 8); return n; } // --------------------------------------------------------------------------- // Input: a (big endian byte arrays) // Output: ++a (increment with carry) inline byte memincr(byte* a, int len) { int i = len-1; byte carry; do { carry = ++a[i] == 0 ? 1 : 0; } while( --i >= 0 && carry != 0); return carry; } // --------------------------------------------------------------------------- // Input: a, b (big endian byte arrays) // Output: a += b (add with carry) inline byte memadd(byte* a, const byte* b, int len, byte carry = 0) { int i = len - 1; unsigned long tmp; for(; i >= 0; --i) { tmp = a[i] + b[i] + carry; a[i] = byte(tmp & 0xff); carry = byte(tmp >> 8); } return carry; } // --------------------------------------------------------------------------- inline void convert_to_upper(std::string& s) { for(std::string::iterator it = s.begin(); it != s.end() ; ++it) *it = toupper(*it); } } //namespace act #endif // ACT_Utility_h