[+] ICertificateStore::RemoveCertificate
[+] ICertificateStore::RemoveCertificatesFromChain [+] ICertificateStore::Size
This commit is contained in:
parent
e63903d0f4
commit
5abfb0eee0
@ -16,10 +16,15 @@ namespace Aurora::Crypto::CA
|
||||
{
|
||||
struct ICertificateStore : IPinCertificate
|
||||
{
|
||||
virtual void Serialize(Memory::ByteBuffer &buffer) = 0;
|
||||
virtual bool Deserialize(Memory::ByteBuffer &buffer) = 0;
|
||||
|
||||
virtual bool AddCertificate(const AuMemoryViewRead &x509Certificate) = 0;
|
||||
virtual bool AddCertificateChain(X509::ICertificateChain *pChain) = 0;
|
||||
|
||||
virtual void Serialize(Memory::ByteBuffer &buffer) = 0;
|
||||
virtual bool Deserialize(Memory::ByteBuffer &buffer) = 0;
|
||||
virtual bool RemoveCertificate(const AuMemoryViewRead &x509Certificate) = 0;
|
||||
virtual AuUInt32 RemoveCertificatesFromChain(X509::ICertificateChain *pChain) = 0;
|
||||
|
||||
virtual AuUInt32 Size() = 0;
|
||||
};
|
||||
}
|
@ -18,9 +18,37 @@ namespace Aurora::Crypto::X509
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
||||
// Digicerts "high assurance" and other special roots trusted by payment insitutions use 2048... FUCKING WHY?
|
||||
// These certs should be expiring in early 2030. Hopefully PayPal, Stripe, and others will get their act
|
||||
// together soon. Oh, and guess what, Amazon and tons of AWS customers use Amazon Root CA 1 with a 2048-bit PK as well.
|
||||
// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
||||
//
|
||||
// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
||||
// Please also note that this profile is only used to verify certificate *chains*
|
||||
//
|
||||
// When chain[0].publicKey is trusted by your client, and you've performed a key exchanged based upon that keypair, we don't care.
|
||||
// Certificate parameter validation is your issue - the clients' implementation side with your expected profile parameters and state container
|
||||
// of the peers connection and hostname,common-name pair. Such validation is not an issue for this relatively stateless * certificate store *.
|
||||
//
|
||||
// However, when *we* recurse a *chain*, we need to verify that the previous certificate the signator to the next, at this point it is our
|
||||
// responsibility to ensure some unsound certificates weren't injected into the middle of the chain to violate the "is trusted by a known root
|
||||
// via a series of unknown middle-man certificates" test. Noting we dont care for testing CN and SANs; we only care about testing the PK infra
|
||||
// which just to happens to include a signature test of the serialized ASN.1 properties from the anonymous root down to the chain[0] common name.
|
||||
// These certificate chains, we have to assume they're arbitrary remote user data, and therefore could be severely malformed or manipulated.
|
||||
// Any provided TLS stack will verify the chain[0] common name and profile parameters of the peer, however as the root-store validator, we need
|
||||
// to vertify cert[1...n] eventually references a good known anon root authority without a breakage the chains of signatures.
|
||||
//
|
||||
// PS: Emphasis on anonymous. I've seen some certificate roots, *ahem google*, change their x509 container without changing their key.
|
||||
// If we're hard-coding a series of CAs to trust, or even storing long term keychains, we're saying "we trust the owner of this key" to not
|
||||
// be a dipshit, therefore we shouldn't need to worry about every minute detail of the CA - we only care about: 1) the binary public key,
|
||||
// and 2) expiration time. It is therefore the case we only serialized these two properties. Do we really care that somebody we trust changed
|
||||
// their their expiration time by an hour after reserializing their root cert? No, not really. Do we care that they added some SANs? Again,
|
||||
// no. What about extended key uses? What are those? The extension RFC specifies use cases we couldn't care less about.
|
||||
// Any certificate revocation or further tests must come from another validator, perhaps connected to us via a "PinCheckTwoAnd" object.
|
||||
//
|
||||
// kAssumeRootIsSmart is used to satisfy this relationship test.
|
||||
// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
||||
static const mbedtls_x509_crt_profile kAssumeRootIsSmart =
|
||||
{
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | // TODO(by 2030): delete me
|
||||
@ -42,17 +70,37 @@ namespace Aurora::Crypto::CA
|
||||
2048, // TODO(by 2030): Raise to 4k
|
||||
};
|
||||
|
||||
bool CertificateStore::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
bool CertificateStore::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain2,
|
||||
const AuMemoryViewRead &derCertificate)
|
||||
{
|
||||
AU_LOCK_GUARD(this->rwLock->AsReadable());
|
||||
AuUPtr<X509::ICertificateChain> pTempChain;
|
||||
X509::ICertificateChain *pChain;
|
||||
bool bFoundTrustedCA {};
|
||||
|
||||
if (!pChain)
|
||||
AU_LOCK_GUARD(this->rwLock->AsReadable());
|
||||
|
||||
if (!pChain2)
|
||||
{
|
||||
if (derCertificate)
|
||||
{
|
||||
pTempChain = X509::NewChainFromOneDerGenericUnique(derCertificate);
|
||||
if (!pTempChain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pChain = pTempChain.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pChain = pChain2.get();
|
||||
}
|
||||
|
||||
auto uCount = pChain->GetCertificateCount();
|
||||
for (AU_ITERATE_N(i, uCount))
|
||||
{
|
||||
@ -199,8 +247,104 @@ namespace Aurora::Crypto::CA
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CertificateStore::RemoveCertificate(const AuMemoryViewRead &x509Certificate)
|
||||
{
|
||||
bool bRet {};
|
||||
mbedtls_x509_crt crt;
|
||||
|
||||
if (!x509Certificate)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return false;
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_init(&crt);
|
||||
|
||||
if (mbedtls_x509_crt_parse(&crt,
|
||||
x509Certificate.Begin<unsigned char>(),
|
||||
x509Certificate.Size()) < 0)
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
return false;
|
||||
}
|
||||
|
||||
AuUInt32 uCode { AuFnv1a32Runtime(crt.pk_raw.p, crt.pk_raw.len) };
|
||||
|
||||
{
|
||||
AU_LOCK_GUARD(this->rwLock->AsWritable());
|
||||
|
||||
auto itr = this->storage.find(uCode);
|
||||
if (itr != this->storage.end())
|
||||
{
|
||||
if (AuTryRemoveByTupleN<0>(itr->second, AuMemoryViewRead { crt.pk_raw.p, crt.pk_raw.len }))
|
||||
{
|
||||
bRet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
AuUInt32 CertificateStore::RemoveCertificatesFromChain(X509::ICertificateChain *pChain)
|
||||
{
|
||||
AuUInt32 uRet {};
|
||||
|
||||
if (!pChain)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return uRet;
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(this->rwLock->AsWritable());
|
||||
|
||||
auto uCount = pChain->GetCertificateCount();
|
||||
for (AU_ITERATE_N(i, uCount))
|
||||
{
|
||||
auto pCert = AuStaticCast<AuCrypto::X509::CertificateChain>(pChain)->GetCertificateInternal(i);
|
||||
if (!pCert)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AuUInt32 uCode { AuFnv1a32Runtime(pCert->pk_raw.p, pCert->pk_raw.len) };
|
||||
|
||||
auto itr = this->storage.find(uCode);
|
||||
if (itr == this->storage.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!AuTryRemoveByTupleN<0>(itr->second, AuMemoryViewRead { pCert->pk_raw.p, pCert->pk_raw.len }))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uRet++;
|
||||
}
|
||||
|
||||
return uRet;
|
||||
}
|
||||
|
||||
AuUInt32 CertificateStore::Size()
|
||||
{
|
||||
AuUInt32 uRet {};
|
||||
|
||||
AU_LOCK_GUARD(this->rwLock->AsReadable());
|
||||
|
||||
for (auto &[uID, storageList] : this->storage)
|
||||
{
|
||||
uRet += storageList.size();
|
||||
}
|
||||
|
||||
return uRet;
|
||||
}
|
||||
|
||||
void CertificateStore::Serialize(Memory::ByteBuffer &buffer)
|
||||
{
|
||||
AU_LOCK_GUARD(this->rwLock->AsReadable());
|
||||
|
||||
for (auto &[uID, storageList] : this->storage)
|
||||
{
|
||||
for (auto &[cert, uValidTo] : storageList)
|
||||
|
@ -17,6 +17,10 @@ namespace Aurora::Crypto::CA
|
||||
bool AddCertificate(const AuMemoryViewRead &x509Certificate) override;
|
||||
bool AddCertificateChain(X509::ICertificateChain *pChain) override;
|
||||
|
||||
bool RemoveCertificate(const AuMemoryViewRead &x509Certificate) override;
|
||||
AuUInt32 RemoveCertificatesFromChain(X509::ICertificateChain *pChain) override;
|
||||
|
||||
AuUInt32 Size() override;
|
||||
|
||||
void Serialize(Memory::ByteBuffer &buffer) override;
|
||||
bool Deserialize(Memory::ByteBuffer &buffer) override;
|
||||
|
Loading…
Reference in New Issue
Block a user