[PATCH 02/16] ncrypt: Implement NCryptOpenStorageProvider
abdaandroid at gmail.com
abdaandroid at gmail.com
Sun Oct 11 10:45:21 CDT 2020
From: Ariel Darshan <abdaandroid at gmail.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48733
Signed-off-by: Ariel Darshan <abdaandroid at gmail.com>
---
dlls/ncrypt/main.c | 125 +++++++++++++++++++++++++++++++++-
dlls/ncrypt/ncrypt_internal.h | 92 +++++++++++++++++++++++++
include/bcrypt.h | 6 ++
3 files changed, 221 insertions(+), 2 deletions(-)
create mode 100644 dlls/ncrypt/ncrypt_internal.h
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c
index 86bc9190717..8a8d8d0ed13 100644
--- a/dlls/ncrypt/main.c
+++ b/dlls/ncrypt/main.c
@@ -2,6 +2,7 @@
* New cryptographic library (ncrypt.dll)
*
* Copyright 2016 Alex Henrie
+ * Copyright 2020 Ariel Darshan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,6 +27,7 @@
#include "winreg.h"
#include "wine/debug.h"
#include "wine/heap.h"
+#include "ncrypt_internal.h"
WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
@@ -264,8 +266,60 @@ SECURITY_STATUS WINAPI NCryptOpenKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HAN
SECURITY_STATUS WINAPI NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE *provider, const WCHAR *name, DWORD flags)
{
- FIXME("(%p, %s, %u): stub\n", provider, wine_dbgstr_w(name), flags);
- return NTE_NOT_SUPPORTED;
+ NCryptProviderName *providerNames;
+ DWORD providerCount;
+ DWORD i;
+ BOOL isKSP;
+ LSTATUS lstatus;
+ SECURITY_STATUS secStatus;
+ WCHAR registryPath[MAX_PATH];
+ WCHAR dllName[MAX_PATH];
+ DWORD dllNameLen;
+
+ TRACE("(%p, %s, %u)\n", provider, wine_dbgstr_w(name), flags);
+
+
+ secStatus = NCryptEnumStorageProviders(&providerCount, &providerNames, 0);
+ if (secStatus != ERROR_SUCCESS)
+ {
+ return secStatus;
+ }
+
+ isKSP = FALSE;
+ for (i = 0; i < providerCount; ++i)
+ {
+ if (!wcscmp(providerNames[i].pszName, name))
+ {
+ isKSP = TRUE;
+ break;
+ }
+ }
+
+ secStatus = NCryptFreeBuffer(providerNames);
+ if (secStatus != ERROR_SUCCESS)
+ {
+ WARN("Failed to free providers list\n");
+ }
+
+ if (!isKSP)
+ {
+ ERR("provider not found: %s\n", wine_dbgstr_w(name));
+ return NTE_INVALID_PARAMETER;
+ }
+
+
+
+ dllNameLen = MAX_PATH;
+ swprintf(registryPath, MAX_PATH, L"SYSTEM\\CurrentControlSet\\Control\\Cryptography\\Providers\\%s\\UM", name);
+
+ lstatus = RegGetValueW(HKEY_LOCAL_MACHINE, registryPath, L"Image", RRF_RT_REG_SZ, NULL, dllName, &dllNameLen);
+ if (lstatus != ERROR_SUCCESS)
+ {
+ ERR("Couldn't find image for provider: %s\n", wine_dbgstr_w(name));
+ return NTE_INVALID_PARAMETER;
+ }
+
+ return open_provider(provider, name, dllName, flags);
}
SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE object, const WCHAR *property,
@@ -275,3 +329,70 @@ SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE object, const WCHAR *prop
flags);
return NTE_NOT_SUPPORTED;
}
+
+static SECURITY_STATUS open_provider(NCRYPT_PROV_HANDLE *providerInstance, const WCHAR *name, const WCHAR *dllName, DWORD flags)
+{
+ unsigned int size;
+ void *buffer;
+ struct ncrypt_provider_instance *ret;
+ HMODULE hDLL;
+ getInterfaceFn getKeyStorageInterface;
+ SECURITY_STATUS status;
+ NCRYPT_KEY_STORAGE_FUNCTION_TABLE *functionTable;
+ NCRYPT_PROV_HANDLE kspHandle;
+
+ hDLL = LoadLibraryW(dllName);
+ if (!hDLL)
+ {
+ ERR("Failed to load provider dll: %s. error code: 0x%08x\n", wine_dbgstr_w(dllName), GetLastError());
+ return NTE_PROV_DLL_NOT_FOUND;
+ }
+
+ getKeyStorageInterface = (getInterfaceFn) GetProcAddress(hDLL, "GetKeyStorageInterface");
+ if (!getKeyStorageInterface)
+ {
+ ERR("Failed to locate the 'GetKeyStorageInterface' export in dll: %s. error code: 0x%08x\n", wine_dbgstr_w(dllName), GetLastError());
+ FreeLibrary(hDLL);
+ return NTE_PROVIDER_DLL_FAIL;
+ }
+
+ /* FIXME: What should flags be? */
+ status = getKeyStorageInterface(name, &functionTable, 0);
+ if (status != ERROR_SUCCESS)
+ {
+ ERR("Failed to get key storage interface from dll: %s\n", wine_dbgstr_w(dllName));
+ FreeLibrary(hDLL);
+ return status;
+ }
+
+ status = functionTable->OpenProvider(&kspHandle, name, flags);
+ if (status != ERROR_SUCCESS)
+ {
+ ERR("OpenProvider failed in dll: %s\n", wine_dbgstr_w(dllName));
+ FreeLibrary(hDLL);
+ return status;
+ }
+
+ /* Allocate both structure and name in the same call */
+ size = sizeof(struct ncrypt_provider_instance) + (wcslen(name) + 1) * sizeof(WCHAR);
+
+ buffer = heap_alloc(size);
+ if (!buffer)
+ {
+ ERR("Out of memory!\n");
+ FreeLibrary(hDLL);
+ return NTE_NO_MEMORY;
+ }
+
+ ret = (struct ncrypt_provider_instance*)buffer;
+ ret->sType = NCRYPT_OBJ_TYPE_PROVIDER;
+ ret->refCount = 1;
+ ret->kspDLL = hDLL;
+ memcpy(&ret->functions, functionTable, sizeof(NCRYPT_KEY_STORAGE_FUNCTION_TABLE));
+ ret->kspHandle = kspHandle;
+ ret->name = (WCHAR*)((char*)buffer + sizeof(struct ncrypt_provider_instance));
+ wcscpy(ret->name, name);
+
+ *providerInstance = provider2handle(ret);
+ return ERROR_SUCCESS;
+}
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h
new file mode 100644
index 00000000000..e5c9a946f2c
--- /dev/null
+++ b/dlls/ncrypt/ncrypt_internal.h
@@ -0,0 +1,92 @@
+/*
+ * Common definitions
+ *
+ * Copyright 2020 Ariel Darshan
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __NCRYPT_INTERNAL__
+#define __NCRYPT_INTERNAL__
+
+#include "bcrypt.h"
+
+typedef struct _NCRYPT_KEY_STORAGE_FUNCTION_TABLE
+{
+ BCRYPT_INTERFACE_VERSION version;
+ SECURITY_STATUS(*OpenProvider)(NCRYPT_PROV_HANDLE *outProvider, LPCWSTR name, DWORD flags);
+ SECURITY_STATUS(*OpenKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *outKey, LPCWSTR keyName, DWORD legacyKeySpec, DWORD flags);
+ SECURITY_STATUS(*CreatePersistedKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE* outKey, LPCWSTR algId, LPCWSTR keyName, DWORD legacyKeySpec, DWORD flags);
+ SECURITY_STATUS(*GetProviderProperty)(NCRYPT_PROV_HANDLE provider, LPCWSTR propertyName, BYTE *output, DWORD outputSize, DWORD *result, DWORD flags);
+ SECURITY_STATUS(*GetKeyProperty)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, LPCWSTR propertyName, BYTE* output, DWORD outputSize, DWORD* result, DWORD flags);
+ SECURITY_STATUS(*SetProviderProperty)(NCRYPT_PROV_HANDLE provider, LPCWSTR propertyName, BYTE* input, DWORD inputSize, DWORD flags);
+ SECURITY_STATUS(*SetKeyProperty)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, LPCWSTR propertyName, BYTE* input, DWORD inputSize, DWORD flags);
+ SECURITY_STATUS(*FinalizeKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, DWORD flags);
+ SECURITY_STATUS(*DeleteKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, DWORD flags);
+ SECURITY_STATUS(*FreeProvider)(NCRYPT_PROV_HANDLE provider);
+ SECURITY_STATUS(*FreeKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key);
+ SECURITY_STATUS(*FreeBuffer)(void *buffer);
+ SECURITY_STATUS(*Encrypt)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, BYTE *input, DWORD inputSize, void *paddingInfo, BYTE *output, DWORD outputSize, DWORD *result, DWORD flags);
+ SECURITY_STATUS(*Decrypt)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, BYTE* input, DWORD inputSize, void *paddingInfo, BYTE* output, DWORD outputSize, DWORD* result, DWORD flags);
+ SECURITY_STATUS(*IsAlgSupported)(NCRYPT_PROV_HANDLE provider, LPCWSTR algId, DWORD flags);
+ SECURITY_STATUS(*EnumAlgorithms)(NCRYPT_PROV_HANDLE provider, DWORD algOperations, DWORD *algCount, NCryptAlgorithmName **algList, DWORD flags);
+ SECURITY_STATUS(*EnumKeys)(NCRYPT_PROV_HANDLE provider, LPCWSTR scope, NCryptKeyName **keyName, void **enumState, DWORD flags);
+ SECURITY_STATUS(*ImportKey)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decryptKey, LPCWSTR blobType, NCryptBufferDesc *parameterList, NCRYPT_KEY_HANDLE *outKey, BYTE *data, DWORD dataSize, DWORD flags);
+ SECURITY_STATUS(*ExportKey)(NCRYPT_KEY_HANDLE key, NCRYPT_KEY_HANDLE encryptKey, LPCWSTR blobType, NCryptBufferDesc *parameterList, BYTE *output, DWORD outputSize, DWORD *result, DWORD flags);
+ SECURITY_STATUS(*SignHash)(NCRYPT_KEY_HANDLE key, void *paddingInfo, BYTE *hashValue, DWORD hashSize, BYTE *outSig, DWORD outSigSize, DWORD *result, DWORD flags);
+ SECURITY_STATUS(*VerifySignature)(NCRYPT_KEY_HANDLE key, void *paddingInfo, BYTE *hashValue, DWORD hashSize, BYTE *signature, DWORD signatureSize, DWORD flags);
+ SECURITY_STATUS(*PromptUser)(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE key, LPCWSTR operation, DWORD flags);
+ SECURITY_STATUS(*NotifyChangeKey)(NCRYPT_PROV_HANDLE provider, HANDLE *event, DWORD flags);
+ SECURITY_STATUS(*SecretAgreement)(NCRYPT_KEY_HANDLE privateKey, NCRYPT_KEY_HANDLE publicKey, NCRYPT_SECRET_HANDLE *agreedSecret, DWORD flags);
+ SECURITY_STATUS(*DeriveKey)(NCRYPT_SECRET_HANDLE sharedSecret, LPCWSTR kdf, NCryptBufferDesc *parameterList, BYTE *outKey, DWORD outKeySize, DWORD *result, DWORD flags);
+ SECURITY_STATUS(*FreeSecret)(NCRYPT_PROV_HANDLE provider, NCRYPT_SECRET_HANDLE sharedSecret);
+
+}NCRYPT_KEY_STORAGE_FUNCTION_TABLE;
+
+typedef NTSTATUS(*getInterfaceFn)(LPCWSTR providerName, NCRYPT_KEY_STORAGE_FUNCTION_TABLE **outFunctionTable, DWORD dwFlags);
+
+
+#define NCRYPT_OBJ_TYPE_PROVIDER 0x44440001
+#define NCRYPT_OBJ_TYPE_KEY 0x44440002
+#define NCRYPT_OBJ_TYPE_HASH 0x44440003
+#define NCRYPT_OBJ_TYPE_SECRET 0x44440004
+
+struct ncrypt_base_object
+{
+ DWORD sType;
+};
+
+struct ncrypt_provider_instance
+{
+ DWORD sType;
+ DWORD refCount;
+ HMODULE kspDLL;
+ NCRYPT_KEY_STORAGE_FUNCTION_TABLE functions;
+ NCRYPT_PROV_HANDLE kspHandle;
+ WCHAR *name;
+};
+
+
+#define handle2baseObject(x) ((struct ncrypt_base_object*)(x))
+#define baseObject2handle(x) ((NCRYPT_HANDLE)(x))
+
+#define handle2provider(x) ((struct ncrypt_provider_instance*)(x))
+#define provider2handle(x) ((NCRYPT_PROV_HANDLE)(x))
+
+
+
+static SECURITY_STATUS open_provider(NCRYPT_PROV_HANDLE *providerInstance ,const WCHAR *name, const WCHAR *dllName, DWORD flags);
+
+#endif /* __NCRYPT_INTERNAL__ */
diff --git a/include/bcrypt.h b/include/bcrypt.h
index a099f2f4b0e..4d3f59c3462 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -221,6 +221,12 @@ static const WCHAR BCRYPT_KDF_RAW_SECRET[] = {'T','R','U','N','C','A','T','E',0}
#define BCRYPT_SUPPORTED_PAD_OAEP 0x00000008
#define BCRYPT_SUPPORTED_PAD_PSS 0x00000010
+typedef struct _BCRYPT_INTERFACE_VERSION
+{
+ USHORT MajorVersion;
+ USHORT MinorVersion;
+}BCRYPT_INTERFACE_VERSION, *PBCRYPT_INTERFACE_VERSION;
+
typedef struct _BCRYPT_ALGORITHM_IDENTIFIER
{
LPWSTR pszName;
--
2.28.0
More information about the wine-devel
mailing list