📄 asn1.cxx
字号:
/* * asn1.cxx * * Abstract Syntax Notation 1 Encoding Rules * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * Copyright (c) 2001 Institute for Information Industry, Taiwan, Republic of China * (http://www.iii.org.tw/iiia/ewelcome.htm) * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): Huang-Ming Huang * * The code is adapted from asner.cxx of PWLib, but the dependancy on PWLib has * been removed. * * $Log: asn1.cxx,v $ * Revision 1.7 2002/07/03 06:01:59 btrummer * Fixed two buffer overflows in OBJECT_IDENTIFIER::decodeCommon(), * that may occur, when decoding invalid (random) data. * * Revision 1.6 2002/07/02 04:45:13 mangelo * Modify for VC.Net and GCC 3.1 * * Revision 1.5 2002/01/11 05:43:12 mangelo * Fixed OBJECT_IDENTIFIER::decodeCommon (Thanks to George Biro) * * Revision 1.4 2001/10/09 16:39:11 mangelo * fixed the problem when vector<char*>::iterator is not char* * * Revision 1.3 2001/10/05 19:15:11 mangelo * Change Log Sequence * * Revision 1.2 2001/10/05 19:00:37 mangelo * Added Log * * 2001/07/16 Huang-Ming Huang * Optional components of SEQUENCE is now created on demand. * * 2001/06/26 Huang-Ming Huang * Version 2.1 Reimplemented to minimize the code size. * * 2001/05/01 Huang-Ming Huang * Fixed problem with unconstrained PASN_NumericString coding in 8 bits * instead of 4 in accordance with PWLib asner.cxx Revision 1.39. */#ifdef _MSC_VER#pragma warning(disable: 4786)#endif#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <boost/cast.hpp>#include <stdio.h>#include "asn1.h"#ifdef ASN1_HAS_IOSTREAM#include "ios_helper.h"#endifnamespace ASN1 { enum TagClass { UniversalTagClass =0, ApplicationTagClass = 0x40, ContextSpecificTagClass = 0x80, PrivateTagClass = 0xC0, }; enum UniversalTags { InvalidUniversalTag, UniversalBoolean, UniversalInteger, UniversalBitString, UniversalOctetString, UniversalNull, UniversalObjectId, UniversalObjectDescriptor, UniversalExternalType, UniversalReal, UniversalEnumeration, UniversalEmbeddedPDV, UniversalSequence = 16, UniversalSet, UniversalNumericString, UniversalPrintableString, UniversalTeletexString, UniversalVideotexString, UniversalIA5String, UniversalUTCTime, UniversalGeneralisedTime, UniversalGraphicString, UniversalVisibleString, UniversalGeneralString, UniversalUniversalString, UniversalBMPString = 30 };unsigned CountBits(unsigned range){ if (range == 0) return sizeof(unsigned)*8; unsigned nBits = 0; while (nBits < (sizeof(unsigned)*8) && range > (unsigned)(1 << nBits)) nBits++; return nBits;}int lexicographic_compare_bytes(const char* first1, const char* last1, const char* first2, const char* last2){ int r; for (; first1 != last1 && first2 != last2; ++first1, ++first2) { r = *first1 - *first2; if (r != 0) return r; } if (first1 == last1 && first2 == last2) return 0; return (first1 != last1 ? 1 : -1);}/////////////////////////////////////////////////////////////////////AbstractData::AbstractData(const void* information): info_(information){}////////////////////////////////////////////////////////////const Null::InfoType Null::theInfo = { Null::create, UniversalTagClass << 16 | UniversalNull};AbstractData* Null::create(const void* info){ return new Null(info);}bool Null::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool Null::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}AbstractData * Null::do_clone() const{ assert(typeid(*this) == typeid(Null)); return new Null(*this);}int Null::do_compare(const AbstractData& other) const{ assert(typeid(other) == typeid(Null)); return 0;}/////////////////////////////////////////////////////////const BOOLEAN::InfoType BOOLEAN::theInfo = { BOOLEAN::create, UniversalTagClass << 16 | UniversalBoolean };BOOLEAN::BOOLEAN(const void* info): AbstractData(info), value(false){}BOOLEAN::BOOLEAN(bool b, const void* info) : AbstractData(info),value(b) {}BOOLEAN::BOOLEAN(const BOOLEAN& that): AbstractData(that), value(that.value){}AbstractData* BOOLEAN::create(const void* info){ return new BOOLEAN(info);}bool BOOLEAN::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool BOOLEAN::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}AbstractData * BOOLEAN::do_clone() const{ assert(typeid(*this) == typeid(BOOLEAN)); return new BOOLEAN(*this);}int BOOLEAN::do_compare(const AbstractData& data) const{ const BOOLEAN& that = *boost::polymorphic_downcast<const BOOLEAN*>(&data); return value - that.value;}///////////////////////////////////////////////////////////////////////const INTEGER::InfoType INTEGER::theInfo = { &INTEGER::create, UniversalTagClass << 16 | UniversalInteger, Unconstrained, 0, UINT_MAX};INTEGER::INTEGER(const void* info): ConstrainedObject(info), value(0){}INTEGER::INTEGER(int_type val, const void* info) : ConstrainedObject(info), value(val){ }INTEGER::INTEGER(const INTEGER& other): ConstrainedObject(other), value(other.value){}AbstractData* INTEGER::create(const void* info){ return new INTEGER(info);}bool INTEGER::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool INTEGER::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}AbstractData * INTEGER::do_clone() const{ return new INTEGER(*this);}int INTEGER::do_compare(const AbstractData& data) const{ const INTEGER& that = *boost::polymorphic_downcast<const INTEGER*>(&data); if (getLowerLimit() >= 0) return value - that.value; else return (int) value - (int) that.value;}///////////////////////////////////////////////////////IntegerWithNamedNumber::IntegerWithNamedNumber(const void* info): INTEGER(info){}IntegerWithNamedNumber::IntegerWithNamedNumber(int val, const void* info): INTEGER(val, info){}AbstractData* IntegerWithNamedNumber::create(const void* info){ return new IntegerWithNamedNumber(info);}bool IntegerWithNamedNumber::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool IntegerWithNamedNumber::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}//////////////////////////////////////////////////////ENUMERATED::ENUMERATED(const void* info): AbstractData(info), value(0){ assert(getMaximum() > 0);}ENUMERATED::ENUMERATED(const ENUMERATED& that): AbstractData(that), value(that.value){ }ENUMERATED& ENUMERATED::operator = (const ENUMERATED& that) { assert(info() == that.info()); // compatible type check value = that.value; return *this;}bool ENUMERATED::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool ENUMERATED::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}AbstractData * ENUMERATED::do_clone() const{ return new ENUMERATED(*this);}int ENUMERATED::do_compare(const AbstractData& other) const{ const ENUMERATED& that = *static_cast<const ENUMERATED*>(&other); assert(info_ == that.info_); // compatible type check return value - that.value;}AbstractData* ENUMERATED::create(const void* info){ return new ENUMERATED(info);}///////////////////////////////////////////////////////////////////////const OBJECT_IDENTIFIER::InfoType OBJECT_IDENTIFIER::theInfo = { OBJECT_IDENTIFIER::create, UniversalTagClass << 16 | UniversalObjectId};OBJECT_IDENTIFIER::OBJECT_IDENTIFIER(const OBJECT_IDENTIFIER & other): AbstractData(other), value(other.value){}AbstractData* OBJECT_IDENTIFIER::create(const void* info){ return new OBJECT_IDENTIFIER(info);}bool OBJECT_IDENTIFIER::do_accept(Visitor& visitor){ return visitor.visit(*this);}bool OBJECT_IDENTIFIER::do_accept(ConstVisitor& visitor) const{ return visitor.visit(*this);}bool OBJECT_IDENTIFIER::decodeCommon(const char* strm, unsigned dataLen){ unsigned byteOffset=0; value.clear(); // handle zero length strings correctly if (dataLen == 0) { return true; } unsigned subId; // Avoid reallocations in the while-loop below. value.reserve(dataLen+1); // start at the second identifier in the buffer, because we will later // expand the first number into the first two IDs value.push_back(0); while (dataLen > 0) { unsigned byte; subId = 0; do { /* shift and add in low order 7 bits */ if (dataLen == 0) return false; byte = strm[byteOffset++]; subId = (subId << 7) + (byte & 0x7f); dataLen--; } while ((byte & 0x80) != 0); value.push_back(subId); } /* * The first two subidentifiers are encoded into the first component * with the value (X * 40) + Y, where: * X is the value of the first subidentifier. * Y is the value of the second subidentifier. */ subId = value[1]; if (subId < 40) { value[0] = 0; value[1] = subId; } else if (subId < 80) { value[0] = 1; value[1] = subId-40; } else { value[0] = 2; value[1] = subId-80; } return true;}void OBJECT_IDENTIFIER::encodeCommon(std::vector<char> & encodecObjectId) const{ unsigned length = value.size(); const unsigned* objId = &value[0]; if (length < 2) { // Thise case is really illegal, but we have to do SOMETHING encodecObjectId.resize(0); return; } unsigned subId = (objId[0] * 40) + objId[1]; objId += 2; unsigned outputPosition = 0; encodecObjectId.reserve(length); std::insert_iterator<std::vector<char> > insertItr(encodecObjectId, encodecObjectId.begin()); while (--length > 0) { if (subId < 128) *insertItr++ = (char)subId; else { unsigned mask = 0x7F; /* handle subid == 0 case */ int bits = 0; /* testmask *MUST* !!!! be of an unsigned type */ unsigned testmask = 0x7F; int testbits = 0; while (testmask != 0) { if (subId & testmask) { /* if any bits set */ mask = testmask; bits = testbits; } testmask <<= 7; testbits += 7; } /* mask can't be zero here */ while (mask != 0x7F) { /* fix a mask that got truncated above */ if (mask == 0x1E00000) mask = 0xFE00000; *insertItr++ = (char)(((subId & mask) >> bits) | 0x80); mask >>= 7; bits -= 7; } *insertItr++ = (char)(subId & mask); } if (length >1) subId = *objId++; }}AbstractData * OBJECT_IDENTIFIER::do_clone() const{ return new OBJECT_IDENTIFIER(*this);}int OBJECT_IDENTIFIER::do_compare(const AbstractData& other) const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -