From 492558c6231e7738f35f140005df5bb31a0af9bc Mon Sep 17 00:00:00 2001 From: gcontini <1121667+gcontini@users.noreply.github.com> Date: 周六, 30 11月 2019 14:56:28 +0800 Subject: [PATCH] merge commits --- src/library/os/windows/signature_verifier.cpp | 243 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 238 insertions(+), 5 deletions(-) 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 */ -- Gitblit v1.9.1