windows-nt/Source/XPSP1/NT/ds/security/csps/cryptoflex/slbpki/beroctet.cpp

303 lines
6.8 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// BEROctet.cpp - Implementation of BEROctet class
//
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
// 1999. This computer program includes Confidential, Proprietary
// Information and is a Trade Secret of Schlumberger Technology Corp. All
// use, disclosure, and/or reproduction is prohibited unless authorized
// in writing. All Rights Reserved.
//////////////////////////////////////////////////////////////////////
#include "pkiBEROctet.h"
using namespace pki;
BEROctet::BEROctet() : m_Octet(0)
{
}
BEROctet::BEROctet(const BEROctet &oct)
{
m_Octet = 0;
*this = oct;
}
BEROctet::BEROctet(const unsigned char *Buffer, const unsigned long Size)
{
m_Octet = new unsigned char[Size];
memcpy(m_Octet,Buffer,Size);
m_OctetSize = Size;
Decode();
}
BEROctet::~BEROctet(void)
{
for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
if(m_Octet) delete[] m_Octet;
}
BEROctet& BEROctet::operator=(const BEROctet &Oct)
{
if(m_Octet) delete[] m_Octet;
for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
m_SubOctetList.resize(0);
if(Oct.m_Octet) {
m_Octet = new unsigned char[Oct.m_OctetSize];
memcpy(m_Octet,Oct.m_Octet,Oct.m_OctetSize);
m_OctetSize = Oct.m_OctetSize;
Decode();
}
else {
m_Octet = 0;
}
return *this;
}
// Returns the octet data
unsigned char *BEROctet::Octet() const
{
return m_Octet;
}
unsigned long BEROctet::OctetSize() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_OctetSize;
}
// Returns true if the octet is constructet, false otherwise
bool BEROctet::Constructed() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_PrimConst ? true : false;
}
// Returns the class of the octet
unsigned long BEROctet::Class() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Class;
}
// Returns the tag of the octet
unsigned long BEROctet::Tag() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Tag;
}
// Returns a the data part of the octet
unsigned char *BEROctet::Data() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Data;
}
// Returns a the size of the data part of the octet
unsigned long BEROctet::DataSize() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_DataSize;
}
// If the octet is a constructed type, this returns list of sub-octets
std::vector<BEROctet*> BEROctet::SubOctetList() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_SubOctetList;
}
// If the octet is an OID, this returns the decoded version, otherwise an empty string
std::string BEROctet::ObjectID() const
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
std::string OID;
if(m_Class==0 && m_Tag==6) {
char text[40];
unsigned long subid;
unsigned char *c = m_Data;
unsigned char *Last = m_Octet + m_OctetSize;
bool First = true;
while(c<Last) {
subid = (*c)&0x7F;
while((*c)&0x80) {
c++; if(c>=Last) throw Exception(ccBERUnexpectedEndOfOctet);
if(subid>0x01FFFFFF) throw Exception(ccBEROIDSubIdentifierOverflow);
subid = (subid<<7) | ((*c)&0x7F);
}
if(First) {
unsigned long X,Y;
if(subid<40) X=0;
else if(subid<80) X=1;
else X=2;
Y = subid-X*40;
sprintf(text,"%d %d",X,Y);
OID = text;
First = false;
}
else {
sprintf(text," %d",subid);
OID += text;
}
c++;
}
}
return OID;
}
// SearchOID returns all the constructed octets that contain a particular OID
void BEROctet::SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const
{
for(int i=0; i<m_SubOctetList.size(); i++) {
if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) {
if(OID==m_SubOctetList[i]->ObjectID()) {
result.push_back(this);
}
}
else if(m_SubOctetList[i]->Constructed()) {
m_SubOctetList[i]->SearchOID(OID,result);
}
}
return;
}
// SearchOIDNext returns all the octets following a particular OID
void BEROctet::SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const
{
for(int i=0; i<m_SubOctetList.size(); i++) {
if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) {
if(OID==m_SubOctetList[i]->ObjectID()) {
if((i+1) < m_SubOctetList.size()) result.push_back(m_SubOctetList[i+1]);
}
}
else if(m_SubOctetList[i]->Constructed()) {
m_SubOctetList[i]->SearchOIDNext(OID,result);
}
}
return;
}
// Decodes recursively a BER octet.
void BEROctet::Decode()
{
if(!m_Octet) throw Exception(ccBEREmptyOctet);
long BufferSize = m_OctetSize;
m_PrimConst = (m_Octet[0]>>5) & 0x1;
m_Class = (m_Octet[0]>>6) & 0x3;
unsigned char *c = m_Octet;
unsigned char *Last = c + BufferSize - 1;
m_Tag = *c & 0x1F;
if(m_Tag>30) {
m_Tag = 0;
c++;
if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
while (*c & 0x80) {
m_Tag = (m_Tag << 7) | ((*c) & 0x7F);
c++;
if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
}
if(m_Tag > 0x01FFFFFF) throw Exception(ccBERTagValueOverflow);
m_Tag = (m_Tag << 7) | ((*c) & 0x7F);
}
c++;
if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
long DataSize;
if((*c)&0x80) {
int n = (*c) & 0x7F;
if(n) {
DataSize = 0;
for(int i=0; i<n; i++) {
c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
if(DataSize>0x007FFFFF) throw Exception(ccBERDataLengthOverflow);
DataSize = (DataSize<<8) | (*c);
}
}
else throw Exception(ccBERUnexpectedIndefiniteLength);
}
else DataSize = *c;
c++;
m_Data = c;
m_DataSize = DataSize;
unsigned long OctetSize = DataSize + (m_Data-m_Octet);
if(OctetSize>BufferSize) throw Exception(ccBERInconsistentDataLength);
m_OctetSize = OctetSize;
for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
m_SubOctetList.resize(0);
if(m_PrimConst) {
// Constructed type
unsigned char *Data = m_Data;
unsigned long DataSize = m_DataSize;
while(DataSize) {
BEROctet *oct = new BEROctet(Data,DataSize);
m_SubOctetList.push_back(oct);
Data += oct->OctetSize();
DataSize -=oct->OctetSize();
}
}
}