mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-15 15:53:55 +00:00
Updated wincrypto to not use global vars for state
This commit is contained in:
@@ -1681,19 +1681,19 @@ duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx
|
|||||||
duk_push_object(ctx);
|
duk_push_object(ctx);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
PCCERT_CONTEXT certCtx = NULL;
|
wincrypto_object j = NULL;
|
||||||
char *certCtx_data = NULL;
|
char *cert_der = NULL, *cert_pfx = NULL;
|
||||||
if (agent->noCertStore == 0 && wincrypto_open_ex(TRUE, rootSubject, &certCtx) == 0) // Force certificate re-generation
|
if (agent->noCertStore == 0 && (j=wincrypto_open(TRUE, rootSubject)) != NULL) // Force certificate re-generation
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
do {
|
do {
|
||||||
// Finish off work with our own certificate
|
// Finish off work with our own certificate
|
||||||
l = wincrypto_getcert_ex(&certCtx_data, certCtx);
|
l = wincrypto_getcert(&cert_der, j);
|
||||||
if (l > 0)
|
if (l > 0)
|
||||||
{
|
{
|
||||||
util_from_cer(certCtx_data, l, &tmpCert);
|
util_from_cer(cert_der, l, &tmpCert);
|
||||||
util_keyhash(tmpCert, tmp);
|
util_keyhash(tmpCert, tmp);
|
||||||
if (((int*)tmp)[0] == 0) { wincrypto_close_ex(certCtx); wincrypto_open_ex(1, rootSubject, &certCtx); }
|
if (((int*)tmp)[0] == 0) { wincrypto_close(j); j=wincrypto_open(1, rootSubject); }
|
||||||
}
|
}
|
||||||
} while (l != 0 && ((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
} while (l != 0 && ((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||||
|
|
||||||
@@ -1706,10 +1706,10 @@ duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx
|
|||||||
duk_put_prop_string(ctx, -3, "der"); // [object][root][buffer]
|
duk_put_prop_string(ctx, -3, "der"); // [object][root][buffer]
|
||||||
duk_pop(ctx); // [object][root]
|
duk_pop(ctx); // [object][root]
|
||||||
duk_put_prop_string(ctx, -2, "root"); // [object]
|
duk_put_prop_string(ctx, -2, "root"); // [object]
|
||||||
memcpy_s(rootBuffer, l, certCtx_data, l);
|
memcpy_s(rootBuffer, l, cert_der, l);
|
||||||
|
|
||||||
// Generate a new TLS certificate & save it.
|
// Generate a new TLS certificate & save it.
|
||||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &certCtx_data);
|
l = wincrypto_mkCert(j, rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &cert_pfx);
|
||||||
|
|
||||||
duk_push_object(ctx); // [object][tls]
|
duk_push_object(ctx); // [object][tls]
|
||||||
char *buffer = duk_push_fixed_buffer(ctx, l); // [object][tls][buffer]
|
char *buffer = duk_push_fixed_buffer(ctx, l); // [object][tls][buffer]
|
||||||
@@ -1718,8 +1718,9 @@ duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx
|
|||||||
duk_pop(ctx); // [object][tls]
|
duk_pop(ctx); // [object][tls]
|
||||||
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
|
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
|
||||||
duk_put_prop_string(ctx, -2, "tls"); // [object]
|
duk_put_prop_string(ctx, -2, "tls"); // [object]
|
||||||
memcpy_s(buffer, l, certCtx_data, l);
|
memcpy_s(buffer, l, cert_pfx, l);
|
||||||
util_free(certCtx_data);
|
util_free(cert_pfx);
|
||||||
|
wincrypto_close(j);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1945,24 +1946,26 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
|
|||||||
{
|
{
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
|
char *rootSubject = (agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY ? "CN=MeshNodeDiagnosticCertificate" : "CN=MeshNodeCertificate";
|
||||||
if (agent->noCertStore == 0 && wincrypto_open(TRUE, rootSubject) == 0) // Force certificate re-generation
|
|
||||||
|
if (agent->noCertStore == 0 && (agent->certObject = wincrypto_open(TRUE, rootSubject)) != NULL) // Force certificate re-generation
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
// Finish off work with our own certificate
|
// Finish off work with our own certificate
|
||||||
l = wincrypto_getcert(&str);
|
l = wincrypto_getcert(&str, agent->certObject);
|
||||||
if (l > 0)
|
if (l > 0)
|
||||||
{
|
{
|
||||||
util_from_cer(str, l, &(agent->selfcert));
|
util_from_cer(str, l, &(agent->selfcert));
|
||||||
util_keyhash(agent->selfcert, agent->g_selfid);
|
util_keyhash(agent->selfcert, agent->g_selfid);
|
||||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_close(); wincrypto_open(1, rootSubject); }
|
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_close(agent->certObject); agent->certObject = 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.
|
} 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)
|
if (l > 0)
|
||||||
{
|
{
|
||||||
// Generate a new TLS certificate & save it.
|
// Generate a new TLS certificate & save it.
|
||||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
l = wincrypto_mkCert(agent->certObject, rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||||
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
||||||
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
||||||
util_free(str);
|
util_free(str);
|
||||||
@@ -2056,19 +2059,19 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
|
|||||||
|
|
||||||
// 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.
|
// 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...
|
// However, if we don't have the second cert created, we need to regen the root...
|
||||||
if (agent->noCertStore == 0 && wincrypto_open(FALSE, rootSubject) == 0 && ILibSimpleDataStore_Get(agent->masterDb, "SelfNodeTlsCert", NULL, 0) != 0)
|
if (agent->noCertStore == 0 && (agent->certObject = wincrypto_open(FALSE, rootSubject)) != NULL && ILibSimpleDataStore_Get(agent->masterDb, "SelfNodeTlsCert", NULL, 0) != 0)
|
||||||
{
|
{
|
||||||
char* str = NULL;
|
char* str = NULL;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Finish off work with our own certificate
|
// Finish off work with our own certificate
|
||||||
l = wincrypto_getcert(&str);
|
l = wincrypto_getcert(&str, agent->certObject);
|
||||||
if (l > 0)
|
if (l > 0)
|
||||||
{
|
{
|
||||||
util_from_cer(str, l, &(agent->selfcert));
|
util_from_cer(str, l, &(agent->selfcert));
|
||||||
util_keyhash(agent->selfcert, agent->g_selfid);
|
util_keyhash(agent->selfcert, agent->g_selfid);
|
||||||
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_open(TRUE, rootSubject); } // Force generation of a new certificate.
|
if (((int*)agent->g_selfid)[0] == 0) { wincrypto_close(agent->certObject); agent->certObject = 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.
|
} while (l != 0 && ((int*)agent->g_selfid)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
|
||||||
|
|
||||||
@@ -2081,7 +2084,7 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent)
|
|||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
// Generate a new TLS certificate & save it.
|
// Generate a new TLS certificate & save it.
|
||||||
util_freecert(&(agent->selftlscert));
|
util_freecert(&(agent->selftlscert));
|
||||||
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
l = wincrypto_mkCert(agent->certObject, rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &str);
|
||||||
if (l > 0) {
|
if (l > 0) {
|
||||||
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
util_from_p12(str, l, "hidden", &(agent->selftlscert));
|
||||||
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l);
|
||||||
@@ -2514,7 +2517,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
|
|||||||
|
|
||||||
// Create a PKCS7 signature using Windows crypto & send it
|
// Create a PKCS7 signature using Windows crypto & send it
|
||||||
char* signature = NULL;
|
char* signature = NULL;
|
||||||
signLen = wincrypto_sign((unsigned char*)ILibScratchPad, sizeof(AuthRequest->serverHash) + UTIL_SHA384_HASHSIZE + UTIL_SHA384_HASHSIZE, &signature);
|
signLen = wincrypto_sign(agent->certObject, (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
|
// Signature succesful, send the result to the server
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ typedef struct MeshAgentHostContainer
|
|||||||
#ifndef MICROSTACK_NOTLS
|
#ifndef MICROSTACK_NOTLS
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
int noCertStore;
|
int noCertStore;
|
||||||
|
void* certObject;
|
||||||
#endif
|
#endif
|
||||||
struct util_cert selfcert;
|
struct util_cert selfcert;
|
||||||
struct util_cert selftlscert;
|
struct util_cert selftlscert;
|
||||||
|
|||||||
@@ -28,12 +28,17 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#include "wincrypto.h"
|
#include "wincrypto.h"
|
||||||
#include "../microstack/ILibParsers.h"
|
#include "../microstack/ILibParsers.h"
|
||||||
HCRYPTPROV wincrypto_hProv = NULL;
|
|
||||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||||
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
|
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
|
||||||
LPWSTR wincrypto_CngProviders[3] = { L"Microsoft Platform Crypto Provider", MS_KEY_STORAGE_PROVIDER, NULL };
|
LPWSTR wincrypto_CngProviders[3] = { L"Microsoft Platform Crypto Provider", MS_KEY_STORAGE_PROVIDER, NULL };
|
||||||
HANDLE wincrypto_hCertStore = NULL;
|
|
||||||
PCCERT_CONTEXT wincrypto_certCtx = NULL;
|
typedef struct wincrypto_data
|
||||||
|
{
|
||||||
|
HCRYPTPROV hProv;
|
||||||
|
HANDLE hCertStore;
|
||||||
|
PCCERT_CONTEXT certCtx;
|
||||||
|
}wincrypto_data;
|
||||||
|
|
||||||
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
|
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
|
||||||
|
|
||||||
#define wincrypto_TlsServerOid "1.3.6.1.5.5.7.3.1" // TLS Server certificate
|
#define wincrypto_TlsServerOid "1.3.6.1.5.5.7.3.1" // TLS Server certificate
|
||||||
@@ -120,26 +125,20 @@ int __fastcall wincrypto_getregistryA(char* name, char** value)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __fastcall wincrypto_isopen()
|
int __fastcall wincrypto_isopen(wincrypto_object j)
|
||||||
{
|
{
|
||||||
return (wincrypto_hProv != NULL && wincrypto_hCertStore != NULL && wincrypto_certCtx != NULL);
|
return (((wincrypto_data*)j)->hProv != NULL && ((wincrypto_data*)j)->hCertStore != NULL && ((wincrypto_data*)j)->certCtx != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx)
|
void __fastcall wincrypto_close(wincrypto_object j)
|
||||||
{
|
{
|
||||||
if (certCtx != NULL)
|
if(((wincrypto_data*)j)->certCtx != NULL) { CertFreeCertificateContext(((wincrypto_data*)j)->certCtx); }
|
||||||
{
|
if(((wincrypto_data*)j)->hProv != NULL) { NCryptFreeObject(((wincrypto_data*)j)->hProv); }
|
||||||
CertFreeCertificateContext(certCtx);
|
if(((wincrypto_data*)j)->hCertStore != NULL) { CertCloseStore(((wincrypto_data*)j)->hCertStore, 0); }
|
||||||
}
|
ILibMemory_Free(j);
|
||||||
else
|
|
||||||
{
|
|
||||||
if (wincrypto_certCtx != NULL) { CertFreeCertificateContext(wincrypto_certCtx); wincrypto_certCtx = NULL; }
|
|
||||||
if (wincrypto_hProv != NULL) { NCryptFreeObject(wincrypto_hProv); wincrypto_hProv = NULL; }
|
|
||||||
if (wincrypto_hCertStore != NULL) { CertCloseStore(wincrypto_hCertStore, 0); wincrypto_hCertStore = NULL; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx)
|
wincrypto_object __fastcall wincrypto_open(int newcert, char *rootSubject)
|
||||||
{
|
{
|
||||||
DWORD KeyLength = 3072;
|
DWORD KeyLength = 3072;
|
||||||
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
||||||
@@ -175,23 +174,23 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT
|
|||||||
char akeycontainer[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;
|
int akeyLen;
|
||||||
size_t wkeyLen;
|
size_t wkeyLen;
|
||||||
if (rootSubject == NULL || strnlen_s(rootSubject, 255) > 64) { return(1); } // X509 distinguished name must be specifified and limited to 64 characters.
|
if (rootSubject == NULL || strnlen_s(rootSubject, 255) > 64) { return(NULL); } // X509 distinguished name must be specifified and limited to 64 characters.
|
||||||
|
|
||||||
akeyLen = sprintf_s(akeycontainer, sizeof(akeycontainer), "%s_privatekey", rootSubject);
|
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
|
if (mbstowcs_s(&wkeyLen, (wchar_t*)wkeycontainer, sizeof(wkeycontainer) / 2, (char*)akeycontainer, 64) != 0) { return(NULL); } // Error creating privatekey container name
|
||||||
if (certCtx == NULL) { certCtx = &wincrypto_certCtx; }
|
|
||||||
|
|
||||||
ZeroMemory(&exts, sizeof(exts));
|
ZeroMemory(&exts, sizeof(exts));
|
||||||
wincrypto_close_ex(*certCtx);
|
|
||||||
|
wincrypto_data *ret = (wincrypto_data*)ILibMemory_SmartAllocate(sizeof(wincrypto_data));
|
||||||
|
|
||||||
// Open the best CNG possible
|
// Open the best CNG possible
|
||||||
while (providerName == NULL && wincrypto_CngProviders[r] != NULL) {
|
while (providerName == NULL && wincrypto_CngProviders[r] != NULL)
|
||||||
|
{
|
||||||
providerName = wincrypto_CngProviders[r];
|
providerName = wincrypto_CngProviders[r];
|
||||||
NCryptOpenStorageProvider(&wincrypto_hProv, providerName, 0);
|
NCryptOpenStorageProvider(&(ret->hProv), providerName, 0);
|
||||||
if (wincrypto_hProv == NULL) providerName = NULL;
|
if (ret->hProv == NULL) providerName = NULL;
|
||||||
r++;
|
r++;
|
||||||
}
|
}
|
||||||
if (wincrypto_hProv == NULL) goto error;
|
if (ret->hProv == NULL) goto error;
|
||||||
|
|
||||||
// Create cert subject string in format csp understands
|
// Create cert subject string in format csp understands
|
||||||
if (!CertStrToName(X509_ASN_ENCODING, (LPCTSTR)rootSubject, 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;
|
||||||
@@ -200,36 +199,28 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT
|
|||||||
sib.cbData = subjectEncodedSize;
|
sib.cbData = subjectEncodedSize;
|
||||||
sib.pbData = subjectEncoded;
|
sib.pbData = subjectEncoded;
|
||||||
|
|
||||||
#ifdef _CONSOLE
|
ret->hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, ret->hProv, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); // CERT_STORE_NO_CRYPT_RELEASE_FLAG
|
||||||
wincrypto_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, wincrypto_hProv, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); // CERT_STORE_NO_CRYPT_RELEASE_FLAG
|
if (!ret->hCertStore) goto error;
|
||||||
if (!wincrypto_hCertStore) goto error;
|
|
||||||
#else
|
|
||||||
wincrypto_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, wincrypto_hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); // CERT_STORE_NO_CRYPT_RELEASE_FLAG // CERT_SYSTEM_STORE_LOCAL_MACHINE
|
|
||||||
if (!wincrypto_hCertStore) goto error;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Look for cert and if exists, delete it
|
// Look for cert and if exists, delete it
|
||||||
wincrypto_certCtx = CertFindCertificateInStore(wincrypto_hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &sib, NULL );
|
ret->certCtx = CertFindCertificateInStore(ret->hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &sib, NULL );
|
||||||
|
|
||||||
// Check if we can get the private key
|
// Check if we can get the private key
|
||||||
if (wincrypto_certCtx != NULL)
|
if (ret->certCtx != NULL)
|
||||||
{
|
{
|
||||||
if (!CryptAcquireCertificatePrivateKey(wincrypto_certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) { newcert = 1; }
|
if (!CryptAcquireCertificatePrivateKey(ret->certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) { newcert = 1; }
|
||||||
if (hKeyNodeSpec != CERT_NCRYPT_KEY_SPEC) { newcert = 1; } // If this private key is not CNG, don't use it.
|
if (hKeyNodeSpec != CERT_NCRYPT_KEY_SPEC) { newcert = 1; } // If this private key is not CNG, don't use it.
|
||||||
if (hFreeKeyNode && hKeyNode != NULL) { if (hKeyNodeSpec == CERT_NCRYPT_KEY_SPEC) NCryptFreeObject(hKeyNode); else CryptReleaseContext(hKeyNode, 0); }
|
if (hFreeKeyNode && hKeyNode != NULL) { if (hKeyNodeSpec == CERT_NCRYPT_KEY_SPEC) NCryptFreeObject(hKeyNode); else CryptReleaseContext(hKeyNode, 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if have a certificate already, or need to create a new one
|
// Check if have a certificate already, or need to create a new one
|
||||||
if (wincrypto_certCtx != NULL && newcert == 0) goto end;
|
if (ret->certCtx != NULL && newcert == 0) goto end;
|
||||||
if (wincrypto_certCtx) { status = CertDeleteCertificateFromStore(wincrypto_certCtx); if (!status) goto error; wincrypto_certCtx = NULL; }
|
if (ret->certCtx) { status = CertDeleteCertificateFromStore(ret->certCtx); if (!status) goto error; ret->certCtx = NULL; }
|
||||||
|
|
||||||
// Generate node RSA key-pair
|
// Generate node RSA key-pair
|
||||||
#ifdef _CONSOLE
|
if (FAILED(status = NCryptCreatePersistedKey(ret->hProv, &hKeyNode, BCRYPT_RSA_ALGORITHM, (LPCWSTR)wkeycontainer, 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;
|
if (FAILED(status = NCryptSetProperty(hKeyNode, NCRYPT_LENGTH_PROPERTY, (PBYTE)&KeyLength, 4, NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG)))
|
||||||
#else
|
{
|
||||||
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.
|
KeyLength = 2048; // If 3072 is not supported, go down to 2048.
|
||||||
if (FAILED(status = NCryptSetProperty(hKeyNode, NCRYPT_LENGTH_PROPERTY, (PBYTE)&KeyLength, 4, NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG))) { goto error; }
|
if (FAILED(status = NCryptSetProperty(hKeyNode, NCRYPT_LENGTH_PROPERTY, (PBYTE)&KeyLength, 4, NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG))) { goto error; }
|
||||||
}
|
}
|
||||||
@@ -292,12 +283,12 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT
|
|||||||
ZeroMemory(&sa, sizeof(sa));
|
ZeroMemory(&sa, sizeof(sa));
|
||||||
sa.pszObjId = szOID_RSA_SHA384RSA; // Using SHA384
|
sa.pszObjId = szOID_RSA_SHA384RSA; // Using SHA384
|
||||||
|
|
||||||
wincrypto_certCtx = CertCreateSelfSignCertificate(NULL, &sib, 0, &kpi, &sa, &st1, &st2, &exts);
|
ret->certCtx = CertCreateSelfSignCertificate(NULL, &sib, 0, &kpi, &sa, &st1, &st2, &exts);
|
||||||
if (!wincrypto_certCtx) { goto error; }
|
if (!ret->certCtx) { goto error; }
|
||||||
|
|
||||||
// Note this is a different context to certCtx, this ctx is the in-store ctx
|
// Note this is a different context to certCtx, this ctx is the in-store ctx
|
||||||
status = CertAddCertificateContextToStore(wincrypto_hCertStore, wincrypto_certCtx, CERT_STORE_ADD_REPLACE_EXISTING, &wincrypto_certCtx);
|
status = CertAddCertificateContextToStore(ret->hCertStore, ret->certCtx, CERT_STORE_ADD_REPLACE_EXISTING, &ret->certCtx);
|
||||||
if (!status || wincrypto_certCtx == NULL) goto error;
|
if (!status || ret->certCtx == NULL) goto error;
|
||||||
|
|
||||||
// Get the selected provider name and save it in the registry
|
// Get the selected provider name and save it in the registry
|
||||||
if (providerName != NULL) wincrypto_setregistry(L"KeyStore", providerName);
|
if (providerName != NULL) wincrypto_setregistry(L"KeyStore", providerName);
|
||||||
@@ -307,12 +298,12 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT
|
|||||||
error:
|
error:
|
||||||
// Clean up
|
// Clean up
|
||||||
if (hKeyNode != NULL) NCryptFreeObject(hKeyNode);
|
if (hKeyNode != NULL) NCryptFreeObject(hKeyNode);
|
||||||
wincrypto_close_ex(*certCtx);
|
wincrypto_close(ret);
|
||||||
return 1;
|
return(NULL);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (subjectEncoded != NULL) free(subjectEncoded);
|
if (subjectEncoded != NULL) free(subjectEncoded);
|
||||||
return 0;
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __fastcall wincrypto_random(int length, char* result)
|
void __fastcall wincrypto_random(int length, char* result)
|
||||||
@@ -352,7 +343,7 @@ int __fastcall wincrypto_sha256(char* data, int datalen, char* result) { return
|
|||||||
int __fastcall wincrypto_sha384(char* data, int datalen, char* result) { return wincrypto_hash(BCRYPT_SHA384_ALGORITHM, data, datalen, result, 32); }
|
int __fastcall wincrypto_sha384(char* data, int datalen, char* result) { return wincrypto_hash(BCRYPT_SHA384_ALGORITHM, data, datalen, result, 32); }
|
||||||
|
|
||||||
// Sign the data with the Mesh Agent certificate and return a PKCS7 result.
|
// Sign the data with the Mesh Agent certificate and return a PKCS7 result.
|
||||||
int __fastcall wincrypto_sign(char* data, int len, char** signature)
|
int __fastcall wincrypto_sign(wincrypto_object j, char* data, int len, char** signature)
|
||||||
{
|
{
|
||||||
int signatureLen = 0;
|
int signatureLen = 0;
|
||||||
DWORD cbSignedBlob;
|
DWORD cbSignedBlob;
|
||||||
@@ -370,7 +361,7 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature)
|
|||||||
BOOL hFreeKeyNode = FALSE;
|
BOOL hFreeKeyNode = FALSE;
|
||||||
|
|
||||||
// Check that we have open context
|
// Check that we have open context
|
||||||
if (wincrypto_hProv == NULL || wincrypto_hCertStore == NULL || wincrypto_certCtx == NULL) return 0;
|
if (!wincrypto_isopen(j)) { return(0); }
|
||||||
|
|
||||||
// Initialize the algorithm identifier structure.
|
// Initialize the algorithm identifier structure.
|
||||||
HashAlgSize = sizeof(HashAlgorithm);
|
HashAlgSize = sizeof(HashAlgorithm);
|
||||||
@@ -380,9 +371,9 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature)
|
|||||||
// Initialize the CMSG_SIGNER_ENCODE_INFO structure.
|
// Initialize the CMSG_SIGNER_ENCODE_INFO structure.
|
||||||
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
|
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
|
||||||
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
|
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
|
||||||
if (!CryptAcquireCertificatePrivateKey(wincrypto_certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) { r = 10; goto end; }
|
if (!CryptAcquireCertificatePrivateKey(((wincrypto_data*)j)->certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) { r = 10; goto end; }
|
||||||
SignerEncodeInfo.hNCryptKey = hKeyNode;
|
SignerEncodeInfo.hNCryptKey = hKeyNode;
|
||||||
SignerEncodeInfo.pCertInfo = wincrypto_certCtx->pCertInfo;
|
SignerEncodeInfo.pCertInfo = ((wincrypto_data*)j)->certCtx->pCertInfo;
|
||||||
SignerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE;
|
SignerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE;
|
||||||
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
|
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
|
||||||
SignerEncodeInfo.pvHashAuxInfo = NULL;
|
SignerEncodeInfo.pvHashAuxInfo = NULL;
|
||||||
@@ -391,8 +382,8 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature)
|
|||||||
SignerEncodeInfoArray[0] = SignerEncodeInfo;
|
SignerEncodeInfoArray[0] = SignerEncodeInfo;
|
||||||
|
|
||||||
// Initialize the CMSG_SIGNED_ENCODE_INFO structure.
|
// Initialize the CMSG_SIGNED_ENCODE_INFO structure.
|
||||||
SignerCertBlob.cbData = wincrypto_certCtx->cbCertEncoded;
|
SignerCertBlob.cbData = ((wincrypto_data*)j)->certCtx->cbCertEncoded;
|
||||||
SignerCertBlob.pbData = wincrypto_certCtx->pbCertEncoded;
|
SignerCertBlob.pbData = ((wincrypto_data*)j)->certCtx->pbCertEncoded;
|
||||||
|
|
||||||
// Initialize the array of one CertBlob.
|
// Initialize the array of one CertBlob.
|
||||||
SignerCertBlobArray[0] = SignerCertBlob;
|
SignerCertBlobArray[0] = SignerCertBlob;
|
||||||
@@ -447,7 +438,7 @@ static BOOL WINAPI wincrypto_CmsgStreamOutputCallback(IN const void *pvArg, IN B
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt the PKCS7 block and return the content.
|
// Decrypt the PKCS7 block and return the content.
|
||||||
int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data)
|
int __fastcall wincrypto_decrypt(wincrypto_object j, char* encdata, int encdatalen, char** data)
|
||||||
{
|
{
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
HCRYPTMSG hMsg = NULL;
|
HCRYPTMSG hMsg = NULL;
|
||||||
@@ -457,7 +448,7 @@ int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data)
|
|||||||
struct wincrypto_stream StreamArg;
|
struct wincrypto_stream StreamArg;
|
||||||
|
|
||||||
// Check that we have open context
|
// Check that we have open context
|
||||||
if (wincrypto_hProv == NULL || wincrypto_hCertStore == NULL || wincrypto_certCtx == NULL) return 0;
|
if (!wincrypto_isopen(j)) { return(0); }
|
||||||
|
|
||||||
// Perform setup
|
// Perform setup
|
||||||
if ((StreamArg.buf = (char*)malloc(encdatalen)) == NULL) ILIBCRITICALEXIT(254);
|
if ((StreamArg.buf = (char*)malloc(encdatalen)) == NULL) ILIBCRITICALEXIT(254);
|
||||||
@@ -470,7 +461,7 @@ int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data)
|
|||||||
if (!CryptMsgUpdate(hMsg, (BYTE*)encdata, encdatalen, TRUE)) goto end;
|
if (!CryptMsgUpdate(hMsg, (BYTE*)encdata, encdatalen, TRUE)) goto end;
|
||||||
|
|
||||||
// Setup the certificate
|
// Setup the certificate
|
||||||
if (!CryptAcquireCertificatePrivateKey(wincrypto_certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &decryptPara.hCryptProv, &decryptPara.dwKeySpec, &flagHandle)) goto end;
|
if (!CryptAcquireCertificatePrivateKey(((wincrypto_data*)j)->certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &decryptPara.hCryptProv, &decryptPara.dwKeySpec, &flagHandle)) goto end;
|
||||||
decryptPara.dwRecipientIndex = 0;
|
decryptPara.dwRecipientIndex = 0;
|
||||||
|
|
||||||
// Perform the decrypt
|
// Perform the decrypt
|
||||||
@@ -487,23 +478,15 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the X509 certificate including the public key (Direct reference, no need to free this).
|
// Get the X509 certificate including the public key (Direct reference, no need to free this).
|
||||||
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx)
|
int __fastcall wincrypto_getcert(char** data, wincrypto_object j)
|
||||||
{
|
{
|
||||||
if (certCtx != NULL)
|
if (((wincrypto_data*)j)->certCtx == NULL) { *data = NULL; return(0); }
|
||||||
{
|
*data = (char*)((wincrypto_data*)j)->certCtx->pbCertEncoded;
|
||||||
*data = (char*)certCtx->pbCertEncoded;
|
return((int)((wincrypto_data*)j)->certCtx->cbCertEncoded);
|
||||||
return (int)certCtx->cbCertEncoded;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (wincrypto_certCtx == NULL) { *data = NULL; return 0; }
|
|
||||||
*data = (char*)wincrypto_certCtx->pbCertEncoded;
|
|
||||||
return (int)wincrypto_certCtx->cbCertEncoded;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an X509, RSA 3027bit certificate with the MeshAgent certificate as signing root.
|
// Create an X509, RSA 3027bit certificate with the MeshAgent certificate as signing root.
|
||||||
int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data)
|
int __fastcall wincrypto_mkCert(wincrypto_object j, char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data) // certtype: 1=Root, 2=Server, 3=Client
|
||||||
{
|
{
|
||||||
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
NCRYPT_KEY_HANDLE hKeyNode = NULL;
|
||||||
DWORD hKeyNodeSpec = 0;
|
DWORD hKeyNodeSpec = 0;
|
||||||
@@ -552,7 +535,7 @@ int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtyp
|
|||||||
DWORD pfxExportFlags = EXPORT_PRIVATE_KEYS; // | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY;
|
DWORD pfxExportFlags = EXPORT_PRIVATE_KEYS; // | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY;
|
||||||
|
|
||||||
// Check that we have open context
|
// Check that we have open context
|
||||||
if (wincrypto_hProv == NULL || wincrypto_hCertStore == NULL || wincrypto_certCtx == NULL) return 0;
|
if (!wincrypto_isopen(j)) { return(0); }
|
||||||
|
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
ZeroMemory(&kpi, sizeof(kpi));
|
ZeroMemory(&kpi, sizeof(kpi));
|
||||||
@@ -663,7 +646,7 @@ int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sign the certificate with the MeshAgent private key
|
// Sign the certificate with the MeshAgent private key
|
||||||
if (!CryptAcquireCertificatePrivateKey(wincrypto_certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) goto end;
|
if (!CryptAcquireCertificatePrivateKey(((wincrypto_data*)j)->certCtx, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyNode, &hKeyNodeSpec, &hFreeKeyNode)) goto end;
|
||||||
if (!CryptSignAndEncodeCertificate(hKeyNode, AT_KEYEXCHANGE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, (LPVOID)&certInfo, &(certInfo.SignatureAlgorithm), NULL, NULL, &certSize)) goto end;
|
if (!CryptSignAndEncodeCertificate(hKeyNode, AT_KEYEXCHANGE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, (LPVOID)&certInfo, &(certInfo.SignatureAlgorithm), NULL, NULL, &certSize)) goto end;
|
||||||
if ((certData = (BYTE*)malloc(certSize)) == NULL) ILIBCRITICALEXIT(254);
|
if ((certData = (BYTE*)malloc(certSize)) == NULL) ILIBCRITICALEXIT(254);
|
||||||
if (!CryptSignAndEncodeCertificate(hKeyNode, AT_KEYEXCHANGE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, (LPVOID)&certInfo, &(certInfo.SignatureAlgorithm), NULL, certData, &certSize)) goto end;
|
if (!CryptSignAndEncodeCertificate(hKeyNode, AT_KEYEXCHANGE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, (LPVOID)&certInfo, &(certInfo.SignatureAlgorithm), NULL, certData, &certSize)) goto end;
|
||||||
|
|||||||
@@ -18,23 +18,22 @@ limitations under the License.
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
typedef void* wincrypto_object;
|
||||||
void __fastcall wincrypto_setregistry(LPWSTR name, LPWSTR value);
|
void __fastcall wincrypto_setregistry(LPWSTR name, LPWSTR value);
|
||||||
void __fastcall wincrypto_setregistryA(char* name, char* value);
|
void __fastcall wincrypto_setregistryA(char* name, char* value);
|
||||||
int __fastcall wincrypto_getregistry(LPCWSTR name, char** value);
|
int __fastcall wincrypto_getregistry(LPCWSTR name, char** value);
|
||||||
int __fastcall wincrypto_getregistryA(char* name, char** value);
|
int __fastcall wincrypto_getregistryA(char* name, char** value);
|
||||||
int __fastcall wincrypto_isopen();
|
|
||||||
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx);
|
int __fastcall wincrypto_isopen(wincrypto_object j);
|
||||||
#define wincrypto_close() wincrypto_close_ex(NULL)
|
void __fastcall wincrypto_close(wincrypto_object j);
|
||||||
#define wincrypto_open(newCert, rootSubject) wincrypto_open_ex(newCert, rootSubject, NULL)
|
wincrypto_object __fastcall wincrypto_open(int newcert, char *rootSubject);
|
||||||
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx);
|
|
||||||
void __fastcall wincrypto_random(int length, char* result);
|
void __fastcall wincrypto_random(int length, char* result);
|
||||||
int __fastcall wincrypto_md5(char* data, int datalen, char* result);
|
int __fastcall wincrypto_md5(char* data, int datalen, char* result);
|
||||||
int __fastcall wincrypto_sha256(char* data, int datalen, char* result);
|
int __fastcall wincrypto_sha256(char* data, int datalen, char* result);
|
||||||
int __fastcall wincrypto_sha384(char* data, int datalen, char* result);
|
int __fastcall wincrypto_sha384(char* data, int datalen, char* result);
|
||||||
int __fastcall wincrypto_sign(char* data, int len, char** signature);
|
int __fastcall wincrypto_sign(wincrypto_object j, char* data, int len, char** signature);
|
||||||
int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data);
|
int __fastcall wincrypto_decrypt(wincrypto_object j, char* encdata, int encdatalen, char** data);
|
||||||
#define wincrypto_getcert(data) wincrypto_getcert_ex(data, NULL)
|
int __fastcall wincrypto_getcert(char** data, wincrypto_object j);
|
||||||
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx);
|
int __fastcall wincrypto_mkCert(wincrypto_object j, char* rootSubject, 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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user