// x509cert.h - X.509 certificate read and write routines for Crypto++.
// Written and placed in the public domain by Jeffrey Walton
// and Geoff Beier
/// \file x509cert.h
/// \brief Classes and functions to read X.509 certificates
/// \details X509Certificate is a partial implementation of X.509 certificate
/// parsing. The class loads a DER encoded certificate and presents many of
/// the more important attributes and values through accessor functions. The
/// attributes and values include signature, signature algorithm, toBeSigned,
/// and subjectPublicKeyInfo exposed as a X509PubliKey ready for use in
/// Crypto++ library algorithms.
/// \details This is a library add-on. You must download and compile it
/// yourself as part of the library.
/// \since Crypto++ 8.3
/// \sa X509Certificate
/// and PEM Pack on the
/// Crypto++ wiki.
/////////////////////////////////////////////////////////////////////////////
#ifndef CRYPTOPP_X509_CERTIFICATE_H
#define CRYPTOPP_X509_CERTIFICATE_H
#include "cryptlib.h"
#include "secblock.h"
#include "stdcpp.h"
#include "asn.h"
#include
#include
#include
#include
NAMESPACE_BEGIN(CryptoPP)
// Forward declaration
class Integer;
/// \brief Convert OID to a LDAP name
/// \param oid the object identifier
/// \param defaultName the name to use if lookup fails
/// \returns the LDAP name for display
/// \details LDAP names are specified in ITU X.520 and other places, like the RFCs.
/// If defaultName is NULL, then the OID is used.
std::string OidToNameLookup(const OID& oid, const char *defaultName=NULLPTR);
/// \brief ASNTag initializer
/// \details 0 is an invalid tag value
const ASNTag InvalidTag = static_cast(0);
//////////////////////////////////////////////////
/// \brief X.500 Relative Distinguished Name value
struct RdnValue : public ASN1Object
{
virtual ~RdnValue() {}
RdnValue() : m_tag(InvalidTag) {}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
bool ValidateTag(byte tag) const;
/// \brief Print an RDN value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
OID m_oid;
SecByteBlock m_value;
ASNTag m_tag;
};
/// \brief Array of Relative Distinguished Name values
/// \details Vector or RdnValue
/// \sa RdnValue
typedef std::vector RdnValueArray;
//////////////////////////////////////////////////
/// \brief X.690 Date value
struct DateValue : public ASN1Object
{
DateValue() : m_tag(InvalidTag) {}
virtual ~DateValue() {}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
bool ValidateTag(byte tag) const;
/// \brief Print a Date value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
SecByteBlock m_value;
ASNTag m_tag;
};
//////////////////////////////////////////////////
/// \brief X.509 Extension value
struct ExtensionValue : public ASN1Object
{
virtual ~ExtensionValue() {}
ExtensionValue() : m_tag(InvalidTag), m_critical(false) {}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
bool ValidateTag(byte tag) const;
/// \brief Print an Extension value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
OID m_oid;
SecByteBlock m_value;
ASNTag m_tag;
bool m_critical;
};
/// \brief Array of X.509 Extension values
/// \details Vector or ExtensionValue
/// \sa ExtensionValue
typedef std::vector ExtensionValueArray;
//////////////////////////////////////////////////
/// \brief X.509 KeyIdentifier value
struct KeyIdentifierValue : public ASN1Object
{
enum KeyIdentifierEnum {
/// \brief Hash of the public key
Hash=1,
/// \brief Distinguised name and serial number
DnAndSn
};
/// \brief Invalid identifier
static const KeyIdentifierEnum InvalidKeyIdentifier = static_cast(0);
virtual ~KeyIdentifierValue() {}
KeyIdentifierValue() : m_type(InvalidKeyIdentifier) {}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
bool ValidateTag(byte tag) const;
/// \brief Print an Extension value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
// The hash of the key is placed in m_value.
// The remaining bits, like DN and Serno, are placed in m_other.
OID m_oid;
SecByteBlock m_value;
SecByteBlock m_other; // raw
KeyIdentifierEnum m_type;
};
//////////////////////////////////////////////////
/// \brief X.509 KU and EKU value
/// \details KeyUsageValue represents Key Usage and Extended Key Usage values
/// \sa KeyUsageValueArray
struct KeyUsageValue : public ASN1Object
{
// https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.3
enum KeyUsageEnum {
/// \brief Digital signature
digitalSignature=0,
/// \brief Signature verification
/// \details nonRepudiation applies to non-certificate data
nonRepudiation=1,
/// \brief Signature verification
/// \details contentCommitment is nonRepudiation and applies to non-certificate data
contentCommitment=nonRepudiation,
/// \brief Key transport
keyEncipherment,
/// \brief Data encryption
/// \details Encryption occurs with the public key, and not a symmetric key
dataEncipherment,
/// \brief Key agreement
keyAgreement,
/// \brief Certificate signature verification
keyCertSign,
/// \brief Certificate revocation list signature verification
cRLSign,
/// \brief Data encryption
/// \details Data encryption occurs with a key agreement key
encipherOnly,
/// \brief Data decryption
/// \details Data decryption occurs with a key agreement key
decipherOnly,
/// \brief TLS server authentication
serverAuth,
/// \brief TLS client authentication
clientAuth,
/// \brief Code signing
codeSigning,
/// \brief Email protection
emailProtection,
/// \brief IPsec end system
ipsecEndSystem,
/// \brief IPsec tunnel
ipsecTunnel,
/// \brief IPsec user
ipsecUser,
/// \brief Time stamping
timeStamping,
/// \brief OCSP signing
OCSPSigning,
/// \brief Data Validation and Certification Server
dvcs,
/// \brief Border gateway CA server
sbgpCertAAServerAuth,
/// \brief SCVP responder
scvpResponder,
/// \brief Extensible Authentication Protocol (EAP) over PPP
eapOverPPP,
/// \brief Extensible Authentication Protocol (EAP) over LAN
eapOverLAN,
/// \brief Server-Based Certificate Validation Protocol
scvpServer,
/// \brief Server-Based Certificate Validation Protocol
scvpClient,
/// \brief IPsec Internet Key Exchange
ipsecIKE,
/// \brief Control And Provisioning of Wireless Access Points (CAPWAP) Protocol
capwapAC,
/// \brief Control And Provisioning of Wireless Access Points (CAPWAP) Protocol
capwapWTP,
/// \brief Session Initiation Protocol (SIP) X.509 Certificates
sipDomain,
/// \brief X.509v3 Certificates for Secure Shell Authentication
secureShellClient,
/// \brief X.509v3 Certificates for Secure Shell Authentication
secureShellServer,
/// \brief Certificate Profile and Certificate Management for SEcure Neighbor Discovery (SEND)
sendRouter,
/// \brief Certificate Profile and Certificate Management for SEcure Neighbor Discovery (SEND)
sendProxiedRouter,
/// \brief Certificate Profile and Certificate Management for SEcure Neighbor Discovery (SEND)
sendOwner,
/// \brief Certificate Profile and Certificate Management for SEcure Neighbor Discovery (SEND)
sendProxiedOwner,
/// \brief Certificate Management over CMS
cmcCA,
/// \brief Certificate Management over CMS
cmcRA,
/// \brief Certificate Management over CMS
cmcArchive,
/// \brief BGPsec Router Certificates, Certificate Revocation Lists, and Certification Requests
bgpsecRouter,
/// \brief Certificate profile for carrying logotypes
brandIndicatorforMessageIdentification
};
/// \brief Invalid key usage
static const KeyUsageEnum InvalidKeyUsage = static_cast(128);
virtual ~KeyUsageValue() {}
/// \brief Construct a KeyUsageValue
/// \details Use this ctor for Extended Key Usage (EKU).
/// KeyUsageEnum can be looked up based on a unique OID.
KeyUsageValue(const OID& oid);
/// \brief Construct a KeyUsageValue
/// \details Use this ctor for Key Usage (KU). KeyUsageEnum
/// bitmask is a value of a common OID.
KeyUsageValue(const OID& oid, KeyUsageEnum usage);
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
/// \brief Print an Extension value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
OID m_oid;
// SecByteBlock m_value;
KeyUsageEnum m_usage;
};
/// \brief Array of X.509 Key usage values
/// \details Vector or KeyUsageValue
/// \sa KeyUsageValue
typedef std::vector KeyUsageValueArray;
//////////////////////////////////////////////////
/// \brief X.509 Basic Constraint
struct BasicConstraintValue : public ASN1Object
{
virtual ~BasicConstraintValue() {}
BasicConstraintValue(bool critical=true) : m_pathLen(0), m_critical(critical), m_ca(false) {}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
/// \brief Print an Extension value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
word32 m_pathLen;
bool m_critical, m_ca;
};
//////////////////////////////////////////////////
/// \brief Identity value
/// \details IdentityValue holds an identity and provides a textual representation of it.
struct IdentityValue
{
/// \brief Identity source
enum IdentityEnum {
/// \brief Subject Unique Identifier
/// \details Optional part of X.509 v2 specification
UniqueId=1,
/// \brief Subject Distinguished Name
/// \details Subject Distinguished Name (DN), which is a mashup of the RDNs
SubjectDN,
/// \brief Subject Common Name
/// \details Common Name RDN, optional part of Subject Distinguished Name (DN)
SubjectCN,
/// \brief Subject Unique Identifier
/// \details Subject Unique Identifier RDN, optional part of Subject Distinguished Name (DN)
SubjectUID,
/// \brief PKCS #9 email address
/// \details PKCS #9 Email RDN, optional part of Subject Distinguished Name (DN)
SubjectEmail,
/// \brief Subject Public Key Identifier (SPKI)
/// \details Optional part of X.509 v3 specification
SubjectPKI,
/// \brief SAN otherName
/// \details Optional Subject Alternate Name (SAN)
otherName,
/// \brief SAN rfc822Name
/// \details Optional Subject Alternate Name (SAN)
rfc822Name,
/// \brief SAN dNSName
/// \details Optional Subject Alternate Name (SAN)
dNSName,
/// \brief SAN x400Address
/// \details Optional Subject Alternate Name (SAN)
x400Address,
/// \brief SAN directoryName
/// \details Optional Subject Alternate Name (SAN)
directoryName,
/// \brief SAN ediPartyName
/// \details Optional Subject Alternate Name (SAN)
ediPartyName,
/// \brief SAN uniformResourceIdentifier
/// \details Optional Subject Alternate Name (SAN)
uniformResourceIdentifier,
/// \brief SAN iPAddress
/// \details Optional Subject Alternate Name (SAN)
iPAddress,
/// \brief SAN registeredID
/// \details Optional Subject Alternate Name (SAN)
registeredID,
/// \brief nsServer
/// \details Optional part of original Netscape specification
nsServer,
/// \brief msOtherNameUPN
/// \details Microsoft Kerberos UserPrincipalName extracted from SAN otherName
msOtherNameUPN
};
static const IdentityEnum InvalidIdentityEnum = static_cast(0);
virtual ~IdentityValue() {}
IdentityValue(const SecByteBlock &value, IdentityEnum src);
IdentityValue(const std::string &value, IdentityEnum src);
IdentityValue(const OID &oid, const SecByteBlock &value, IdentityEnum src);
IdentityValue(const OID &oid, const std::string &value, IdentityEnum src);
/// \brief Print an Identity value
/// \returns ostream reference
std::ostream& Print(std::ostream& out) const;
/// \brief Textual representation
/// \returns string representing the value
std::string EncodeValue() const;
/// \brief Convert otherName into a different IdentityValue
/// \details ConvertOtherName() operates on this object.
/// m_value and m_src can be changed to a new identity
/// type, like a UPN string and msOtherNameUPN type.
void ConvertOtherName();
OID m_oid;
SecByteBlock m_value; // Raw value from source
IdentityEnum m_src;
};
/// \brief Array of Identity values
/// \details Vector or IdentityValue
/// \sa IdentityValue
typedef std::vector IdentityValueArray;
//////////////////////////////////////////////////
/// \brief X.509 Certificate
/// \details X509Certificate is a partial implementation of X.509 certificate
/// support. The class loads a DER encoded certificate and presents many of
/// the important attributes and values through accessor functions. The
/// attributes and values include signature, signature algorithm, toBeSigned,
/// serialNumber, issuerDistinguishedName, subjectDistinguishedName, and
/// subjectPublicKeyInfo exposed as a X509PubliKey ready for use in Crypto++
/// library algorithms.
/// \details Most member functions related to saving or encoding a certificate
/// have not been cut-in. Calling member functions that have not been cut-in will
/// result in NotImplemented exception. Future versions of the X509Certificate
/// can provide them.
/// \throws NotImplemented if a particular function has not been cut-in. Member
/// functions that throw NotImplemented include DEREncode*.
/// \details This is a library add-on. You must download and compile it
/// yourself as part of the library.
/// \since Crypto++ 8.3
/// \sa X509Certificate
/// and PEM Pack on the
/// Crypto++ wiki.
class X509Certificate : public ASN1CryptoMaterial
{
public:
/// \brief Certificate version
enum Version {
/// \brief Version 1
v1=0,
/// \brief Version 2
v2,
/// \brief Version 3
v3
};
public:
virtual ~X509Certificate() {}
X509Certificate() {}
// NameValuePairs
virtual void AssignFrom (const NameValuePairs &source);
virtual bool GetVoidValue (const char *name, const std::type_info &valueType, void *pValue) const;
/// \name VALIDATION
//@{
// CryptoMaterial
virtual bool Validate (RandomNumberGenerator &rng, unsigned int level) const;
/// \brief Validate signature on this certificate
/// \param rng a RandomNumberGenerator for objects which use randomized
/// testing
/// \param key the public key of the keypair used to sign this certificate
/// \returns true if the test succeeds, false otherwise
/// \details If this certificate is self-signed then the signature can be
/// verified using the public key in this certificate. In this case call
/// ValidateSignature() with GetSubjectPublicKey().
/// \details If this certificate is signed by a CA certificate, then call
/// ValidateSignature() using signing CA's public key. The CA's public
/// key is found in the CA certificate using GetSubjectPublicKey().
/// \sa GetSubjectPublicKey
bool ValidateSignature (RandomNumberGenerator &rng, const X509PublicKey &key) const;
//@}
/// \name ENCODE/DECODE
//@{
// ASN1CryptoMaterial
virtual void Save (BufferedTransformation &bt) const;
virtual void Load (BufferedTransformation &bt);
// ASN1Object
virtual void BERDecode (BufferedTransformation &bt);
virtual void DEREncode (BufferedTransformation &bt) const;
//@}
/// \name ASN.1 OPTIONAL
//@{
/// \brief Determine if Issuer UniqueId is present
/// \returns true if Issuer UniqueId is present, false otherwise
/// \details Issuer UniqueId is optional and available with X.509 v2.
/// \sa HasSubjectUniqueId, GetIssuerUniqueId
bool HasIssuerUniqueId() const;
/// \brief Determine if Subject UniqueId is present
/// \returns true if Subject UniqueId is present, false otherwise
/// \details Subject UniqueId is optional and available with X.509 v2.
/// \sa HasIssuerUniqueId, GetSubjectUniqueId
bool HasSubjectUniqueId() const;
/// \brief Determine if Extensions are present
/// \returns true if Extensions are present, false otherwise
/// \details Extensions are optional and available with X.509 v3.
/// \sa GetExtensions
bool HasExtensions() const;
/// \brief Determine if AKI is present
/// \returns true if Authority Key Identifier is present, false otherwise
/// \details AKI is an optional extension and available with X.509 v3.
/// \sa HasSubjectKeyIdentifier, GetAuthorityKeyIdentifier
bool HasAuthorityKeyIdentifier() const;
/// \brief Determine if SPKI is present
/// \returns true if Subject Public Key Identifier is present, false otherwise
/// \details SPKI is an optional extension and available with X.509 v3.
/// \sa HasAuthorityKeyIdentifier, GetSubjectKeyIdentifier
bool HasSubjectKeyIdentifier() const;
//@}
/// \name ACCESSORS
//@{
/// \brief Retrieve complete DER encoded certicate
/// \returns the certificate data
/// \sa GetToBeSigned, GetCertificateSignature
const SecByteBlock& GetCertificate () const
{ return m_origCertificate; }
/// \brief Retrieve DER encoded ToBeSigned
/// \returns the toBeSigned data
/// \sa GetCertificate, GetCertificateSignature
const SecByteBlock& GetToBeSigned () const;
/// \brief Version number
/// \returns Certificate version number
/// \note Version number is 0 based, so X.509 v3 value is 2.
Version GetVersion() const
{ return m_version; }
/// \brief Serial number
/// \returns Certificate serial number
const Integer& GetSerialNumber() const
{ return m_serialNumber; }
/// \brief Certificate signature algorithm
/// \returns Certificate signature algorithm
/// \sa GetCertificate, GetToBeSigned, GetCertificateSignature
const OID& GetCertificateSignatureAlgorithm() const
{ return m_certSignatureAlgortihm; }
/// \brief Certificate signature
/// \returns Certificate signature
/// \sa GetCertificate, GetToBeSigned, GetCertificateSignatureAlgorithm
const SecByteBlock& GetCertificateSignature() const
{ return m_certSignature; }
/// \brief Validity not before
/// \returns Validity not before
/// \sa GetNotAfter
const DateValue& GetNotBefore() const
{ return m_notBefore; }
/// \brief Validity not after
/// \returns Validity not after
/// \sa GetNotBefore
const DateValue& GetNotAfter() const
{ return m_notAfter; }
/// \brief Issuer distinguished name
/// \returns Issuer distinguished name
const RdnValueArray& GetIssuerDistinguishedName() const
{ return m_issuerName; }
/// \brief Subject distinguished name
/// \returns Subject distinguished name
const RdnValueArray& GetSubjectDistinguishedName() const
{ return m_subjectName; }
/// \brief Issuer UniqueId
/// \returns Issuer UniqueId
/// \details Issuer UniqueId is optional and available with X.509 v2.
/// \sa HasIssuerUniqueId
const SecByteBlock& GetIssuerUniqueId() const
{ return m_issuerUid.get() ? *m_issuerUid.get() : g_nullByteBlock; }
/// \brief Subject UniqueId
/// \returns Subject UniqueId
/// \details Subject UniqueId is optional and available with X.509 v2.
/// \sa HasSubjectUniqueId
const SecByteBlock& GetSubjectUniqueId() const
{ return m_subjectUid.get() ? *m_subjectUid.get() : g_nullByteBlock; }
/// \brief Certificate extensions
/// \returns Certificate extensions array
/// \details Certificate extensions are available with X.509 v3.
/// \sa HasExtensions
const ExtensionValueArray& GetExtensions() const
{ return m_extensions.get() ? *m_extensions.get() : g_nullExtensions; }
/// \brief Subject public key algorithm
/// \returns Subject public key algorithm
/// \sa GetSubjectPublicKey
const OID& GetSubjectPublicKeyAlgorithm() const
{ return m_subjectSignatureAlgortihm; }
/// \brief Subject public key
/// \returns Subject public key
/// \sa GetSubjectPublicKeyAlgorithm
const X509PublicKey& GetSubjectPublicKey() const
{ return *m_subjectPublicKey.get(); }
/// \brief Authority key identifier
/// \returns Authority key identifier
/// \details Authority key identifier is optional and available with X.509 v3.
/// \sa HasAuthorityKeyIdentifier, GetSubjectKeyIdentifier
const KeyIdentifierValue& GetAuthorityKeyIdentifier() const;
/// \brief Subject key identifier
/// \returns Subject key identifier
/// \details Subject key identifier is optional and available with X.509 v3.
/// \sa HasSubjectKeyIdentifier, GetAuthorityKeyIdentifier
const KeyIdentifierValue& GetSubjectKeyIdentifier() const;
/// \brief Identities
/// \returns Identities
/// \details GetSubjectIdentities() collects the identities in the certificate.
const IdentityValueArray& GetSubjectIdentities() const;
/// \brief Identities
/// \returns Identities
/// \details GetSubjectIdentities() collects the identities in the certificate.
const KeyUsageValueArray& GetSubjectKeyUsage() const;
//@}
/// \name CERTIFICATE
//@{
/// \brief Determine if certificate is a CA
/// \returns true if the certificate is a CA, false otherwise
/// \details There are two types of certificates. The first is a CA certificate and
/// signaled with basicConstraint, CA:TRUE. The second is an end entity
/// certificate and signaled with basicConstraint, CA:FALSE.
/// CA certificates can certify other certificates, while end entity certificates
/// cannot. End entity certificates are leaf certificates.
/// \sa IsSelfSigned
bool IsCertificateAuthority() const;
/// \brief Determine if certificate is self-signed
/// \returns true if the certificate is self-signed, false otherwise
/// \sa IsCertificateAuthority
bool IsSelfSigned() const;
//@}
/// \name DEBUG
//@{
/// \brief Print a certificate
/// \param out ostream object
/// \returns ostream reference
/// \details Print() displays some of the fields of a certificate for
/// debug purposes. Users should modify the class or override this
/// class in a derived class to suit their taste.
virtual std::ostream& Print(std::ostream& out) const;
/// \brief Write certificate data
/// \param bt BufferedTransformation object
/// \details WriteCertificateBytes() is a debug function. It dumps
/// the bytes stored in m_origCertificate. WriteCertificateBytes()
/// also sets up a try/catch and silently swallows exceptions.
void WriteCertificateBytes(BufferedTransformation &bt) const;
//@}
protected:
// Crib away the original certificate
void SaveCertificateBytes(BufferedTransformation &bt);
// Clear old certificate data
void Reset();
// RFC 2459, section 7.3.1, http://www.ietf.org/rfc/rfc2459.txt
virtual bool BERDecodeAlgorithmParameters (BufferedTransformation &bt)
{BERDecodeNull(bt); return false;}
virtual bool DEREncodeAlgorithmParameters (BufferedTransformation &bt) const
{DEREncodeNull(bt); return false;}
// X509Certificate
void BERDecodeVersion(BufferedTransformation &bt, Version &version);
void BERDecodeSerialNumber(BufferedTransformation &bt, Integer &serno);
void BERDecodeSignature(BufferedTransformation &bt, SecByteBlock &signature);
void BERDecodeSignatureAlgorithm(BufferedTransformation &bt, OID &algorithm);
void BERDecodeDistinguishedName(BufferedTransformation &bt, RdnValueArray &rdnArray);
void BERDecodeValidity(BufferedTransformation &bt, DateValue ¬Before, DateValue ¬After);
void BERDecodeSubjectPublicKeyInfo(BufferedTransformation &bt, member_ptr& publicKey);
// Optional attributes
bool HasOptionalAttribute(const BufferedTransformation &bt, byte tag) const;
void BERDecodeIssuerUniqueId(BufferedTransformation &bt);
void BERDecodeSubjectUniqueId(BufferedTransformation &bt);
void BERDecodeExtensions(BufferedTransformation &bt);
// BERDecodeSubjectPublicKeyInfo peeks at the subjectPublicKeyInfo because the
// information is less ambiguous. If we used subjectPublicKeyAlgorithm we would
// still need to peek because subjectPublicKeyAlgorithm lacks field information
// (prime vs. binary). We need a field to instantiate a key. For example,
// subjectPublicKeyAlgorithm==ecdsa_with_sha384() does not contain enough
// information to determine PublicKey_EC or PublicKey_EC.
void GetSubjectPublicKeyInfoOids(const BufferedTransformation &bt, OID& algorithm, OID& field) const;
// Identity helper functions. Find them wherever we can.
void GetIdentitiesFromSubjectDistName(IdentityValueArray& identityArray) const;
void GetIdentitiesFromSubjectAltName(IdentityValueArray& identityArray) const;
void GetIdentitiesFromSubjectUniqueId(IdentityValueArray& identityArray) const;
void GetIdentitiesFromSubjectPublicKeyId(IdentityValueArray& identityArray) const;
void GetIdentitiesFromNetscapeServer(IdentityValueArray& identityArray) const;
// Find an extension with the OID. Returns false and end() if not found.
bool FindExtension(const OID& oid, ExtensionValueArray::const_iterator& loc) const;
// Get the verifier object for an algorithm and key
PK_Verifier* GetPK_VerifierObject(const OID &algorithm, const X509PublicKey &key) const;
private:
// Version and serial number, required v1
Version m_version;
Integer m_serialNumber;
// Certificate algorithm and signature, required v1
OID m_certSignatureAlgortihm;
SecByteBlock m_certSignature;
// Issuer and subject DNs, required v1
RdnValueArray m_issuerName;
RdnValueArray m_subjectName;
// Validity dates, required v1
DateValue m_notBefore, m_notAfter;
// The subject's key and algorithm, required v1
OID m_subjectSignatureAlgortihm;
member_ptr m_subjectPublicKey;
// Issue and Subject UniqueId, optional v2
ASNOptional m_issuerUid;
ASNOptional m_subjectUid;
// Extensions, optional v3
ASNOptional m_extensions;
// AKI and SPKI extensions, optional v3
mutable member_ptr m_authorityKeyIdentifier; // lazy
mutable member_ptr m_subjectKeyIdentifier; // lazy
// KU and EKU, optional v3
mutable member_ptr m_keyUsage; // lazy
// Identities
mutable member_ptr m_identities; // lazy
// To be signed, required v1
mutable member_ptr m_toBeSigned; // lazy
// Hack so we can examine the octets. Also see WriteCertificateBytes.
SecByteBlock m_origCertificate;
// Null values so we can return something
static const SecByteBlock g_nullByteBlock;
static const ExtensionValueArray g_nullExtensions;
};
//////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& out, const X509Certificate &cert)
{ return cert.Print(out); }
inline std::ostream& operator<<(std::ostream& out, const RdnValue &value)
{ return value.Print(out); }
inline std::ostream& operator<<(std::ostream& out, const DateValue &value)
{ return value.Print(out); }
inline std::ostream& operator<<(std::ostream& out, const KeyIdentifierValue &value)
{ return value.Print(out); }
inline std::ostream& operator<<(std::ostream& out, const KeyUsageValue &value)
{ return value.Print(out); }
inline std::ostream& operator<<(std::ostream& out, const IdentityValue &value)
{ return value.Print(out); }
inline bool operator==(const RdnValue &first, const RdnValue &second)
{ return first.m_value == second.m_value; }
inline bool operator==(const KeyIdentifierValue &first, const KeyIdentifierValue &second)
{ return first.m_value == second.m_value; }
inline std::ostream& operator<<(std::ostream& out, const RdnValueArray &values)
{
RdnValueArray::const_iterator first = values.begin();
RdnValueArray::const_iterator last = values.end();
std::ostringstream oss;
while (first != last)
{
oss << *first;
if (++first != last)
{ oss << "; "; }
}
return out << oss.str();
}
inline std::ostream& operator<<(std::ostream& out, const IdentityValueArray &values)
{
IdentityValueArray::const_iterator first = values.begin();
IdentityValueArray::const_iterator last = values.end();
std::ostringstream oss;
while (first != last)
{
oss << *first;
if (++first != last)
{ oss << "\n"; }
}
return out << oss.str();
}
inline std::ostream& operator<<(std::ostream& out, const KeyUsageValueArray &values)
{
KeyUsageValueArray::const_iterator first = values.begin();
KeyUsageValueArray::const_iterator last = values.end();
std::ostringstream oss;
while (first != last)
{
oss << *first;
if (++first != last)
{ oss << ", "; }
}
return out << oss.str();
}
//////////////////////////////////////////////////
// Make these defines to avoid global objects
#define id_sha1WithRSASignature (OID(1)+2+840+113549+1+1+5)
#define id_sha256WithRSAEncryption (OID(1)+2+840+113549+1+1+11)
#define id_sha384WithRSAEncryption (OID(1)+2+840+113549+1+1+12)
#define id_sha512WithRSAEncryption (OID(1)+2+840+113549+1+1+13)
#define id_secp256v1 (OID(1)+2+840+10045+3+1+7)
#define id_ecdsaWithSHA1 (OID(1)+2+840+10045+4+1)
#define id_ecdsaWithSHA256 (OID(1)+2+840+10045+4+3+2)
#define id_ecdsaWithSHA384 (OID(1)+2+840+10045+4+3+3)
#define id_ecdsaWithSHA512 (OID(1)+2+840+10045+4+3+4)
NAMESPACE_END
#endif // CRYPTOPP_X509_CERTIFICATE_H