// X509Cert.cpp - Implementation of X509Cert 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 "pkiX509Cert.h" using namespace pki; X509Cert::X509Cert() { } X509Cert::X509Cert(const X509Cert &cert) { *this = cert; } X509Cert::X509Cert(const std::string &buffer) { *this = buffer; } X509Cert::X509Cert(const unsigned char *buffer, const unsigned long size) { m_Cert = BEROctet(buffer,size); Decode(); } X509Cert& X509Cert::operator=(const X509Cert &cert) { m_Cert = cert.m_Cert; Decode(); return *this; } X509Cert& X509Cert::operator=(const std::string &buffer) { m_Cert = BEROctet((unsigned char*)buffer.data(),buffer.size()); Decode(); return *this; } // Returns Serial Number (long) integer value. std::string X509Cert::SerialNumber() const { std::string RetVal((char*)m_SerialNumber.Data(),m_SerialNumber.DataSize()); return RetVal; } // Returns whole DER string of Issuer std::string X509Cert::Issuer() const { std::string RetVal((char*)m_Issuer.Octet(),m_Issuer.OctetSize()); return RetVal; } // Returns list of attributes in Issuer matching id-at-organizationName. // List will be invalidated when object changes. std::vector X509Cert::IssuerOrg() const { std::vector orgNames; std::vector orgOcts; m_Issuer.SearchOIDNext("2 5 4 10",orgOcts); // Issuer's id-at-organizationName for(long i=0; iData(), orgOcts[i]->DataSize()); orgNames.push_back(oName); } return orgNames; } // Returns whole DER string of Subject std::string X509Cert::Subject() const { std::string RetVal((char*)m_Subject.Octet(),m_Subject.OctetSize()); return RetVal; } // Returns list of attributes in Subject matching id-at-commonName // List will be invalidated when object changes. std::vector X509Cert::SubjectCommonName() const { std::vector cnNames; std::vector cnOcts; m_Subject.SearchOIDNext("2 5 4 3",cnOcts); // Subject's id-at-commonName for(long i=0; iData(), cnOcts[i]->DataSize()); cnNames.push_back(cnName); } return cnNames; } // Returns modulus from SubjectPublicKeyInfo, stripped for any leading zero(s). std::string X509Cert::Modulus() const { std::string RawMod = RawModulus(); unsigned long i = 0; while(!RawMod[i] && iData(); unsigned long ModSize = PubKeyOct.SubOctetList()[0]->DataSize(); return std::string((char*)Mod,ModSize); } // Returns public exponent from SubjectPublicKeyInfo, stripped for any leading zero(s). std::string X509Cert::PublicExponent() const { std::string RawPubExp = RawPublicExponent(); unsigned long i = 0; while(!RawPubExp[i] && iData(); unsigned long PubExpSize = PubKeyOct.SubOctetList()[1]->DataSize(); return std::string((char*)PubExp,PubExpSize); } // Returns KeyUsage attribute, left justified with most significant bit as first bit (BER convention) unsigned long X509Cert::KeyUsage() const { if(!m_Extensions.Octet()) throw Exception(ccX509CertExtensionNotPresent); unsigned long ReturnKeyUsage = 0; const unsigned char UnusedBitsMask[] = {0xFF,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80}; std::vector ExtensionList; m_Extensions.SearchOID("2 5 29 15",ExtensionList); // "Extensions" octets containing id-ce-keyUsage if(ExtensionList.size()!=1) throw Exception(ccX509CertExtensionNotPresent); // One and only one instance BEROctet const* Extension = ExtensionList[0]; BEROctet* extnValue = 0; if(Extension->SubOctetList().size()==2) extnValue = Extension->SubOctetList()[1]; // No "critical" attribute present else if(Extension->SubOctetList().size()==3) extnValue = Extension->SubOctetList()[2]; // A "critical" attribute present else throw Exception(ccX509CertFormatError); // "Extensions" must contain either 2 or 3 octets unsigned char *KeyUsageBlob = extnValue->Data(); unsigned long KeyUsageBlobSize = extnValue->DataSize(); BEROctet KeyUsage(KeyUsageBlob,KeyUsageBlobSize); unsigned char *KeyUsageBitString = KeyUsage.Data(); unsigned long KeyUsageBitStringSize = KeyUsage.DataSize(); unsigned char UnusedBits = KeyUsageBitString[0]; unsigned long NumBytes = KeyUsageBitStringSize-1; if(NumBytes>4) { NumBytes = 4; // Truncate to fit the ulong, should be plenty though UnusedBits = 0; } unsigned long Shift = 24; for(unsigned long i=0; iSubOctetList().size(); if(!Size) throw Exception(ccX509CertFormatError); int i = 0; BEROctet *first = tbsCert->SubOctetList()[i]; if((first->Class()==2) && (first->Tag()==0)) i++; // Version if(Size < (6+i)) throw Exception(ccX509CertFormatError); m_SerialNumber = *(tbsCert->SubOctetList()[i]); i++; // SerialNumber i++; // Signature (algorithm) m_Issuer = *(tbsCert->SubOctetList()[i]); i++; // Issuer i++; // Validity m_Subject = *(tbsCert->SubOctetList()[i]); i++; // Subject m_SubjectPublicKeyInfo = *(tbsCert->SubOctetList()[i]); i++; // SubjectPublicKeyInfo m_Extensions = BEROctet(); while(iSubOctetList()[i]; if((oct->Class()==2) && (oct->Tag()==3)) { m_Extensions = *oct; break; } i++; } }