From 8f01d6c808cb61d2186fdfb802ecf35ee8db8065 Mon Sep 17 00:00:00 2001
From: gcontini <1121667+gcontini@users.noreply.github.com>
Date: 周六, 30 11月 2019 13:40:50 +0800
Subject: [PATCH] verify signature windows

---
 /dev/null                                     |    1 
 .gitmodules                                   |    4 
 src/library/os/windows/signature_verifier.cpp |  243 ++++++++++++++++++++++++++
 extern/license-generator                      |    1 
 test/functional/generate-license.cpp          |   13 
 src/library/base/base64.c                     |  267 ++++++++++++++--------------
 test/CMakeLists.txt                           |    9 
 7 files changed, 387 insertions(+), 151 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index 256a5c4..3372773 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
-[submodule "extern/license-generator"]
+[submodule "license-generator"]
 	path = extern/license-generator
 	url = https://github.com/open-license-manager/lcc-license-generator.git
-	branch = develop
\ No newline at end of file
+	branch = develop
diff --git a/extern/license-generator b/extern/license-generator
new file mode 160000
index 0000000..9cb1530
--- /dev/null
+++ b/extern/license-generator
@@ -0,0 +1 @@
+Subproject commit 9cb153091edbd55d31e2a1fb1f2e3a2ab5e364b1
diff --git a/src/library/base/.gitignore b/src/library/base/.gitignore
deleted file mode 100644
index 28988b3..0000000
--- a/src/library/base/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/public-key.h
diff --git a/src/library/base/base64.c b/src/library/base/base64.c
index 4d17d33..1e1ea5b 100644
--- a/src/library/base/base64.c
+++ b/src/library/base/base64.c
@@ -1,133 +1,134 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-const static char* b64 =
-		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-// maps A=>0,B=>1..
-const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
-		0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
-		54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
-		0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
-		5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
-		15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
-		25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
-		29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
-		39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
-		49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
-		0, 0, 0, 0, 0, 0, }; // This array has 255 elements
-
-//review api
-char* base64(const void* binaryData, int len, int *flen) {
-	const unsigned char* bin = (const unsigned char*) binaryData;
-	char* res;
-
-	int rc = 0; // result counter
-	int byteNo; // I need this after the loop
-
-	int modulusLen = len % 3;
-	int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
-
-	*flen = 4 * (len + pad) / 3;
-	res = (char*) malloc(*flen + 1); // and one for the null
-	if (!res) {
-		puts("ERROR: base64 could not allocate enough memory.");
-		puts("I must stop because I could not get enough");
-		return 0;
-	}
-
-	for (byteNo = 0; byteNo <= len - 3; byteNo += 3) {
-		unsigned char BYTE0 = bin[byteNo];
-		unsigned char BYTE1 = bin[byteNo + 1];
-		unsigned char BYTE2 = bin[byteNo + 2];
-		res[rc++] = b64[BYTE0 >> 2];
-		res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
-		res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
-		res[rc++] = b64[0x3f & BYTE2];
-	}
-
-	if (pad == 2) {
-		res[rc++] = b64[bin[byteNo] >> 2];
-		res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
-		res[rc++] = '=';
-		res[rc++] = '=';
-	} else if (pad == 1) {
-		res[rc++] = b64[bin[byteNo] >> 2];
-		res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
-		res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
-		res[rc++] = '=';
-	}
-
-	res[rc] = 0; // NULL TERMINATOR! ;)
-	return res;
-}
-
-unsigned char* unbase64(const char* ascii, int len, int *flen) {
-	const unsigned char *safeAsciiPtr = (const unsigned char*) ascii;
-	unsigned char *bin;
-	int cb = 0;
-	int charNo;
-	int pad = 0;
-
-	if (len < 2) { // 2 accesses below would be OOB.
-		// catch empty string, return NULL as result.
-		puts(
-				"ERROR: You passed an invalid base64 string (too short). You get NULL back.");
-		*flen = 0;
-		return 0;
-	}
-	if (safeAsciiPtr[len - 1] == '=')
-		++pad;
-	if (safeAsciiPtr[len - 2] == '=')
-		++pad;
-
-	*flen = 3 * len / 4 - pad;
-	bin = (unsigned char*) malloc(*flen);
-	if (!bin) {
-		puts("ERROR: unbase64 could not allocate enough memory.");
-		puts("I must stop because I could not get enough");
-		return 0;
-	}
-
-	for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) {
-		int A = unb64[safeAsciiPtr[charNo]];
-		int B = unb64[safeAsciiPtr[charNo + 1]];
-		int C = unb64[safeAsciiPtr[charNo + 2]];
-		int D = unb64[safeAsciiPtr[charNo + 3]];
-
-		bin[cb++] = (A << 2) | (B >> 4);
-		bin[cb++] = (B << 4) | (C >> 2);
-		bin[cb++] = (C << 6) | (D);
-	}
-
-	if (pad == 1) {
-		int A = unb64[safeAsciiPtr[charNo]];
-		int B = unb64[safeAsciiPtr[charNo + 1]];
-		int C = unb64[safeAsciiPtr[charNo + 2]];
-
-		bin[cb++] = (A << 2) | (B >> 4);
-		bin[cb++] = (B << 4) | (C >> 2);
-	} else if (pad == 2) {
-		int A = unb64[safeAsciiPtr[charNo]];
-		int B = unb64[safeAsciiPtr[charNo + 1]];
-
-		bin[cb++] = (A << 2) | (B >> 4);
-	}
-
-	return bin;
-}
+#include <stdio.h>
+#include <stdlib.h>
+
+const static char* b64 =
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+// maps A=>0,B=>1..
+const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
+		0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
+		54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
+		0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
+		5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
+		15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
+		25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
+		29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
+		39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
+		49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
+		0, 0, 0, 0, 0, 0, }; // This array has 255 elements
+
+//review api
+char* base64(const void* binaryData, int len, int *flen) {
+	const unsigned char* bin = (const unsigned char*) binaryData;
+	char* res;
+
+	int rc = 0; // result counter
+	int byteNo; // I need this after the loop
+
+	int modulusLen = len % 3;
+	int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
+
+	*flen = 4 * (len + pad) / 3;
+	res = (char*) malloc(*flen + 1); // and one for the null
+	if (!res) {
+		puts("ERROR: base64 could not allocate enough memory.");
+		puts("I must stop because I could not get enough");
+		return 0;
+	}
+
+	for (byteNo = 0; byteNo <= len - 3; byteNo += 3) {
+		unsigned char BYTE0 = bin[byteNo];
+		unsigned char BYTE1 = bin[byteNo + 1];
+		unsigned char BYTE2 = bin[byteNo + 2];
+		res[rc++] = b64[BYTE0 >> 2];
+		res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
+		res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
+		res[rc++] = b64[0x3f & BYTE2];
+	}
+
+	if (pad == 2) {
+		res[rc++] = b64[bin[byteNo] >> 2];
+		res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
+		res[rc++] = '=';
+		res[rc++] = '=';
+	} else if (pad == 1) {
+		res[rc++] = b64[bin[byteNo] >> 2];
+		res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
+		res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
+		res[rc++] = '=';
+	}
+
+	res[rc] = 0; // NULL TERMINATOR! ;)
+	return res;
+}
+
+//FIXME! 
+unsigned char* unbase64(const char* ascii, int len, int *flen) {
+	const unsigned char *safeAsciiPtr = (const unsigned char*) ascii;
+	unsigned char *bin;
+	int cb = 0;
+	int charNo;
+	int pad = 0;
+
+	if (len < 2) { // 2 accesses below would be OOB.
+		// catch empty string, return NULL as result.
+		puts(
+				"ERROR: You passed an invalid base64 string (too short). You get NULL back.");
+		*flen = 0;
+		return 0;
+	}
+	if (safeAsciiPtr[len - 1] == '=')
+		++pad;
+	if (safeAsciiPtr[len - 2] == '=')
+		++pad;
+
+	*flen = 3 * len / 4 - pad;
+	bin = (unsigned char*) malloc(*flen);
+	if (!bin) {
+		puts("ERROR: unbase64 could not allocate enough memory.");
+		puts("I must stop because I could not get enough");
+		return 0;
+	}
+
+	for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) {
+		int A = unb64[safeAsciiPtr[charNo]];
+		int B = unb64[safeAsciiPtr[charNo + 1]];
+		int C = unb64[safeAsciiPtr[charNo + 2]];
+		int D = unb64[safeAsciiPtr[charNo + 3]];
+
+		bin[cb++] = (A << 2) | (B >> 4);
+		bin[cb++] = (B << 4) | (C >> 2);
+		bin[cb++] = (C << 6) | (D);
+	}
+
+	if (pad == 1) {
+		int A = unb64[safeAsciiPtr[charNo]];
+		int B = unb64[safeAsciiPtr[charNo + 1]];
+		int C = unb64[safeAsciiPtr[charNo + 2]];
+
+		bin[cb++] = (A << 2) | (B >> 4);
+		bin[cb++] = (B << 4) | (C >> 2);
+	} else if (pad == 2) {
+		int A = unb64[safeAsciiPtr[charNo]];
+		int B = unb64[safeAsciiPtr[charNo + 1]];
+
+		bin[cb++] = (A << 2) | (B >> 4);
+	}
+
+	return bin;
+}
diff --git a/src/library/os/windows/signature_verifier.cpp b/src/library/os/windows/signature_verifier.cpp
index 6d73513..88194a2 100644
--- a/src/library/os/windows/signature_verifier.cpp
+++ b/src/library/os/windows/signature_verifier.cpp
@@ -5,16 +5,249 @@
  *      Author: devel
  */
 
-#include "verifier.hpp"
+#include "../os.h"
+#include <stdio.h>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <bcrypt.h>
+#include <wincrypt.h>
+#include <iphlpapi.h>
+#include <windows.h>
+#pragma comment(lib, "bcrypt.lib")
+
+#include <public_key.h>
+#include "../../base/logger.h"
+#include "../../base/base64.h"
+#include "../signature_verifier.h"
+
+#define RSA_KEY_BITLEN 1024
 
 namespace license {
+using namespace std;
+#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
 
-verifier::verifier() {
-	// TODO Auto-generated constructor stub
+static const void formatError(DWORD status, const char* description) {
+	char msgBuffer[256];
+	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &msgBuffer[0],
+				  sizeof(msgBuffer) - 1, nullptr);
+	LOG_DEBUG("error %s : %s %h", description, msgBuffer, status);
 }
 
-verifier::~verifier() {
-	// TODO Auto-generated destructor stub
+#pragma pack(push, 1)
+typedef struct {
+	BCRYPT_RSAKEY_BLOB rsakey;
+	BYTE pkExp[3];
+	BYTE modulus[RSA_KEY_BITLEN / 8];
+} PUBKEY_BLOB, *P_PUBKEY_BLOB;
+#pragma pack(pop)
+
+static BCRYPT_ALG_HANDLE openSignatureProvider() {
+	DWORD status;
+	BCRYPT_ALG_HANDLE hSignAlg = nullptr;
+
+	return hSignAlg;
+}
+
+static BCRYPT_ALG_HANDLE openHashProvider() {
+	DWORD status;
+	BCRYPT_ALG_HANDLE hHashAlg = nullptr;
+	if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hHashAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0))) {
+		throw logic_error("Error opening hash provider");
+	}
+	return hHashAlg;
+}
+
+static DWORD hashData(BCRYPT_HASH_HANDLE& hHash, const string& data, PBYTE pbHash, DWORD hashDataLenght) {
+	DWORD status;
+	bool success = false;
+	if (NT_SUCCESS(status = BCryptHashData(hHash, (BYTE*)data.c_str(), (ULONG)data.length(), 0))) {
+		status = BCryptFinishHash(hHash, pbHash, hashDataLenght, 0);
+	}
+	return status;
+}
+
+static size_t read_length(uint8_t*& ptr) {
+	uint8_t len = *ptr++;
+	size_t result = 0;
+	cout << (len & 0x80) << endl;
+	if ((len & 0x80) > 0) {
+		size_t blen = len & 0x7F;
+		for (int i = 0; i < blen; i++) {
+			result += (*(ptr++) << (i * 8));
+		}
+	} else {
+		result = len;
+	}
+	return result;
+}
+
+static FUNCTION_RETURN read_sequence(uint8_t*& ptr) {
+	uint8_t tag = *ptr++;
+	if (tag != 0x30) {
+		return FUNC_RET_ERROR;
+	}
+	read_length(ptr);
+	return FUNC_RET_OK;
+}
+
+static FUNCTION_RETURN read_integer(uint8_t*& ptr, BYTE* location, const size_t expected_length) {
+	uint8_t tag = *ptr++;
+	if (tag != 0x02) {
+		return FUNC_RET_ERROR;
+	}
+	size_t length = read_length(ptr);
+	// skip the padding byte
+	if (*ptr == 0) {
+		length--;
+		ptr++;
+	}
+	if (expected_length < length) {
+		return FUNC_RET_ERROR;
+	}
+	for (int i = 0; i < length; i++) {
+		location[i] = *(ptr++);
+	}
+	return FUNC_RET_OK;
+}
+
+static FUNCTION_RETURN readPublicKey(const BCRYPT_ALG_HANDLE sig_alg, BCRYPT_KEY_HANDLE* hKey) {
+	FUNCTION_RETURN result = FUNC_RET_ERROR;
+	DWORD status;
+	PUBKEY_BLOB pubk;
+	pubk.rsakey.Magic = BCRYPT_RSAPUBLIC_MAGIC;
+	pubk.rsakey.BitLength = RSA_KEY_BITLEN;
+	pubk.rsakey.cbPublicExp = 3;
+	pubk.rsakey.cbModulus = RSA_KEY_BITLEN / 8;
+	pubk.rsakey.cbPrime1 = 0;
+	pubk.rsakey.cbPrime2 = 0;
+	uint8_t pubKey[] = PUBLIC_KEY;
+	uint8_t* pub_key_idx = &pubKey[0];
+	read_sequence(pub_key_idx);
+	read_integer(pub_key_idx, (BYTE*)&pubk.modulus, sizeof(pubk.modulus));
+	read_integer(pub_key_idx, (BYTE*)&pubk.pkExp, sizeof(pubk.pkExp));
+	if (NT_SUCCESS(status = BCryptImportKeyPair(sig_alg, nullptr, BCRYPT_RSAPUBLIC_BLOB, hKey, (PUCHAR)&pubk,
+												sizeof(pubk), 0))) {
+		result = FUNC_RET_OK;
+	} else {
+#ifdef _DEBUG
+		formatError(status, "error importing public key");
+#endif
+	}
+	return result;
+}
+
+static FUNCTION_RETURN verifyHash(const PBYTE pbHash, const DWORD hashDataLenght, const string& signatureBuffer) {
+	BCRYPT_KEY_HANDLE phKey = nullptr;
+	DWORD status;
+	FUNCTION_RETURN result = FUNC_RET_ERROR;
+	PBYTE pbSignature = nullptr;
+	DWORD dwSigLen;
+	BYTE* sigBlob = nullptr;
+	BCRYPT_ALG_HANDLE hSignAlg = nullptr;
+
+	// FIXME!!
+	sigBlob = unbase64(signatureBuffer.c_str(), (int)signatureBuffer.size(), (int*)&dwSigLen);
+
+	if (NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hSignAlg, BCRYPT_RSA_ALGORITHM, NULL, 0))) {
+		if ((result = readPublicKey(hSignAlg, &phKey)) == FUNC_RET_OK) {
+			BCRYPT_PKCS1_PADDING_INFO paddingInfo;
+			ZeroMemory(&paddingInfo, sizeof(paddingInfo));
+			paddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM;
+			if (NT_SUCCESS(status = BCryptVerifySignature(phKey, &paddingInfo, pbHash, hashDataLenght, sigBlob,
+														  dwSigLen, BCRYPT_PAD_PKCS1))) {
+				result = FUNC_RET_OK;
+			} else {
+				result = FUNC_RET_ERROR;
+#ifdef _DEBUG
+				formatError(status, "error verifying signature");
+#endif
+			}
+		} else {
+			LOG_DEBUG("Error reading public key");
+		}
+	} else {
+		result = FUNC_RET_NOT_AVAIL;
+#ifdef _DEBUG
+		formatError(status, "error opening RSA provider");
+#endif
+	}
+
+	if (phKey != nullptr) {
+		BCryptDestroyKey(phKey);
+	}
+	if (hSignAlg != nullptr) {
+		BCryptCloseAlgorithmProvider(hSignAlg, 0);
+	}
+	if (sigBlob) {
+		free(sigBlob);
+	}
+	return result;
+}
+
+FUNCTION_RETURN verify_signature(const std::string& stringToVerify, const std::string& signatureB64) {
+	BCRYPT_HASH_HANDLE hHash = nullptr;
+	PBYTE pbHashObject = nullptr, pbHashData = nullptr;
+
+	FUNCTION_RETURN result = FUNC_RET_ERROR;
+	const HANDLE hProcessHeap = GetProcessHeap();
+	// BCRYPT_ALG_HANDLE sig_alg = openSignatureProvider();
+
+	BCRYPT_ALG_HANDLE hash_alg = openHashProvider();
+	DWORD status;
+
+	// calculate the size of the buffer to hold the hash object
+	DWORD cbData = 0, cbHashObject = 0;
+	// and the size to keep the hashed data
+	DWORD cbHashDataLenght = 0;
+	if (NT_SUCCESS(status = BCryptGetProperty(hash_alg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD),
+											  &cbData, 0)) &&
+		NT_SUCCESS(status = BCryptGetProperty(hash_alg, BCRYPT_HASH_LENGTH, (PBYTE)&cbHashDataLenght, sizeof(DWORD),
+											  &cbData, 0))) {
+		// allocate the hash object on the heap
+		pbHashObject = (PBYTE)HeapAlloc(hProcessHeap, 0, cbHashObject);
+		pbHashData = (PBYTE)HeapAlloc(hProcessHeap, 0, cbHashDataLenght);
+		if (NULL != pbHashObject && nullptr != pbHashData) {
+			if (NT_SUCCESS(status = BCryptCreateHash(hash_alg, &hHash, pbHashObject, cbHashObject, NULL, 0, 0))) {
+				if (NT_SUCCESS(status = hashData(hHash, stringToVerify, pbHashData, cbHashDataLenght))) {
+					result = verifyHash(pbHashData, cbHashDataLenght, signatureB64);
+				} else {
+					result = FUNC_RET_NOT_AVAIL;
+#ifdef _DEBUG
+					formatError(status, "error hashing data");
+#endif
+				}
+			} else {
+				result = FUNC_RET_NOT_AVAIL;
+#ifdef _DEBUG
+				formatError(status, "error creating hash");
+#endif
+			}
+		} else {
+			result = FUNC_RET_BUFFER_TOO_SMALL;
+			LOG_DEBUG("Error allocating memory");
+		}
+	} else {
+		result = FUNC_RET_NOT_AVAIL;
+#ifdef _DEBUG
+		formatError(status, "**** Error returned by BCryptGetProperty");
+#endif
+	}
+
+	if (hHash) {
+		BCryptDestroyHash(hHash);
+	}
+	if (pbHashObject) {
+		HeapFree(hProcessHeap, 0, pbHashObject);
+	}
+	if (pbHashData) {
+		HeapFree(hProcessHeap, 0, pbHashData);
+	}
+	if (hash_alg != nullptr) {
+		BCryptCloseAlgorithmProvider(hash_alg, 0);
+	}
+	return result;
 }
 
 } /* namespace license */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index d790c3f..c1be16e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,8 +1,7 @@
 #if we're here boost has been found
 add_definitions(-DBOOST_ALL_NO_LIB) #Disable Boost Microsoft magic, all dependencies are handled by cmake
 add_definitions(-DBOOST_LIB_DIAGNOSTIC) #Check it is really disabled
-include_directories(${Boost_INCLUDE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
 link_directories ( ${Boost_LIBRARY_DIR} )
 
 configure_file (
@@ -10,8 +9,10 @@
 	"${CMAKE_BINARY_DIR}/licensecc_properties_test.h.tmp"
 )
 
-file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/licensecc_properties_test.h" 
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/include/$<CONFIG>/licensecc_properties_test.h" 
 		INPUT "${CMAKE_BINARY_DIR}/licensecc_properties_test.h.tmp")
-		
+
+include_directories ( ${CMAKE_BINARY_DIR}/include/$<CONFIG> )
 add_subdirectory(library)
 add_subdirectory(functional)
\ No newline at end of file
diff --git a/test/functional/generate-license.cpp b/test/functional/generate-license.cpp
index b41ff66..febf621 100644
--- a/test/functional/generate-license.cpp
+++ b/test/functional/generate-license.cpp
@@ -28,8 +28,9 @@
 		BOOST_REQUIRE_MESSAGE(fs::create_directories(licenses_base), "test folders created " + licenses_base.string());
 	}
 
-	fs::path license_fname(licenses_base / (license_name + ".lic"));
-	remove(license_fname.c_str());
+	const fs::path license_fname(licenses_base / (license_name + ".lic"));
+	const string license_fname_s = license_fname.string();
+	remove(license_fname_s.c_str());
 
 	stringstream ss;
 	ss << LCC_EXE << " license issue";
@@ -60,15 +61,15 @@
 		BOOST_REQUIRE_MESSAGE(fs::create_directories(licenses_base), "test folders created " + licenses_base.string());
 	}
 
-	fs::path outputFile(fs::path(PROJECT_TEST_TEMP_DIR) / (test_name + ".tmp"));
-
-	remove(outputFile.c_str());
+	const fs::path outputFile(fs::path(PROJECT_TEST_TEMP_DIR) / (test_name + ".tmp"));
+	const string output_file_s = outputFile.string();
+	remove(output_file_s.c_str());
 
 	stringstream ss;
 	ss << LCC_EXE << " test sign";
 	ss << " --" PARAM_PRIMARY_KEY " " << LCC_PROJECT_PRIVATE_KEY;
 	ss << " -d " << data;
-	ss << " -o " << outputFile.string();
+	ss << " -o " << output_file_s;
 
 	cout << "executing :" << ss.str() << endl;
 	const int retCode = std::system(ss.str().c_str());

--
Gitblit v1.9.1