1
0
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:
Bryan Roe
2019-04-04 14:25:44 -07:00
parent f6ccbce1fb
commit 5c09f92446
3 changed files with 48 additions and 23 deletions

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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