1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

Added cert generation helper for Diagnostic Agent use

This commit is contained in:
Bryan Roe
2019-04-05 14:33:19 -07:00
parent 5c09f92446
commit f7025b3629
3 changed files with 120 additions and 14 deletions

View File

@@ -1670,6 +1670,92 @@ duk_ret_t ILibDuktape_MeshAgent_ServerInfo(duk_context *ctx)
return(1);
}
duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx)
{
char *rootSubject = (char*)duk_require_string(ctx, 0);
char tmp[UTIL_SHA384_HASHSIZE];
struct util_cert tmpCert;
duk_push_this(ctx);
MeshAgentHostContainer *agent = (MeshAgentHostContainer*)Duktape_GetPointerProperty(ctx, -1, MESH_AGENT_PTR);
duk_push_object(ctx);
#ifdef WIN32
PCCERT_CONTEXT certCtx = NULL;
char *certCtx_data = NULL;
if (wincrypto_open_ex(TRUE, rootSubject, &certCtx) == 0) // Force certificate re-generation
{
int l;
do {
// Finish off work with our own certificate
l = wincrypto_getcert_ex(&certCtx_data, certCtx);
if (l > 0)
{
util_from_cer(certCtx_data, l, &tmpCert);
util_keyhash(tmpCert, tmp);
if (((int*)tmp)[0] == 0) { wincrypto_close_ex(certCtx); wincrypto_open_ex(1, rootSubject, &certCtx); }
}
} while (l != 0 && ((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
if (l > 0)
{
// Save the root cert in CER format
duk_push_object(ctx); // [object][root]
char *rootBuffer = duk_push_fixed_buffer(ctx, l); // [object][root][buffer]
duk_push_buffer_object(ctx, -1, 0, l, DUK_BUFOBJ_NODEJS_BUFFER); // [object][root][buffer][nodeBuffer]
duk_put_prop_string(ctx, -3, "der"); // [object][root][buffer]
duk_pop(ctx); // [object][root]
duk_put_prop_string(ctx, -2, "root"); // [object]
memcpy_s(rootBuffer, l, certCtx_data, l);
// Generate a new TLS certificate & save it.
l = wincrypto_mkCert(rootSubject, L"CN=localhost", CERTIFICATE_TLS_SERVER, L"hidden", &certCtx_data);
duk_push_object(ctx); // [object][tls]
char *buffer = duk_push_fixed_buffer(ctx, l); // [object][tls][buffer]
duk_push_buffer_object(ctx, -1, 0, l, DUK_BUFOBJ_NODEJS_BUFFER); // [object][tls][buffer][nodeBuffer]
duk_put_prop_string(ctx, -3, "pfx"); // [object][tls][buffer]
duk_pop(ctx); // [object][tls]
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
duk_put_prop_string(ctx, -2, "tls"); // [object]
memcpy_s(buffer, l, certCtx_data, l);
util_free(certCtx_data);
return(1);
}
// wincrypto error
return(ILibDuktape_Error(ctx, "Error Generating Certificates using WinCrypto"));
}
else
{
#endif
// Generate a new self-signed root certificate for this node using OpenSSL
do
{
if (util_mkCert(NULL, &(tmpCert), 3072, 10000, "MeshNodeCertificate", CERTIFICATE_ROOT, NULL) == 0)
{
return(ILibDuktape_Error(ctx, "Error Generating Certificates using OpenSSL"));
}
util_keyhash(tmpCert, tmp);
} while (((int*)tmp)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
duk_push_object(ctx); // [object][root]
char *pfx = NULL;
int pfxLen = util_to_p12(tmpCert, "hidden", &pfx);
char *jspfx = duk_push_fixed_buffer(ctx, pfxLen); // [object][root][buffer]
duk_push_buffer_object(ctx, -1, 0, pfxLen, DUK_BUFOBJ_NODEJS_BUFFER); // [object][root][buffer][nodeBuffer]
duk_put_prop_string(ctx, -3, "pfx"); // [object][root][buffer]
duk_pop(ctx); // [object][root]
duk_push_string(ctx, "hidden"); duk_put_prop_string(ctx, -2, "passphrase");
duk_put_prop_string(ctx, -2, "root"); // [object]
memcpy_s(jspfx, pfxLen, pfx, pfxLen);
util_free(pfx);
util_freecert(&tmpCert);
return(1);
}
}
void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
{
MeshAgentHostContainer *agent;
@@ -1715,6 +1801,7 @@ void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
// Always use the root cert for agent authentication
duk_push_pointer(ctx, &agent->selfcert);
duk_put_prop_string(ctx, -2, ILibDuktape_MeshAgent_Cert_NonLeaf);
ILibDuktape_CreateInstanceMethod(ctx, "GenerateAgentCertificate", ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent, 1);
#endif
ILibDuktape_EventEmitter_CreateEventEx(emitter, "Ready");

View File

@@ -125,14 +125,21 @@ int __fastcall wincrypto_isopen()
return (wincrypto_hProv != NULL && wincrypto_hCertStore != NULL && wincrypto_certCtx != NULL);
}
void __fastcall wincrypto_close()
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx)
{
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; }
if (certCtx != NULL)
{
CertFreeCertificateContext(certCtx);
}
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(int newcert, char *rootSubject)
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx)
{
DWORD KeyLength = 3072;
NCRYPT_KEY_HANDLE hKeyNode = NULL;
@@ -172,9 +179,10 @@ int __fastcall wincrypto_open(int newcert, char *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 (certCtx == NULL) { certCtx = &wincrypto_certCtx; }
ZeroMemory(&exts, sizeof(exts));
wincrypto_close();
wincrypto_close_ex(*certCtx);
// Open the best CNG possible
while (providerName == NULL && wincrypto_CngProviders[r] != NULL) {
@@ -299,7 +307,7 @@ int __fastcall wincrypto_open(int newcert, char *rootSubject)
error:
// Clean up
if (hKeyNode != NULL) NCryptFreeObject(hKeyNode);
wincrypto_close();
wincrypto_close_ex(*certCtx);
return 1;
end:
@@ -479,11 +487,19 @@ end:
}
// Get the X509 certificate including the public key (Direct reference, no need to free this).
int __fastcall wincrypto_getcert(char** data)
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx)
{
if (wincrypto_certCtx == NULL) { *data = NULL; return 0; }
*data = (char*)wincrypto_certCtx->pbCertEncoded;
return (int)wincrypto_certCtx->cbCertEncoded;
if (certCtx != NULL)
{
*data = (char*)certCtx->pbCertEncoded;
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.

View File

@@ -23,15 +23,18 @@ void __fastcall wincrypto_setregistryA(char* name, char* value);
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, char *rootSubject);
void __fastcall wincrypto_close_ex(PCCERT_CONTEXT certCtx);
#define wincrypto_close() wincrypto_close_ex(NULL)
#define wincrypto_open(newCert, rootSubject) wincrypto_open_ex(newCert, rootSubject, NULL)
int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx);
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);
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);
#define wincrypto_getcert(data) wincrypto_getcert_ex(data, NULL)
int __fastcall wincrypto_getcert_ex(char** data, PCCERT_CONTEXT certCtx);
int __fastcall wincrypto_mkCert(char* rootSubject, wchar_t* subject, int certtype, wchar_t* password, char** data); // certtype: 1=Root, 2=Server, 3=Client
#endif