diff --git a/misc/windows/min-wincrypt.h b/misc/windows/min-wincrypt.h
index 07aed556f..6c0f30026 100644
--- a/misc/windows/min-wincrypt.h
+++ b/misc/windows/min-wincrypt.h
@@ -4,7 +4,6 @@
typedef void* HCERTSTORE;
typedef void* PCCERT_CONTEXT;
-typedef void* PCCERT_CHAIN_CONTEXT;
#define szOID_PKIX_KP_SERVER_AUTH "1.3.6.1.5.5.7.3.1"
#define szOID_SERVER_GATED_CRYPTO "1.3.6.1.4.1.311.10.3.3"
@@ -37,6 +36,25 @@ typedef struct _CERT_CHAIN_PARA {
CERT_USAGE_MATCH RequestedUsage;
} CERT_CHAIN_PARA;
+typedef struct _CERT_TRUST_STATUS {
+ DWORD dwErrorStatus;
+ DWORD dwInfoStatus;
+} CERT_TRUST_STATUS, *PCERT_TRUST_STATUS;
+
+typedef struct _CERT_CHAIN_CONTEXT {
+ DWORD cbSize;
+ CERT_TRUST_STATUS TrustStatus;
+ DWORD cChain;
+ void* rgpChain;
+ DWORD cLowerQualityChainContext;
+ void* rgpLowerQualityChainContext;
+ BOOL fHasRevocationFreshnessTime;
+ DWORD dwRevocationFreshnessTime;
+ DWORD dwCreateFlags;
+ GUID ChainId;
+} CERT_CHAIN_CONTEXT, *PCERT_CHAIN_CONTEXT;
+typedef const CERT_CHAIN_CONTEXT* PCCERT_CHAIN_CONTEXT;
+
CC_CRYPT32_FUNC BOOL (WINAPI *_CryptProtectData )(DATA_BLOB* dataIn, PCWSTR dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut);
CC_CRYPT32_FUNC BOOL (WINAPI *_CryptUnprotectData)(DATA_BLOB* dataIn, PWSTR* dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut);
diff --git a/readme.md b/readme.md
index 9bbc24b7a..a12917b7b 100644
--- a/readme.md
+++ b/readme.md
@@ -139,7 +139,7 @@ Setting up TCC:
Compiling with TCC:
1. Navigate to the directory with ClassiCube's source code
2. In `ExtMath.c`, change `fabsf` to `fabs` and `sqrtf` to `sqrt`
-3. Run `tcc.exe -o ClassiCube.exe *.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
+3. Run `tcc.exe -o ClassiCube.exe src/*.c third_party/bearssl/*.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
(Note: You may need to specify the full path to `tcc.exe` instead of just `tcc.exe`)
## Compiling - Linux
diff --git a/src/Certs.c b/src/Certs.c
index 4bebe6336..c96bef581 100644
--- a/src/Certs.c
+++ b/src/Certs.c
@@ -315,30 +315,21 @@ static const LPCSTR const usage[] = {
szOID_SGC_NETSCAPE
};
-int Certs_VerifyChain(struct X509CertContext* x509) {
- struct X509Cert* cert = &x509->certs[0];
+static BOOL BuildChain(struct X509CertContext* x509, HCERTSTORE store, PCCERT_CONTEXT* end_cert, PCCERT_CHAIN_CONTEXT* chain) {
+ struct X509Cert* cert;
CERT_CHAIN_PARA para = { 0 };
- PCCERT_CHAIN_CONTEXT chain;
- PCCERT_CONTEXT end_cert;
- HCERTSTORE store;
- BOOL ok;
int i;
- if (!_CertOpenStore) return ERR_NOT_SUPPORTED;
- store = _CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
- if (!store) return ERR_NOT_SUPPORTED;
-
- end_cert = NULL;
- ok = _CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, cert->data, cert->offset,
- CERT_STORE_ADD_ALWAYS, &end_cert);
- if (!ok || !end_cert)
- return -1;
+ BOOL ok = _CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, cert->data, cert->offset,
+ CERT_STORE_ADD_ALWAYS, end_cert);
+ if (!ok || !(*end_cert)) return FALSE;
for (i = 1; i < x509->numCerts; i++)
{
cert = &x509->certs[i];
- ok = _CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, cert->data, cert->offset,
+ ok = _CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, cert->data, cert->offset,
CERT_STORE_ADD_ALWAYS, NULL);
+
}
para.cbSize = sizeof(para);
@@ -346,13 +337,30 @@ int Certs_VerifyChain(struct X509CertContext* x509) {
para.RequestedUsage.Usage.cUsageIdentifier = Array_Elems(usage);
para.RequestedUsage.Usage.rgpszUsageIdentifier = (LPSTR*)usage;
- chain = NULL;
- ok = _CertGetCertificateChain(NULL, end_cert, NULL, NULL, ¶, 0, NULL, &chain);
- // TODO look at dwErrorStatus
+ return _CertGetCertificateChain(NULL, *end_cert, NULL, NULL, ¶, 0, NULL, chain);
+}
+
+int Certs_VerifyChain(struct X509CertContext* x509) {
+ struct X509Cert* cert = &x509->certs[0];
+ PCCERT_CHAIN_CONTEXT chain = NULL;
+ PCCERT_CONTEXT end_cert = NULL;
+ HCERTSTORE store;
+ DWORD res = 200;
+ BOOL ok;
+
+ if (!_CertOpenStore) return ERR_NOT_SUPPORTED;
+ store = _CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
+ if (!store) return ERR_NOT_SUPPORTED;
+
+ ok = BuildChain(x509, store, &end_cert, &chain);
+ if (ok) {
+ res = chain->TrustStatus.dwErrorStatus;
+ if (res) Platform_Log1("Cert validation failed: %h", &res);
+ }
_CertFreeCertificateChain(chain);
ok = _CertFreeCertificateContext(end_cert);
- ok = _CertCloseStore(store, 0); // TODO check memory all released
+ ok = _CertCloseStore(store, 0);
return ERR_NOT_SUPPORTED;
}
#endif