mirror of
https://github.com/Ylianst/MeshAgent
synced 2026-01-06 18:43:46 +00:00
Updated wincrypto, so if windows crypto store is used, certs between diagnostic agent and regular agent don't collide
This commit is contained in:
@@ -67,6 +67,7 @@ limitations under the License.
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define HEX_IDENTIFIER (unsigned short)12408
|
||||
#define EXE_IDENTIFIER (unsigned int)778401893
|
||||
#define MSH_IDENTIFIER (unsigned int)778924904
|
||||
@@ -1851,7 +1852,8 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
|
||||
if (certfile == NULL)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
if (wincrypto_open(TRUE) == 0) // Force certificate re-generation
|
||||
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
|
||||
if (wincrypto_open(TRUE, rootSubject) == 0) // Force certificate re-generation
|
||||
{
|
||||
int l;
|
||||
do {
|
||||
@@ -1861,14 +1863,14 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
|
||||
{
|
||||
util_from_cer(str, l, &(agent->selfcert));
|
||||
util_keyhash(agent->selfcert, agent->g_selfid);
|
||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_close(); wincrypto_open(1); }
|
||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_close(); wincrypto_open(1, rootSubject); }
|
||||
}
|
||||
} while (l != 0 && ((int*)agent->g_selfid)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||
|
||||
if (l > 0)
|
||||
{
|
||||
// Generate a new TLS certificate & save it.
|
||||
l = wincrypto_mkCert(L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
||||
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
||||
util_free(str);
|
||||
@@ -1958,9 +1960,11 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
|
||||
if (len == 0 || util_from_p12(ILibScratchPad2, len, "hidden", &(agent->selfcert)) == 0)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
|
||||
|
||||
// No cert in this .db file. Try to load or generate a root certificate from a Windows crypto provider. This can be TPM backed which is great.
|
||||
// However, if we don't have the second cert created, we need to regen the root...
|
||||
if (wincrypto_open(FALSE) == 0 && ILibSimpleDataStore_Get(agent->masterDb, "SelfNodeTlsCert", NULL, 0) != 0)
|
||||
if (wincrypto_open(FALSE, rootSubject) == 0 && ILibSimpleDataStore_Get(agent->masterDb, "SelfNodeTlsCert", NULL, 0) != 0)
|
||||
{
|
||||
char* str = NULL;
|
||||
int l;
|
||||
@@ -1972,7 +1976,7 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
|
||||
{
|
||||
util_from_cer(str, l, &(agent->selfcert));
|
||||
util_keyhash(agent->selfcert, agent->g_selfid);
|
||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_open(TRUE); } // Force generation of a new certificate.
|
||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_open(TRUE, rootSubject); } // Force generation of a new certificate.
|
||||
}
|
||||
} while (l != 0 && ((int*)agent->g_selfid)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||
|
||||
@@ -1985,7 +1989,7 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
|
||||
if (len == 0) {
|
||||
// Generate a new TLS certificate & save it.
|
||||
util_freecert(&(agent->selftlscert));
|
||||
l = wincrypto_mkCert(L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||
if (l > 0) {
|
||||
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
||||
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
||||
@@ -2419,7 +2423,8 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
|
||||
// Create a PKCS7 signature using Windows crypto & send it
|
||||
char* signature = NULL;
|
||||
signLen = wincrypto_sign((unsigned char*)ILibScratchPad, sizeof(AuthRequest->serverHash) + UTIL_SHA384_HASHSIZE + UTIL_SHA384_HASHSIZE, &signature);
|
||||
if (signLen > 0) {
|
||||
if (signLen > 0)
|
||||
{
|
||||
// Signature succesful, send the result to the server
|
||||
memcpy_s((unsigned char*)(rav->data + certLen), sizeof(ILibScratchPad2) - sizeof(MeshCommand_BinaryPacket_AuthVerify_Header) - certLen, signature, signLen);
|
||||
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rav, sizeof(MeshCommand_BinaryPacket_AuthVerify_Header) + certLen + signLen, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
|
||||
@@ -3619,7 +3624,10 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
|
||||
int ri;
|
||||
for (ri = 0; ri < paramLen; ++ri)
|
||||
{
|
||||
if (strcmp(param[ri], "-recovery") == 0) { agentHost->capabilities |= MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY; parseCommands = 0; }
|
||||
if (strcmp(param[ri], "-recovery") == 0)
|
||||
{
|
||||
agentHost->capabilities |= MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY; parseCommands = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3745,8 +3753,18 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
|
||||
{
|
||||
char* str = NULL;
|
||||
int len = (int)util_readfile(MeshAgent_MakeAbsolutePath(agentHost->exePath, ".proxy"), &str, 1024);
|
||||
if (str != NULL) { ILibSimpleDataStore_PutEx(agentHost->masterDb, "WebProxy", 8, str, len); free(str); }
|
||||
else { ILibSimpleDataStore_DeleteEx(agentHost->masterDb, "WebProxy", 8); }
|
||||
if (str != NULL)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
ILibSimpleDataStore_PutEx(agentHost->masterDb, "WebProxy", 8, str, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ILibSimpleDataStore_DeleteEx(agentHost->masterDb, "WebProxy", 8);
|
||||
}
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ HCRYPTPROV wincrypto_hProv = NULL;
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
|
||||
LPWSTR wincrypto_CngProviders[3] = { L"Microsoft Platform Crypto Provider", MS_KEY_STORAGE_PROVIDER, NULL };
|
||||
LPWSTR wincrypto_containername = L"MeshAgentContainer";
|
||||
LPCTSTR wincrypto_subject = "CN=MeshNodeCertificate";
|
||||
HANDLE wincrypto_hCertStore = NULL;
|
||||
PCCERT_CONTEXT wincrypto_certCtx = NULL;
|
||||
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
|
||||
@@ -134,7 +132,7 @@ void __fastcall wincrypto_close()
|
||||
if (wincrypto_hCertStore != NULL) { CertCloseStore(wincrypto_hCertStore, 0); wincrypto_hCertStore = NULL; }
|
||||
}
|
||||
|
||||
int __fastcall wincrypto_open(int newcert)
|
||||
int __fastcall wincrypto_open(int newcert, char *rootSubject)
|
||||
{
|
||||
DWORD KeyLength = 3072;
|
||||
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
||||
@@ -166,6 +164,15 @@ int __fastcall wincrypto_open(int newcert)
|
||||
CRYPT_BIT_BLOB keyusage2;
|
||||
DWORD pkSize = 0;
|
||||
|
||||
char wkeycontainer[255]; // MAX Length of X509 distinguished name is 64 characters, so this should be OK
|
||||
char akeycontainer[255]; // MAX Length of X509 distinguished name is 64 characters, so this should be OK
|
||||
int akeyLen;
|
||||
size_t wkeyLen;
|
||||
if (rootSubject == NULL || strnlen_s(rootSubject, 255) > 64) { return(1); } // X509 distinguished name must be specifified and limited to 64 characters.
|
||||
|
||||
akeyLen = sprintf_s(akeycontainer, sizeof(akeycontainer), "%s_privatekey", rootSubject);
|
||||
if (mbstowcs_s(&wkeyLen, (wchar_t*)wkeycontainer, sizeof(wkeycontainer) / 2, (char*)akeycontainer, 64) != 0) { return(1); } // Error creating privatekey container name
|
||||
|
||||
ZeroMemory(&exts, sizeof(exts));
|
||||
wincrypto_close();
|
||||
|
||||
@@ -179,9 +186,9 @@ int __fastcall wincrypto_open(int newcert)
|
||||
if (wincrypto_hProv == NULL) goto error;
|
||||
|
||||
// Create cert subject string in format csp understands
|
||||
if (!CertStrToName(X509_ASN_ENCODING, wincrypto_subject, CERT_X500_NAME_STR, NULL, NULL, &subjectEncodedSize, NULL)) goto error;
|
||||
if (!CertStrToName(X509_ASN_ENCODING, (LPCTSTR)rootSubject, CERT_X500_NAME_STR, NULL, NULL, &subjectEncodedSize, NULL)) goto error;
|
||||
if ((subjectEncoded = (PBYTE)malloc(subjectEncodedSize)) == NULL) ILIBCRITICALEXIT(254);
|
||||
if (!CertStrToName(X509_ASN_ENCODING, wincrypto_subject, CERT_X500_NAME_STR, NULL, subjectEncoded, &subjectEncodedSize, NULL)) goto error;
|
||||
if (!CertStrToName(X509_ASN_ENCODING, (LPCTSTR)rootSubject, CERT_X500_NAME_STR, NULL, subjectEncoded, &subjectEncodedSize, NULL)) goto error;
|
||||
sib.cbData = subjectEncodedSize;
|
||||
sib.pbData = subjectEncoded;
|
||||
|
||||
@@ -210,9 +217,9 @@ int __fastcall wincrypto_open(int newcert)
|
||||
|
||||
// Generate node RSA key-pair
|
||||
#ifdef _CONSOLE
|
||||
if (FAILED(status = NCryptCreatePersistedKey(wincrypto_hProv, &hKeyNode, BCRYPT_RSA_ALGORITHM, wincrypto_containername, 0, NCRYPT_OVERWRITE_KEY_FLAG))) goto error;
|
||||
if (FAILED(status = NCryptCreatePersistedKey(wincrypto_hProv, &hKeyNode, BCRYPT_RSA_ALGORITHM, (LPCWSTR)wkeycontainer, 0, NCRYPT_OVERWRITE_KEY_FLAG))) goto error;
|
||||
#else
|
||||
if (FAILED(status = NCryptCreatePersistedKey(wincrypto_hProv, &hKeyNode, BCRYPT_RSA_ALGORITHM, wincrypto_containername, 0, NCRYPT_MACHINE_KEY_FLAG | NCRYPT_OVERWRITE_KEY_FLAG))) goto error;
|
||||
if (FAILED(status = NCryptCreatePersistedKey(wincrypto_hProv, &hKeyNode, BCRYPT_RSA_ALGORITHM, (LPCWSTR)wkeycontainer, 0, NCRYPT_MACHINE_KEY_FLAG | NCRYPT_OVERWRITE_KEY_FLAG))) goto error;
|
||||
#endif
|
||||
if (FAILED(status = NCryptSetProperty(hKeyNode, NCRYPT_LENGTH_PROPERTY, (PBYTE)&KeyLength, 4, NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG))) {
|
||||
KeyLength = 2048; // If 3072 is not supported, go down to 2048.
|
||||
@@ -222,7 +229,7 @@ int __fastcall wincrypto_open(int newcert)
|
||||
|
||||
// Create self signed cert
|
||||
ZeroMemory(&kpi, sizeof(kpi));
|
||||
kpi.pwszContainerName = wincrypto_containername;
|
||||
kpi.pwszContainerName = (LPWSTR)wkeycontainer;
|
||||
kpi.pwszProvName = providerName;
|
||||
kpi.dwProvType = 0;
|
||||
kpi.dwFlags = 0;
|
||||
@@ -480,7 +487,7 @@ int __fastcall wincrypto_getcert(char** data)
|
||||
}
|
||||
|
||||
// Create an X509, RSA 3027bit certificate with the MeshAgent certificate as signing root.
|
||||
int __fastcall wincrypto_mkCert(wchar_t* subject, int certtype, wchar_t* password, char** data)
|
||||
int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data)
|
||||
{
|
||||
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
||||
DWORD hKeyNodeSpec = 0;
|
||||
@@ -553,9 +560,9 @@ int __fastcall wincrypto_mkCert(wchar_t* subject, int certtype, wchar_t* passwor
|
||||
if (!CryptExportPublicKeyInfo(hNewKey, AT_KEYEXCHANGE, X509_ASN_ENCODING, pkInfo, &pkSize)) goto end;
|
||||
|
||||
// Create cert issuer string in format the CSP understands
|
||||
if (!CertStrToName(X509_ASN_ENCODING, wincrypto_subject, CERT_X500_NAME_STR, NULL, NULL, &subject1EncodedSize, NULL)) goto end;
|
||||
if (!CertStrToName(X509_ASN_ENCODING, (LPCTSTR)rootSubject, CERT_X500_NAME_STR, NULL, NULL, &subject1EncodedSize, NULL)) goto end;
|
||||
if ((subject1Encoded = (PBYTE)malloc(subject1EncodedSize)) == NULL) ILIBCRITICALEXIT(254);
|
||||
if (!CertStrToName(X509_ASN_ENCODING, wincrypto_subject, CERT_X500_NAME_STR, NULL, subject1Encoded, &subject1EncodedSize, NULL)) goto end;
|
||||
if (!CertStrToName(X509_ASN_ENCODING, (LPCTSTR)rootSubject, CERT_X500_NAME_STR, NULL, subject1Encoded, &subject1EncodedSize, NULL)) goto end;
|
||||
sib1.cbData = subject1EncodedSize;
|
||||
sib1.pbData = subject1Encoded;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ int __fastcall wincrypto_getregistry(LPCWSTR name, char** value);
|
||||
int __fastcall wincrypto_getregistryA(char* name, char** value);
|
||||
int __fastcall wincrypto_isopen();
|
||||
void __fastcall wincrypto_close();
|
||||
int __fastcall wincrypto_open(int newcert);
|
||||
int __fastcall wincrypto_open(int newcert, char *rootSubject);
|
||||
void __fastcall wincrypto_random(int length, char* result);
|
||||
int __fastcall wincrypto_md5(char* data, int datalen, char* result);
|
||||
int __fastcall wincrypto_sha256(char* data, int datalen, char* result);
|
||||
@@ -32,6 +32,6 @@ int __fastcall wincrypto_sha384(char* data, int datalen, char* result);
|
||||
int __fastcall wincrypto_sign(char* data, int len, char** signature);
|
||||
int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data);
|
||||
int __fastcall wincrypto_getcert(char** data);
|
||||
int __fastcall wincrypto_mkCert(wchar_t* subject, int certtype, wchar_t* password, char** data); // certtype: 1=Root, 2=Server, 3=Client
|
||||
int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data); // certtype: 1=Root, 2=Server, 3=Client
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user