gcontini
2019-11-30 8f01d6c808cb61d2186fdfb802ecf35ee8db8065
verify signature windows
5个文件已修改
1个文件已添加
1个文件已删除
538 ■■■■ 已修改文件
.gitmodules 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
extern/license-generator @ 9cb153 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/base64.c 267 ●●●● 补丁 | 查看 | 原始文档 | 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/license-generator
New file
@@ -0,0 +1 @@
Subproject commit 9cb153091edbd55d31e2a1fb1f2e3a2ab5e364b1
src/library/base/.gitignore
File was deleted
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;
}
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());