[+] AuCrypto::CA::ICertificateStore
[+] 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
This commit is contained in:
parent
b5c4271807
commit
7a0593adeb
@ -1,5 +1,5 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CA.hpp
|
||||
Date: 2021-6-11
|
||||
@ -7,30 +7,12 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::RSA
|
||||
{
|
||||
struct IRSAPublic;
|
||||
}
|
||||
#include "IPinCertificate.hpp"
|
||||
#include "ICertificateStore.hpp"
|
||||
#include "PinCertificate.hpp"
|
||||
#include "CertificateStore.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
class ICertificateStore
|
||||
{
|
||||
public:
|
||||
virtual void AddSignature(const AuSPtr<RSA::IRSAPublic> &CA,
|
||||
const Memory::ByteBuffer &sig,
|
||||
Aurora::Hashing::EHashType method,
|
||||
EPaddingType type) = 0;
|
||||
|
||||
virtual void AddPublicCert(const X509::Certificate &cert) = 0;
|
||||
|
||||
/// For future support of http gets of the CA list
|
||||
virtual bool& AllowHTTPTree() = 0;
|
||||
|
||||
virtual bool CheckKey(const AuSPtr<RSA::IRSAPublic> &pub) = 0;
|
||||
virtual bool CheckCert(const X509::Certificate &cert) = 0;
|
||||
};
|
||||
|
||||
|
||||
AUKN_SHARED_API(NewCA, ICertificateStore);
|
||||
}
|
13
Include/Aurora/Crypto/CA/CertificateStore.hpp
Executable file
13
Include/Aurora/Crypto/CA/CertificateStore.hpp
Executable file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CertificateStore.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
AUKN_SHARED_API(NewCertificateStore, ICertificateStore)
|
||||
}
|
25
Include/Aurora/Crypto/CA/ICertificateStore.hpp
Executable file
25
Include/Aurora/Crypto/CA/ICertificateStore.hpp
Executable file
@ -0,0 +1,25 @@
|
||||
/***
|
||||
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ICertificateStore.hpp
|
||||
Date: 2021-6-11
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct ICertificateChain;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
struct ICertificateStore : IPinCertificate
|
||||
{
|
||||
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;
|
||||
};
|
||||
}
|
@ -7,12 +7,15 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct NetError;
|
||||
struct ICertificateChain;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
AUKN_INTERFACE(IPinCertificate,
|
||||
AUI_METHOD(bool, CheckCertificate, (const AuSPtr<ICertificateChain> &, pChain,
|
||||
const Memory::MemoryViewRead &, derCertificate))
|
||||
AUI_METHOD(bool, CheckCertificate, (const AuSPtr<X509::ICertificateChain> &, pChain,
|
||||
const AuMemoryViewRead &, derCertificate))
|
||||
);
|
||||
}
|
48
Include/Aurora/Crypto/CA/PinCertificate.hpp
Executable file
48
Include/Aurora/Crypto/CA/PinCertificate.hpp
Executable file
@ -0,0 +1,48 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: PinCertificate.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
/*
|
||||
* Dummy pinner
|
||||
*/
|
||||
AUKN_SHARED_API(PinAlwaysFail, IPinCertificate)
|
||||
|
||||
/*
|
||||
* Dummy pinner
|
||||
*/
|
||||
AUKN_SHARED_API(PinAlwaysPass, IPinCertificate)
|
||||
|
||||
/*
|
||||
* Provides an instance of the platforms certificate validation framework
|
||||
*/
|
||||
AUKN_SHARED_API(PinCheckOS, IPinCertificate)
|
||||
|
||||
/*
|
||||
* Provides an instance of the (limited) builtin certificate authority store
|
||||
*/
|
||||
AUKN_SHARED_API(PinCheckBuiltin, IPinCertificate)
|
||||
|
||||
/*
|
||||
* Per application configuration, provides an instance of the default TLS certificate validator
|
||||
*/
|
||||
AUKN_SHARED_API(PinCheckDefault, IPinCertificate)
|
||||
|
||||
/**
|
||||
* See: SetGlobalTLSPinner
|
||||
*/
|
||||
AUKN_SHARED_API(PinCheckGlobal, IPinCertificate)
|
||||
|
||||
AUKN_SHARED_API(PinCheckBasicValidity, IPinCertificate)
|
||||
|
||||
AUKN_SHARED_API(PinCheckTwoAnd, IPinCertificate, const AuSPtr<IPinCertificate> &pCheckA, const AuSPtr<IPinCertificate> &pCheckB)
|
||||
AUKN_SHARED_API(PinCheckTwoOr, IPinCertificate, const AuSPtr<IPinCertificate> &pCheckA, const AuSPtr<IPinCertificate> &pCheckB)
|
||||
|
||||
AUKN_SYM void SetGlobalTLSPinner(const AuSPtr<IPinCertificate> &pNewDefault);
|
||||
}
|
@ -40,6 +40,7 @@ namespace Aurora::Crypto
|
||||
#include "ECC/ECC.hpp"
|
||||
#include "PEM/PEM.hpp"
|
||||
#include "RSA/RSA.hpp"
|
||||
#include "KeyPair/KeyPair.hpp"
|
||||
#include "X509/X509.hpp"
|
||||
#include "BCrypt/BCrypt.hpp"
|
||||
#include "HMAC/HMAC.hpp"
|
||||
|
@ -1,27 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: EHashType.hpp
|
||||
Date: 2021-6-11
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto
|
||||
{
|
||||
#if 0
|
||||
AUE_DEFINE(EHashType,
|
||||
(
|
||||
eMD5,
|
||||
eSHA1_20_160,
|
||||
eTiger_24_192,
|
||||
eSHA2_32_256,
|
||||
eSHA2_48_384,
|
||||
eSHA2_64_512,
|
||||
eSHA3_28_224,
|
||||
eSHA3_32_256,
|
||||
eSHA3_48_384,
|
||||
eSHA3_64_512
|
||||
));
|
||||
#endif
|
||||
}
|
22
Include/Aurora/Crypto/KeyPair/IPrivateKeyPair.hpp
Normal file
22
Include/Aurora/Crypto/KeyPair/IPrivateKeyPair.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/***
|
||||
Copyright (C) 2022 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPrivateKeyPair.hpp
|
||||
File: ITLSPrivateKeyPair.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct ICertificateChain;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
struct IPrivateKeyPair
|
||||
{
|
||||
virtual AuSPtr<X509::ICertificateChain> GetChain() = 0;
|
||||
};
|
||||
}
|
15
Include/Aurora/Crypto/KeyPair/IPrivateKeyProvider.hpp
Executable file
15
Include/Aurora/Crypto/KeyPair/IPrivateKeyProvider.hpp
Executable file
@ -0,0 +1,15 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPrivateKeyProvider.hpp
|
||||
Date: 2024-10-13
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
AUKN_INTERFACE(IPrivateKeyProvider,
|
||||
AUI_METHOD(AuSPtr<IPrivateKeyPair>, FetchBySNI, (const AuROString &, SNI))
|
||||
);
|
||||
}
|
17
Include/Aurora/Crypto/KeyPair/KeyPair.hpp
Executable file
17
Include/Aurora/Crypto/KeyPair/KeyPair.hpp
Executable file
@ -0,0 +1,17 @@
|
||||
/***
|
||||
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: KeyPair.hpp
|
||||
Date: 2024-10-13
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "PrivateKeyPair.hpp"
|
||||
#include "IPrivateKeyPair.hpp"
|
||||
#include "IPrivateKeyProvider.hpp"
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
AUKN_SHARED_API(ImportPrivateKeyPair, IPrivateKeyPair, const PrivateKeyPair &keyPair);
|
||||
}
|
24
Include/Aurora/Crypto/KeyPair/PrivateKeyPair.hpp
Normal file
24
Include/Aurora/Crypto/KeyPair/PrivateKeyPair.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
/***
|
||||
Copyright (C) 2022 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: PrivateKeyPair.hpp
|
||||
File: TLSPrivateKeyPair.hpp
|
||||
Date: 2022-8-26
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct ICertificateChain;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
struct PrivateKeyPair
|
||||
{
|
||||
AuSPtr<X509::ICertificateChain> pCertificateChain;
|
||||
AuMemoryViewRead privateKey;
|
||||
AuString sPassword;
|
||||
};
|
||||
}
|
19
Include/Aurora/Crypto/X509/CertificateChain.hpp
Executable file
19
Include/Aurora/Crypto/X509/CertificateChain.hpp
Executable file
@ -0,0 +1,19 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CertificateChain.hpp
|
||||
Date: 2024-10-13
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
AUKN_SHARED_API(NewChainFromOneDer, ICertificateChain, const AuMemoryViewRead &read);
|
||||
AUKN_SHARED_API(NewChainFromManyDer, ICertificateChain, const AuList<AuMemoryViewRead> &read);
|
||||
AUKN_SHARED_API(NewChainFromManyDerInStream, ICertificateChain, const AuMemoryViewRead &read);
|
||||
|
||||
AUKN_SHARED_API(NewChainFromOnePem, ICertificateChain, const AuROString &read);
|
||||
AUKN_SHARED_API(NewChainFromManyPem, ICertificateChain, const AuList<AuROString> &read);
|
||||
AUKN_SHARED_API(NewChainFromManyPemInStream, ICertificateChain, const AuROString &read);
|
||||
}
|
50
Include/Aurora/Crypto/X509/CertificateDecoded.hpp
Executable file
50
Include/Aurora/Crypto/X509/CertificateDecoded.hpp
Executable file
@ -0,0 +1,50 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CertificateDecoded.hpp
|
||||
Date: 2021-6-11
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertificateDecoded
|
||||
{
|
||||
AU_COPY_MOVE_DEF(CertificateDecoded);
|
||||
int version {};
|
||||
int iMaxPath {};
|
||||
bool bIsCA {};
|
||||
Hashing::EHashType digest;
|
||||
|
||||
struct Issuer : CertificateName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Issuer);
|
||||
Memory::ByteBuffer id;
|
||||
} issuer;
|
||||
|
||||
struct Subject : CertificateName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Subject);
|
||||
Memory::ByteBuffer id;
|
||||
} subject;
|
||||
|
||||
struct Vaildity
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Vaildity);
|
||||
AuUInt issued;
|
||||
AuUInt expire;
|
||||
} validity;
|
||||
|
||||
AuList<EExtendedUsage> usage;
|
||||
Memory::ByteBuffer publicKey;
|
||||
Memory::ByteBuffer serialNumber;
|
||||
Memory::ByteBuffer algorithmOid;
|
||||
AuList<AuString> AIAs;
|
||||
AuList<AuString> OCSPs;
|
||||
|
||||
// TODO: AuString CRL;
|
||||
// TODO: AuList<String> subjectNames;
|
||||
// TODO: ...
|
||||
};
|
||||
}
|
29
Include/Aurora/Crypto/X509/CertificateName.hpp
Executable file
29
Include/Aurora/Crypto/X509/CertificateName.hpp
Executable file
@ -0,0 +1,29 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CertificateName.hpp
|
||||
Date: 2021-6-11
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertificateName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(CertificateName);
|
||||
AuString commonName;
|
||||
|
||||
AuString department;
|
||||
AuString organization;
|
||||
AuString address;
|
||||
AuString locality;
|
||||
AuString state;
|
||||
AuString countryCode;
|
||||
AuString postcode;
|
||||
|
||||
AuString name;
|
||||
AuString email;
|
||||
AuString title;
|
||||
};
|
||||
}
|
49
Include/Aurora/Crypto/X509/CertificateRequest.hpp
Executable file
49
Include/Aurora/Crypto/X509/CertificateRequest.hpp
Executable file
@ -0,0 +1,49 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CertificateRequest.hpp
|
||||
File: GenerateCertificate.hpp
|
||||
Date: 2022-11-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
struct IPrivateKeyPair;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertificateRequest
|
||||
{
|
||||
// subject --
|
||||
CertificateName name;
|
||||
|
||||
// metadata --
|
||||
Hashing::EHashType digest;
|
||||
AuUInt8 uVersion { 3 };
|
||||
bool bIsCA { };
|
||||
AuInt8 iMaxPathLength { -1 };
|
||||
bool bSubjectKeyId { };
|
||||
AuList<EExtendedUsage> usage;
|
||||
AuUInt8 uSerialRadix { 10 };
|
||||
AuString sSerial { "69420" };
|
||||
|
||||
// validity --
|
||||
AuSInt iIssuedDateMs {};
|
||||
AuSInt iExpirationDateMs {};
|
||||
|
||||
// public key ---
|
||||
AuSPtr<RSA::IRSAPublic> pRSAKey;
|
||||
AuSPtr<ECC::IECCPublic> pECCKey;
|
||||
|
||||
// private key ---
|
||||
AuSPtr<RSA::IRSAPrivate> pSelfSigningRSAKey;
|
||||
AuSPtr<ECC::IECCPrivate> pSelfSigningECCKey;
|
||||
|
||||
// or
|
||||
|
||||
AuSPtr<KeyPair::IPrivateKeyPair> pSigningChain;
|
||||
};
|
||||
}
|
@ -7,44 +7,7 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct ITLSPrivateKeyPair;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertRequest
|
||||
{
|
||||
// subject --
|
||||
CertName name;
|
||||
|
||||
// metadata --
|
||||
Hashing::EHashType digest;
|
||||
AuUInt8 uVersion { 3 };
|
||||
bool bIsCA { };
|
||||
AuInt8 iMaxPathLength { -1 };
|
||||
bool bSubjectKeyId { };
|
||||
AuList<EExtendedUsage> usage;
|
||||
AuUInt8 uSerialRadix { 10 };
|
||||
AuString sSerial { "69420" };
|
||||
|
||||
// validity --
|
||||
AuSInt iIssuedDateMs {};
|
||||
AuSInt iExpirationDateMs {};
|
||||
|
||||
// public key ---
|
||||
AuSPtr<RSA::IRSAPublic> pRSAKey;
|
||||
AuSPtr<ECC::IECCPublic> pECCKey;
|
||||
|
||||
// private key ---
|
||||
AuSPtr<RSA::IRSAPrivate> pSelfSigningRSAKey;
|
||||
AuSPtr<ECC::IECCPrivate> pSelfSigningECCKey;
|
||||
|
||||
// or
|
||||
|
||||
AuSPtr<Aurora::IO::TLS::ITLSPrivateKeyPair> pSigningChain;
|
||||
};
|
||||
|
||||
AUKN_SYM AuResult<Memory::ByteBuffer> GenerateCertificate(const CertRequest &request);
|
||||
AUKN_SYM AuResult<Memory::ByteBuffer> GenerateCertificate(const CertificateRequest &request);
|
||||
}
|
18
Include/Aurora/Crypto/X509/ICertificateChain.hpp
Normal file
18
Include/Aurora/Crypto/X509/ICertificateChain.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ICertifiateChain.hpp
|
||||
Date: 2022-8-30
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct ICertificateChain
|
||||
{
|
||||
virtual AuUInt32 GetCertificateCount() = 0;
|
||||
virtual AuMemoryViewRead GetCertificate(AuUInt32 idx) = 0;
|
||||
virtual AuOptional<const CertificateDecoded &> GetCertificateDetails(AuUInt32 idx) = 0;
|
||||
};
|
||||
}
|
@ -9,70 +9,17 @@
|
||||
|
||||
#include "EExtendedUsage.hpp"
|
||||
|
||||
#include "CertificateName.hpp"
|
||||
#include "CertificateDecoded.hpp"
|
||||
|
||||
#include "ICertificateChain.hpp"
|
||||
#include "CertificateChain.hpp"
|
||||
|
||||
#include "CertificateRequest.hpp"
|
||||
#include "GenerateCertificate.hpp"
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(CertName);
|
||||
AuString commonName;
|
||||
|
||||
AuString department;
|
||||
AuString organization;
|
||||
AuString address;
|
||||
AuString locality;
|
||||
AuString state;
|
||||
AuString countryCode;
|
||||
AuString postcode;
|
||||
|
||||
AuString name;
|
||||
AuString email;
|
||||
AuString title;
|
||||
};
|
||||
|
||||
struct DecodedCertificate
|
||||
{
|
||||
AU_COPY_MOVE_DEF(DecodedCertificate);
|
||||
int version {};
|
||||
|
||||
struct Issuer : CertName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Issuer);
|
||||
Memory::ByteBuffer id;
|
||||
} issuer;
|
||||
|
||||
struct Subject : CertName
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Subject);
|
||||
Memory::ByteBuffer id;
|
||||
} subject;
|
||||
|
||||
struct Vaildity
|
||||
{
|
||||
AU_COPY_MOVE_DEF(Vaildity);
|
||||
AuUInt issued;
|
||||
AuUInt expire;
|
||||
} validity;
|
||||
|
||||
AuList<AuUInt8> serialNumber;
|
||||
AuList<AuUInt8> algorithmOid;
|
||||
|
||||
AuList<AuString> AIAs;
|
||||
// TODO: AuString CRL;
|
||||
|
||||
// TODO: AuList<String> subjectNames;
|
||||
|
||||
Hashing::EHashType digest;
|
||||
|
||||
AuList<EExtendedUsage> usage;
|
||||
|
||||
int iMaxPath {};
|
||||
bool bIsCA {};
|
||||
|
||||
// TODO: ...
|
||||
};
|
||||
|
||||
AUKN_SYM bool Decode(const Certificate &der, DecodedCertificate &out);
|
||||
AUKN_SYM bool Validate(const Certificate &der, const Certificate &parentDer);
|
||||
}
|
||||
|
||||
#include "GenerateCertificate.hpp"
|
||||
AUKN_SYM bool Decode(const AuMemoryViewRead &der, CertificateDecoded &out);
|
||||
AUKN_SYM bool Validate(const AuMemoryViewRead &der, const AuMemoryViewRead &parentDer);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ICertifiateChain.hpp
|
||||
Date: 2022-8-30
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct ICertificateChain
|
||||
{
|
||||
virtual AuUInt32 GetCertificateCount() = 0;
|
||||
virtual AuSPtr<Memory::MemoryViewRead> GetCertificate(AuUInt32 idx) = 0;
|
||||
virtual Crypto::X509::DecodedCertificate GetCertificateDetails(AuUInt32 idx) = 0;
|
||||
};
|
||||
|
||||
AUKN_SYM AuSPtr<ICertificateChain> ChainFromOne(const Memory::MemoryViewRead &read);
|
||||
AUKN_SYM AuSPtr<ICertificateChain> ChainFromMany(const AuList<Memory::MemoryViewRead> &read);
|
||||
}
|
@ -25,24 +25,24 @@ namespace Aurora::IO::TLS
|
||||
{
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
Memory::ByteBuffer serverTransportId {};
|
||||
|
||||
int iServerCookies { 0 };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
bool bServerNoRelay { true };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
int iServerBadMacLimit { 0 };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
int iMTUSize { 0 };
|
||||
};
|
||||
|
||||
@ -55,42 +55,56 @@ namespace Aurora::IO::TLS
|
||||
{
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
bool bSessionCache { true };
|
||||
|
||||
/**
|
||||
* @brief Forces server side pinning of clients
|
||||
*/
|
||||
*/
|
||||
bool bPinServerPeers { false };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
int iCacheMax { -1 };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
int iCacheTimeout { 0 };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
bool bEnableTickets { true };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
bool bTicketsRotate { false };
|
||||
|
||||
/**
|
||||
* @brief Allows the serving of default keypairs via requests of unknown SNIs.
|
||||
* Not recommended.
|
||||
*/
|
||||
bool bAllowSNIToFallBackDefault { false };
|
||||
|
||||
/**
|
||||
* @brief Allows the serving of default keypairs via SNI-less connections.
|
||||
* Use me if you care about hiding from service scanners.
|
||||
* SNI glows for end-users, but, lets say you dont want this server to scream "im publicinfra.servicetype.aws.companyname.com", this could be useful.
|
||||
* Might be required for legacy clients or privacy configs.
|
||||
*/
|
||||
bool bAllowSNILessUseDefaultCert { true };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
int iTicketTimeout { 300 }; // 5m
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
AuString alternativeTicketCipher;
|
||||
};
|
||||
|
||||
@ -98,7 +112,7 @@ namespace Aurora::IO::TLS
|
||||
{
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
AuString sSNIServerName;
|
||||
};
|
||||
|
||||
@ -106,52 +120,62 @@ namespace Aurora::IO::TLS
|
||||
{
|
||||
/**
|
||||
* @brief Input to-send, output-buffer size
|
||||
*/
|
||||
*/
|
||||
AuUInt uOutPageSize {};
|
||||
|
||||
/**
|
||||
* @brief Switches between server/client mode
|
||||
*/
|
||||
*/
|
||||
bool bIsClient { true };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
bool bEnableDebug { false };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
Net::ETransportProtocol transportProtocol { Net::ETransportProtocol::eProtocolTCP };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AuSPtr<IPinCertificate> pCertPin;
|
||||
*/
|
||||
AuSPtr<Crypto::CA::IPinCertificate> pCertPin;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyProvider> pKeyPairProvider;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AuSPtr<ITLSPrivateKeyPair> pKeyPair;
|
||||
*/
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> pDefaultKeyPair;
|
||||
|
||||
/**
|
||||
* @brief Override the cipersuites defined by ::GetDefaultCipherSuites()
|
||||
*/
|
||||
*/
|
||||
AuList<AuUInt16> cipherSuites;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
TLSMetaDTLS dtls;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
TLSMetaTCP tcp;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
TLSServer server;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
TLSClient client;
|
||||
};
|
||||
|
||||
@ -160,25 +184,25 @@ namespace Aurora::IO::TLS
|
||||
/**
|
||||
* @brief Returns the protocol stack provided to NewTLSContextEx
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuSPtr<Protocol::IProtocolStack> ToReadStack() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the protocol stack provided to NewTLSContextEx
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuSPtr<Protocol::IProtocolStack> ToWriteStack() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the input buffered inbound interceptor
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuSPtr<Protocol::IProtocolInterceptorEx> GetRecvInterceptor() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the to-send outbound interceptor
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuSPtr<Protocol::IProtocolInterceptorEx> GetSendInterceptor() = 0;
|
||||
|
||||
/**
|
||||
@ -194,58 +218,58 @@ namespace Aurora::IO::TLS
|
||||
* This function is a hybrid utility that does one internal action and calls
|
||||
* ISocketChannel::SpecifyRecvProtocol, ISocketChannel::SpecifySendProtocol to
|
||||
* activate the protocol stack on the socket (if not already).
|
||||
*/
|
||||
*/
|
||||
virtual void Attach(const AuSPtr<Net::ISocket> &pSocket) = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
virtual void StartHandshake() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
virtual void StartClose() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual bool HasCompletedHandshake() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuUInt16 GetCurrentCipherSuite() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual bool HasFailed() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual bool HasEnded() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual int GetFatalErrorCode() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
*/
|
||||
virtual AuString GetFatalErrorCodeAsString() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
*/
|
||||
virtual void Destroy() = 0;
|
||||
};
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ITLSPrivateKeyPair.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct ITLSPrivateKeyPair
|
||||
{
|
||||
virtual AuSPtr<ICertificateChain> GetChain() = 0;
|
||||
};
|
||||
|
||||
AUKN_SYM AuSPtr<ITLSPrivateKeyPair> ImportPrivateKeyPair(const TLSPrivateKeyPair &keyPair);
|
||||
}
|
@ -8,10 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Protocol/Protocol.hpp"
|
||||
#include "ICertificateChain.hpp"
|
||||
#include "IPinCertificate.hpp"
|
||||
#include "TLSPrivateKeyPair.hpp"
|
||||
#include "ITLSPrivateKeyPair.hpp"
|
||||
#include "ITLSContext.hpp"
|
||||
#include "TLSCipherSuites.hpp"
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: TLSPrivateKeyPair.hpp
|
||||
Date: 2022-8-26
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct TLSPrivateKeyPair
|
||||
{
|
||||
AuList<Memory::ByteBuffer> certificateChain;
|
||||
Memory::ByteBuffer privateKey;
|
||||
AuString sPassword;
|
||||
};
|
||||
}
|
@ -99,14 +99,8 @@ namespace Aurora
|
||||
|
||||
struct CryptoConfig
|
||||
{
|
||||
/// Defer to the rationales in the implementation
|
||||
/// Update 2023: world war 3 hasnt happened yet
|
||||
bool allowChineseCerts {false};
|
||||
|
||||
/// Defer to the rationales in the implementation
|
||||
/// Update 2023: spoilers it had nothing to do with the 2022 russian trolling directly, but who didn't see it coming?
|
||||
/// i dont care about politics; its just useful to divide the glow by factions.
|
||||
bool allowRussianCerts {true};
|
||||
bool bPreferSystemCertStoreOverBuiltin { false };
|
||||
bool bReserved[31];
|
||||
};
|
||||
|
||||
struct AsyncConfig
|
||||
|
@ -43,8 +43,10 @@
|
||||
#include <mimalloc.h>
|
||||
#include "Process/AuProcessStartTime.hpp"
|
||||
#include "AuProcAddresses.hpp"
|
||||
#include "Crypto/CA/CA.hpp"
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
#include "Crypto/CA/AuPinOS.Linux.hpp"
|
||||
void LinuxSuperSecretIOTick();
|
||||
#endif
|
||||
|
||||
@ -75,7 +77,11 @@ static void Init()
|
||||
|
||||
Crypto::InitCrypto();
|
||||
Aurora::IO::TLS::TLSInit();
|
||||
|
||||
Aurora::Crypto::CA::InitDefaultBuiltinCA();
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
Aurora::Crypto::CA::InitLinuxPinner();
|
||||
#endif
|
||||
|
||||
AuProcess::WarmStartupCaches();
|
||||
|
||||
Aurora::Threading::InitSleep();
|
||||
@ -174,6 +180,11 @@ static void RuntimeLateClean()
|
||||
|
||||
Aurora::IO::FS::DeinitResources();
|
||||
Aurora::CmdLine::Deinit();
|
||||
|
||||
Aurora::Crypto::CA::DeinitDefaultBuiltinCA();
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
Aurora::Crypto::CA::DeinitLinuxPinner();
|
||||
#endif
|
||||
|
||||
Aurora::RNG::Release(); // RNG and crypto should remain alive whilst IO work is ongoing.
|
||||
// At this point, we should assume libtomcrypt and mbedtls wont be called
|
||||
|
30
Source/Crypto/CA/AuCA.cpp
Normal file
30
Source/Crypto/CA/AuCA.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/***
|
||||
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuCA.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
Date: 2021-6-12
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
AUKN_SYM IPinCertificate *PinCheckDefaultNew()
|
||||
{
|
||||
if (gRuntimeConfig.crypto.bPreferSystemCertStoreOverBuiltin)
|
||||
{
|
||||
if (auto pOS = PinCheckOSNew())
|
||||
{
|
||||
return pOS;
|
||||
}
|
||||
}
|
||||
|
||||
return PinCheckBuiltinNew();
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckDefaultRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CA.cpp
|
||||
File: AuCA.hpp
|
||||
Date: 2021-6-12
|
||||
Author: Reece
|
||||
***/
|
260
Source/Crypto/CA/AuCertificateStore.cpp
Executable file
260
Source/Crypto/CA/AuCertificateStore.cpp
Executable file
@ -0,0 +1,260 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuCertificateStore.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuCertificateStore.hpp"
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include <Source/Crypto/X509/AuCertificateChain.hpp>
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
AuInt64 ConvertTime(const mbedtls_x509_time &time);
|
||||
}
|
||||
|
||||
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.
|
||||
static const mbedtls_x509_crt_profile kAssumeRootIsSmart =
|
||||
{
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | // TODO(by 2030): delete me
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
|
||||
0xFFFFFFF, /* Any PK alg */
|
||||
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
|
||||
0,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
2048, // TODO(by 2030): Raise to 4k
|
||||
};
|
||||
|
||||
bool CertificateStore::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate)
|
||||
{
|
||||
AU_LOCK_GUARD(this->rwLock->AsReadable());
|
||||
bool bFoundTrustedCA {};
|
||||
|
||||
if (!pChain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto uCount = pChain->GetCertificateCount();
|
||||
for (AU_ITERATE_N(i, uCount))
|
||||
{
|
||||
auto pCurrentCert = AuStaticCast<AuCrypto::X509::CertificateChain>(pChain)->GetCertificateInternal(i);
|
||||
if (!pCurrentCert)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
auto pPrevCert = AuStaticCast<AuCrypto::X509::CertificateChain>(pChain)->GetCertificateInternal(i - 1);
|
||||
if (!pPrevCert)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t flags {};
|
||||
if (mbedtls_x509_crt_verify_restartable(pCurrentCert, pPrevCert, NULL, &kAssumeRootIsSmart, NULL, &flags, NULL, NULL, NULL) < 0)
|
||||
{
|
||||
SysPushErrorCrypto("Bad certificate chain");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
SysPushErrorCrypto("Bad certificate chain");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto uCode = AuFnv1a32Runtime(pCurrentCert->pk_raw.p, pCurrentCert->pk_raw.len);
|
||||
|
||||
auto uItrA = this->storage.find(uCode);
|
||||
if (uItrA == this->storage.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto &[that, iDate] : uItrA->second)
|
||||
{
|
||||
AuMemoryViewRead toCompare { that };
|
||||
AuMemoryViewRead currentCert { pCurrentCert->pk_raw.p, pCurrentCert->pk_raw.len };
|
||||
|
||||
if (toCompare.uLength != currentCert.uLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AuTime::CurrentClockMS() > iDate)
|
||||
{
|
||||
SysPushErrorCrypto("Expired Certificate Authority");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AuMemcmp(toCompare.Begin(),
|
||||
currentCert.Begin(),
|
||||
currentCert.uLength) == 0)
|
||||
{
|
||||
bFoundTrustedCA = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFoundTrustedCA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bFoundTrustedCA;
|
||||
}
|
||||
|
||||
bool CertificateStore::AddCertificate(const AuMemoryViewRead &x509Certificate)
|
||||
{
|
||||
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) };
|
||||
AuByteBuffer buffer { AuMemoryViewRead { crt.pk_raw.p, crt.pk_raw.len } };
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
return false;
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(this->rwLock->AsWritable());
|
||||
this->storage[uCode].push_back(AuMakePair(AuMove(buffer), X509::ConvertTime(crt.valid_to)));
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CertificateStore::AddCertificateChain(X509::ICertificateChain *pChain)
|
||||
{
|
||||
if (!pChain)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return false;
|
||||
}
|
||||
|
||||
AuUInt32 uCode { AuFnv1a32Runtime(pCert->pk_raw.p, pCert->pk_raw.len) };
|
||||
AuByteBuffer buffer { AuMemoryViewRead { pCert->pk_raw.p, pCert->pk_raw.len } };
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->storage[uCode].push_back(AuMakePair(AuMove(buffer), X509::ConvertTime(pCert->valid_to)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CertificateStore::Serialize(Memory::ByteBuffer &buffer)
|
||||
{
|
||||
for (auto &[uID, storageList] : this->storage)
|
||||
{
|
||||
for (auto &[cert, uValidTo] : storageList)
|
||||
{
|
||||
buffer.Write<AuUInt32>(cert.size());
|
||||
buffer.Write<AuInt64>(uValidTo);
|
||||
buffer.Write(AuMemoryViewRead { cert });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CertificateStore::Deserialize(Memory::ByteBuffer &buffer)
|
||||
{
|
||||
AU_LOCK_GUARD(this->rwLock->AsWritable());
|
||||
|
||||
while (buffer.RemainingBytes())
|
||||
{
|
||||
auto uLength = buffer.Read<AuUInt32>();
|
||||
if (!uLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto iValidTo = buffer.Read<AuInt64>();
|
||||
|
||||
auto view = buffer.GetLinearReadableForExactly(uLength);
|
||||
if (!view)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
buffer.readPtr += uLength;
|
||||
|
||||
AuUInt32 uCode { AuFnv1a32Runtime(view.Begin(), view.Size()) };
|
||||
AuByteBuffer buffer { view };
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->storage[uCode].push_back(AuMakePair(AuMove(buffer), iValidTo));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AUKN_SYM ICertificateStore *NewCertificateStoreNew()
|
||||
{
|
||||
return _new CertificateStore();
|
||||
}
|
||||
|
||||
AUKN_SYM void NewCertificateStoreRelease(ICertificateStore *pHandle)
|
||||
{
|
||||
AuSafeDelete<CertificateStore *>(pHandle);
|
||||
}
|
||||
}
|
27
Source/Crypto/CA/AuCertificateStore.hpp
Executable file
27
Source/Crypto/CA/AuCertificateStore.hpp
Executable file
@ -0,0 +1,27 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AauCertificateStore.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
struct CertificateStore : ICertificateStore
|
||||
{
|
||||
bool CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) override;
|
||||
|
||||
bool AddCertificate(const AuMemoryViewRead &x509Certificate) override;
|
||||
bool AddCertificateChain(X509::ICertificateChain *pChain) override;
|
||||
|
||||
|
||||
void Serialize(Memory::ByteBuffer &buffer) override;
|
||||
bool Deserialize(Memory::ByteBuffer &buffer) override;
|
||||
|
||||
AuHashMap<AuUInt32, AuList<AuPair<AuMemory::ByteBuffer, AuInt64>>> storage;
|
||||
AuRWLock rwLock;
|
||||
};
|
||||
}
|
2281
Source/Crypto/CA/AuPinBuiltin.cpp
Executable file
2281
Source/Crypto/CA/AuPinBuiltin.cpp
Executable file
File diff suppressed because it is too large
Load Diff
13
Source/Crypto/CA/AuPinBuiltin.hpp
Executable file
13
Source/Crypto/CA/AuPinBuiltin.hpp
Executable file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinBuiltin.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
|
||||
}
|
34
Source/Crypto/CA/AuPinDummy.cpp
Executable file
34
Source/Crypto/CA/AuPinDummy.cpp
Executable file
@ -0,0 +1,34 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinDummy.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPinDummy.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
AUKN_SYM IPinCertificate *PinAlwaysPassNew()
|
||||
{
|
||||
static DummyPinner<true> gInstance;
|
||||
return &gInstance;
|
||||
}
|
||||
|
||||
AUKN_SYM void PinAlwaysPassRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
// Singleton NOP
|
||||
}
|
||||
|
||||
AUKN_SYM IPinCertificate *PinAlwaysFailNew()
|
||||
{
|
||||
static DummyPinner<false> gInstance;
|
||||
return &gInstance;
|
||||
}
|
||||
|
||||
AUKN_SYM void PinAlwaysFailRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
// Singleton NOP
|
||||
}
|
||||
}
|
21
Source/Crypto/CA/AuPinDummy.hpp
Executable file
21
Source/Crypto/CA/AuPinDummy.hpp
Executable file
@ -0,0 +1,21 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinDummy.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
template<bool bStatus>
|
||||
struct DummyPinner : IPinCertificate
|
||||
{
|
||||
bool CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) override
|
||||
{
|
||||
return bStatus;
|
||||
}
|
||||
};
|
||||
}
|
47
Source/Crypto/CA/AuPinGlobal.cpp
Executable file
47
Source/Crypto/CA/AuPinGlobal.cpp
Executable file
@ -0,0 +1,47 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinGlobal.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPinGlobal.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
static AuSPtr<IPinCertificate> gDefaultPinner;
|
||||
static GlobalPinner gGlobalPinner;
|
||||
static AuRWLock gRWPinnerLock;
|
||||
|
||||
bool GlobalPinner::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate)
|
||||
{
|
||||
AU_LOCK_GUARD(gRWPinnerLock->AsReadable());
|
||||
|
||||
if (gDefaultPinner)
|
||||
{
|
||||
return gDefaultPinner->CheckCertificate(pChain, derCertificate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PinCheckDefaultNew()->CheckCertificate(pChain, derCertificate);
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM IPinCertificate *PinCheckGlobalNew()
|
||||
{
|
||||
return &gGlobalPinner;
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckGlobalRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
// Singleton NOP
|
||||
}
|
||||
|
||||
AUKN_SYM void SetGlobalTLSPinner(const AuSPtr<IPinCertificate> &pNewDefault)
|
||||
{
|
||||
AU_LOCK_GUARD(gRWPinnerLock->AsWritable());
|
||||
gDefaultPinner = pNewDefault;
|
||||
}
|
||||
}
|
17
Source/Crypto/CA/AuPinGlobal.hpp
Executable file
17
Source/Crypto/CA/AuPinGlobal.hpp
Executable file
@ -0,0 +1,17 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinGlobal.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
struct GlobalPinner : IPinCertificate
|
||||
{
|
||||
bool CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) override;
|
||||
};
|
||||
}
|
54
Source/Crypto/CA/AuPinLinuxLike.cpp
Executable file
54
Source/Crypto/CA/AuPinLinuxLike.cpp
Executable file
@ -0,0 +1,54 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinLinuxLike.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPinLinuxLike.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
IPinCertificate *PinLinuxLikeNew()
|
||||
{
|
||||
auto pStore = NewCertificateStoreNew();
|
||||
if (!pStore)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuString certs;
|
||||
if (!AuFS::ReadString("/etc/ssl/certs/ca-bundle.crt", certs))
|
||||
{
|
||||
if (!AuFS::ReadString("/etc/ssl/certs/ca-certificates.crt", certs))
|
||||
{
|
||||
SysPushErrorIO("No SSL certificates.crt file");
|
||||
NewCertificateStoreRelease(pStore);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto pChain = AuCrypto::X509::NewChainFromManyPemInStreamUnique(certs);
|
||||
if (!pChain)
|
||||
{
|
||||
SysPushErrorSyntax("Couldn't parse system cert file!");
|
||||
NewCertificateStoreRelease(pStore);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pStore->AddCertificateChain(pChain.get()))
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
NewCertificateStoreRelease(pStore);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pStore;
|
||||
}
|
||||
|
||||
void PinLinuxLikeRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
NewCertificateStoreRelease(AuStaticCast<ICertificateStore>(pHandle));
|
||||
}
|
||||
}
|
14
Source/Crypto/CA/AuPinLinuxLike.hpp
Executable file
14
Source/Crypto/CA/AuPinLinuxLike.hpp
Executable file
@ -0,0 +1,14 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinLinuxLike.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
IPinCertificate *PinLinuxLikeNew();
|
||||
void PinLinuxLikeRelease(IPinCertificate *pHandle);
|
||||
}
|
35
Source/Crypto/CA/AuPinOS.Linux.cpp
Executable file
35
Source/Crypto/CA/AuPinOS.Linux.cpp
Executable file
@ -0,0 +1,35 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinOS.Linux.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPinOS.Linux.hpp"
|
||||
#include "AuPinLinuxLike.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
static IPinCertificate *gLinuxPinner;
|
||||
|
||||
AUKN_SYM IPinCertificate *PinCheckOSNew()
|
||||
{
|
||||
return gLinuxPinner;
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckOSRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InitLinuxPinner()
|
||||
{
|
||||
gLinuxPinner = PinLinuxLikeNew();
|
||||
}
|
||||
|
||||
void DeinitLinuxPinner()
|
||||
{
|
||||
PinLinuxLikeRelease(AuExchange(gLinuxPinner, nullptr));
|
||||
}
|
||||
}
|
14
Source/Crypto/CA/AuPinOS.Linux.hpp
Executable file
14
Source/Crypto/CA/AuPinOS.Linux.hpp
Executable file
@ -0,0 +1,14 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinOS.Linux.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
void DeinitLinuxPinner();
|
||||
void InitLinuxPinner();
|
||||
}
|
21
Source/Crypto/CA/AuPinOS.NT.cpp
Executable file
21
Source/Crypto/CA/AuPinOS.NT.cpp
Executable file
@ -0,0 +1,21 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinOS.NT.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
AUKN_SYM IPinCertificate *PinCheckOSNew()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckOSRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
// Singleton NOP
|
||||
}
|
||||
}
|
13
Source/Crypto/CA/AuPinOS.NT.hpp
Executable file
13
Source/Crypto/CA/AuPinOS.NT.hpp
Executable file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinOS.NT.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
|
||||
}
|
68
Source/Crypto/CA/AuPinPair.cpp
Executable file
68
Source/Crypto/CA/AuPinPair.cpp
Executable file
@ -0,0 +1,68 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinPair.cpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPinPair.hpp"
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
OpAndPinner::OpAndPinner(const AuSPtr<IPinCertificate> &pA,
|
||||
const AuSPtr<IPinCertificate> &pB) :
|
||||
pA(pA),
|
||||
pB(pB)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool OpAndPinner::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate)
|
||||
{
|
||||
return this->pA->CheckCertificate(pChain, derCertificate) &&
|
||||
this->pB->CheckCertificate(pChain, derCertificate);
|
||||
}
|
||||
|
||||
OpOrPinner::OpOrPinner(const AuSPtr<IPinCertificate> &pA,
|
||||
const AuSPtr<IPinCertificate> &pB) :
|
||||
pA(pA),
|
||||
pB(pB)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool OpOrPinner::CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate)
|
||||
{
|
||||
return this->pA->CheckCertificate(pChain, derCertificate) ||
|
||||
this->pB->CheckCertificate(pChain, derCertificate);
|
||||
}
|
||||
|
||||
AUKN_SYM IPinCertificate *PinCheckTwoAndNew(const AuSPtr<IPinCertificate> &pCheckA,
|
||||
const AuSPtr<IPinCertificate> &pCheckB)
|
||||
{
|
||||
SysCheckArgNotNull(pCheckA, {});
|
||||
SysCheckArgNotNull(pCheckB, {});
|
||||
return _new OpOrPinner(pCheckA, pCheckB);
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckTwoAndRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
AuSafeDelete<OpAndPinner *>(pHandle);
|
||||
}
|
||||
|
||||
AUKN_SYM IPinCertificate *PinCheckTwoOrNew(const AuSPtr<IPinCertificate> &pCheckA,
|
||||
const AuSPtr<IPinCertificate> &pCheckB)
|
||||
{
|
||||
SysCheckArgNotNull(pCheckA, {});
|
||||
SysCheckArgNotNull(pCheckB, {});
|
||||
return _new OpOrPinner(pCheckA, pCheckB);
|
||||
}
|
||||
|
||||
AUKN_SYM void PinCheckTwoOrRelease(IPinCertificate *pHandle)
|
||||
{
|
||||
AuSafeDelete<OpOrPinner *>(pHandle);
|
||||
}
|
||||
}
|
33
Source/Crypto/CA/AuPinPair.hpp
Executable file
33
Source/Crypto/CA/AuPinPair.hpp
Executable file
@ -0,0 +1,33 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPinPair.hpp
|
||||
Date: 2024-10-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
struct OpAndPinner : IPinCertificate
|
||||
{
|
||||
AuSPtr<IPinCertificate> pA;
|
||||
AuSPtr<IPinCertificate> pB;
|
||||
|
||||
OpAndPinner(const AuSPtr<IPinCertificate> &pA, const AuSPtr<IPinCertificate> &pB);
|
||||
|
||||
bool CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) override;
|
||||
};
|
||||
|
||||
struct OpOrPinner : IPinCertificate
|
||||
{
|
||||
AuSPtr<IPinCertificate> pA;
|
||||
AuSPtr<IPinCertificate> pB;
|
||||
|
||||
OpOrPinner(const AuSPtr<IPinCertificate> &pA, const AuSPtr<IPinCertificate> &pB);
|
||||
|
||||
bool CheckCertificate(const AuSPtr<X509::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) override;
|
||||
};
|
||||
}
|
12
Source/Crypto/CA/CA.hpp
Normal file → Executable file
12
Source/Crypto/CA/CA.hpp
Normal file → Executable file
@ -1,7 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
#pragma once
|
||||
|
||||
File: CA.hpp
|
||||
Date: 2021-6-12
|
||||
Author: Reece
|
||||
***/
|
||||
namespace Aurora::Crypto::CA
|
||||
{
|
||||
void InitDefaultBuiltinCA();
|
||||
void DeinitDefaultBuiltinCA();
|
||||
}
|
104
Source/Crypto/KeyPair/AuPrivateKeyPair.cpp
Normal file
104
Source/Crypto/KeyPair/AuPrivateKeyPair.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/***
|
||||
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPrivateKeyPair.cpp
|
||||
File: TLSPrivateKeyPair.cpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuPrivateKeyPair.hpp"
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
AuString TLSErrorToString(int iError);
|
||||
}
|
||||
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/timing.h> // TODO: deprecate me
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
extern mbedtls_entropy_context gEntropy;
|
||||
extern mbedtls_ctr_drbg_context gCtrDrbg;
|
||||
}
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
PrivateKeyPairImpl::PrivateKeyPairImpl(const AuSPtr<X509::ICertificateChain> &pCertificateChain) :
|
||||
pCertificateChain(pCertificateChain)
|
||||
{
|
||||
::mbedtls_pk_init(&this->privateKey_);
|
||||
}
|
||||
|
||||
PrivateKeyPairImpl::PrivateKeyPairImpl()
|
||||
{
|
||||
::mbedtls_pk_init(&this->privateKey_);
|
||||
}
|
||||
|
||||
PrivateKeyPairImpl::~PrivateKeyPairImpl()
|
||||
{
|
||||
::mbedtls_pk_free(&this->privateKey_);
|
||||
AuMemset(&this->privateKey_, 0xFF, sizeof(this->privateKey_));
|
||||
}
|
||||
|
||||
AuSPtr<X509::ICertificateChain> PrivateKeyPairImpl::GetChain()
|
||||
{
|
||||
return this->pCertificateChain;
|
||||
}
|
||||
|
||||
X509::CertificateChain *PrivateKeyPairImpl::ToChain()
|
||||
{
|
||||
if (this->pCertificateChain)
|
||||
{
|
||||
return AuStaticCast<X509::CertificateChain>(this->pCertificateChain.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_pk_context &PrivateKeyPairImpl::GetInternal()
|
||||
{
|
||||
return this->privateKey_;
|
||||
}
|
||||
|
||||
AUKN_SYM IPrivateKeyPair *ImportPrivateKeyPairNew(const PrivateKeyPair &keyPair)
|
||||
{
|
||||
int iRet {};
|
||||
|
||||
if (!keyPair.pCertificateChain)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return {};
|
||||
}
|
||||
|
||||
auto pPrivateKey = _new PrivateKeyPairImpl(keyPair.pCertificateChain);
|
||||
if (!pPrivateKey)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return {};
|
||||
}
|
||||
|
||||
iRet = ::mbedtls_pk_parse_key(&pPrivateKey->GetInternal(),
|
||||
(const unsigned char *)keyPair.privateKey.Begin(),
|
||||
keyPair.privateKey.Size(),
|
||||
keyPair.sPassword.size() ? (const unsigned char *)keyPair.sPassword.c_str() : nullptr,
|
||||
keyPair.sPassword.size(),
|
||||
mbedtls_ctr_drbg_random,
|
||||
&Aurora::IO::TLS::gCtrDrbg);
|
||||
if (iRet != 0)
|
||||
{
|
||||
SysPushErrorCrypto("Invalid Private Key: {} ({})", Aurora::IO::TLS::TLSErrorToString(iRet), iRet);
|
||||
return {};
|
||||
}
|
||||
|
||||
return pPrivateKey;
|
||||
}
|
||||
|
||||
AUKN_SYM void ImportPrivateKeyPairRelease(IPrivateKeyPair *pHandle)
|
||||
{
|
||||
AuSafeDelete<PrivateKeyPairImpl *>(pHandle);
|
||||
}
|
||||
}
|
29
Source/Crypto/KeyPair/AuPrivateKeyPair.hpp
Normal file
29
Source/Crypto/KeyPair/AuPrivateKeyPair.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/***
|
||||
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuPrivateKeyPair.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include <Source/Crypto/X509/AuCertificateChain.hpp>
|
||||
|
||||
namespace Aurora::Crypto::KeyPair
|
||||
{
|
||||
struct PrivateKeyPairImpl : IPrivateKeyPair, AuEnableSharedFromThis<PrivateKeyPairImpl>
|
||||
{
|
||||
PrivateKeyPairImpl();
|
||||
PrivateKeyPairImpl(const AuSPtr<X509::ICertificateChain> &pCertificateChain);
|
||||
~PrivateKeyPairImpl();
|
||||
|
||||
virtual AuSPtr<X509::ICertificateChain> GetChain() override;
|
||||
|
||||
X509::CertificateChain *ToChain();
|
||||
mbedtls_pk_context &GetInternal();
|
||||
|
||||
private:
|
||||
AuSPtr<X509::ICertificateChain> pCertificateChain;
|
||||
mbedtls_pk_context privateKey_;
|
||||
};
|
||||
}
|
476
Source/Crypto/X509/AuCertificateChain.cpp
Normal file
476
Source/Crypto/X509/AuCertificateChain.cpp
Normal file
@ -0,0 +1,476 @@
|
||||
/***
|
||||
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);
|
||||
}
|
||||
}
|
45
Source/Crypto/X509/AuCertificateChain.hpp
Normal file
45
Source/Crypto/X509/AuCertificateChain.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuCertificateChain.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/oid.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct CertificateChain : ICertificateChain, AuEnableSharedFromThis<CertificateChain>
|
||||
{
|
||||
CertificateChain();
|
||||
~CertificateChain();
|
||||
|
||||
virtual AuUInt32 GetCertificateCount() override;
|
||||
virtual AuMemoryViewRead GetCertificate(AuUInt32 idx) override;
|
||||
virtual AuOptional<const CertificateDecoded &> GetCertificateDetails(AuUInt32 idx) override;
|
||||
|
||||
mbedtls_x509_crt *GetCertificateInternal(AuUInt32 idx);
|
||||
|
||||
bool Init(const AuList<AuMemoryViewRead> &certs);
|
||||
bool Init(const AuMemoryViewRead &cert);
|
||||
bool Init2(const AuMemoryViewRead &cert);
|
||||
bool Init(const AuList<AuROString> &certs);
|
||||
bool Init(const AuROString &cert);
|
||||
bool Init2(const AuROString &cert);
|
||||
bool Init(const mbedtls_x509_crt *pCert);
|
||||
|
||||
bool Precache();
|
||||
|
||||
mbedtls_x509_crt *pCertificate;
|
||||
mbedtls_x509_crt ownCertificate {};
|
||||
AuList<Crypto::X509::CertificateDecoded> decoded;
|
||||
AuMutex mutex;
|
||||
AuList<AuMemoryViewRead> ownership;
|
||||
AuMemoryViewRead ownership2;
|
||||
};
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
Copyright (C) 2022 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: GenerateCertificate.cpp
|
||||
File: AuGenerateCertificate.cpp
|
||||
Date: 2022-11-18
|
||||
Author: Reece
|
||||
***/
|
||||
@ -9,13 +9,13 @@
|
||||
#include "../Crypto.hpp"
|
||||
#include "x509.hpp"
|
||||
#include <Source/IO/TLS/TLS.hpp>
|
||||
#include <Source/IO/TLS/TLSPrivateKeyPair.hpp>
|
||||
#include <Source/Crypto/KeyPair/AuPrivateKeyPair.hpp>
|
||||
#include <mbedtls/asn1write.h>
|
||||
#include <mbedtls/oid.h>
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
AUKN_SYM AuResult<Memory::ByteBuffer> GenerateCertificate(const CertRequest &request)
|
||||
AUKN_SYM AuResult<Memory::ByteBuffer> GenerateCertificate(const CertificateRequest &request)
|
||||
{
|
||||
int iRet {};
|
||||
mbedtls_x509write_cert crt;
|
||||
@ -64,6 +64,9 @@ namespace Aurora::Crypto::X509
|
||||
{
|
||||
if (request.pRSAKey)
|
||||
{
|
||||
AuCrypto::RSA::RSAMeta rsaKeyMetadata;
|
||||
rsaKeyMetadata.encoding = AuCrypto::RSA::ERSAKeyType::eRsaKey;
|
||||
rsaKeyMetadata.type = AuCrypto::EKeyType::eKeyPublic;
|
||||
if (!request.pRSAKey->ToKey(RSA::ERSAKeyType::eRsaKey, bufPb))
|
||||
{
|
||||
SysPushErrorNested();
|
||||
@ -93,7 +96,7 @@ namespace Aurora::Crypto::X509
|
||||
|
||||
if (request.pSigningChain)
|
||||
{
|
||||
ctxPv = AuStaticCast<IO::TLS::TLSPrivateKeyPairImpl>(request.pSigningChain)->GetInternal();
|
||||
ctxPv = AuStaticCast<KeyPair::PrivateKeyPairImpl>(request.pSigningChain)->GetInternal();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -163,13 +166,14 @@ namespace Aurora::Crypto::X509
|
||||
|
||||
if (request.pSigningChain)
|
||||
{
|
||||
crt.private_issuer = &AuStaticCast<IO::TLS::CertificateChain>(request.pSigningChain->GetChain())->pCertificate->issuer;
|
||||
crt.private_issuer = &AuStaticCast<X509::CertificateChain>(request.pSigningChain->GetChain())->pCertificate->issuer;
|
||||
}
|
||||
else
|
||||
{
|
||||
crt.private_issuer = crt.private_subject;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto issueNorm = AuTime::ToCivilTime(request.iIssuedDateMs, AuTime::ETimezoneShift::eUTC);
|
||||
auto issue = fmt::format("{:04}{:02}{:02}{:02}{:02}{:02}",
|
13
Source/Crypto/X509/AuGenerateCertificate.hpp
Normal file
13
Source/Crypto/X509/AuGenerateCertificate.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2022 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuGenerateCertificate.hpp
|
||||
Date: 2022-11-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: x509.cpp
|
||||
File: Aux509.cpp
|
||||
Date: 2021-6-12
|
||||
Author: Reece
|
||||
***/
|
||||
@ -306,7 +306,7 @@ namespace Aurora::Crypto::X509
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
static void FindCommonNames(const mbedtls_x509_name &name, CertName &out)
|
||||
static void FindCommonNames(const mbedtls_x509_name &name, CertificateName &out)
|
||||
{
|
||||
find_oid_value_in_name(&name, MBEDTLS_OID_AT_CN, out.commonName);
|
||||
find_oid_value_in_name(&name, MBEDTLS_OID_AT_COUNTRY, out.countryCode);
|
||||
@ -321,28 +321,41 @@ namespace Aurora::Crypto::X509
|
||||
find_oid_value_in_name(&name, MBEDTLS_OID_AT_LOCALITY, out.locality);
|
||||
}
|
||||
|
||||
static bool ParseCert(const Certificate &der, AuFunction<void(mbedtls_x509_crt &crt)> cb)
|
||||
bool ParseCert(const AuMemoryViewRead &der, const AuFunction<void(mbedtls_x509_crt &crt)> &cb)
|
||||
{
|
||||
bool ret = false;
|
||||
bool bRet {};
|
||||
mbedtls_x509_crt crt {};
|
||||
|
||||
mbedtls_x509_crt_init(&crt);
|
||||
|
||||
auto status = mbedtls_x509_crt_parse(&crt,
|
||||
reinterpret_cast<const unsigned char *>(der.data()),
|
||||
der.size());
|
||||
der.Begin<unsigned char>(),
|
||||
der.Size());
|
||||
|
||||
if (status < 0) goto out;
|
||||
if (status < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb(crt);
|
||||
try
|
||||
{
|
||||
if (cb)
|
||||
{
|
||||
cb(crt);
|
||||
}
|
||||
bRet = true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorCatch();
|
||||
}
|
||||
|
||||
ret = true;
|
||||
out:
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
return ret;
|
||||
return bRet;
|
||||
}
|
||||
|
||||
static AuInt64 ConvertTime(const mbedtls_x509_time &time)
|
||||
AuInt64 ConvertTime(const mbedtls_x509_time &time)
|
||||
{
|
||||
AuTime::tm tm = {};
|
||||
tm.year = time.year;
|
||||
@ -354,7 +367,7 @@ namespace Aurora::Crypto::X509
|
||||
return AuTime::FromCivilTime(tm, AuTime::ETimezoneShift::eUTC);
|
||||
}
|
||||
|
||||
static void FindUsage(DecodedCertificate &out,
|
||||
static void FindUsage(CertificateDecoded &out,
|
||||
const mbedtls_x509_sequence *extended_key_usage)
|
||||
{
|
||||
const mbedtls_x509_sequence *pCur = extended_key_usage;
|
||||
@ -384,7 +397,7 @@ namespace Aurora::Crypto::X509
|
||||
}
|
||||
}
|
||||
|
||||
void DecodeInternal(const mbedtls_x509_crt &crt, DecodedCertificate &out)
|
||||
bool DecodeInternal(const mbedtls_x509_crt &crt, CertificateDecoded &out)
|
||||
{
|
||||
auto &issuer = crt.issuer;
|
||||
auto &subject = crt.subject;
|
||||
@ -403,24 +416,34 @@ namespace Aurora::Crypto::X509
|
||||
|
||||
x509_get_ca_id((mbedtls_x509_crt *)&crt, out.issuer.id);
|
||||
x509_get_subject_id((mbedtls_x509_crt *)&crt, out.subject.id);
|
||||
x509_get_aia((mbedtls_x509_crt *)&crt, out.OCSPs, out.AIAs);
|
||||
|
||||
out.serialNumber.resize(crt.serial.len);
|
||||
memcpy(out.serialNumber.data(), crt.serial.p, out.serialNumber.size());
|
||||
if (out.serialNumber.Write(crt.serial.p, crt.serial.len) != crt.serial.len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
out.algorithmOid.resize(crt.sig_oid.len);
|
||||
memcpy(out.algorithmOid.data(), crt.sig_oid.p, out.algorithmOid.size());
|
||||
if (out.algorithmOid.Write(crt.sig_oid.p, crt.sig_oid.len) != crt.sig_oid.len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AuList<AuString> oscp;
|
||||
x509_get_aia((mbedtls_x509_crt *)&crt, oscp, out.AIAs);
|
||||
if (out.publicKey.Write(crt.pk_raw.p, crt.pk_raw.len) != crt.pk_raw.len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AUKN_SYM bool Decode(const Certificate &der, DecodedCertificate &out)
|
||||
AUKN_SYM bool Decode(const AuMemoryViewRead &der, CertificateDecoded &out)
|
||||
{
|
||||
bool bRet { true };
|
||||
return ParseCert(der,
|
||||
[&](mbedtls_x509_crt &crt)
|
||||
{
|
||||
DecodeInternal(crt, out);
|
||||
});
|
||||
bRet = DecodeInternal(crt, out);
|
||||
}) && bRet;
|
||||
}
|
||||
|
||||
static bool IsHighRiskStateIssuer(const mbedtls_x509_crt &ca)
|
||||
@ -439,62 +462,15 @@ namespace Aurora::Crypto::X509
|
||||
return true;
|
||||
}
|
||||
|
||||
// Winnie the Pooh has been caught with his paws in the honey jar one too many times
|
||||
// At least other nation state attacks have been covert enough for us to not know about any *TLS* MITM attacks originating from them
|
||||
// Pro-china cuckolds at mozilla suggested we merely block certs issued issued by compromised cn CAs using their issue date. lol no
|
||||
// https://arstechnica.com/information-technology/2015/03/google-warns-of-unauthorized-tls-certificates-trusted-by-almost-all-oses/
|
||||
// https://www.zdnet.com/article/china-is-now-blocking-all-encrypted-https-traffic-using-tls-1-3-and-esni/
|
||||
// https://www.popularmechanics.com/military/news/a28510/china-secret-plan-invade-taiwan/
|
||||
// https://www.theguardian.com/world/2021/mar/10/china-could-invade-taiwan-in-next-six-years-top-us-admiral-warns
|
||||
// https://en.wikipedia.org/wiki/Lazarus_Group (use chinese connections)
|
||||
if ((!gRuntimeConfig.crypto.allowChineseCerts) &&
|
||||
(stricmp(issuer.c_str(), "cn") == 0) || // mainland and countries the communists decided are theirs. often used by the dprk
|
||||
(stricmp(issuer.c_str(), "mo") == 0) || // macau, china special admin region
|
||||
(stricmp(issuer.c_str(), "hk") == 0) || // hong kong
|
||||
/*(stricmp(issuer.c_str(), "tw") == 0)*/ false) // tehe yes we will be ready to invade by 2020. i suppose taiwan is safe enough for.now
|
||||
{
|
||||
SysPushErrorCrypt("The funny western yellow bear in the east is behind you");
|
||||
return true;
|
||||
}
|
||||
|
||||
// The intersection between technical threats and countries we can't do business with legally
|
||||
// https://en.wikipedia.org/wiki/United_States_sanctions
|
||||
// https://en.wikipedia.org/wiki/Communications_in_Iran
|
||||
// https://www.gov.uk/government/collections/financial-sanctions-regime-specific-consolidated-lists-and-releases
|
||||
// https://en.wikipedia.org/wiki/Lazarus_Group
|
||||
// https://www.bbc.co.uk/news/stories-57520169
|
||||
if ((stricmp(issuer.c_str(), "ir") == 0) || // iran - has own intranet. IXPs are owned by the state
|
||||
(stricmp(issuer.c_str(), "iq") == 0) || // iraq
|
||||
(stricmp(issuer.c_str(), "kp") == 0)) // north korea - has own intranet. IXPs are owned by the state
|
||||
{
|
||||
SysPushErrorCrypt("Service is unavailable in your country for legal and/or technical safety concerns");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Russia is somewhat misunderstood and have their hands tied in a lot of cases, not to excuse blatent corruption
|
||||
// Moscow wants MSK-IX IXP to be independent and have ran tests to validate their intranet could work without the rest of the world
|
||||
// I wonder if Pavel Durov would trust russian certificates, probably not, right? Major states, especially Russia, shouldn't be trusted with foreign services
|
||||
// allowRussianCerts is true by default; however, services targeting a market of close political enemies of russia should consider disallowing russian certs
|
||||
// Further, private infrastructure around Russian territories should consider a heightened global pinning security policy
|
||||
if ((!gRuntimeConfig.crypto.allowRussianCerts) &&
|
||||
(stricmp(issuer.c_str(), "ru") == 0))
|
||||
{
|
||||
SysPushErrorCrypt("Service is unavailable in your country for technical safety concerns");
|
||||
return true;
|
||||
}
|
||||
|
||||
// The 5 eyes are smart enough to know MITM attacks would send alarms ringing at major services providers
|
||||
// They are known to MITM plain text traffic and hoard vulns; however, we can design around these issues
|
||||
// Do not use NIST curves, do not use plain text across public IXPs, don't save data in plain text in EU/US datacenters, etc
|
||||
// There is nothing we can do about western powers. They seem to be playing... not fair... but smart
|
||||
{
|
||||
// obama bin listening
|
||||
}
|
||||
// TODO: removed <on pastebin>
|
||||
// We need some kind of shim objects for IPinCertificate &
|
||||
// some kind of plan on how intrastructure that has to trust public exchange points will deal with state sponsored attacks.
|
||||
// this old check isnt it.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AUKN_SYM bool Validate(const Certificate &der, const Certificate &parentDer)
|
||||
AUKN_SYM bool Validate(const AuMemoryViewRead &der, const AuMemoryViewRead &parentDer)
|
||||
{
|
||||
bool failed = false;
|
||||
|
||||
@ -511,7 +487,9 @@ namespace Aurora::Crypto::X509
|
||||
return;
|
||||
}
|
||||
|
||||
failed |= 0 > mbedtls_x509_crt_verify_restartable(&crt, &ca, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
uint32_t flags {};
|
||||
failed |= 0 > mbedtls_x509_crt_verify_restartable(&crt, &ca, NULL, &mbedtls_x509_crt_profile_default, NULL, &flags, NULL, NULL, NULL);
|
||||
failed |= flags != 0;
|
||||
});
|
||||
}) && !failed;
|
||||
}
|
10
Source/Crypto/X509/AuX509.hpp
Executable file
10
Source/Crypto/X509/AuX509.hpp
Executable file
@ -0,0 +1,10 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Aux509.hpp
|
||||
Date: 2021-6-12
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "x509.hpp"
|
@ -1,13 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: GenerateCertificate.hpp
|
||||
Date: 2022-11-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
|
||||
namespace Aurora::Crypto::X509
|
||||
{
|
||||
struct DecodedCertificate;
|
||||
struct CertificateDecoded;
|
||||
|
||||
void DecodeInternal(const mbedtls_x509_crt &crt, DecodedCertificate &out);
|
||||
bool DecodeInternal(const mbedtls_x509_crt &crt, CertificateDecoded &out);
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/debug.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/timing.h> // TODO: deprecate me
|
||||
|
@ -1,209 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: TLSCertificateChain.cpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#include "TLS.hpp"
|
||||
#include "TLSCertificateChain.hpp"
|
||||
#include <Source/Crypto/X509/x509.hpp>
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
AuSPtr<AuMemoryViewRead> CertificateChain::GetCertificate(AuUInt32 idx)
|
||||
{
|
||||
AuUInt32 ret {};
|
||||
|
||||
auto pCert = this->pCertificate;
|
||||
if (!pCert)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
do
|
||||
{
|
||||
auto index = ret++;
|
||||
|
||||
if (index == idx)
|
||||
{
|
||||
struct View : AuMemoryViewRead
|
||||
{
|
||||
View(const AuMemoryViewRead &in, AuSPtr<void> pin) :
|
||||
AuMemoryViewRead(in),
|
||||
pin(pin)
|
||||
{ }
|
||||
|
||||
AuSPtr<void> pin;
|
||||
};
|
||||
|
||||
return AuMakeSharedThrow<View>(AuMemoryViewRead { pCert->raw.p, pCert->raw.len}, AuSharedFromThis());
|
||||
}
|
||||
}
|
||||
while ((pCert = pCert->next));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Crypto::X509::DecodedCertificate CertificateChain::GetCertificateDetails(AuUInt32 idx)
|
||||
{
|
||||
AuUInt32 ret {};
|
||||
|
||||
auto pCert = this->pCertificate;
|
||||
if (!pCert)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
do
|
||||
{
|
||||
auto index = ret++;
|
||||
|
||||
if (index == idx)
|
||||
{
|
||||
Crypto::X509::DecodedCertificate cert;
|
||||
AuCrypto::X509::DecodeInternal(*pCert, cert);
|
||||
return cert;
|
||||
}
|
||||
}
|
||||
while ((pCert = pCert->next));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool CertificateChain::Init(const AuList<AuByteBuffer> &certs)
|
||||
{
|
||||
int iRet {};
|
||||
|
||||
this->pCertificate = &this->ownCertificate;
|
||||
::mbedtls_x509_crt_init(&this->ownCertificate);
|
||||
|
||||
for (const auto &cert : certs)
|
||||
{
|
||||
iRet = ::mbedtls_x509_crt_parse(&this->ownCertificate,
|
||||
(const unsigned char *)cert.base,
|
||||
cert.length);
|
||||
if (iRet != 0)
|
||||
{
|
||||
this->pCertificate = nullptr;
|
||||
SysPushErrorCrypto("Failed to parse certificate chain: {}", iRet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this->Precache();
|
||||
}
|
||||
|
||||
bool CertificateChain::Init(const AuList<AuMemoryViewRead> &certs)
|
||||
{
|
||||
int iRet {};
|
||||
|
||||
this->pCertificate = &this->ownCertificate;
|
||||
::mbedtls_x509_crt_init(&this->ownCertificate);
|
||||
|
||||
for (const auto &cert : certs)
|
||||
{
|
||||
iRet = ::mbedtls_x509_crt_parse(&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);
|
||||
|
||||
iRet = ::mbedtls_x509_crt_parse(&this->ownCertificate,
|
||||
(const unsigned char *)cert.ToPointer(),
|
||||
cert.length);
|
||||
if (iRet != 0)
|
||||
{
|
||||
SysPushErrorCrypto("Failed to parse certificate chain: {}", iRet);
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->Precache();
|
||||
}
|
||||
|
||||
bool CertificateChain::Init(const mbedtls_x509_crt *pCert)
|
||||
{
|
||||
this->pCertificate = (mbedtls_x509_crt *)pCert;
|
||||
return this->Precache();
|
||||
}
|
||||
|
||||
bool CertificateChain::Precache()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ICertificateChain> ChainFromOne(const AuMemoryViewRead &read)
|
||||
{
|
||||
auto pCertificateChain = AuMakeShared<CertificateChain>();
|
||||
if (!pCertificateChain)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pCertificateChain->Init(read))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return pCertificateChain;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ICertificateChain> ChainFromMany(const AuList<AuMemoryViewRead> &read)
|
||||
{
|
||||
auto pCertificateChain = AuMakeShared<CertificateChain>();
|
||||
if (!pCertificateChain)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pCertificateChain->Init(read))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return pCertificateChain;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: TLSCertificateChain.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct CertificateChain : ICertificateChain, AuEnableSharedFromThis<CertificateChain>
|
||||
{
|
||||
CertificateChain();
|
||||
~CertificateChain();
|
||||
|
||||
virtual AuUInt32 GetCertificateCount() override;
|
||||
virtual AuSPtr<AuMemoryViewRead> GetCertificate(AuUInt32 idx) override;
|
||||
virtual Crypto::X509::DecodedCertificate GetCertificateDetails(AuUInt32 idx) override;
|
||||
|
||||
bool Init(const AuList<AuByteBuffer> &certs);
|
||||
bool Init(const AuList<AuMemoryViewRead> &certs);
|
||||
bool Init(const AuMemoryViewRead &cert);
|
||||
bool Init(const mbedtls_x509_crt *pCert);
|
||||
|
||||
bool Precache();
|
||||
|
||||
mbedtls_x509_crt *pCertificate;
|
||||
mbedtls_x509_crt ownCertificate {};
|
||||
};
|
||||
}
|
@ -11,7 +11,8 @@
|
||||
#include <Aurora/IO/Net/NetExperimental.hpp>
|
||||
#include <Source/IO/Net/AuNetSocket.hpp>
|
||||
#include <Source/Crypto/X509/x509.hpp>
|
||||
#include "TLSCertificateChain.hpp"
|
||||
#include <Source/Crypto/X509/AuCertificateChain.hpp>
|
||||
#include <Source/Crypto/KeyPair/AuPrivateKeyPair.hpp>
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
@ -22,7 +23,7 @@ namespace Aurora::IO::TLS
|
||||
|
||||
AuString TLSErrorToString(int iError)
|
||||
{
|
||||
char description[1024];
|
||||
char description[1024] { 0 };
|
||||
::mbedtls_strerror(iError, description, AuArraySize(description));
|
||||
return description;
|
||||
}
|
||||
@ -84,6 +85,7 @@ namespace Aurora::IO::TLS
|
||||
TLSContext::~TLSContext()
|
||||
{
|
||||
this->Destroy();
|
||||
AuMemset(&this->ssl, 0, sizeof(this->ssl));
|
||||
}
|
||||
|
||||
//
|
||||
@ -132,12 +134,7 @@ namespace Aurora::IO::TLS
|
||||
|
||||
bool TLSContext::CheckCertificate(mbedtls_x509_crt const *child, const AuMemoryViewRead &read)
|
||||
{
|
||||
if (!this->meta_.pCertPin)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto pCertChain = AuMakeShared<CertificateChain>();
|
||||
auto pCertChain = AuMakeShared<AuCrypto::X509::CertificateChain>();
|
||||
if (!pCertChain)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
@ -146,11 +143,94 @@ namespace Aurora::IO::TLS
|
||||
|
||||
pCertChain->Init(child);
|
||||
|
||||
auto bRet = this->meta_.pCertPin->CheckCertificate(pCertChain, read);
|
||||
bool bRet;
|
||||
if (this->meta_.pCertPin)
|
||||
{
|
||||
bRet = this->meta_.pCertPin->CheckCertificate(pCertChain, read);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No release needed!
|
||||
bRet = AuCrypto::CA::PinCheckGlobalNew()->CheckCertificate(pCertChain, read);
|
||||
}
|
||||
pCertChain->pCertificate = nullptr;
|
||||
return bRet;
|
||||
}
|
||||
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> TLSContext::GetKeyPairForSNI(const AuROString &name)
|
||||
{
|
||||
if (this->meta_.pKeyPairProvider)
|
||||
{
|
||||
if (auto pRet = this->meta_.pKeyPairProvider->FetchBySNI(name))
|
||||
{
|
||||
return pRet;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->meta_.bIsClient || this->meta_.server.bAllowSNIToFallBackDefault)
|
||||
{
|
||||
return this->GetDefaultKeyPair();
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> TLSContext::GetDefaultKeyPair()
|
||||
{
|
||||
if (this->meta_.pDefaultKeyPair)
|
||||
{
|
||||
return this->meta_.pDefaultKeyPair;
|
||||
}
|
||||
|
||||
if (auto pRet = this->meta_.pKeyPairProvider->FetchBySNI({}))
|
||||
{
|
||||
return pRet;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool TLSContext::SetBasicCerts()
|
||||
{
|
||||
if (this->meta_.bIsClient || this->meta_.server.bAllowSNILessUseDefaultCert)
|
||||
{
|
||||
this->pStoredPair = this->GetDefaultKeyPair();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TLSContext::OnSNI(const AuROString &name)
|
||||
{
|
||||
this->pStoredPair = this->GetKeyPairForSNI(name);
|
||||
}
|
||||
|
||||
bool TLSContext::DoFinalCerts()
|
||||
{
|
||||
auto pKeyVal = this->pStoredPair;
|
||||
if (!pKeyVal)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
pKeyVal = this->GetDefaultKeyPair();
|
||||
}
|
||||
|
||||
if (!pKeyVal)
|
||||
{
|
||||
AuLogWarn("no key val");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto pKeyPairEx = AuStaticCast<AuCrypto::KeyPair::PrivateKeyPairImpl>(pKeyVal);
|
||||
auto pPKContext = &pKeyPairEx->GetInternal();
|
||||
auto pPublicChain = AuStaticCast<AuCrypto::X509::CertificateChain>(pKeyPairEx->GetChain());
|
||||
auto pCertificate = pPublicChain ? pPublicChain->pCertificate : nullptr;
|
||||
|
||||
return mbedtls_ssl_set_hs_own_cert(&this->ssl, pCertificate, pPKContext) == 0;
|
||||
}
|
||||
|
||||
//
|
||||
// tls context
|
||||
//
|
||||
@ -187,11 +267,12 @@ namespace Aurora::IO::TLS
|
||||
|
||||
::mbedtls_ssl_init(&this->ssl);
|
||||
::mbedtls_ssl_config_init(&this->conf);
|
||||
::mbedtls_ssl_set_user_data_p(&this->ssl, this);
|
||||
|
||||
if ((iRet = ::mbedtls_ssl_config_defaults(&this->conf,
|
||||
this->meta_.bIsClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
this->meta_.transportProtocol == AuNet::ETransportProtocol::eProtocolUDP ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
this->meta_.bIsClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
this->meta_.transportProtocol == AuNet::ETransportProtocol::eProtocolUDP ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
{
|
||||
SysPushErrorNet("{} ({})", TLSErrorToString(iRet), iRet);
|
||||
return false;
|
||||
@ -214,32 +295,96 @@ namespace Aurora::IO::TLS
|
||||
}
|
||||
|
||||
::mbedtls_ssl_conf_verify(&this->conf, [](void *p_ctx, mbedtls_x509_crt *crt,
|
||||
int depth, uint32_t *flags)
|
||||
int depth, uint32_t *flags)
|
||||
{
|
||||
*flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
|
||||
if (depth != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
((TLSContext *)p_ctx)->CheckCertificate(crt, { crt->raw.p, crt->raw.len }) ? 0 : -1;
|
||||
if (!((TLSContext *)p_ctx)->CheckCertificate(crt, { crt->raw.p, crt->raw.len }))
|
||||
{
|
||||
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}, this);
|
||||
|
||||
//
|
||||
|
||||
#if 0
|
||||
// todo: useful for clients or servers of single certs? p2p pinning?
|
||||
::mbedtls_ssl_conf_ca_cb(&this->conf, [](void *p_ctx,
|
||||
mbedtls_x509_crt const *child,
|
||||
mbedtls_x509_crt **candidate_cas) -> int
|
||||
{
|
||||
return 0;// ((TLSContext *)p_ctx)->CheckCertificate(child, { child->raw.p, child->raw.len }) ? 0 : -1;
|
||||
}, this);
|
||||
#endif
|
||||
|
||||
::mbedtls_ssl_conf_rng(&this->conf, mbedtls_ctr_drbg_random, &gCtrDrbg);
|
||||
|
||||
::mbedtls_ssl_conf_dbg(&this->conf, [](void *, int, const char *as, int, const char *ad)
|
||||
if (this->meta_.bEnableDebug)
|
||||
{
|
||||
//AuLogDbg("{} <--> {}", as, ad);
|
||||
}, nullptr);
|
||||
::mbedtls_ssl_conf_dbg(&this->conf, [](void *p_ctx, int, const char *file, int line, const char *message)
|
||||
{
|
||||
AuLogDbg("{} : {}\t {}", file, line, message);
|
||||
}, nullptr);
|
||||
mbedtls_debug_set_threshold(5);
|
||||
}
|
||||
|
||||
if (!this->meta_.bIsClient)
|
||||
{
|
||||
::mbedtls_ssl_conf_sni(&this->conf, [](void *p_ctx, mbedtls_ssl_context *ssl,
|
||||
const unsigned char *name, size_t name_len) -> int
|
||||
{
|
||||
auto pTlsContext = (TLSContext *)p_ctx;
|
||||
|
||||
pTlsContext->OnSNI( AuROString { (const char *)name, name_len});
|
||||
|
||||
if (!pTlsContext->DoFinalCerts())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}, this);
|
||||
|
||||
::mbedtls_ssl_conf_cert_cb(&this->conf, [](mbedtls_ssl_context *ssl) -> int
|
||||
{
|
||||
auto pTlsContext = (TLSContext *)::mbedtls_ssl_get_user_data_p(ssl);
|
||||
|
||||
if (!pTlsContext->pStoredPair)
|
||||
{
|
||||
if (!pTlsContext->SetBasicCerts())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pTlsContext->DoFinalCerts())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
#if 1
|
||||
else
|
||||
{
|
||||
::mbedtls_ssl_conf_ca_cb(&this->conf, [](void *p_ctx,
|
||||
mbedtls_x509_crt const *child,
|
||||
mbedtls_x509_crt **candidate_cas) -> int
|
||||
{
|
||||
return 0;
|
||||
}, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((iRet = ::mbedtls_ssl_setup(&this->ssl, &this->conf)) != 0)
|
||||
{
|
||||
|
@ -53,6 +53,14 @@ namespace Aurora::IO::TLS
|
||||
|
||||
AuString GetFatalErrorCodeAsString() override;
|
||||
|
||||
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> GetKeyPairForSNI(const AuROString &name);
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> GetDefaultKeyPair();
|
||||
|
||||
bool SetBasicCerts();
|
||||
bool DoFinalCerts();
|
||||
void OnSNI(const AuROString &name);
|
||||
|
||||
void OnClose();
|
||||
void OnFatal();
|
||||
|
||||
@ -65,6 +73,7 @@ namespace Aurora::IO::TLS
|
||||
|
||||
mbedtls_ssl_context ssl {};
|
||||
mbedtls_ssl_config conf {};
|
||||
bool bDebugging {};
|
||||
|
||||
int Read(void *pOut, AuUInt length);
|
||||
int Write(const void *pIn, AuUInt length);
|
||||
@ -88,6 +97,7 @@ namespace Aurora::IO::TLS
|
||||
|
||||
AuList<int> cipherSuites_;
|
||||
TLSMeta meta_;
|
||||
AuSPtr<Crypto::KeyPair::IPrivateKeyPair> pStoredPair {};
|
||||
AuWPtr<Net::ISocket> wpSocket_;
|
||||
TLSProtocolRecv channelRecv_;
|
||||
TLSProtocolSend channelSend_;
|
||||
|
@ -1,69 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: TLSPrivateKeyPair.cpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#include "TLS.hpp"
|
||||
#include "TLSPrivateKeyPair.hpp"
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
TLSPrivateKeyPairImpl::TLSPrivateKeyPairImpl()
|
||||
{
|
||||
::mbedtls_pk_init(&this->privateKey_);
|
||||
}
|
||||
|
||||
TLSPrivateKeyPairImpl::~TLSPrivateKeyPairImpl()
|
||||
{
|
||||
::mbedtls_pk_free(&this->privateKey_);
|
||||
}
|
||||
|
||||
AuSPtr<ICertificateChain> TLSPrivateKeyPairImpl::GetChain()
|
||||
{
|
||||
return AuSPtr<ICertificateChain>(AuSharedFromThis(), &this->chain_);
|
||||
}
|
||||
|
||||
CertificateChain *TLSPrivateKeyPairImpl::ToChain()
|
||||
{
|
||||
return &this->chain_;
|
||||
}
|
||||
|
||||
mbedtls_pk_context &TLSPrivateKeyPairImpl::GetInternal()
|
||||
{
|
||||
return this->privateKey_;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ITLSPrivateKeyPair> ImportPrivateKeyPair(const TLSPrivateKeyPair &keyPair)
|
||||
{
|
||||
int iRet {};
|
||||
auto pPrivateKey = AuMakeShared<TLSPrivateKeyPairImpl>();
|
||||
if (!pPrivateKey)
|
||||
{
|
||||
SysPushErrorMemory();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pPrivateKey->ToChain()->Init(keyPair.certificateChain))
|
||||
{
|
||||
// Not going to bother with a nested push
|
||||
return {};
|
||||
}
|
||||
|
||||
iRet = ::mbedtls_pk_parse_key(&pPrivateKey->GetInternal(),
|
||||
(const unsigned char *)keyPair.privateKey.readPtr,
|
||||
keyPair.privateKey.RemainingBytes(),
|
||||
keyPair.sPassword.size() ? (const unsigned char *)keyPair.sPassword.c_str() : nullptr,
|
||||
keyPair.sPassword.size(),
|
||||
mbedtls_ctr_drbg_random,
|
||||
&gCtrDrbg);
|
||||
if (iRet != 0)
|
||||
{
|
||||
SysPushErrorCrypto("Invalid Private Key: {} ({})", TLSErrorToString(iRet), iRet);
|
||||
return {};
|
||||
}
|
||||
|
||||
return pPrivateKey;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: TLSPrivateKeyPair.hpp
|
||||
Date: 2022-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "TLSCertificateChain.hpp"
|
||||
|
||||
namespace Aurora::IO::TLS
|
||||
{
|
||||
struct TLSPrivateKeyPairImpl : ITLSPrivateKeyPair, AuEnableSharedFromThis<TLSPrivateKeyPairImpl>
|
||||
{
|
||||
TLSPrivateKeyPairImpl();
|
||||
~TLSPrivateKeyPairImpl();
|
||||
|
||||
virtual AuSPtr<ICertificateChain> GetChain() override;
|
||||
|
||||
CertificateChain *ToChain();
|
||||
mbedtls_pk_context &GetInternal();
|
||||
|
||||
private:
|
||||
CertificateChain chain_;
|
||||
mbedtls_pk_context privateKey_;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user