gcontini
2019-11-30 492558c6231e7738f35f140005df5bb31a0af9bc
merge commits
4个文件已修改
1个文件已添加
1个文件已删除
270 ■■■■■ 已修改文件
.gitmodules 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
extern/.gitkeep 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/signature_verifier.cpp 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/CMakeLists.txt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/generate-license.cpp 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.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
    branch = develop
extern/.gitkeep
src/library/base/.gitignore
File was deleted
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 */
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)
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());