J Reece Wilson
7a0593adeb
[+] AuCrypto::CA::INewCertificateStore [+] AuCrypto::CA::IPinCertificate [+] AuCrypto::CA::PinAlwaysFail [+] AuCrypto::CA::PinAlwaysPass [+] AuCrypto::CA::PinCheckOS [+] AuCrypto::CA::PinCheckDefault [+] AuCrypto::CA::PinCheckBuiltin [+] AuCrypto::CA::PinCheckGlobal [+] AuCrypto::CA::PinCheckTwoAnd [+] AuCrypto::CA::PinCheckTwoOr [+] AuCrypto::CA::SetGlobalTLSPinner [*] Minor AuCrypto::X509 decoder work [*] AuCrypto::X509: transition to memory views (x509 is bytebuffer era and earlier code, beri early) [+] AuCrypto::IPrivateKeyProvider [+] AuCrypto::IPrivateKeyPair [+] AuCrypto::PrivateKeyPair [+] AuCrypto::ImportPrivateKeyPair [*] Refactor: AuCrypto::X509::GenerateCertificate(...) [+] AuCrypto::X509::NewChainFromOneDer [+] AuCrypto::X509::NewChainFromManyDer [+] AuCrypto::X509::NewChainFromManyDerInStream [+] AuCrypto::X509::NewChainFromOnePem [+] AuCrypto::X509::NewChainFromManyPem [+] AuCrypto::X509::NewChainFromManyPemInStream [*] Fix TLS code that was abandoned since its introduction with the net code. mbedtls is a hairbrained mess. so many *blocking* github issues starting after 2017. so little progress. [+] AuIO::TLS::TLSMeta::pKeyPairProvider [+] AuIO::TLS::TLSServer::bAllowSNIToFallBackDefault [+] AuIO::TLS::TLSServer::bAllowSNILessUseDefaultCert
476 lines
12 KiB
C++
476 lines
12 KiB
C++
/***
|
|
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: AuCertificateChain.cpp
|
|
File: TLSCertificateChain.cpp
|
|
Date: 2022-8-27
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "AuCertificateChain.hpp"
|
|
#include <Source/Crypto/X509/x509.hpp>
|
|
|
|
namespace Aurora::Crypto::X509
|
|
{
|
|
CertificateChain::CertificateChain()
|
|
{
|
|
|
|
}
|
|
|
|
CertificateChain::~CertificateChain()
|
|
{
|
|
::mbedtls_x509_crt_free(&this->ownCertificate);
|
|
}
|
|
|
|
AuUInt32 CertificateChain::GetCertificateCount()
|
|
{
|
|
AuUInt32 ret {};
|
|
|
|
auto pCert = this->pCertificate;
|
|
if (!pCert)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
do
|
|
{
|
|
auto index = ret++;
|
|
}
|
|
while ((pCert = pCert->next));
|
|
|
|
return ret;
|
|
}
|
|
|
|
AuMemoryViewRead CertificateChain::GetCertificate(AuUInt32 idx)
|
|
{
|
|
AuUInt32 ret {};
|
|
|
|
auto pCert = this->pCertificate;
|
|
if (!pCert)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
do
|
|
{
|
|
auto index = ret++;
|
|
if (index == idx)
|
|
{
|
|
return AuMemoryViewRead { AuMemoryViewRead { pCert->raw.p, pCert->raw.len}, AuSharedFromThis() };
|
|
}
|
|
}
|
|
while ((pCert = pCert->next));
|
|
|
|
return {};
|
|
}
|
|
|
|
AuOptional<const X509::CertificateDecoded &> CertificateChain::GetCertificateDetails(AuUInt32 uSelectedIndex)
|
|
{
|
|
AU_LOCK_GUARD(this->mutex);
|
|
|
|
if (auto uSize = this->decoded.size())
|
|
{
|
|
if (uSize <= uSelectedIndex)
|
|
{
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
return this->decoded[uSelectedIndex];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto pCert = this->pCertificate;
|
|
if (!pCert)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
AuUInt32 uIterator {};
|
|
do
|
|
{
|
|
uIterator++;
|
|
Crypto::X509::CertificateDecoded cert;
|
|
AuCrypto::X509::DecodeInternal(*pCert, cert);
|
|
this->decoded.push_back(cert);
|
|
}
|
|
while ((pCert = pCert->next));
|
|
|
|
if (uIterator <= uSelectedIndex)
|
|
{
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
return this->decoded[uSelectedIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
mbedtls_x509_crt *CertificateChain::GetCertificateInternal(AuUInt32 idx)
|
|
{
|
|
AuUInt32 ret {};
|
|
|
|
auto pCert = this->pCertificate;
|
|
if (!pCert)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
do
|
|
{
|
|
if (ret++ == idx)
|
|
{
|
|
return pCert;
|
|
}
|
|
}
|
|
while ((pCert = pCert->next));
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool CertificateChain::Init(const AuList<AuMemoryViewRead> &certs)
|
|
{
|
|
int iRet {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
this->ownership = certs;
|
|
|
|
for (auto &cert : this->ownership)
|
|
{
|
|
if (!cert.HasControlBlock())
|
|
{
|
|
if (!cert.TryCloneSelf())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
iRet = ::mbedtls_x509_crt_parse_der_nocopy(&this->ownCertificate,
|
|
(const unsigned char *)cert.ToPointer(),
|
|
cert.length);
|
|
if (iRet != 0)
|
|
{
|
|
this->pCertificate = nullptr;
|
|
SysPushErrorCrypto("Failed to parse certificate chain: {}", iRet);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init(const AuMemoryViewRead &cert)
|
|
{
|
|
int iRet {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
this->ownership2 = cert;
|
|
if (!this->ownership2.HasControlBlock())
|
|
{
|
|
if (!this->ownership2.TryCloneSelf())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
iRet = ::mbedtls_x509_crt_parse_der_nocopy(&this->ownCertificate,
|
|
(const unsigned char *)this->ownership2.ToPointer(),
|
|
this->ownership2.length);
|
|
if (iRet != 0)
|
|
{
|
|
SysPushErrorCrypto("Failed to parse certificate chain: {}", iRet);
|
|
return false;
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init2(const AuMemoryViewRead &cert)
|
|
{
|
|
int iRet {};
|
|
AuUInt uReadOffset {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
this->ownership2 = cert;
|
|
if (!this->ownership2.HasControlBlock())
|
|
{
|
|
if (!this->ownership2.TryCloneSelf())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
while (uReadOffset != cert.uLength)
|
|
{
|
|
iRet = ::mbedtls_x509_crt_parse_der_nocopy(&this->ownCertificate,
|
|
(const unsigned char *)this->ownership2.ToPointer() + uReadOffset,
|
|
this->ownership2.length - uReadOffset);
|
|
if (iRet != 0)
|
|
{
|
|
SysPushErrorCrypto("Failed to parse certificate chain: {} at {}", iRet, uReadOffset);
|
|
return false;
|
|
}
|
|
|
|
{
|
|
auto pCert = this->pCertificate;
|
|
while (pCert->next)
|
|
{
|
|
pCert = pCert->next;
|
|
}
|
|
uReadOffset += pCert->raw.len;
|
|
}
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init(const mbedtls_x509_crt *pCert)
|
|
{
|
|
this->pCertificate = (mbedtls_x509_crt *)pCert;
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init(const AuList<AuROString> &certs)
|
|
{
|
|
int iRet {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
for (auto &cert : certs)
|
|
{
|
|
AuByteBuffer buffer;
|
|
if (!PEM::FromString(cert, buffer))
|
|
{
|
|
SysPushErrorSyntax("Couldnt parse PEM");
|
|
return false;
|
|
}
|
|
|
|
iRet = ::mbedtls_x509_crt_parse_der(&this->ownCertificate,
|
|
(const unsigned char *)buffer.base,
|
|
buffer.length);
|
|
if (iRet != 0)
|
|
{
|
|
SysPushErrorCrypto("Failed to parse certificate chain: {}", iRet);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init(const AuROString &cert)
|
|
{
|
|
int iRet {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
AuByteBuffer buffer;
|
|
if (!PEM::FromString(cert, buffer))
|
|
{
|
|
SysPushErrorSyntax("Couldnt parse PEM");
|
|
return false;
|
|
}
|
|
|
|
iRet = ::mbedtls_x509_crt_parse_der(&this->ownCertificate,
|
|
(const unsigned char *)buffer.base,
|
|
buffer.length);
|
|
if (iRet != 0)
|
|
{
|
|
SysPushErrorCrypto("Failed to parse certificate chain [TEXT]: {}", iRet);
|
|
return false;
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Init2(const AuROString &cert)
|
|
{
|
|
int iRet {};
|
|
AuUInt uIndex {};
|
|
|
|
this->pCertificate = &this->ownCertificate;
|
|
::mbedtls_x509_crt_init(&this->ownCertificate);
|
|
|
|
uIndex = cert.find("-----BEGIN CERTIFICATE-----");
|
|
while (uIndex != AuROString::npos)
|
|
{
|
|
AuByteBuffer buffer;
|
|
|
|
auto uEndIndex = cert.find("-----END CERTIFICATE-----", uIndex);
|
|
if (uEndIndex == AuROString::npos)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!PEM::FromString(cert.SubStr(uIndex, uEndIndex + 25 - uIndex), buffer))
|
|
{
|
|
SysPushErrorSyntax("Couldnt parse PEM");
|
|
return false;
|
|
}
|
|
|
|
iRet = ::mbedtls_x509_crt_parse_der(&this->ownCertificate,
|
|
(const unsigned char *)buffer.base,
|
|
buffer.length);
|
|
if (iRet != 0)
|
|
{
|
|
SysPushErrorCrypto("Failed to parse certificate chain: {}, PEM: {}", iRet, cert.SubStr(uIndex, uEndIndex + 25 - uIndex));
|
|
return false;
|
|
}
|
|
|
|
uIndex = cert.find("-----BEGIN CERTIFICATE-----", uIndex + 10);
|
|
}
|
|
|
|
return this->Precache();
|
|
}
|
|
|
|
bool CertificateChain::Precache()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromOneDerNew(const AuMemoryViewRead &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init(read))
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromOneDerRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromManyDerNew(const AuList<AuMemoryViewRead> &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init(read))
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromManyDerRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromOnePemNew(const AuROString &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init(read))
|
|
{
|
|
NewChainFromOnePemRelease(pCertificateChain);
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromOnePemRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromManyPemNew(const AuList<AuROString> &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init(read))
|
|
{
|
|
NewChainFromManyPemRelease(pCertificateChain);
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromManyPemRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromManyPemInStreamNew(const AuROString &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init2(read))
|
|
{
|
|
NewChainFromManyPemInStreamRelease(pCertificateChain);
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromManyPemInStreamRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
|
|
AUKN_SYM ICertificateChain *NewChainFromManyDerInStreamNew(const AuMemoryViewRead &read)
|
|
{
|
|
auto pCertificateChain = _new CertificateChain();
|
|
if (!pCertificateChain)
|
|
{
|
|
SysPushErrorMemory();
|
|
return {};
|
|
}
|
|
|
|
if (!pCertificateChain->Init2(read))
|
|
{
|
|
NewChainFromManyDerInStreamRelease(pCertificateChain);
|
|
return {};
|
|
}
|
|
|
|
return pCertificateChain;
|
|
}
|
|
|
|
AUKN_SYM void NewChainFromManyDerInStreamRelease(ICertificateChain *pHandle)
|
|
{
|
|
AuSafeDelete<CertificateChain *>(pHandle);
|
|
}
|
|
} |