diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index 7dd9d29..c72c25d 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -1681,19 +1681,19 @@ duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx duk_push_object(ctx); #ifdef WIN32 - PCCERT_CONTEXT certCtx = NULL; - char *certCtx_data = NULL; - if (agent->noCertStore == 0 && wincrypto_open_ex(TRUE, rootSubject, &certCtx) == 0) // Force certificate re-generation + wincrypto_object j = NULL; + char *cert_der = NULL, *cert_pfx = NULL; + if (agent->noCertStore == 0 && (j=wincrypto_open(TRUE, rootSubject)) != NULL) // Force certificate re-generation { int l; do { // Finish off work with our own certificate - l = wincrypto_getcert_ex(&certCtx_data, certCtx); + l = wincrypto_getcert(&cert_der, j); if (l > 0) { - util_from_cer(certCtx_data, l, &tmpCert); + util_from_cer(cert_der, l, &tmpCert); 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. @@ -1706,10 +1706,10 @@ duk_ret_t ILibDuktape_MeshAgent_GenerateCertsForDiagnosticAgent(duk_context *ctx 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); + memcpy_s(rootBuffer, l, cert_der, l); // 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] 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_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); + memcpy_s(buffer, l, cert_pfx, l); + util_free(cert_pfx); + wincrypto_close(j); return(1); } @@ -1945,24 +1946,26 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile) { #if defined(WIN32) 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; - do { + do + { // Finish off work with our own certificate - l = wincrypto_getcert(&str); + l = wincrypto_getcert(&str, agent->certObject); if (l > 0) { 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, 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. if (l > 0) { // 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)); ILibSimpleDataStore_PutEx(agent->masterDb, "SelfNodeTlsCert", 15, str, l); 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. // 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; int l; do { // Finish off work with our own certificate - l = wincrypto_getcert(&str); + l = wincrypto_getcert(&str, agent->certObject); if (l > 0) { util_from_cer(str, l, &(agent->selfcert)); 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. @@ -2081,7 +2084,7 @@ int agent_LoadCertificates(MeshAgentHostContainer *agent) if (len == 0) { // Generate a new TLS certificate & save it. 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) { util_from_p12(str, l, "hidden", &(agent->selftlscert)); 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 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) { // Signature succesful, send the result to the server diff --git a/meshcore/agentcore.h b/meshcore/agentcore.h index 87e9f01..ba46bef 100644 --- a/meshcore/agentcore.h +++ b/meshcore/agentcore.h @@ -182,6 +182,7 @@ typedef struct MeshAgentHostContainer #ifndef MICROSTACK_NOTLS #ifdef WIN32 int noCertStore; + void* certObject; #endif struct util_cert selfcert; struct util_cert selftlscert; diff --git a/meshcore/wincrypto.cpp b/meshcore/wincrypto.cpp index 1d91a3d..d2dfc88 100644 --- a/meshcore/wincrypto.cpp +++ b/meshcore/wincrypto.cpp @@ -28,12 +28,17 @@ extern "C" { #include "wincrypto.h" #include "../microstack/ILibParsers.h" -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 }; -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 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; } -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) - { - 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; } - } + if(((wincrypto_data*)j)->certCtx != NULL) { CertFreeCertificateContext(((wincrypto_data*)j)->certCtx); } + if(((wincrypto_data*)j)->hProv != NULL) { NCryptFreeObject(((wincrypto_data*)j)->hProv); } + if(((wincrypto_data*)j)->hCertStore != NULL) { CertCloseStore(((wincrypto_data*)j)->hCertStore, 0); } + ILibMemory_Free(j); } -int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT *certCtx) +wincrypto_object __fastcall wincrypto_open(int newcert, char *rootSubject) { DWORD KeyLength = 3072; 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 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. + 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); - 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; } - + if (mbstowcs_s(&wkeyLen, (wchar_t*)wkeycontainer, sizeof(wkeycontainer) / 2, (char*)akeycontainer, 64) != 0) { return(NULL); } // Error creating privatekey container name ZeroMemory(&exts, sizeof(exts)); - wincrypto_close_ex(*certCtx); + + wincrypto_data *ret = (wincrypto_data*)ILibMemory_SmartAllocate(sizeof(wincrypto_data)); // Open the best CNG possible - while (providerName == NULL && wincrypto_CngProviders[r] != NULL) { + while (providerName == NULL && wincrypto_CngProviders[r] != NULL) + { providerName = wincrypto_CngProviders[r]; - NCryptOpenStorageProvider(&wincrypto_hProv, providerName, 0); - if (wincrypto_hProv == NULL) providerName = NULL; + NCryptOpenStorageProvider(&(ret->hProv), providerName, 0); + if (ret->hProv == NULL) providerName = NULL; r++; } - if (wincrypto_hProv == NULL) goto error; + if (ret->hProv == NULL) goto error; // 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; @@ -200,36 +199,28 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT sib.cbData = subjectEncodedSize; sib.pbData = subjectEncoded; -#ifdef _CONSOLE - 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 (!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 + 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 + if (!ret->hCertStore) goto error; // 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 - 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 (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 - if (wincrypto_certCtx != NULL && newcert == 0) goto end; - if (wincrypto_certCtx) { status = CertDeleteCertificateFromStore(wincrypto_certCtx); if (!status) goto error; wincrypto_certCtx = NULL; } + if (ret->certCtx != NULL && newcert == 0) goto end; + if (ret->certCtx) { status = CertDeleteCertificateFromStore(ret->certCtx); if (!status) goto error; ret->certCtx = NULL; } // Generate node RSA key-pair -#ifdef _CONSOLE - 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, (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))) { + if (FAILED(status = NCryptCreatePersistedKey(ret->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))) + { 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; } } @@ -292,12 +283,12 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT ZeroMemory(&sa, sizeof(sa)); sa.pszObjId = szOID_RSA_SHA384RSA; // Using SHA384 - wincrypto_certCtx = CertCreateSelfSignCertificate(NULL, &sib, 0, &kpi, &sa, &st1, &st2, &exts); - if (!wincrypto_certCtx) { goto error; } + ret->certCtx = CertCreateSelfSignCertificate(NULL, &sib, 0, &kpi, &sa, &st1, &st2, &exts); + if (!ret->certCtx) { goto error; } // 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); - if (!status || wincrypto_certCtx == NULL) goto error; + status = CertAddCertificateContextToStore(ret->hCertStore, ret->certCtx, CERT_STORE_ADD_REPLACE_EXISTING, &ret->certCtx); + if (!status || ret->certCtx == NULL) goto error; // Get the selected provider name and save it in the registry if (providerName != NULL) wincrypto_setregistry(L"KeyStore", providerName); @@ -307,12 +298,12 @@ int __fastcall wincrypto_open_ex(int newcert, char *rootSubject, PCCERT_CONTEXT error: // Clean up if (hKeyNode != NULL) NCryptFreeObject(hKeyNode); - wincrypto_close_ex(*certCtx); - return 1; + wincrypto_close(ret); + return(NULL); end: if (subjectEncoded != NULL) free(subjectEncoded); - return 0; + return(ret); } 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); } // 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; DWORD cbSignedBlob; @@ -370,7 +361,7 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature) BOOL hFreeKeyNode = FALSE; // 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. HashAlgSize = sizeof(HashAlgorithm); @@ -380,9 +371,9 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature) // Initialize the CMSG_SIGNER_ENCODE_INFO structure. memset(&SignerEncodeInfo, 0, 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.pCertInfo = wincrypto_certCtx->pCertInfo; + SignerEncodeInfo.pCertInfo = ((wincrypto_data*)j)->certCtx->pCertInfo; SignerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE; SignerEncodeInfo.HashAlgorithm = HashAlgorithm; SignerEncodeInfo.pvHashAuxInfo = NULL; @@ -391,8 +382,8 @@ int __fastcall wincrypto_sign(char* data, int len, char** signature) SignerEncodeInfoArray[0] = SignerEncodeInfo; // Initialize the CMSG_SIGNED_ENCODE_INFO structure. - SignerCertBlob.cbData = wincrypto_certCtx->cbCertEncoded; - SignerCertBlob.pbData = wincrypto_certCtx->pbCertEncoded; + SignerCertBlob.cbData = ((wincrypto_data*)j)->certCtx->cbCertEncoded; + SignerCertBlob.pbData = ((wincrypto_data*)j)->certCtx->pbCertEncoded; // Initialize the array of one CertBlob. 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. -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; HCRYPTMSG hMsg = NULL; @@ -457,7 +448,7 @@ int __fastcall wincrypto_decrypt(char* encdata, int encdatalen, char** data) struct wincrypto_stream StreamArg; // 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 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; // 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; // Perform the decrypt @@ -487,23 +478,15 @@ end: } // 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) - { - *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; - } + if (((wincrypto_data*)j)->certCtx == NULL) { *data = NULL; return(0); } + *data = (char*)((wincrypto_data*)j)->certCtx->pbCertEncoded; + return((int)((wincrypto_data*)j)->certCtx->cbCertEncoded); } // 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; 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; // 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; 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 - 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 ((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; diff --git a/meshcore/wincrypto.h b/meshcore/wincrypto.h index 2b3f865..42069b4 100644 --- a/meshcore/wincrypto.h +++ b/meshcore/wincrypto.h @@ -18,23 +18,22 @@ limitations under the License. #include +typedef void* wincrypto_object; void __fastcall wincrypto_setregistry(LPWSTR name, LPWSTR value); 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_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); + +int __fastcall wincrypto_isopen(wincrypto_object j); +void __fastcall wincrypto_close(wincrypto_object j); +wincrypto_object __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); 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); -#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 +int __fastcall wincrypto_sign(wincrypto_object j, char* data, int len, char** signature); +int __fastcall wincrypto_decrypt(wincrypto_object j, char* encdata, int encdatalen, char** data); +int __fastcall wincrypto_getcert(char** data, wincrypto_object j); +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 #endif