diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..bac69ab --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.22000.0", + "compilerPath": "g++.exe", + // "cStandard": "c99", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x86" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/_outputOld/createbase64.bat b/_outputOld/createbase64.bat new file mode 100644 index 0000000..2a52202 --- /dev/null +++ b/_outputOld/createbase64.bat @@ -0,0 +1 @@ +licenceGenerator.exe -cid=9f544930303030300000000b47015423 -csd=400e00325b5900003a0d7f800a40008d -outputType=base64 -configFileName=licData.xml \ No newline at end of file diff --git a/_outputOld/createnew.bat b/_outputOld/createnew.bat new file mode 100644 index 0000000..77416ee --- /dev/null +++ b/_outputOld/createnew.bat @@ -0,0 +1 @@ +licenceGenerator.exe -cid=9f544930303030300000000b47015423 -csd=400e00325b5900003a0d7f800a40008d -outputType=file -configFileName=licData.xml \ No newline at end of file diff --git a/_outputOld/ezlic_eovosv0_vaxvcpalxjx.lic b/_outputOld/ezlic_eovosv0_vaxvcpalxjx.lic new file mode 100644 index 0000000..2c9d5c5 Binary files /dev/null and b/_outputOld/ezlic_eovosv0_vaxvcpalxjx.lic differ diff --git a/_outputOld/ezlic_eovosv0_vaxvcpalxjx_back.lic b/_outputOld/ezlic_eovosv0_vaxvcpalxjx_back.lic new file mode 100644 index 0000000..b7f4dd1 Binary files /dev/null and b/_outputOld/ezlic_eovosv0_vaxvcpalxjx_back.lic differ diff --git a/_outputOld/licData.xml b/_outputOld/licData.xml new file mode 100644 index 0000000..7cdac51 --- /dev/null +++ b/_outputOld/licData.xml @@ -0,0 +1,8 @@ + + + WAGO + EOV_OSV + Licence pro EOV_OSV + ceskatrebova + RO1 + \ No newline at end of file diff --git a/_outputOld/licenceGenerator b/_outputOld/licenceGenerator new file mode 100644 index 0000000..d3662c6 Binary files /dev/null and b/_outputOld/licenceGenerator differ diff --git a/_outputOld/licenceGenerator.exe b/_outputOld/licenceGenerator.exe new file mode 100644 index 0000000..e69de29 diff --git a/docker/Dockerfile b/docker/Dockerfile index 68ba18e..6c1b444 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -8,6 +8,9 @@ RUN chmod 755 /app/generate.sh COPY ./start.sh /app/ RUN chmod 755 /app/start.sh +COPY ./startok.sh /app/ +RUN chmod 755 /app/startok.sh + COPY ./Makefile /app/ ENTRYPOINT ["tail"] diff --git a/docker/start.sh b/docker/start.sh index 05c0749..264802a 100644 --- a/docker/start.sh +++ b/docker/start.sh @@ -1,7 +1,7 @@ #!/bin/bash chmod 777 output/licenceGenerator -#./output/licenceGenerator -cid=9f544930303030300000000b47015423 -csd=400e00325b5900003a0d7f800a40008d -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV +#./output/licenceGenerator -cid=9f5449534443495461457815de0164a9 -csd=400e00325b5900003be77f800a400043 -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV cd output -./licenceGenerator -cid=9f544930303030300000000b47015423 -csd=400e00325b5900003a0d7f800a40008d -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV \ No newline at end of file +./licenceGenerator -cid=9f5449534443495461457815de0164a9 -csd=400e00325b5900003be77f800a400043 -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV \ No newline at end of file diff --git a/docker/startok.sh b/docker/startok.sh new file mode 100644 index 0000000..4c6b39e --- /dev/null +++ b/docker/startok.sh @@ -0,0 +1,7 @@ +#!/bin/bash +chmod 777 output/licenceGeneratorok + +#./output/licenceGeneratorok -cid=9f5449534443495461457815de0164a9 -csd=400e00325b5900003be77f800a400043 -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV + +cd output +./licenceGeneratorok -cid=9f5449534443495461457815de0164a9 -csd=400e00325b5900003be77f800a400043 -outputType=file -configFileName=licData.xml -licenceFileName=ezlic_eovosv0_vaxvcpalxjx.lic -licenceVersion=1 -licenceType=EOV_OSV \ No newline at end of file diff --git a/include/SDCard.h b/include/SDCard.h new file mode 100644 index 0000000..9ad1918 --- /dev/null +++ b/include/SDCard.h @@ -0,0 +1,71 @@ +#ifndef SDCARD_H_ +#define SDCARD_H_ + +#define CID_LENGTH 32 +#define CSD_LENGTH 32 + +using namespace std; + +typedef uint32_t DWORD; +typedef uint16_t WORD; +typedef uint8_t BYTE; +typedef uint32_t UDINT; +typedef uint32_t DATE; +typedef uint8_t USINT; +typedef int32_t DINT; +typedef uint16_t UINT; +typedef int16_t INT; + +const BYTE cnibblescount = 32; + +const string cidFilePath = ""; + +class SDCard +{ + + + + struct SDCardData + { + uint8_t isCorrectLoad = 0; // SD karta je korektne nactena //bool vs byte ? + uint8_t CID_nibble[32] = {0}; // surova data CID ze souboru + uint8_t CID[16] = {0}; // prekodovane CID informace + uint8_t manufacturerID = 0; // ID vyrobce 1B -> Byte 15 + char oemID[2] = {}; // ID aplikace/oem 2B -> Byte 13-14 // oemID: !!STRING(3); + char name[5] = {}; // jmeno produktu 5B -> Byte 8-12 !!STRING(6); + uint8_t productRevision_hw = 0; + uint8_t productRevision_sw = 0; + float productRevision = 0; // revize produktu 1B [bcd sh] -> Byte 7, bity 0-3 = revize HW, bity 4-7 = revize SW + uint32_t serialNumber = 0; // seriove cislo karty 4B -> Byte 3-6 + uint16_t manufacturerDate_year = 0; + uint8_t manufacturerDate_month = 0; + char manufacturerDate[10] = {}; //: STRING(10); // datum vyroby 2B [bcd -yym] -> Byte 1-2, bity 0-3 = mesic, bity 4-11 = posledni cislice roku or roku 2000, bity 12-15 nepouzito + uint8_t CRCOK = 0; // CRC 1B -> Byte 0, bity 1-7, bit 0 je vzdy = 1 + uint8_t CSD_nibble[32] = {}; //: ARRAY [0..31] OF BYTE; // surova data CSD ze souboru + uint8_t CSD[16] = {}; //: ARRAY [0..15] OF BYTE; // prekodovane CSD informace + uint32_t cardSize = 0; //: UDINT; // velikost SD karty + uint8_t cardGSize = 0; // prepocitana velikost na GB + }; + +bool readSDCard(); +bool getCIDFromFile(); +bool getCSDFromFile(); + +public: + + SDCardData cardData; + bool isLoaded = false; + char cid[32] = {}; + char csd[32] = {}; + string filePath = ""; + string cidString = ""; //pro předání pro starý generátor + string csdString = ""; //pro předání pro starý generátor + + SDCard(); + SDCard(string cid, string csd); + SDCard(const string filesPath); + + +}; + +#endif \ No newline at end of file diff --git a/include/licenceCommon.h b/include/licenceCommon.h new file mode 100644 index 0000000..65d74f9 --- /dev/null +++ b/include/licenceCommon.h @@ -0,0 +1,194 @@ +#ifndef LICENCE_COMMON_H_ +#define LICENCE_COMMON_H_ + +#include +#include +#include "pugixml.hpp" + +using namespace std; + +#define XML_VERSION 1 +#define SOFTWARE_VERSION 1 +#define SUCCES 0; + +const int cidSize = 32; +const int csdSize = 32; +const int generatorVersion = 1; + + + +enum class GeneralError +{ + GeneralError = 1, + FileOpenError = 2, + FileReadError = 3, + FileWriteError = 4, + ELCNotImplemented = 5, + LicenceTypeNotImplemented = 6, + CompatibilityTypeNotImplemented = 7, + ELCMismatch = 8, + CRCMismatch = 9 +}; + +// map mapGeneralErrors = { +// // 1,"test" +// // {CommonError::GeneralError, "Obecná chyba."}, +// // {CommonError::FileReadError, "Chyba čtení souboru."}, +// // {CommonError::FileReadError, "Chyba zápisu souboru."}, +// // {CommonError::ELCNotImplemented, "ELC není implementováno."}, +// // {CommonError::LicenceTypeNotImplemented, "Typ licence není implementován"} +// }; + +enum class ELCType +{ + ELC1 = 1, + ELC2 = 2, + ELC3 = 3 +}; +enum class ELCSubType +{ + DEFAULT = 1 +}; // subtype = dataVersion +enum class LicenceType +{ + EOS_EOV, + DDTS, + DRT +}; // +enum class HeaderType +{ + DEFAULT = 0 +}; ////subtype = version + +enum class EncryptionType +{ + CID_AES256 = 10, + FIX_AES256 = 20 +}; +enum class BinaryType +{ + FILE = 1, + BASE64 = 2 +}; +enum class PlcType +{ + WAGO = 1, + TECO = 2 +}; +enum class FileNameGenerationType +{ + DEFAULT = 1 +}; + +struct Mapping +{ + std::map licMapTypes = {{"EOV_OSV", LicenceType::EOS_EOV}, {"DDTS", LicenceType::DDTS}, {"DRT", LicenceType::DRT}}; + std::map licMapEncryption = {{"CID_AES256", EncryptionType::CID_AES256}, {"FIX_AES256", EncryptionType::FIX_AES256}}; + std::map licMapPlcType = {{"WAGO", PlcType::WAGO}, {"TECO", PlcType::TECO}}; +}; + +struct ErrorMessage +{ + int code = 0; + string message = ""; +}; + +struct LicenceIdentification +{ + ELCType licElcType = ELCType::ELC2; + LicenceType licLicenceType; + string licTypeName = ""; + PlcType licPlcType; + + uint8_t licenceVersion = 1; // verze licence, určitě kodování, pojmenování souborů + uint8_t licenceIndex = 0; + uint8_t revision; + uint8_t licCompatibility = 1; // identikator hlavního ELC + + uint16_t licItemsCount = 0; +}; + +struct LicData +{ + string station = ""; + string distributor = ""; + string licenceName = ""; + string projectDescription = ""; + string cid = ""; // CID z SD karty + string csd = ""; // CSD z SD karty + string uid = ""; // jedinečný identifikátor z jiného systému + pugi::xml_document *doc; +}; + +struct LicenceItem11 +{ + int protocolId = -1; + int dataPointsCount = 0; +}; + +struct LicenceItem21 +{ + int protocolId = -1; + int dataPointsCount = 0; +}; + +struct LicenceItem31 +{ + int protocolId = -1; + int dataPointsCount = 0; +}; + +struct LicenceInfo11 + { + int reqDataPointsCount = 0; + map licences = {}; + }; + + struct LicenceInfo21 + { + int reqDataPointsCount = 0; + map licences = {}; + }; + + struct LicenceInfo31 + { + int reqDataPointsCount = 0; + map licences = {}; + }; + + struct LicenceInfoGeneral + { + int reqDataPointsCount = 0; + map licences = {}; + }; + +class LicenceException : public std::exception +{ +public: + // Constructor with int and string parameters + LicenceException(int errorCode, const std::string &errorMessage) + : errorCode_(errorCode), errorMessage_(errorMessage) {} + + // Override the what() function to provide a description of the exception + const char *what() const noexcept override + { + return errorMessage_.c_str(); + } + + // Getter functions for the exception members + int getErrorCode() const + { + return errorCode_; + } + + const std::string &getErrorMessage() const + { + return errorMessage_; + } + +private: + int errorCode_; + std::string errorMessage_; +}; + +#endif diff --git a/include/licenceELC11.h b/include/licenceELC11.h new file mode 100644 index 0000000..0006003 --- /dev/null +++ b/include/licenceELC11.h @@ -0,0 +1,283 @@ +#ifndef PLC_LICENCE11_H +#define PLC_LICENCE11_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "licenceCommon.h" +#include "SDCard.h" + +using namespace std; + +#define MAX_LICENCE_COUNT 100 + +enum InputLicenceType +{ + EOSEOV = 1 +}; + +enum BinaryGenerationType +{ + Base64Cout = 1, + File = 2 +}; + +enum PlcLicenceType +{ + LicenceOther = 0, + LicenceEov = 1 +}; +enum LidIdType +{ + Ddts = 1, + EovOsv = 2 +}; +enum PrefixType +{ + ELC1 = 1 +}; + +typedef uint32_t DWORD; +typedef uint16_t WORD; +typedef uint8_t BYTE; +typedef uint32_t UDINT; +typedef uint32_t DATE; +typedef uint8_t USINT; +typedef int32_t DINT; +typedef uint16_t UINT; +typedef int16_t INT; + +/// @brief identifikace licence +typedef struct LicenceIdent +{ + WORD licPrefixType = 0; // WORD; typ licencniho souboru - pro kazdy prefig je jiny typ souboru a jiny zpusob zpracovani dat [sifrovani, podpis, komprese, ...] + WORD licHeaderType = 0; //: WORD; typ hlavicky kriptovane casti licencniho souboru + WORD licDataType = 0; //: WORD; typ licence - pro kazdou hlavicku jsou samostatne typy licenci - mohou byt i shodne s typem jine hlavicky + WORD licSubType = 0; //: WORD; slouceny typ hlavicku a typ licence => typ hlavicky * 256 + typ licence + WORD licIDType = 0; //: WORD; id aplikace, pro kterou je licence urcena => 1 = ddts, 2 = eov-osv + BYTE licPostfix = 0; //: BYTE; rozliseni licence pro stejny typ - napr. pokud mam 2x SW pro DRT na 2 nezavisle ED +} LicenceIdent; + +/// @brief struktura pro přípravu dat na generování +typedef struct LicenceSourceData +{ + + BYTE startGen; // na nabeznou hranu se vygeneruje licence + BYTE loadSD; //: BOOL; na nabeznou hranu se nacte SD karta + // zadavane hodnoty + BYTE licType_id; // vybrany typ licence + char licDescription1[40] = {}; //: STRING(39); jmeno stanice + char licDescription2[20] = {}; //: STRING(19); jmeno rozvadece + BYTE licPostfix; // rozliseni licence pro stejny typ - napr. pokud mam 2x SW pro DRT na 2 nezavisle ED + BYTE enInit; //: BOOL; inicializace (promazani) adresare pro licence + // interne generovane hodnoty + WORD licType; //: WORD; hlavicka licence + BYTE licIdOk; //: BOOL; korektne zvoleny typ licence + string licPostfixIdent; //[2]; //: STRING(2); vygenerovany postfix z cisla pro rozliseni postfixu v souborech a textech +} LicenceSourceData; + +/// @brief struktura obsahující dodatečné informace k licenci +typedef struct PlcData +{ + string plcType = ""; + string licenceType = ""; // typ + string licenceVersion = "1"; + string licenceName = ""; // název + string station = ""; // stanice + string distributor = ""; // rozvadec +} PlcData; + +/* +MID (Manufacturer ID): 8 bits - Identifies the manufacturer of the SD card. +OID (OEM/Application ID): 16 bits - Identifies the OEM and application-specific information. +PNM (Product Name): 40 bits - A string representing the product name of the SD card. +PRV (Product Revision): 8 bits - The product revision/version. +PSN (Product Serial Number): 32 bits - A unique serial number assigned to the SD card during manufacturing. +MDT (Manufacturing Date): 12 bits - Represents the manufacturing date of the SD card. +CRC (CRC7 Checksum): 7 bits - A cyclic redundancy check for error detection. +unused: 4 bits - Reserved for future use. +*/ + +/// @brief struktura pro načtení CIS a CSD dat +typedef struct SDData +{ + BYTE isCorrectLoad = 0; // SD karta je korektne nactena //bool vs byte ? + BYTE CID_nibble[32] = {0}; // surova data CID ze souboru + BYTE CID[16] = {0}; // prekodovane CID informace + BYTE manufacturerID = 0; // ID vyrobce 1B -> Byte 15 + char oemID[2] = {}; // ID aplikace/oem 2B -> Byte 13-14 // oemID: !!STRING(3); + char name[5] = {}; // jmeno produktu 5B -> Byte 8-12 !!STRING(6); + BYTE productRevision_hw = 0; + BYTE productRevision_sw = 0; + float productRevision = 0; // revize produktu 1B [bcd sh] -> Byte 7, bity 0-3 = revize HW, bity 4-7 = revize SW + DWORD serialNumber = 0; // seriove cislo karty 4B -> Byte 3-6 + WORD manufacturerDate_year = 0; + BYTE manufacturerDate_month = 0; + char manufacturerDate[10] = {}; //: STRING(10); // datum vyroby 2B [bcd -yym] -> Byte 1-2, bity 0-3 = mesic, bity 4-11 = posledni cislice roku or roku 2000, bity 12-15 nepouzito + BYTE CRCOK = 0; // CRC 1B -> Byte 0, bity 1-7, bit 0 je vzdy = 1 + BYTE CSD_nibble[32] = {}; //: ARRAY [0..31] OF BYTE; // surova data CSD ze souboru + BYTE CSD[16] = {}; //: ARRAY [0..15] OF BYTE; // prekodovane CSD informace + UDINT cardSize = 0; //: UDINT; // velikost SD karty + BYTE cardGSize = 0; // prepocitana velikost na GB +} CidData; + +// nekodovana cast licence + +/// @brief nekryptovaná hlavička licence +typedef struct LicenceDataMainHeaderELC +{ + BYTE licType = 0; + ; // typ licence => duplicitni polozka s hlavickou kodovane casti licence - pouze pro ucely dekodovani dat + BYTE dummy1 = 0; + WORD licSubType = 0; // horni byte = typ hlavicky kodovane casti, spodni byte = typ dat polozkove casti => duplicitni casti s id a hlavickou kodovane casti - pouze pro ucely dekodovani + char description[80] = {}; // viditelny popis licincniho souboru + UDINT sizeData = 0; // velikost kodovane casti licence v Bytech +} LicenceDataMainHeaderELC; + +// hlavní struktura licence +typedef struct LicenceDataMainELC +{ + // prefix MUSI zustat jako prvni prvek struktury a MUSI byt typu DWORD + DWORD prefix = 0; // urcuje strukturu dat citelne casti licencniho souboru [teto struktury] + zpusob sifrovani, dig, podpis, kompresi... dat + LicenceDataMainHeaderELC licHeader; // nekodovana cast licence +} LicenceDataMain; + +// polozkova cast licence verze 1.0 +typedef struct LicenceDataItem +{ + WORD protoId = 0; // id protokolu pro ktery je licence + WORD licCount = 0; // pocet datovych bodu licence + DWORD data1 = 0; // doplnkove nahodne cislo, slouzi pro overeni licence v runtime +} LicenceDataItem; + +// identifikace kodovane casti licence - !!! MUSI yustat pro vsechny verze STEJNA !!! +typedef struct LicenceDataId +{ + WORD version = 0; // verze hlavicky + WORD rez = 0; + UDINT cardSize = 0; +} LicenceDataId; + +typedef struct LicenceDataHeader +{ + BYTE licType = 0; // typ licence => 0...neznamy (chyba), 1...DDTS, 2...EOV-OSV + BYTE licReserve = 0; // rezerva + WORD licVersion = 0; //: WORD; verze polozkove casti licence + DATE licDate = 0; // datum vygenerovani licence + char licDescription1[40] = {}; // licDescription1: STRING(39); stanice, pro kterou byla licence generovana + char licDescription2[20] = {}; // STRING(19); rozvadec, pro ktery byla licence generovana + USINT licCount = 0; // aktivni pocet dat polozkove casti licence + BYTE licDummy = 0; // rezerva + WORD licReservew = 0; // rezerva +} LicenceDataHeader; + +// kodovana cast licence verze 1.1 s polozkovou casi licence verze 1.0 +typedef struct LicenceData +{ + LicenceDataId id; // id !!! MUSI zustat na PRVNIM miste struktury + LicenceDataHeader header; + LicenceDataItem items[MAX_LICENCE_COUNT]; // polozkova cast licence + WORD dummy = 0; // pro zarovnani struktur - jinak nebude fungovat vypocet a kontrola CRC !!! + WORD crc = 0; // kontrolni kod - !!! MUSI zustat na konci struktury +} LicenceData; + +typedef struct LicenceRetData +{ + BYTE retCode = 0; // navratovy kod funkce pro nacteni SD + DINT subCode = 0; // doplnkova informace chyby + std::string text = ""; // textovy popis navratove hodnoty + bool isDone = false; // operace korektne dokoncena +} LicenceRetData; + +typedef struct CryptData +{ + bool initDone = false; + DWORD cryptDataAddress = 0; // adresa na data, ktera se maji cryptovat + UINT cryptDataSize = 0; // velikostdat, ktera semaji cryptovat + BYTE aesInitVector[15] = {0}; //] : ARRAY [0..14] OF BYTE;// AES 128 bit IV + BYTE aesKey[32] = {0}; // : ARRAY [0..31] OF BYTE; // AES 256 bit key + DINT aesRetVal = 0; // navratova hodnota AES + DWORD retDataAddress = 0; // adresa na ulozeni cryptovana dat + UINT retDataSize = 0; // velikost cryptovanych dat + LicenceData *licenseData; +} CryptData; + +/// @brief licence class +class LicenceELC11 +{ + + enum class Error11 + { + SDCardReadError = 50, + LicenceReadError = 51, + LicenceSizeMismatch = 52, + LicenceSizeCardMismatch = 53, + LicenceMismatch = 54, + ItemsCountMismatch = 61 + }; + + // unordered_map map11Errors = { + // {Error11::SDCardReadError, "Nepodařilo se načíst SD kartu."}, + // {Error11::ItemsCountMismatch, "Nesouhlasí počet položek licence."} + // }; + + private: + SDCard sdCard; + const string cid_cdsPath = ""; //"c:\\_projects\\LicenceGenerator\\output\\"; ///sys/block/mmcblk0/device/ + const string licenceFilePath = ""; //"c:\\_projects\\LicenceGenerator\\output\\"; + string cidString = ""; + char cid[32] = {}; + string csdString = ""; + char csd[32] = {}; // CSD + string stationName; // name of station + string distributor; // name of switch + const char *dataFileName; // name of xml containing data (if not taken from commandline) + WORD licType = 2; // type of licence + BinaryGenerationType binaryGeneration = BinaryGenerationType::Base64Cout; //typ generování binárního souboru + + string dataLicenceType = ""; //type of licence from xmlFile; + string dataLicenceVersion = ""; //version type of licence from xmlFile; + string dataCryptoVersion = ""; //version of crypting from xmlFile + string dataGenerationType = ""; //version of dataGeneration from xmlFile + string dataLicenceDataFileName = ""; //name of licence file to read + + //InputLicenceType dataLicenceType = InputLicenceType::EOSEOV; + + CryptData cryptData; // structure for encryp + CidData sdData; // data loaded from SD card + + void processConfigFile(string &dataFileName); //process data from config file + void getSDData(); // reads SD card + string getLicenceName(BYTE licPostfix); // get proper licencename + string getLicenceName(); + void initCrypto(); + bool createEosEovLicence(); // create licence for EOV_OSV + bool readEosEovLicence(string dataFileName); + LicenceIdentification lIdentification; + +public: + + string operationErrors = ""; + ErrorMessage errorMessage; + + LicenceELC11(); + ~LicenceELC11(); + + LicenceELC11(string cid, string csd, string binaryType, string dataFileName); + LicenceELC11(LicenceIdentification & licIdentification); + + bool createLicence(); // creates licence + bool readLicence(string dataFileName, string licenceType, string licenceVersion, string cidArg, string csdArg); + bool readLicence(LicenceInfoGeneral * licences); + + +}; + +#endif diff --git a/include/licenceELC21.h b/include/licenceELC21.h new file mode 100644 index 0000000..528ab93 --- /dev/null +++ b/include/licenceELC21.h @@ -0,0 +1,125 @@ +#ifndef PLC_LICENCE21_H +#define PLC_LICENCE21_H + +#include +#include +#include +#include +#include "utils.h" +#include "licenceCommon.h" +#include "SDCard.h" + +using namespace std; + +class LicenceELC21 +{ + const string cid_cdsPath = ""; //"c:\\_projects\\LicenceGenerator\\output\\"; ///sys/block/mmcblk0/device/ + const string licenceFilePath = ""; //"c:\\_projects\\LicenceGenerator\\output\\"; + + enum class Error21 + { + SDCardReadError = 50, + LicenceReadError = 51, + LicenceSizeMismatch = 52, + LicenceSizeCardMismatch = 53, + LicenceMismatch = 54, + ItemsCountMismatch = 61 + }; + + unordered_map map21Errors = { + {Error21::SDCardReadError, "Nepodařilo se načíst SD kartu."}, + {Error21::ItemsCountMismatch, "Nesouhlasí počet položek licence."}, + {Error21::LicenceSizeMismatch, "Nesouhlasí velikost souboru licence."}, + {Error21::LicenceSizeCardMismatch, "Nesouhlasí velikost SD karty."}, + {Error21::LicenceMismatch, "Nesouhlasí licence."}, + {Error21::ItemsCountMismatch, "Nesouhlasí počet položek licence."}, + }; + + + struct LicenceId + { + char licIdent[5] = { 'E', 'L', 'C', '0','_'}; + }; + + //struct __attribute__((__packed__)) LicencePublicHeader + + struct LicenceIdentDataHeader + { + BYTE licenceType = 0; //EOSEOV, DRT ... + BYTE licenceTypeVersion = 1; //verze licence, urcuje nuance sifrování a pojmenování souborů + BYTE licenceIndex = 0; //puvodní post fix, identifikátor pro více licencí + BYTE compatibilityVersion = 1; //udava verzi komplet PrivateContent + BYTE licItemCount = 0; //počet licenčních bodů + WORD publicHeaderLength = 0; //délka veřejné hlavičy + WORD cardSize = 0; //velikost SD karty + DWORD serialNumber = 0;//seriove cislo karty + }; + + /// + struct licDataItem + { + WORD protoId = 0; // id protokolu pro ktery je licence + WORD licCount = 0; // pocet datovych bodu licence + char dummy[64] = {}; + }; + + struct PublicHeader + { + string version = ""; + string projectDescription = ""; + string date = ""; + string licenceType = ""; + int crc = 0; + }; + + struct PrivateContent //privátní šifrovaná část + { + LicenceIdentDataHeader licenceIdentHeader; + vector dataItems; + WORD crc = 0; + }; + + struct LicenceBody + { + LicenceId licId; + LicenceIdentDataHeader licenceIdentHeader; + string publicHeader = ""; //JSON + PrivateContent privateContent; + }; + + private: + int licItemCount = 0; + LicenceBody licBody; + LicenceIdentification lIdentification; + LicData lData; + SDCard sdCard; + void getHeader(); + string getVersion(int middleVersion); + void getLicenceItems(); + bool processInputConfiguration(); + vector cryptPrivateContent(const std::vector& content); + vector decryptPrivateContent(const std::vector& content); + void initVector(BYTE (&iVector)[], BYTE (&key)[]); + string getLicenceName(); + + + public: + + ErrorMessage errorMessage; + LicenceInfo21 licenceInfo; + + LicenceELC21(); + ~LicenceELC21(); + LicenceELC21(LicenceIdentification & licIdentification, LicData & icData); + LicenceELC21(LicenceIdentification & licIdentification); + LicenceELC21(LicData & icData); + bool createLicence(); + bool readLicence(LicenceInfoGeneral * licences); + int getDataPointsCount(int protocolId); + bool getLicenceInfo(int protocolId, void * ptr); + bool getLicenceItemInfo(int protocolId, void *returnItemStructure); + + +}; + +#endif diff --git a/include/licenceELC31.h b/include/licenceELC31.h new file mode 100644 index 0000000..10b53b6 --- /dev/null +++ b/include/licenceELC31.h @@ -0,0 +1,29 @@ +#ifndef PLC_LICENCE31_H +#define PLC_LICENCE31_H + +#include +#include +#include +#include "utils.h" +#include "licenceCommon.h" + +using namespace std; + +class LicenceELC31 +{ + LicData lData; + bool processInputConfiguration(); + + public: + LicenceELC31(); + ~LicenceELC31(); + LicenceELC31(LicData & licData); + LicenceELC31(LicenceIdentification & licIdentification); + void createLicence(); + void readLicence(); + int getDataPointsCount(int protocolId); + bool getLicenceInfo(int protocolId, void * ptr); +}; + +#endif + diff --git a/include/licenceGenerator.h b/include/licenceGenerator.h new file mode 100644 index 0000000..cc9d05b --- /dev/null +++ b/include/licenceGenerator.h @@ -0,0 +1,84 @@ +#ifndef LICENCE_GENERATOR_H_ +#define LICENCE_GENERATOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "licenceCommon.h" +#include "licenceELC11.h" +#include "licenceELC21.h" +#include "licenceELC31.h" + +using namespace std; + + struct InitStructure + { + int elcType = 0; + int licenceType = 0; + int licenceVersion = 0; + int licenceIndex = 0; + int compatibility = 0; + string licenceFilePath = ""; + }; + +class LicenceGenerator +{ + + + +public: + int elcSwitchType; + string operationErrors = ""; + pugi::xml_document doc; + bool argumentsCorrect = false; + ErrorMessage error; + LicenceELC11 *licence11; + LicenceELC21 *licence21; + LicenceELC31 *licence31; + + LicenceGenerator(); + ~LicenceGenerator(); + LicenceGenerator(map &arguments); + // LicenceGenerator(string cid, string csd, string dataFileName, string binaryType); + LicenceGenerator(string uid, string cid, string csd, string dataFileName); + LicenceGenerator(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility); + bool init(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility); + bool init(InitStructure &initStructure); + bool initread(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility); + bool initread(InitStructure &initStructure); + + void createLicenceFile(); + void readLicenceFile(); + + int getDataPointsCount(int protocolId); + bool getLicenceInfo(int protocolId, void *returnStructure); + bool getLicenceItemInfo(int protocolId, void *returnItemStructure); + + LicenceInfoGeneral licenceInfo; + +private: + LicenceIdentification licIdentification; + LicData licData; + string configFileName = ""; + + void *licence = nullptr; + + bool processInputConfiguration(); + + void createLicenceELC1(); + void createLicenceELC2(); + void createLicenceELC3(); + + void readLicenceELC1(); + void readLicenceELC2(); + void readLicenceELC3(); +}; + +#endif \ No newline at end of file diff --git a/include/plcLicence.h b/include/plcLicence.h index 11fa5ec..ffb625f 100644 --- a/include/plcLicence.h +++ b/include/plcLicence.h @@ -18,7 +18,7 @@ using namespace std; enum InputLicenceType { - EOSEOV + EOSEOV = 1 }; enum BinaryGenerationType @@ -227,6 +227,7 @@ private: string dataCryptoVersion = ""; //version of crypting from xmlFile string dataGenerationType = ""; //version of dataGeneration from xmlFile string dataLicenceDataFileName = ""; //name of licence file to read + //InputLicenceType dataLicenceType = InputLicenceType::EOSEOV; CryptData cryptData; // structure for encryp CidData sdData; // data loaded from SD card diff --git a/include/utils.h b/include/utils.h index c20be33..cd557ab 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,11 +1,17 @@ +#define LINUX 1 + +#ifndef UTILS_H_ +#define UTILS_H_ + #include +#include +#include #include #include #include -#include +#include #include - -#define LINUX 1 +#include #define PEM_BUFSIZE_TEXT 1024 #define BitVal(data, y) ((data >> y) & 1) /** Return Data.Y value **/ @@ -16,21 +22,11 @@ #define PEM_BUFSIZE_TEXT 1024 -#ifndef BYTE + typedef uint8_t BYTE; -#endif - -#ifndef WORD typedef uint16_t WORD; -#endif - -#ifndef DWORD typedef uint32_t DWORD; -#endif - -#ifndef DATE typedef uint32_t DATE; -#endif using namespace std; @@ -56,19 +52,37 @@ DateAndTime getCurrentDateTimeAsCODESYSDateTime(); uint16_t convertToCODESYSDate(int day, int month, int year); uint16_t convertToCODESYSTime(int hour, int minute); DATE getLicDate(); -int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext); +string getDate(); +int encrypt(const unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext); bool CompareFiles(const char *fileName, const char *fileName1); unsigned short crc16(const unsigned char* data_p, unsigned char length); -int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext); +int decrypt(const unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext); string convertToString(char* a, int size); std::string base64_encode_ai(const std::string &input); std::string base64_decode_ai(const std::string &encoded); -map getArguments(int argc, char *argv[]); -map mapArguments(int argc, char *argv[]); +unordered_map getArguments(int argc, char *argv[]); +unordered_map mapArguments(int argc, char *argv[]); char* getCharArray(string source); void getCharsFromString1(string source, char *charArray); void getCharsFromString(string& source, char *charArray, int length); string getCompletePath(string fileName); +char* getFileContent(string fileName); +void appendStringToVector(const std::string& str, std::vector& charVector); +void coutVector (std::vector& charVector); +uint16_t calculateCRC16(std::vector& charVector); +uint32_t bytesToDword(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4); +uint32_t bytesToWord(uint8_t byte1, uint8_t byte2); +vector joinVectors(const std::vector& vector1, const std::vector& vector2); +string readFileToString(const std::string& filename, std::size_t sizeS); +bool readFile(string fileName, vector &output); + +#endif + + + + + + diff --git a/output/___vzor_ezlic_eovosv0_wuygadtvxji.lic b/output/___vzor_ezlic_eovosv0_wuygadtvxji.lic new file mode 100644 index 0000000..0f5bb55 Binary files /dev/null and b/output/___vzor_ezlic_eovosv0_wuygadtvxji.lic differ diff --git a/output/cid b/output/cid new file mode 100644 index 0000000..32a9336 --- /dev/null +++ b/output/cid @@ -0,0 +1,5 @@ +9f5449534443495461457815de0164a9 +6   . x4   .. nt$6 & manfid 6 +  cid "6  fwrev 6 Jm  csd ,6 gEd$ +subsystem 46 % +driver (6 -  ocr -6 ? power *6 4L  type 6 1M  date #6 rTP hwrev )6 nyR  dsr '6 ` serial 6 NNm erase_size 6 6m block 6 n uevent 6 o  ssr 6 q  scr &6 &y oemid !6 y ( preferred_erase_size %6   name \ No newline at end of file diff --git a/output/csd b/output/csd new file mode 100644 index 0000000..50b4809 --- /dev/null +++ b/output/csd @@ -0,0 +1,2 @@ +400e00325b5900003a0d7f800a40008d + \ No newline at end of file diff --git a/output/ezlic_eovosv0_jjfgcgtvxtb.lic b/output/ezlic_eovosv0_jjfgcgtvxtb.lic new file mode 100644 index 0000000..5f08e87 Binary files /dev/null and b/output/ezlic_eovosv0_jjfgcgtvxtb.lic differ diff --git a/output/ezlic_eovosv0_vaxvcpalxjx_back.lic b/output/ezlic_eovosv0_vaxvcpalxjx_back.lic new file mode 100644 index 0000000..b7f4dd1 Binary files /dev/null and b/output/ezlic_eovosv0_vaxvcpalxjx_back.lic differ diff --git a/output/ezlic_eovosv0_wuygadtvxji.lic b/output/ezlic_eovosv0_wuygadtvxji.lic new file mode 100644 index 0000000..f1f1f01 Binary files /dev/null and b/output/ezlic_eovosv0_wuygadtvxji.lic differ diff --git a/output/licData.xml b/output/licData.xml index 7cdac51..efbf708 100644 --- a/output/licData.xml +++ b/output/licData.xml @@ -1,8 +1,32 @@ - - WAGO - EOV_OSV - Licence pro EOV_OSV - ceskatrebova - RO1 - \ No newline at end of file + +EOV_OSV +WAGO +Licence pro EOV_OSV +start.cz +wago +Projekt XXX stanice YYY + + + Položka licence 1 + 666 + 100 + + + Položka licence 2 + 777 + 200 + + + Položka licence 3 + 888 + 300 + + + Položka licence 3 + 999 + 1600 + + + + \ No newline at end of file diff --git a/output/licDataOld.xml b/output/licDataOld.xml new file mode 100644 index 0000000..824dbb8 --- /dev/null +++ b/output/licDataOld.xml @@ -0,0 +1,8 @@ + + + WAGO + EOV_OSV + Licence pro EOV_OSV + start.cz + wago + \ No newline at end of file diff --git a/output/licenceGenerator b/output/licenceGenerator new file mode 100644 index 0000000..bccbdd4 Binary files /dev/null and b/output/licenceGenerator differ diff --git a/output/licenceGeneratorok b/output/licenceGeneratorok new file mode 100644 index 0000000..3ee0513 Binary files /dev/null and b/output/licenceGeneratorok differ diff --git a/src/CreateLicence.cpp b/src/CreateLicence.cpp index a5efe49..8253053 100644 --- a/src/CreateLicence.cpp +++ b/src/CreateLicence.cpp @@ -3,6 +3,7 @@ #include "utils.h" #include + #define FILEBUFFER 300 #define TWO_HOURSE_SECONDS 7200 @@ -11,10 +12,10 @@ /// @param argv parametry pro generování licence /// 1-cid, 2-csd, 3-stanice 4-rozvadec 5-typ licence /// @return -int main(int argc, char *argv[]) +int main5(int argc, char *argv[]) { - map arguments = getArguments(argc, argv); + unordered_map arguments = getArguments(argc, argv); PlcLicence plcWriteLicence = PlcLicence(arguments["-cid"], arguments["-csd"], arguments["-outputType"], arguments["-configFileName"]); if (plcWriteLicence.CreateLicence() == false) @@ -22,16 +23,7 @@ int main(int argc, char *argv[]) cerr << "Licence creation failed"; } - /* READ LICENCE CODE - // arguments: -cid, -csd, -licenceFi leName, -licenceType=EOV_OSV, -licenceVersion - PlcLicence plcLicence = PlcLicence(); - if (plcLicence.ReadLicence(argumentsString["-licenceFileName"], argumentsString["-licenceType"], argumentsString["-licenceVersion"], argumentsString["-cid"], argumentsString["-csd"]) == false) - { - cout << "Reading error: " << plcLicence.operationErrors << endl; - } - - */ return EXIT_SUCCESS; } diff --git a/src/LicenceELC11.cpp b/src/LicenceELC11.cpp new file mode 100644 index 0000000..8364a21 --- /dev/null +++ b/src/LicenceELC11.cpp @@ -0,0 +1,800 @@ +#include +#include +#include +#include "licenceELC11.h" +#include "utils.h" +#include "pugixml.hpp" + +#define CID_LENGTH 32 +#define CSD_LENGTH 32 + +const std::string cEzLic_p78ou3_sdinfofilepath = "/sys/block/mmcblk0/device/"; +const std::string cEzLic_p78ou3_licencfilepath_f21 = "/mnt/mmc/ez_sys/licence/"; +const std::string cEzLic_p78ou3_licencfilepath_f17 = "/home/admin/ez/licence/"; +const string cEzLic_p78ou3_licencfilepath_f10 = "/root/ez_sys/licence/"; +const WORD maxDataToFile = 10000; // velikost datoveho bufferu pro ulozeni dat licence + +const BYTE licMaxCount = 100; +const DWORD cEzLic_p78ou3_CheckLicNumber_ERR = 0xFFFFFFFF; // 16#FFFFFFFF; // chybna identifikace licence +const DWORD cEzLic_p78ou3_CheckLicNumber_EOV1 = 3781234965; // cislo pro overeni licence EOV, OSV verze 1 +const BYTE cEzLic_p78ou3_CheckLicNumberId_ERR = 0; // id licence pro neidentifikovanou licenci +const BYTE cEzLic_p78ou3_CheckLicNumberId_EOV1 = 1; // id licence pro EOV, OSV verze 1 +const BYTE cEzLic_p78ou3_MaxCheckLicNumberId = cEzLic_p78ou3_CheckLicNumberId_EOV1; // pocet identifikatoru licenci +const DWORD cEzLic_p78ou3_CheckLicNumber[] = {cEzLic_p78ou3_CheckLicNumber_ERR, cEzLic_p78ou3_CheckLicNumber_EOV1}; +const WORD cEzLic_p78ou3_LicPrefixType_ELC1 = 1; // prefix typ1 = pouze zasifrovani dat +const WORD cEzLic_p78ou3_HeaderType_10 = 10; // hlavicka kriptovane casti verze 1.0 +const WORD cEzLic_p78ou3_DataType_10 = 10; // data licence verze 1.0 +const WORD cEzLic_p78ou3_SubType_10_10 = 0x0A0A; // subtype - verze hlavicky + verze data -> cEzLic_p78ou3_HeaderType_XX * 256 + cEzLic_p78ou3_DataType_XX +// ID aplikace +const WORD cEzLic_p78ou3_IDType_DDTS = 1; // aplikace DDTS +const WORD cEzLic_p78ou3_IDType_EOVOSV = 2; // aplikace EOV-OSV +const WORD cEzLic_p78ou3_IDType_DRT = 3; // aplikace DRT +// std::string cEzLic_p78ou3_IDTypeStrData11[] = {"neznamo", "DDTS", "EOV-OSV", "DRT"}; +const BYTE cnibblescount11 = 32; +std::string cSDMonthStr11[] = {"-", "I.", "II.", "III.", "IV.", "V.", "VI.", "VII.", "VIII.", "IX.", "X.", "XI.", "XII.", "-", "-", "-"}; +BYTE cHexNibble_to_No11[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +const string eoseovLicenceType = "EOV_OSV"; +// enum LicenceType { EovOsv = 1 }; + +LicenceELC11::LicenceELC11() +{ +} + +LicenceELC11::LicenceELC11(LicenceIdentification &licIdentification) +{ + lIdentification = licIdentification; +} + +LicenceELC11::LicenceELC11(string cisArg, string csdArg, string binaryType, string dataFileName) +{ + + for (int i = 0; i < cisArg.length(); i++) + this->cid[i] = cisArg[i]; + for (int i = 0; i < csdArg.length(); i++) + this->csd[i] = csdArg[i]; + + this->stationName = ""; + this->distributor = ""; + this->licType = 2; + + processConfigFile(dataFileName); + + if (binaryType == "base64") + this->binaryGeneration = BinaryGenerationType::Base64Cout; + else + this->binaryGeneration = BinaryGenerationType::File; +} + +/// @brief process config file +/// @param dataFileName +void LicenceELC11::processConfigFile(string &dataFileName) +{ + string fullFile = getCompletePath(dataFileName); + const int fileNameLength = fullFile.length(); + char fileName[fileNameLength] = {}; + getCharsFromString(fullFile, fileName, fileNameLength); + + pugi::xml_document doc; +#ifdef WINDOWS + pugi::xml_parse_result result = doc.load_file("licData.xml"); +#else + pugi::xml_parse_result result = doc.load_file(fileName); +#endif + + if (result) + { + const char *dataRootName = doc.child("data") ? "data" : "licence"; // kompatibilita s verzí, která měla ještě root "data" + + this->stationName = doc.child(dataRootName).child("station").child_value(); + this->distributor = doc.child(dataRootName).child("distributor").child_value(); + this->dataLicenceType = doc.child(dataRootName).child("licenceType").child_value(); + this->dataLicenceVersion = doc.child(dataRootName).child("licenceType").attribute("version").value(); + this->dataGenerationType = this->dataLicenceVersion; + this->dataCryptoVersion = this->dataLicenceVersion; + } + else + { + std::cerr << "Unable to open the config file." << std::endl; + } +} + +/// @brief reads data from CID a CSD +void LicenceELC11::getSDData() +{ + for (int i = 0; i < CID_LENGTH; i++) + this->sdData.CID_nibble[i] = (BYTE)cid[i]; + + for (int i = 0; i < cnibblescount / 2; i++) + { + this->sdData.CID[i] = cHexNibble_to_No11[this->sdData.CID_nibble[2 * i]] << 4 | cHexNibble_to_No11[this->sdData.CID_nibble[2 * i + 1]]; + } + + this->sdData.manufacturerID = this->sdData.CID[0]; + this->sdData.oemID[0] = this->sdData.CID[1]; + this->sdData.oemID[1] = this->sdData.CID[2]; + this->sdData.name[0] = this->sdData.CID[3]; + this->sdData.name[1] = this->sdData.CID[4]; + this->sdData.name[2] = this->sdData.CID[5]; + this->sdData.name[3] = this->sdData.CID[6]; + this->sdData.name[4] = this->sdData.CID[7]; + this->sdData.productRevision_hw = cHexNibble_to_No11[this->sdData.CID[16]]; + this->sdData.productRevision_sw = cHexNibble_to_No11[this->sdData.CID[17]]; + + if (this->sdData.productRevision_sw < 10) + this->sdData.productRevision = (float)this->sdData.productRevision_hw + ((float)this->sdData.productRevision_sw * 0.1); + else + this->sdData.productRevision = (float)this->sdData.productRevision_hw + ((float)this->sdData.productRevision_sw * 0.01); + + this->sdData.serialNumber = this->sdData.CID[9] << 24 | this->sdData.CID[10] << 16 | this->sdData.CID[11] << 8 | this->sdData.CID[12]; + this->sdData.manufacturerDate_year = cHexNibble_to_No11[this->sdData.CID_nibble[27]] * 10 + cHexNibble_to_No11[this->sdData.CID_nibble[28]] + 2000; + this->sdData.manufacturerDate_month = cHexNibble_to_No11[this->sdData.CID_nibble[29]]; + string date = cSDMonthStr11[this->sdData.manufacturerDate_month] + std::to_string(this->sdData.manufacturerDate_year); + + for (int i = 0; i < date.length(); i++) + this->sdData.manufacturerDate[i] = date[i]; + + // CSD + for (int i = 0; i < CSD_LENGTH; i++) + this->sdData.CSD_nibble[i] = (BYTE)csd[i]; + + for (int i = 0; i < cnibblescount / 2; i++) + { + // + this->sdData.CSD[i] = cHexNibble_to_No11[this->sdData.CSD_nibble[2 * i]] << 4 | cHexNibble_to_No11[this->sdData.CSD_nibble[2 * i + 1]]; + } + + if (this->sdData.CSD_nibble[0] == 0x34) + { + this->sdData.cardSize = this->sdData.CSD[7] << 16 | this->sdData.CSD[8] << 8 | this->sdData.CSD[9]; + this->sdData.cardGSize = (this->sdData.cardSize + 1) / 2048; + + if (this->sdData.cardSize > 17200) // TODO result.cardSize + { + } + } + + BYTE sdCrc = 0; + for (int i = 0; i <= 14; i++) + { + BYTE sdChar = this->sdData.CID[i]; + for (int j = 0; j <= 7; j++) + { + sdCrc = sdCrc << 1; + if ((sdChar ^ sdCrc) & 0x80) + sdCrc = sdCrc ^ 0x09; + sdChar = sdChar << 1; + } + sdCrc = sdCrc & 0x7F; + } + this->sdData.CRCOK = ((sdCrc << 1) | 1) == this->sdData.CID[15]; +} + +/// @brief inits keys and vectors for encrypting +void LicenceELC11::initCrypto() +{ + if (this->licType == cEzLic_p78ou3_IDType_EOVOSV) + { + this->cryptData.aesInitVector[0] = this->sdData.CID[10]; + this->cryptData.aesInitVector[1] = this->sdData.CID[12]; + this->cryptData.aesInitVector[2] = this->sdData.CID[11]; + this->cryptData.aesInitVector[3] = this->sdData.CID[9]; + this->cryptData.aesInitVector[4] = this->sdData.CID_nibble[22] - 15; + this->cryptData.aesInitVector[5] = this->sdData.CID_nibble[24] - 15; + this->cryptData.aesInitVector[6] = this->sdData.CID_nibble[25] - 15; + this->cryptData.aesInitVector[7] = this->sdData.CID_nibble[21] - 15; + memcpy(&this->cryptData.aesInitVector[8], &this->cryptData.aesInitVector[0], 8); + + this->cryptData.aesKey[0] = this->sdData.CID[12]; + this->cryptData.aesKey[1] = this->sdData.CID_nibble[23] - 15; + this->cryptData.aesKey[2] = this->sdData.CID_nibble[25] - 15; + this->cryptData.aesKey[3] = this->sdData.CID[11]; + this->cryptData.aesKey[4] = this->sdData.CID[9]; + this->cryptData.aesKey[5] = this->sdData.CID_nibble[21] - 15; + this->cryptData.aesKey[6] = 97 + this->sdData.CID[9] % 25; + this->cryptData.aesKey[7] = this->sdData.CID_nibble[22] - 15; + memcpy(&this->cryptData.aesKey[8], &this->cryptData.aesKey[0], 8); + memcpy(&this->cryptData.aesKey[16], &this->cryptData.aesKey[6], 8); + memcpy(&this->cryptData.aesKey[24], &this->cryptData.aesKey[12], 8); + } +} +string LicenceELC11::getLicenceName() +{ + string result = ""; + char prefixChar = 97; + int licType = (int)lIdentification.licLicenceType; + int lVersion = lIdentification.licenceVersion; + int licIndex = lIdentification.licenceIndex; + + // natvrdo, stará ELC + result = "ezlic_eovosv" + to_string(licIndex) + "_"; + result += prefixChar + (this->sdCard.cardData.CID[12] % 25); + result += prefixChar + (this->sdCard.cardData.CID[10] % 25); + result += prefixChar + (this->sdCard.cardData.CID_nibble[22] % 25); + result += prefixChar + ((this->sdCard.cardData.CID_nibble[23] * 2) % 25); + result += prefixChar + (this->sdCard.cardData.CID_nibble[24] % 25); + result += prefixChar + ((this->sdCard.cardData.CID_nibble[25] * 3) % 25); + result += prefixChar + (this->sdCard.cardData.CID[9] % 25); + result += prefixChar + (this->sdCard.cardData.CID[11] % 25); + result += prefixChar + (this->sdCard.cardData.CID[2] % 25); + result += prefixChar + (this->sdCard.cardData.CID[1] % 25); + result += prefixChar + (this->sdCard.cardData.CID[3] % 25); + result += ".lic"; + + return result; +} + +/// @brief get proper licencename +/// @param licPostfix +/// @return +string LicenceELC11::getLicenceName(BYTE licPostfix) +{ + string result = ""; + char prefixChar = 97; + + if (licPostfix > 9) // chyba + { + } + + if (licType == PlcLicenceType::LicenceOther) + { + result = "ezlic_"; + result += prefixChar + (this->sdData.CID[12] % 25); + result += prefixChar + (this->sdData.CID[10] % 25); + result += prefixChar + (this->sdData.CID_nibble[22] % 25); + result += prefixChar + ((this->sdData.CID_nibble[23] * 2) % 25); + result += prefixChar + (this->sdData.CID_nibble[24] % 25); + result += prefixChar + ((this->sdData.CID_nibble[25] * 3) % 25); + result += prefixChar + (this->sdData.CID[9] % 25); + result += prefixChar + (this->sdData.CID[11] % 25); + result += prefixChar + (this->sdData.CID[2] % 25); + result += prefixChar + (this->sdData.CID[1] % 25); + result += prefixChar + (this->sdData.CID[3] % 25); + result += ".lic"; + } + else + { + result = "ezlic_eovosv" + to_string(licPostfix) + "_"; + result += prefixChar + (this->sdData.CID[12] % 25); + result += prefixChar + (this->sdData.CID[10] % 25); + result += prefixChar + (this->sdData.CID_nibble[22] % 25); + result += prefixChar + ((this->sdData.CID_nibble[23] * 2) % 25); + result += prefixChar + (this->sdData.CID_nibble[24] % 25); + result += prefixChar + ((this->sdData.CID_nibble[25] * 3) % 25); + result += prefixChar + (this->sdData.CID[9] % 25); + result += prefixChar + (this->sdData.CID[11] % 25); + result += prefixChar + (this->sdData.CID[2] % 25); + result += prefixChar + (this->sdData.CID[1] % 25); + result += prefixChar + (this->sdData.CID[3] % 25); + result += ".lic"; + } + return result; +} + +bool LicenceELC11::createLicence() +{ + if (this->dataLicenceType == eoseovLicenceType) + { + return createEosEovLicence(); + } + else + { + return false; + } +} + +bool LicenceELC11::createEosEovLicence() +{ + getSDData(); + initCrypto(); + + // promenne pro praci se soubory a adresari + LicenceDataMainELC dataMainToFileELC1; //: tEz_LicenceDataMainELC1; hlavicka urcena pro zapis do souboru - typ ELC1 + LicenceData dataToFile; // tEz_LicenceData_10_10; // data urcena pro sifrovani a zapis do soubotu - verze => hlavicka: 1.0, data: 1.0 + + // pomocne promenne + BYTE dataWriteToFile[maxDataToFile]; // OF BYTE; data zapisovana do souboru + string licencePostfix; //: STRING; pomocna promenna pro kontrolu postfixu + string mainLicDescription; //: STRING(79); globalni pojmenovani licence v nesifrovane casti licence + + UINT freeDataSize; //: UINT; velikost volne citelnych dat v souboru licenci + UINT cryptDataSize; //: UINT; velikost volne cryptovanych dat v souboru licenci + UINT fullDataSize; //: UINT; celkova velikost souboru licenci + + USINT generation = 2; //: USINT; verze SW pro licence + + PlcData plcData; + plcData.licenceName = "Licence"; + plcData.licenceType = "1"; + plcData.station = stationName; + plcData.distributor = distributor; + + LicenceSourceData licSourceData; + + if (plcData.licenceType == "EOV" || plcData.licenceType == to_string((int)PlcLicenceType::LicenceEov)) + { + licSourceData.licType = 0x1AA2; // 6818 ... proč ? + licSourceData.licPostfix = 0; + getCharsFromString(plcData.station, licSourceData.licDescription1); + getCharsFromString(plcData.station, dataToFile.header.licDescription1); + getCharsFromString(plcData.distributor, licSourceData.licDescription2); + getCharsFromString(plcData.distributor, dataToFile.header.licDescription2); + } + + LicenceIdent licIdent; + licIdent.licPrefixType = licSourceData.licType >> 12; + licIdent.licHeaderType = licSourceData.licType >> 8 & 0x000F; + licIdent.licDataType = licSourceData.licType >> 4 & 0x000F; + licIdent.licSubType = licIdent.licHeaderType << 8 | licIdent.licHeaderType; + licIdent.licIDType = licSourceData.licType & 0x000F; + + if (licSourceData.licPostfix > 9) + licSourceData.licPostfix = 0; + licencePostfix = to_string(licSourceData.licPostfix); + + string licenseFileName = getLicenceName(0); + licSourceData.licPostfixIdent = right(licencePostfix, 1); + + int sizeOfData = sizeof(dataToFile); + + if (licIdent.licHeaderType == cEzLic_p78ou3_HeaderType_10) + { + if (licIdent.licDataType == cEzLic_p78ou3_DataType_10) + { + dataToFile.id.version = 10; + dataToFile.id.cardSize = this->sdData.cardSize; + + switch (licIdent.licIDType) + { + case cEzLic_p78ou3_IDType_DDTS: + mainLicDescription = "ddts "; + break; + case cEzLic_p78ou3_IDType_EOVOSV: + mainLicDescription = "eov, osv "; + break; + default: + mainLicDescription = "neznama app "; + } + + mainLicDescription += licSourceData.licPostfixIdent; + mainLicDescription += " => "; + + dataToFile.header.licVersion = 10; + dataToFile.header.licType = licIdent.licIDType; + dataToFile.header.licDate = getLicDate(); // 1692230400; //getLicDate(); //1692144000;// getLicDate(); + mainLicDescription += dataToFile.header.licDescription1; + mainLicDescription += " ["; + mainLicDescription += dataToFile.header.licDescription2; + mainLicDescription += "]"; + + if (licIdent.licIDType == cEzLic_p78ou3_IDType_EOVOSV) + { + if (generation == 1) // stará verze + { + dataToFile.header.licCount = 1; + dataToFile.items[0].licCount = 65535; + dataToFile.items[0].protoId = cEzLic_p78ou3_CheckLicNumberId_EOV1; + dataToFile.items[0].data1 = cEzLic_p78ou3_CheckLicNumber_EOV1; + } + else + { + dataToFile.header.licCount = 1; + dataToFile.items[1].licCount = 999;//65535; + dataToFile.items[1].protoId = cEzLic_p78ou3_CheckLicNumberId_EOV1; + dataToFile.items[1].data1 = cEzLic_p78ou3_CheckLicNumber_EOV1; + } + } + + unsigned char encrypted[10000] = {}; + const int s = sizeof(dataToFile); + unsigned char byteArray[s] = {}; + memcpy(byteArray, &dataToFile, sizeof(dataToFile)); + + dataToFile.crc = calculateCRC16(byteArray, s - sizeof(dataToFile.crc)); // 47535 | 884:38382 + + memcpy(byteArray, &dataToFile, sizeof(dataToFile)); + + int finalEncryptedLength = encrypt(byteArray, sizeof(dataToFile), this->cryptData.aesKey, this->cryptData.aesInitVector, encrypted); + + if (licIdent.licPrefixType == cEzLic_p78ou3_LicPrefixType_ELC1) // typ1 = pouze zasifrovani dat + { + freeDataSize = sizeof(dataMainToFileELC1); // melo by byt 92 + + if (1) // EzLic_p78ou3_CryptoData.aesRetVal > 0 crypto + { + dataMainToFileELC1.prefix = 0x31434C45; + getCharsFromString(mainLicDescription, dataMainToFileELC1.licHeader.description); + dataMainToFileELC1.licHeader.sizeData = finalEncryptedLength; // sizeof(dataToFile); // 884; + dataMainToFileELC1.licHeader.licType = licIdent.licIDType; + dataMainToFileELC1.licHeader.licSubType = licIdent.licHeaderType << 8 | licIdent.licDataType; + } + } + + const int dataMainLength = sizeof(dataMainToFileELC1); + const int dataToFileLength = sizeof(dataToFile); + const int dataEncryptedLength = finalEncryptedLength; + const int totalLength = dataMainLength + dataToFileLength; + const int totalEncryptedLength = dataMainLength + finalEncryptedLength; + + unsigned char bdataMainToFileELC1[dataMainLength] = {}; + memcpy(bdataMainToFileELC1, &dataMainToFileELC1, dataMainLength); + + unsigned char bdataToFile[dataToFileLength] = {}; + memcpy(bdataToFile, &dataToFile, dataToFileLength); + unsigned char totalEncryptedArray[totalEncryptedLength] = {}; + + for (int i = 0; i < dataMainLength; i++) + totalEncryptedArray[i] = bdataMainToFileELC1[i]; + for (int i = 0; i < finalEncryptedLength; i++) + totalEncryptedArray[i + dataMainLength] = encrypted[i]; + + string fullFile = getCompletePath(licenseFileName); + + if (binaryGeneration == BinaryGenerationType::File) + { +#ifdef WINDOWS + + char licFileNameToSave[licenseFileName.length()] = {}; + getCharsFromString(licenseFileName, licFileNameToSave, licenseFileName.length()); + + FILE *fileLicence = fopen(licFileNameToSave, "wb"); + if (fileLicence) + { + size_t r1 = fwrite(&totalEncryptedArray, sizeof(totalEncryptedArray), 1, fileLicence); + // printf("License binary saved.\n"); + fclose(fileLicence); + cout << licenseFileName << endl; + return true; + } + +#else + std::ofstream outputFile(fullFile); + if (outputFile.is_open()) + { + outputFile.write(reinterpret_cast(totalEncryptedArray), totalEncryptedLength); + outputFile.close(); + std::cout << licenseFileName; + } + else + { + std::cerr << "Unable to open licence file." << std::endl; + } + return true; +#endif + } + else + { + int totalFileSize = sizeof(totalEncryptedArray); + // cout << "data:text/plain;base64,"; + cout << "data:application/octet-stream;base64,"; + + char encryptedChars[totalFileSize]; + + for (int i = 0; i < totalFileSize; i++) + encryptedChars[i] = static_cast(totalEncryptedArray[i]); + + string strToBase = convertToString(encryptedChars, totalFileSize); + string base64Coded = base64_encode_ai(strToBase); + cout << base64Coded << endl; + + return true; + } + } + } + + return false; +} + +bool LicenceELC11::readEosEovLicence(string dataFileName) +{ + BYTE licPostfix = 0; + FILE *licenceFile; + char ch; + long lSize; + size_t result; + + const int fileNameLength = dataFileName.length(); + char fileNameCh[fileNameLength] = {}; + for (int i = 0; i < dataFileName.length(); i++) + fileNameCh[i] = dataFileName[i]; + + cout << dataFileName << endl; + + licenceFile = fopen(fileNameCh, "rb"); // read mode + fseek(licenceFile, 0, SEEK_END); // seek to end of file + const int size = ftell(licenceFile); // get current file pointer + fseek(licenceFile, 0, SEEK_SET); + + if (licenceFile == nullptr) + { + perror("Error while opening the file.\n"); + operationErrors = "Error while opening the file.\n"; + return false; + } + + int count = 0; + + unsigned char licenceContent[size]; + + for (int i = 0; i < size; i++) + { + ch = fgetc(licenceFile); + licenceContent[i] = ch; + count++; + } + + fclose(licenceFile); + + // this->cid = cid; + // this->csd = csd; + + getSDData(); + + string licFileName = getLicenceName(licPostfix); + + LicenceDataMainELC licenceHeader; + LicenceIdent licIdent; + LicenceData licEncryptedData; + + memset(&licenceHeader, 0, sizeof(LicenceDataMainELC)); + memcpy(&licenceHeader, licenceContent, sizeof(LicenceDataMainELC)); + + const int sizeOfEncryptedData = size - sizeof(LicenceDataMainELC); + unsigned char encryptedData[sizeOfEncryptedData] = {}; + for (int i = 0; i < sizeOfEncryptedData; i++) + encryptedData[i] = licenceContent[i + sizeof(LicenceDataMainELC)]; + + // original jsou testy na velikost přečteného file, zatím TODO + + BYTE prefixType = (int)licenceContent[3] - 0x30; + if (prefixType == PrefixType::ELC1) + { + if (licenceHeader.licHeader.sizeData > 0) + { + licIdent.licIDType = licenceHeader.licHeader.licType; + licIdent.licSubType = licenceHeader.licHeader.licSubType; + + if (licenceHeader.licHeader.licSubType == cEzLic_p78ou3_SubType_10_10) // zatim natvrdo + { + initCrypto(); + // CryptData cryptData = initCrypto(sdData, licIdent.licIDType); + unsigned char decrypted[2000] = {}; + int decrypted_len = decrypt(encryptedData, sizeof(encryptedData), cryptData.aesKey, cryptData.aesInitVector, decrypted); + + if (sizeof(licEncryptedData) != decrypted_len) + { + operationErrors = "License size mismatch"; + return false; + } + else + { + memset(&licEncryptedData, 0, sizeof(licEncryptedData)); + memcpy(&licEncryptedData, decrypted, sizeof(licEncryptedData)); + + if (licEncryptedData.id.version == cEzLic_p78ou3_HeaderType_10 && licEncryptedData.header.licVersion == cEzLic_p78ou3_HeaderType_10) + { + if (licEncryptedData.header.licType == cEzLic_p78ou3_IDType_EOVOSV) + { + if (licEncryptedData.id.cardSize != sdData.cardSize) + { + operationErrors = "Size card mismatch"; + return false; + } + + if (licEncryptedData.header.licCount > 0) + { + + if (licType == PlcLicenceType::LicenceOther) + { + // TODO stará + } + else + { + // maxLic := MIN(EzLlic_5rq4_DataFromFile_10_10.header.licCount, cEzLic_p78ou3_licMaxCount); ? + int maxLic = min(licEncryptedData.header.licCount, licMaxCount); + for (int i = 1; i < maxLic; i++) + { + if (licEncryptedData.items[i].protoId > 0 || licEncryptedData.items[i].licCount > 0 || licEncryptedData.items[i].data1 > 0) + { + // EzLlic_5rq4_CheckData.LicId[EzLlic_5rq4_DataFromFile_10_10.items[licId].protoId] := licId; + } + else + { + operationErrors = "Licence items mismatch"; + return false; + } + } + } + } + else + { + operationErrors = "Size card info mismatch"; + return false; + } + } + } + else + { + operationErrors = "Licence mismatch"; + return false; + } + } + } + } + else + { + operationErrors = "Licence error"; + return false; + } + } + else + { + operationErrors = "Licence error"; + return false; + } + + cout << "Licence readed: " << size << endl + << ", data: " << licenceHeader.licHeader.description << endl; + return true; +} + +bool LicenceELC11::readLicence(LicenceInfoGeneral *licences) +{ + sdCard = SDCard(this->cid_cdsPath); + if (sdCard.isLoaded == false) + throw LicenceException((int)51, "Chyba při čtení SD karty, cesta: " + cid_cdsPath); + + for (int i = 0; i < sdCard.cidString.length(); i++) + this->cid[i] = sdCard.cidString[i]; // nutné pro původní algoritmus + for (int i = 0; i < sdCard.csdString.length(); i++) + this->csd[i] = sdCard.csdString[i]; // nutné pro původní algoritmus + + string licFileName = getLicenceName(); + string licFilePath = this->licenceFilePath + licFileName; + + BYTE licPostfix = 0; + FILE *licenceFile; + char ch; + long lSize; + size_t result; + + const int fileNameLength = licFilePath.length(); + char fileNameCh[fileNameLength] = {}; + for (int i = 0; i < fileNameLength; i++) + fileNameCh[i] = licFilePath[i]; + + licenceFile = fopen(fileNameCh, "rb"); // read mode + fseek(licenceFile, 0, SEEK_END); // seek to end of file + const int size = ftell(licenceFile); // get current file pointer + fseek(licenceFile, 0, SEEK_SET); + + if (size <= 0) + throw LicenceException((int)Error11::LicenceReadError, "Licence read error: " + licFilePath); + + int count = 0; + + unsigned char licenceContent[size]; + + for (int i = 0; i < size; i++) + { + ch = fgetc(licenceFile); + licenceContent[i] = ch; + count++; + } + + fclose(licenceFile); + + getSDData(); + + LicenceDataMainELC licenceHeader; + LicenceIdent licIdent; + LicenceData licEncryptedData; + + memset(&licenceHeader, 0, sizeof(LicenceDataMainELC)); + memcpy(&licenceHeader, licenceContent, sizeof(LicenceDataMainELC)); + + const int sizeOfEncryptedData = size - sizeof(LicenceDataMainELC); + unsigned char encryptedData[sizeOfEncryptedData] = {}; + for (int i = 0; i < sizeOfEncryptedData; i++) + encryptedData[i] = licenceContent[i + sizeof(LicenceDataMainELC)]; + + BYTE prefixType = (int)licenceContent[3] - 0x30; + if (prefixType == PrefixType::ELC1) + { + if (licenceHeader.licHeader.sizeData > 0) + { + licIdent.licIDType = licenceHeader.licHeader.licType; + licIdent.licSubType = licenceHeader.licHeader.licSubType; + + if (licenceHeader.licHeader.licSubType == cEzLic_p78ou3_SubType_10_10) // zatim natvrdo + { + initCrypto(); + // CryptData cryptData = initCrypto(sdData, licIdent.licIDType); + unsigned char decrypted[2000] = {}; + int decrypted_len = decrypt(encryptedData, sizeof(encryptedData), cryptData.aesKey, cryptData.aesInitVector, decrypted); + #ifdef DEB + cout << "sizeof(licEncryptedData: " << sizeof(licEncryptedData) << endl; + cout << "decrypted_len: " << decrypted_len << endl; + #endif + + if (sizeof(licEncryptedData) != decrypted_len) + { + throw LicenceException((int)Error11::LicenceSizeMismatch, "License size mismatch "); + } + else + { + memset(&licEncryptedData, 0, sizeof(licEncryptedData)); + memcpy(&licEncryptedData, decrypted, sizeof(licEncryptedData)); + + if (licEncryptedData.id.version == cEzLic_p78ou3_HeaderType_10 && licEncryptedData.header.licVersion == cEzLic_p78ou3_HeaderType_10) + { + if (licEncryptedData.header.licType == cEzLic_p78ou3_IDType_EOVOSV) + { + if (licEncryptedData.header.licCount > 0) + { + for (int i = 0; i < licMaxCount; i++) + { + licences->licences.insert(pair(licEncryptedData.items[i].protoId, licEncryptedData.items[i].licCount)); + } + } + else + { + throw LicenceException((int)Error11::LicenceSizeCardMismatch, "Size card info mismatch"); + } + } + } + else + { + throw LicenceException((int)Error11::LicenceMismatch, "Licence mismatch"); + } + } + } + } + else + { + throw LicenceException((int)Error11::LicenceMismatch, "Licence mismatch"); + } + } + else + { + throw LicenceException((int)Error11::LicenceReadError, "Licence error"); + } + + return true; +} + +bool LicenceELC11::readLicence(string dataFileName, string licenceType, string licenceVersion, string cidArg, string csdArg) +{ + + for (int i = 0; i < cidArg.length(); i++) + this->cid[i] = cidArg[i]; + for (int i = 0; i < csdArg.length(); i++) + this->csd[i] = csdArg[i]; + this->dataLicenceType = licenceType; + this->dataLicenceVersion = licenceVersion; + + if (this->dataLicenceType == eoseovLicenceType) + { + return readEosEovLicence(dataFileName); + } + + return true; +} + +LicenceELC11::~LicenceELC11() {} diff --git a/src/LicenceELC31.cpp b/src/LicenceELC31.cpp new file mode 100644 index 0000000..4940746 --- /dev/null +++ b/src/LicenceELC31.cpp @@ -0,0 +1,45 @@ +#include "licenceELC31.h" +#include "utils.h" +#include +#include + +LicenceELC31::LicenceELC31() +{ +} + +LicenceELC31::LicenceELC31(LicData &licData) +{ + lData = licData; + processInputConfiguration(); +} + +LicenceELC31::LicenceELC31(LicenceIdentification &licIdentification) +{ +} + +bool LicenceELC31::processInputConfiguration() +{ + return true; +} + +int LicenceELC31::getDataPointsCount(int protocolId) +{ + return 0; +} + +bool LicenceELC31::getLicenceInfo(int protocolId, void * ptr) +{ + return true; +} + + + +void LicenceELC31::createLicence() +{ +} + +void LicenceELC31::readLicence() +{ +} + +LicenceELC31::~LicenceELC31() { } diff --git a/src/LicenceGenerator.cpp b/src/LicenceGenerator.cpp new file mode 100644 index 0000000..113f9d2 --- /dev/null +++ b/src/LicenceGenerator.cpp @@ -0,0 +1,489 @@ +#include +#include +#include +#include +#include "utils.h" +#include "pugixml.hpp" +#include + +ELCType licElcType = ELCType::ELC2; +LicenceType licLicenceType; +PlcType licPlcType; + +uint8_t licenceVersion = 1; // verze licence, určitě kodování, pojmenování souborů +uint8_t licenceIndex = 0; +uint8_t revision; +uint8_t licCompatibility = 1; // identikator hlavního ELC + + + +LicenceGenerator::LicenceGenerator() +{ +} + +LicenceGenerator::LicenceGenerator(string uid, string cid, string csd, string dataFileName) +{ + try + { + if (dataFileName.empty()) + throw std::runtime_error("Missing dataFileName par."); + + if (uid.empty() == false) + { + this->licData.uid = uid; + } + else + { + if (cid.empty()) + throw std::runtime_error("Missing CID par."); + if (csd.empty()) + throw std::runtime_error("Missing CSD par."); + } + } + catch (const std::exception &e) + { + this->argumentsCorrect = false; + std::cerr << "error: " << e.what() << endl; + return; + } + + this->configFileName = dataFileName; + this->licData.cid = cid; + this->licData.csd = csd; + + this->argumentsCorrect = true; + + if (processInputConfiguration() == false) + { + cerr << "Chyba: " << error.message << endl; + } +} + +LicenceGenerator::LicenceGenerator(map &arguments) +{ +} + +LicenceGenerator::LicenceGenerator(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility) +{ + this->licIdentification.licElcType = (ELCType)elcType; + this->licIdentification.licLicenceType = (LicenceType)licenceType; + this->licIdentification.licenceVersion = licenceVersion; + this->licIdentification.licenceIndex = licenceIndex; + this->licIdentification.licCompatibility = compatibility; +} + +/// @brief inicializace generátoru a načtení licenčních bodů +/// @param elcType +/// @param licenceType +/// @param licenceVersion +/// @param licenceIndex +/// @param compatibility +/// @return +bool LicenceGenerator::initread(InitStructure &initStructure) +{ + try + { + elcSwitchType = initStructure.elcType * 10 + licCompatibility; + + if (init(initStructure)) + { + switch (elcSwitchType) + { + case 11: + { // old eoseov + LicenceELC11 licence = LicenceELC11(this->licIdentification); + licence.readLicence(&this->licenceInfo); + break; + } + case 21: + { + LicenceELC21 licence = LicenceELC21(this->licIdentification); + this->licence21 = &licence; + this->licence21->readLicence(&this->licenceInfo); + break; + } + case 31: + { + LicenceELC31 licence = LicenceELC31(this->licIdentification); + break; + } + } + } + else + return false; + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + + return true; // TODO testy +} + +bool LicenceGenerator::initread(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility) +{ + try + { + elcSwitchType = elcType * 10 + licCompatibility; + + if (init(elcType, licenceType, licenceVersion, licenceIndex, compatibility)) + { + switch (elcSwitchType) + { + case 11: + { // old eoseov + LicenceELC11 licence = LicenceELC11(this->licIdentification); + licence.readLicence(&this->licenceInfo); + break; + } + case 21: + { + LicenceELC21 licence = LicenceELC21(this->licIdentification); + this->licence21 = &licence; + this->licence21->readLicence(&this->licenceInfo); + break; + } + case 31: + { + LicenceELC31 licence = LicenceELC31(this->licIdentification); + break; + } + } + } + else + return false; + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + + return true; // TODO testy +} + +/// @brief inicicialize generátoro, pouze vstupní kontrola +/// @param elcType +/// @param licenceType +/// @param licenceVersion +/// @param licenceIndex +/// @param compatibility +/// @return +bool LicenceGenerator::init(int elcType, int licenceType, int licenceVersion, int licenceIndex, int compatibility) +{ + try + { + if (elcType > 3) + { + error.code = (int)GeneralError::ELCNotImplemented; + error.message = "ELC není implementováno."; + throw LicenceException((int)GeneralError::ELCNotImplemented, error.message); + return false; + } + + this->licIdentification.licElcType = (ELCType)elcType; + this->licIdentification.licLicenceType = (LicenceType)licenceType; + this->licIdentification.licenceVersion = licenceVersion; + this->licIdentification.licenceIndex = licenceIndex; + this->licIdentification.licCompatibility = compatibility; + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + + elcSwitchType = elcType * 10 + licCompatibility; + + return true; // TODO testy +} + +bool LicenceGenerator::init(InitStructure &initStructure) +{ + try + { + if (initStructure.elcType > 3) + { + error.code = (int)GeneralError::ELCNotImplemented; + error.message = "ELC není implementováno."; + throw LicenceException((int)GeneralError::ELCNotImplemented, error.message); + return false; + } + + this->licIdentification.licElcType = (ELCType)initStructure.elcType; + this->licIdentification.licLicenceType = (LicenceType)initStructure.licenceType; + this->licIdentification.licenceVersion = licenceVersion; + this->licIdentification.licenceIndex = licenceIndex; + this->licIdentification.licCompatibility = initStructure.compatibility; + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + + elcSwitchType = initStructure.elcType * 10 + licCompatibility; + + return true; // TODO testy +} + +int LicenceGenerator::getDataPointsCount(int protocolId) +{ +} + +bool LicenceGenerator::getLicenceItemInfo(int protocolId, void *returnItemStructure) +{ + int result = 0; + // const type_info &ti1 = typeid(LicenceELC21); + + try + { + switch (elcSwitchType) + { + case 11: + { // old eoseov + LicenceItem11 *resultPtr = static_cast(returnItemStructure); + resultPtr->protocolId = protocolId; // protocolId; + if (this->licenceInfo.licences.count(protocolId)) + resultPtr->dataPointsCount = this->licenceInfo.licences.at(protocolId); + else + resultPtr->dataPointsCount = 0; + // licence21->getLicenceItemInfo(protocolId, returnItemStructure); stará verze, nová má k dispozici polozky z readLicence + break; + } + case 21: + { + + LicenceItem21 *resultPtr = static_cast(returnItemStructure); + resultPtr->protocolId = protocolId; // protocolId; + if (this->licenceInfo.licences.count(protocolId)) + resultPtr->dataPointsCount = this->licenceInfo.licences.at(protocolId); + else + resultPtr->dataPointsCount = 0; + // licence21->getLicenceItemInfo(protocolId, returnItemStructure); stará verze, nová má k dispozici polozky z readLicence + break; + } + case 31: + { + LicenceELC31 licence = LicenceELC31(this->licIdentification); + break; + } + default: + { + error.code = -1; + error.message = "Nepodařilo se identifikovat licenci"; + return false; + } + } + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + + return true; +} + +bool LicenceGenerator::getLicenceInfo(int protocolId, void *returnStructure) +{ + int result = 0; + const type_info &ti1 = typeid(LicenceELC21); + // const type_info& ti1 = typeid(returnStructure); + // cout << "TTTYP: " << ti1.name() << endl; + switch (elcSwitchType) + { + case 11: + { // old eoseov + break; + } + case 21: + { + LicenceELC21 licence = LicenceELC21(this->licIdentification); + try + { + licence.readLicence(&this->licenceInfo); + return licence.getLicenceInfo(protocolId, returnStructure); + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + break; + } + case 31: + { + LicenceELC31 licence = LicenceELC31(this->licIdentification); + try + { + licence.readLicence(); + return licence.getLicenceInfo(protocolId, returnStructure); + } + catch (const LicenceException &ex) + { + error.code = ex.getErrorCode(); + error.message = ex.getErrorMessage(); + return false; + } + break; + } + } + + error.code = -1; + error.message = "Nepodařilo se identifikovat licenci"; + return false; +} + +bool LicenceGenerator::processInputConfiguration() +{ + string fullFile = getCompletePath(this->configFileName); + const int fileNameLength = fullFile.length(); + char fileName[fileNameLength] = {}; + getCharsFromString(fullFile, fileName, fileNameLength); + +#ifdef WINDOWS + pugi::xml_parse_result result = doc.load_file("licData.xml"); +#else + pugi::xml_parse_result result = doc.load_file(fileName); +#endif + + if (result) + { + const char *dataRootName = doc.child("data") ? "data" : "licence"; // kompatibilita s verzí, která měla ještě root "data" + Mapping mapping; + + if (atoi(&doc.child(dataRootName).attribute("xmlVersion").value()[0]) != XML_VERSION) + { + error.code = -1; + error.message = "Invalid XML VERSION"; + return false; + } + + this->licData.doc = &doc; + + string licType = doc.child(dataRootName).child("licenceType").child_value(); + if (!licType.empty()) + { + this->licIdentification.licLicenceType = mapping.licMapTypes[licType]; // LicenceType::EOS_EOV; + } + else + { + cerr << endl + << " ERROR MISSING licenceType " << endl; + return false; + } + + this->licIdentification.licenceVersion = atoi(&doc.child(dataRootName).child("licenceType").attribute("licenceVersion").value()[0]); + this->licIdentification.revision = doc.child(dataRootName).attribute("revision").value()[0]; + this->licIdentification.licenceIndex = atoi(&doc.child(dataRootName).child("licenceType").attribute("licenceIndex").value()[0]); + this->licIdentification.licElcType = (ELCType)atoi(&doc.child(dataRootName).attribute("elc").value()[0]); + + licElcType = (ELCType)atoi(&doc.child(dataRootName).attribute("elc").value()[0]); + licCompatibility = atoi(&doc.child(dataRootName).attribute("compatibility").value()[0]); + + this->licIdentification.licCompatibility = atoi(&doc.child(dataRootName).attribute("compatibility").value()[0]); + + string plcType = doc.child(dataRootName).child("plcType").child_value(); + if (!plcType.empty()) + { + this->licIdentification.licPlcType = mapping.licMapPlcType[plcType]; + } + } + else + { + std::cerr << "Unable to open the config file." << std::endl; + } + + return true; +} + +void LicenceGenerator::createLicenceFile() +{ + switch (licElcType) + { + case ELCType::ELC1: + createLicenceELC1(); + break; + + case ELCType::ELC2: + createLicenceELC2(); + break; + + case ELCType::ELC3: + createLicenceELC3(); + break; + } +} + +void LicenceGenerator::readLicenceFile() +{ + switch (this->licIdentification.licElcType) + { + case ELCType::ELC1: + readLicenceELC1(); + break; + + case ELCType::ELC2: + readLicenceELC2(); + break; + + case ELCType::ELC3: + readLicenceELC3(); + break; + } +} + +void LicenceGenerator::createLicenceELC1() // přejmenvat na ELC1 +{ + LicenceELC11 plcWriteLicence = LicenceELC11(this->licData.cid, this->licData.csd, "file", this->configFileName); + plcWriteLicence.createLicence(); +} + +void LicenceGenerator::createLicenceELC2() +{ + switch (licCompatibility) + { + case 1: + LicenceELC21 licence = LicenceELC21(this->licData); + licence.createLicence(); + break; + } +} + +void LicenceGenerator::createLicenceELC3() +{ + switch (licCompatibility) + { + case 1: + LicenceELC31 licence = LicenceELC31(this->licData); + licence.createLicence(); + break; + } +} + +void LicenceGenerator::readLicenceELC1() +{ + cout << "reading ELC1" << endl; +} + +void LicenceGenerator::readLicenceELC2() +{ + LicenceELC21 licence = LicenceELC21(this->licIdentification); +} + +void LicenceGenerator::readLicenceELC3() +{ + cout << "reading ELC3" << endl; +} + +LicenceGenerator::~LicenceGenerator() +{ +} diff --git a/src/NewGeneration.cpp b/src/NewGeneration.cpp new file mode 100644 index 0000000..8380186 --- /dev/null +++ b/src/NewGeneration.cpp @@ -0,0 +1,69 @@ +#include +#include "utils.h" +#include "licenceGenerator.h" +#include "licenceCommon.h" + +/// @brief hlavní funkce +/// @param argc +/// @param argv parametry pro generování licence +/// @return +int main(int argc, char *argv[]) +{ + // cout << "test" << endl; + // unordered_map arguments = getArguments(argc, argv); + // LicenceGenerator generatorOld = LicenceGenerator(arguments["-uid"], arguments["-cid"], arguments["-csd"], arguments["-configFileName"]); + // generatorOld.createLicenceFile(); + // return 0; + //cout << "Reading Test" << endl; + LicenceGenerator licenceGenerator = LicenceGenerator(); + + InitStructure initStructure; + initStructure.elcType = 2; + initStructure.licenceType = (int)LicenceType::EOS_EOV; + initStructure.licenceVersion = 1; + initStructure.licenceIndex = 0; + initStructure.compatibility = 1; + initStructure.licenceFilePath = ""; + + // if (licenceGenerator.init(initStructure)) + // { + // LicenceInfo21 info; // podle ELC a kompatibility určit strukuru (LicenceInfo11, LicenceInfo21, LicenceInfo31) + + // if (licenceGenerator.getLicenceInfo(888, &info)) + // { + // std::cout << "Počet licenčních bodů pro 888: " << info.reqDataPointsCount << std::endl; + // if (info.licences.count(888) > 0) cout << "počet z vectoru pro 888: " << info.licences.at(888) << endl; + // cout << "všechny licenční body: " << endl; + + // for (const auto& pair : info.licences) { std::cout << "<" << pair.first << ", " << pair.second << ">" << endl; + // } + + // } + // else + // cerr << "Došlo k chybě: " << licenceGenerator.error.message; + // } + // else + // { + // cerr << "Došlo k chybě: " << licenceGenerator.error.message; + // } + + if (licenceGenerator.initread(initStructure)) + { + LicenceItem21 info; // podle ELC a kompatibility určit strukuru (LicenceInfo11, LicenceInfo21, LicenceInfo31) + if (licenceGenerator.getLicenceItemInfo(777, &info)) + { + std::cout << "Počet licenčních bodů pro " << info.protocolId << ": " << info.dataPointsCount << std::endl; + //for (const auto& pair : info.licences) { std::cout << "<" << pair.first << ", " << pair.second << ">" << endl; + } + else cerr << "Došlo k chybě: " << licenceGenerator.error.message; + } + else + { + cerr << "Došlo k chybě: " << licenceGenerator.error.message; + } + + + system("pause"); + + return EXIT_SUCCESS; +} diff --git a/src/PlcLicence.cpp b/src/PlcLicence.cpp index 5d55c01..b7fcecd 100644 --- a/src/PlcLicence.cpp +++ b/src/PlcLicence.cpp @@ -52,6 +52,7 @@ BYTE cHexNibble_to_No[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, std::string cEzLic_p78ou3_CipherAES = "aes-256-cbc"; // konfigurace kriptovaciho algoritmu const string eoseovLicenceType = "EOV_OSV"; +//enum LicenceType { EovOsv = 1 }; PlcLicence::PlcLicence() { @@ -86,6 +87,9 @@ void PlcLicence::processConfigFile(string &dataFileName) char fileName[fileNameLength] = {}; getCharsFromString(fullFile, fileName, fileNameLength); + std::map licTypes; + licTypes["EOV_OSV"] = LicenceType::LicenceEov; + pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(fileName); if (result) @@ -599,8 +603,7 @@ bool PlcLicence::ReadEosEovLicence(string dataFileName) return false; } - cout << "Licence readed: " << size << endl - << ", data: " << licenceHeader.licHeader.description << endl; + cout << "Licence readed: " << size << endl << ", data: " << licenceHeader.licHeader.description << endl; return true; } diff --git a/src/SDCard.cpp b/src/SDCard.cpp new file mode 100644 index 0000000..9ec0ea0 --- /dev/null +++ b/src/SDCard.cpp @@ -0,0 +1,116 @@ +#include "utils.h" +#include "SDCard.h" +#include +#include +#include + +SDCard::SDCard() +{ +} + +SDCard::SDCard(const string cds_cid_Path) +{ + this->filePath = cds_cid_Path; + getCIDFromFile(); + getCSDFromFile(); + this->isLoaded = SDCard::readSDCard(); +} + +SDCard::SDCard(string cid, string csd) +{ + for (int i = 0; i < cid.length(); i++) + this->cid[i] = cid[i]; + for (int i = 0; i < csd.length(); i++) + this->csd[i] = csd[i]; + + this->isLoaded = SDCard::readSDCard(); +} + +bool SDCard::readSDCard() +{ + + BYTE cHexNibbleToNo[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < CID_LENGTH; i++) + this->cardData.CID_nibble[i] = (BYTE)cid[i]; + + for (int i = 0; i < cnibblescount / 2; i++) + { + this->cardData.CID[i] = cHexNibbleToNo[this->cardData.CID_nibble[2 * i]] << 4 | cHexNibbleToNo[this->cardData.CID_nibble[2 * i + 1]]; + } + + this->cardData.manufacturerID = this->cardData.CID[0]; + this->cardData.oemID[0] = this->cardData.CID[1]; + this->cardData.oemID[1] = this->cardData.CID[2]; + this->cardData.name[0] = this->cardData.CID[3]; + this->cardData.name[1] = this->cardData.CID[4]; + this->cardData.name[2] = this->cardData.CID[5]; + this->cardData.name[3] = this->cardData.CID[6]; + this->cardData.name[4] = this->cardData.CID[7]; + this->cardData.productRevision_hw = cHexNibbleToNo[this->cardData.CID[16]]; + this->cardData.productRevision_sw = cHexNibbleToNo[this->cardData.CID[17]]; + + if (this->cardData.productRevision_sw < 10) + this->cardData.productRevision = (float)this->cardData.productRevision_hw + ((float)this->cardData.productRevision_sw * 0.1); + else + this->cardData.productRevision = (float)this->cardData.productRevision_hw + ((float)this->cardData.productRevision_sw * 0.01); + + this->cardData.serialNumber = this->cardData.CID[9] << 24 | this->cardData.CID[10] << 16 | this->cardData.CID[11] << 8 | this->cardData.CID[12]; + + // this->cardData.manufacturerDate_year = cHexNibbleToNo[this->cardData.CID_nibble[27]] * 10 + cHexNibbleToNo[this->cardData.CID_nibble[28]] + 2000; + // this->cardData.manufacturerDate_month = cHexNibbleToNo[this->cardData.CID_nibble[29]]; + // string date = cSDMonthStr[this->cardData.manufacturerDate_month] + std::to_string(this->cardData.manufacturerDate_year); + // for (int i = 0; i < date.length(); i++) this->cardData.manufacturerDate[i] = date[i]; + + // CSD + for (int i = 0; i < CSD_LENGTH; i++) + this->cardData.CSD_nibble[i] = (BYTE)csd[i]; + + for (int i = 0; i < cnibblescount / 2; i++) + { + this->cardData.CSD[i] = cHexNibbleToNo[this->cardData.CSD_nibble[2 * i]] << 4 | cHexNibbleToNo[this->cardData.CSD_nibble[2 * i + 1]]; + } + + if (this->cardData.CSD_nibble[0] == 0x34) + { + this->cardData.cardSize = this->cardData.CSD[7] << 16 | this->cardData.CSD[8] << 8 | this->cardData.CSD[9]; + this->cardData.cardGSize = (this->cardData.cardSize + 1) / 2048; + } + + return true; +} + +bool SDCard::getCIDFromFile() +{ + // string cid = "9f544930303030300000000b47015423"; + cidString = readFileToString(this->filePath + "cid", 32); + if (cidString.empty()) return false; + for (int i = 0; i < cidString.length(); i++) this->cid[i] = cidString[i]; + return true; +} + +bool SDCard::getCSDFromFile() +{ + // string cid = "9f544930303030300000000b47015423"; + csdString = readFileToString(this->filePath + "csd", 32); + if (csdString.empty()) return false; + for (int i = 0; i < csdString.length(); i++) this->csd[i] = csdString[i]; + return true; +} + diff --git a/src/cid b/src/cid new file mode 100644 index 0000000..32a9336 --- /dev/null +++ b/src/cid @@ -0,0 +1,5 @@ +9f5449534443495461457815de0164a9 +6   . x4   .. nt$6 & manfid 6 +  cid "6  fwrev 6 Jm  csd ,6 gEd$ +subsystem 46 % +driver (6 -  ocr -6 ? power *6 4L  type 6 1M  date #6 rTP hwrev )6 nyR  dsr '6 ` serial 6 NNm erase_size 6 6m block 6 n uevent 6 o  ssr 6 q  scr &6 &y oemid !6 y ( preferred_erase_size %6   name \ No newline at end of file diff --git a/src/csd b/src/csd new file mode 100644 index 0000000..50b4809 --- /dev/null +++ b/src/csd @@ -0,0 +1,2 @@ +400e00325b5900003a0d7f800a40008d + \ No newline at end of file diff --git a/src/licenceELC21.cpp b/src/licenceELC21.cpp new file mode 100644 index 0000000..b704668 --- /dev/null +++ b/src/licenceELC21.cpp @@ -0,0 +1,674 @@ +#include "licenceELC21.h" + +#include "utils.h" +#include "SDCard.h" +#include +#include +#include +#include + +LicenceELC21::LicenceELC21() +{ +} + +LicenceELC21::LicenceELC21(LicenceIdentification &licIdentification, LicData &licData) +{ + lIdentification = licIdentification; + lData = licData; +} + +LicenceELC21::LicenceELC21(LicenceIdentification &licIdentification) +{ + lIdentification = licIdentification; +} + +LicenceELC21::LicenceELC21(LicData &licData) +{ + lData = licData; + processInputConfiguration(); +} + +bool LicenceELC21::createLicence() +{ + getLicenceItems(); + getHeader(); + + sdCard = SDCard(lData.cid, lData.csd); + if (sdCard.isLoaded == false) + cerr << "SD card read error." << endl; + this->licBody.licenceIdentHeader.cardSize = sdCard.cardData.cardSize; + this->licBody.licenceIdentHeader.serialNumber = sdCard.cardData.serialNumber; + this->licBody.licenceIdentHeader.licItemCount = this->licBody.privateContent.dataItems.size(); + this->licBody.licenceIdentHeader.publicHeaderLength = this->licBody.publicHeader.length(); + + vector publicContent; + publicContent.reserve(1000); + vector privateContent; + privateContent.reserve(1000); + vector privateContentEncrypted; + privateContentEncrypted.reserve(1000); + + publicContent.push_back(this->licBody.licId.licIdent[0]); + publicContent.push_back(this->licBody.licId.licIdent[1]); + publicContent.push_back(this->licBody.licId.licIdent[2]); + publicContent.push_back(((char)48 + (int)this->lIdentification.licElcType)); + publicContent.push_back(this->licBody.licId.licIdent[4]); + publicContent.push_back(this->licBody.licenceIdentHeader.licenceType); + publicContent.push_back(this->licBody.licenceIdentHeader.licenceTypeVersion); + publicContent.push_back(this->licBody.licenceIdentHeader.licenceIndex); + publicContent.push_back(this->licBody.licenceIdentHeader.compatibilityVersion); + publicContent.push_back(this->licBody.privateContent.dataItems.size()); + publicContent.push_back(this->licBody.licenceIdentHeader.publicHeaderLength & 0xFF); + publicContent.push_back((this->licBody.licenceIdentHeader.publicHeaderLength >> 8) & 0xFF); + publicContent.push_back(this->licBody.licenceIdentHeader.cardSize & 0xFF); + publicContent.push_back((this->licBody.licenceIdentHeader.cardSize >> 8) & 0xFF); + publicContent.push_back(this->licBody.licenceIdentHeader.serialNumber & 0xFF); + publicContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 8) & 0xFF); + publicContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 16) & 0xFF); + publicContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 24) & 0xFF); + +#ifdef DEB + cout << "publicHeaderLength: " << this->licBody.licenceIdentHeader.publicHeaderLength << endl; + cout << "cardSize: " << this->licBody.licenceIdentHeader.cardSize << endl; + cout << "serialNumber: " << this->licBody.licenceIdentHeader.serialNumber << endl; + cout << "item count: " << this->licBody.privateContent.dataItems.size() << endl; +#endif + + appendStringToVector(this->licBody.publicHeader, publicContent); + uint16_t crcPublic = calculateCRC16(publicContent); + +#ifdef DEB + cout << "CRC pubblic: " << crcPublic << endl; +#endif + + publicContent.push_back(crcPublic & 0xFF); + publicContent.push_back((crcPublic >> 8) & 0xFF); + + privateContent.push_back(this->licBody.licenceIdentHeader.licenceType); + privateContent.push_back(this->licBody.licenceIdentHeader.licenceTypeVersion); + privateContent.push_back(this->licBody.licenceIdentHeader.licenceIndex); + privateContent.push_back(this->licBody.licenceIdentHeader.compatibilityVersion); + privateContent.push_back(this->licBody.privateContent.dataItems.size()); + privateContent.push_back(this->licBody.licenceIdentHeader.publicHeaderLength & 0xFF); + privateContent.push_back((this->licBody.licenceIdentHeader.publicHeaderLength >> 8) & 0xFF); + privateContent.push_back(this->licBody.licenceIdentHeader.cardSize & 0xFF); + privateContent.push_back((this->licBody.licenceIdentHeader.cardSize >> 8) & 0xFF); + privateContent.push_back(this->licBody.licenceIdentHeader.serialNumber & 0xFF); + privateContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 8) & 0xFF); + privateContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 16) & 0xFF); + privateContent.push_back((this->licBody.licenceIdentHeader.serialNumber >> 24) & 0xFF); + + for (licDataItem dataItem : this->licBody.privateContent.dataItems) + { + privateContent.push_back(dataItem.protoId & 0xFF); + privateContent.push_back((dataItem.protoId >> 8) & 0xFF); + privateContent.push_back(dataItem.licCount & 0xFF); + privateContent.push_back((dataItem.licCount >> 8) & 0xFF); + for (int i = 0; i < sizeof(dataItem.dummy); i++) + privateContent.push_back(i); + } + + vector completeVector = joinVectors(publicContent, privateContent); + licBody.privateContent.crc = calculateCRC16(completeVector); + uint16_t crcComplete = calculateCRC16(completeVector); + + privateContent.push_back(crcComplete & 0xFF); + privateContent.push_back((crcComplete >> 8) & 0xFF); + + privateContentEncrypted = cryptPrivateContent(privateContent); + +#ifdef DEB + + cout << endl + << hex << "test original: " << privateContent.size() << endl; + for (auto x : privateContent) + cout << (int)x << "-"; + + cout << endl + << "test encrypt: " << privateContentEncrypted.size() << endl; + for (auto x : privateContentEncrypted) + cout << (int)x << "-"; + + vector privateContentDecrypted; + privateContentDecrypted = decryptPrivateContent(privateContentEncrypted); + + cout << endl + << "test decrypt: " << privateContentDecrypted.size() << endl; + for (auto x : privateContentDecrypted) + cout << (int)x << "-"; +#endif + + // return; + + string licfileName = getLicenceName(); + std::ofstream outputFile(licfileName, std::ios::out | std::ios::binary); + + // Check if the file is open + if (!outputFile.is_open()) + { + std::cerr << "Error opening file: " << licfileName << std::endl; + return false; + } + + std::copy(publicContent.cbegin(), publicContent.cend(), std::ostream_iterator(outputFile)); + std::copy(privateContentEncrypted.cbegin(), privateContentEncrypted.cend(), std::ostream_iterator(outputFile)); + + outputFile.close(); + + cout << licfileName; + + return true; +} + +bool LicenceELC21::readLicence(LicenceInfoGeneral * licences) +{ + try + { + // sdCard = SDCard("9f544930303030300000000b47015423", "400e00325b5900003a0d7f800a40008d"); + sdCard = SDCard(this->cid_cdsPath); + if (sdCard.isLoaded == false) + throw LicenceException((int)Error21::SDCardReadError, "Chyba při čtení SD karty, cesta: " + cid_cdsPath); + + string licFileName = getLicenceName(); + string licFilePath = this->licenceFilePath+licFileName; + + + // Create an unsigned char vector to store the file data + vector content; + if (readFile(licFilePath, content) == false) + { + throw LicenceException((int)GeneralError::FileOpenError, "Chyba otevření souboru licence."); + } + + this->licBody.licId.licIdent[0] = content[0]; + this->licBody.licId.licIdent[1] = content[1]; + this->licBody.licId.licIdent[2] = content[2]; + this->licBody.licId.licIdent[3] = content[3]; + this->licBody.licId.licIdent[4] = content[4]; + + this->licBody.licenceIdentHeader.licenceType = content[5]; + this->licBody.licenceIdentHeader.licenceTypeVersion = content[6]; + this->licBody.licenceIdentHeader.licenceIndex = content[7]; + this->licBody.licenceIdentHeader.compatibilityVersion = content[8]; + this->licBody.licenceIdentHeader.licItemCount = content[9]; + this->licBody.licenceIdentHeader.publicHeaderLength = bytesToWord(content[10], content[11]); + this->licBody.licenceIdentHeader.cardSize = bytesToWord(content[12], content[13]); + this->licBody.licenceIdentHeader.serialNumber = bytesToDword(content[14], content[15], content[16], content[17]); + + uint16_t crcPublic = bytesToWord(content[18 + licBody.licenceIdentHeader.publicHeaderLength], content[19 + licBody.licenceIdentHeader.publicHeaderLength]); + +#ifdef DEB + cout << "licenceType: " << to_string(licBody.licenceIdentHeader.licenceType) << endl; + cout << "licenceTypeVersion: " << to_string(licBody.licenceIdentHeader.licenceTypeVersion) << endl; + cout << "licenceIndex: " << to_string(licBody.licenceIdentHeader.licenceIndex) << endl; + cout << "compatibilityVersion: " << to_string(licBody.licenceIdentHeader.compatibilityVersion) << endl; + cout << "licItemCount: " << to_string(licBody.licenceIdentHeader.licItemCount) << endl; + cout << "headerLength: " << to_string(licBody.licenceIdentHeader.publicHeaderLength) << endl; + cout << "card: " << to_string(licBody.licenceIdentHeader.cardSize) << endl; + cout << "serial: " << to_string(licBody.licenceIdentHeader.serialNumber) << endl; + cout << "crcPublic: " << to_string(crcPublic) << endl; +#endif + + int elcVersion = (int)licBody.licId.licIdent[3] - 48; + + if (elcVersion != (int)this->lIdentification.licElcType) + { + throw LicenceException((int)GeneralError::ELCMismatch, "Nesouhlasí ELC."); + } + + vector encryptedPart(content.begin() + licBody.licenceIdentHeader.publicHeaderLength + 20, content.begin() + content.size()); + +#ifdef DEB + cout << " encrypted part: " << hex << encryptedPart.size() << endl; + for (auto x : encryptedPart) + { + cout << (int)x << "-"; + } +#endif + + vector privateContentDecrypted; + privateContentDecrypted = decryptPrivateContent(encryptedPart); + +#ifdef DEB + cout << dec << endl + << " decrypted part: " << privateContentDecrypted.size() << endl; + for (auto x : privateContentDecrypted) + { + cout << dec << (int)x << "-"; + } +#endif + + LicenceBody licBodyDecrypted; + licBodyDecrypted.licenceIdentHeader.licenceType = privateContentDecrypted[0]; + licBodyDecrypted.licenceIdentHeader.licenceTypeVersion = privateContentDecrypted[1]; + licBodyDecrypted.licenceIdentHeader.licenceIndex = privateContentDecrypted[2]; + licBodyDecrypted.licenceIdentHeader.compatibilityVersion = privateContentDecrypted[3]; + licBodyDecrypted.licenceIdentHeader.licItemCount = privateContentDecrypted[4]; + licBodyDecrypted.licenceIdentHeader.publicHeaderLength = bytesToWord(privateContentDecrypted[5], privateContentDecrypted[6]); + licBodyDecrypted.licenceIdentHeader.cardSize = bytesToWord(privateContentDecrypted[7], privateContentDecrypted[8]); + licBodyDecrypted.licenceIdentHeader.serialNumber = bytesToDword(privateContentDecrypted[9], privateContentDecrypted[10], privateContentDecrypted[11], privateContentDecrypted[12]); + + //TODO testy na CRC + + if (licBodyDecrypted.licenceIdentHeader.licItemCount != this->licBody.licenceIdentHeader.licItemCount) + { + throw LicenceException((int)Error21::ItemsCountMismatch, map21Errors.at(Error21::ItemsCountMismatch)); + } + + int index = 13; + for (int i = 0; i < this->licBody.licenceIdentHeader.licItemCount; i++) + { + licDataItem item; + item.protoId = bytesToWord(privateContentDecrypted[index], privateContentDecrypted[index + 1]); + item.licCount = bytesToWord(privateContentDecrypted[index + 2], privateContentDecrypted[index + 3]); + index = index + sizeof(licDataItem); + this->licBody.privateContent.dataItems.push_back(item); + this->licenceInfo.licences.insert(pair(item.protoId, item.licCount)); + licences->licences.insert(pair(item.protoId, item.licCount)); + } + } + + catch (const LicenceException &ex) + { + errorMessage.code = ex.getErrorCode(); + errorMessage.message = ex.getErrorMessage(); + return false; + } + + return true; +} + +string LicenceELC21::getVersion(int middleVersion) +{ + string result = ""; + result.append(to_string(generatorVersion)); + result.append("."); + result.append(to_string(middleVersion)); + result.append("."); + string tempLicenceCount = "3"; // TODO + result.append(tempLicenceCount); + return result; +} + +bool LicenceELC21::processInputConfiguration() +{ + const char *dataRootName = "licence"; + Mapping mapping; + + string licType = lData.doc->child(dataRootName).child("licenceType").child_value(); + if (!licType.empty()) + { + this->lIdentification.licLicenceType = mapping.licMapTypes[licType]; // LicenceType::EOS_EOV; + this->lIdentification.licTypeName = licType; + } + else + { + cerr << endl + << " ERROR MISSING licenceType " << endl; + return false; + } + + this->lIdentification.licenceVersion = atoi(&lData.doc->child(dataRootName).child("licenceType").attribute("licenceVersion").value()[0]); + this->lIdentification.revision = lData.doc->child(dataRootName).attribute("revision").value()[0]; + this->lIdentification.licenceIndex = atoi(&lData.doc->child(dataRootName).child("licenceType").attribute("licenceIndex").value()[0]); + this->lIdentification.licElcType = (ELCType)atoi(&lData.doc->child(dataRootName).attribute("elc").value()[0]); + + this->lIdentification.licCompatibility = atoi(&lData.doc->child(dataRootName).attribute("compatibility").value()[0]); + + string plcType = lData.doc->child(dataRootName).child("plcType").child_value(); + if (!plcType.empty()) + { + this->lIdentification.licPlcType = mapping.licMapPlcType[plcType]; + } + + this->lData.station = &lData.doc->child(dataRootName).child("station").child_value()[0]; + this->lData.distributor = &lData.doc->child(dataRootName).child("distributor").child_value()[0]; + this->lData.projectDescription = &lData.doc->child(dataRootName).child("project").child_value()[0]; + + licBody.licenceIdentHeader.cardSize = 0; + licBody.licenceIdentHeader.compatibilityVersion = this->lIdentification.licCompatibility; + licBody.licenceIdentHeader.licenceIndex = this->lIdentification.licenceIndex; + licBody.licenceIdentHeader.licenceType = this->lIdentification.licenceVersion; + licBody.licenceIdentHeader.licenceTypeVersion = this->lIdentification.licenceVersion; + licBody.licenceIdentHeader.serialNumber = 0; + + return true; +} + +void LicenceELC21::getLicenceItems() +{ + int nodeIndex = 0; + int itemIndex = 0; + + for (pugi::xml_node licItemNode : lData.doc->child("licence").child("items")) + { + licDataItem item; +#ifdef DEB + cout << "protoId: " << licItemNode.child("protoId").child_value() << endl; + cout << "datapoints: " << licItemNode.child("dataPointsCount").child_value() << endl; +#endif + + item.protoId = atoi(licItemNode.child("protoId").child_value()); + item.licCount = atoi(licItemNode.child("dataPointsCount").child_value()); + + this->licBody.privateContent.dataItems.push_back(item); + + nodeIndex = 0; + itemIndex++; + for (pugi::xml_node child : licItemNode.children()) + { + nodeIndex++; + if (nodeIndex == 1) + { + licBody.publicHeader.append("\"name\":\""); + licBody.publicHeader.append(child.child_value()); + licBody.publicHeader.append("\","); + continue; + } + if (nodeIndex == 3) + { + licBody.publicHeader.append("\"dataPointsCount\":\""); + licBody.publicHeader.append(child.child_value()); + licBody.publicHeader.append("\""); + } + } + if (itemIndex != lIdentification.licItemsCount) + { + licBody.publicHeader.append("},"); + } + else + { + licBody.publicHeader.append("}"); + } + } +} + +void LicenceELC21::getHeader() +{ + PublicHeader publicHeader; + publicHeader.version = getVersion(7); + publicHeader.projectDescription = lData.projectDescription; + publicHeader.date = getDate(); + publicHeader.licenceType = lIdentification.licTypeName; + publicHeader.licenceType += to_string(lIdentification.licenceIndex); + + licBody.publicHeader = ""; + + licBody.publicHeader.append("{\"version\":"); + licBody.publicHeader.append(publicHeader.version); + licBody.publicHeader.append("\","); + // \"1.2.3\","); + licBody.publicHeader.append("\"project\":\""); + licBody.publicHeader.append(publicHeader.projectDescription); + licBody.publicHeader.append("\","); + + licBody.publicHeader.append("\"date\":\""); + licBody.publicHeader.append(publicHeader.date); + licBody.publicHeader.append("\","); + + licBody.publicHeader.append("\"note\":\"poznámka\","); + licBody.publicHeader.append("\"licenceType\":\""); + licBody.publicHeader.append(publicHeader.licenceType); + licBody.publicHeader.append("\","); + + licBody.publicHeader.append("\"items\":["); + + for (pugi::xml_node tool : lData.doc->child("licence").child("items")) + { + lIdentification.licItemsCount++; + } + + int nodeIndex = 0; + int itemIndex = 0; + + for (pugi::xml_node licItemNode : lData.doc->child("licence").child("items")) + { + licBody.publicHeader.append("{"); + nodeIndex = 0; + itemIndex++; + for (pugi::xml_node child : licItemNode.children()) + { + nodeIndex++; + if (nodeIndex == 1) + { + licBody.publicHeader.append("\"name\":\""); + licBody.publicHeader.append(child.child_value()); + licBody.publicHeader.append("\","); + continue; + } + if (nodeIndex == 3) + { + licBody.publicHeader.append("\"dataPointsCount\":\""); + licBody.publicHeader.append(child.child_value()); + licBody.publicHeader.append("\""); + } + } + if (itemIndex != lIdentification.licItemsCount) + { + licBody.publicHeader.append("},"); + } + else + { + licBody.publicHeader.append("}"); + } + } + + licBody.publicHeader.append("]"); + licBody.publicHeader.append("}"); +} + +vector LicenceELC21::cryptPrivateContent(const std::vector &content) +{ + + BYTE initVector[15] = {0}; + BYTE aesKey[32] = {0}; + + LicenceELC21::initVector(initVector, aesKey); + + unsigned char encrypted[10000] = {}; + const unsigned char *plainTextArray = content.data(); + int finalEncryptedLength = encrypt(plainTextArray, content.size(), aesKey, initVector, encrypted); + + std::size_t charArraySize = sizeof(encrypted) / sizeof(unsigned char); + std::vector result(encrypted, encrypted + finalEncryptedLength); + + return result; +} + +vector LicenceELC21::decryptPrivateContent(const std::vector &content) +{ + + BYTE initVector[15] = {0}; + BYTE aesKey[32] = {0}; + + LicenceELC21::initVector(initVector, aesKey); + + const unsigned char *encryptedData = content.data(); + unsigned char decrypted[10000] = {}; + + int decrypted_len = decrypt(encryptedData, content.size(), aesKey, initVector, decrypted); + + std::size_t charArraySize = sizeof(decrypted) / sizeof(unsigned char); + std::vector result(decrypted, decrypted + decrypted_len); + + return result; +} + +void LicenceELC21::initVector(BYTE (&iVector)[], BYTE (&key)[]) +{ + + struct Vector15 + { + int vec[15]; + }; + + Vector15 vec1 = {this->sdCard.cardData.CID[10], + this->sdCard.cardData.CID[12], + this->sdCard.cardData.CID[11], + this->sdCard.cardData.CID[9], + this->sdCard.cardData.CID_nibble[22] - 15, + this->sdCard.cardData.CID_nibble[24] - 15, + this->sdCard.cardData.CID_nibble[25] - 15, + this->sdCard.cardData.CID_nibble[21] - 15, + 9, 10, 11, 12, 13, 14, 15}; + Vector15 vec2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; //TODO přidat smysluplnější indexy + Vector15 vec3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + std::unordered_map vectors; + vectors.insert(std::pair(1, vec1)); + vectors.insert(std::pair(2, vec2)); + vectors.insert(std::pair(3, vec3)); + + struct Key32 + { + int key[32]; + }; + + Key32 key1 = {this->sdCard.cardData.CID[12], + this->sdCard.cardData.CID[23] - 15, + this->sdCard.cardData.CID[25] - 15, + this->sdCard.cardData.CID[11], + this->sdCard.cardData.CID[9], + this->sdCard.cardData.CID_nibble[21], + this->sdCard.cardData.CID[9] % 25, + this->sdCard.cardData.CID_nibble[22] - 15, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + Key32 key2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + Key32 key3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + + std::unordered_map keys; + keys.insert(std::pair(1, key1)); + keys.insert(std::pair(2, key2)); + keys.insert(std::pair(3, key3)); + + int lVersion = lIdentification.licenceVersion; + + iVector[0] = vectors.at(lVersion).vec[0]; + iVector[1] = vectors.at(lVersion).vec[1]; + iVector[2] = vectors.at(lVersion).vec[2]; + iVector[3] = vectors.at(lVersion).vec[3]; + iVector[4] = vectors.at(lVersion).vec[4]; + iVector[5] = vectors.at(lVersion).vec[5]; + iVector[6] = vectors.at(lVersion).vec[6]; + iVector[7] = vectors.at(lVersion).vec[7]; + + memcpy(&iVector[8], &iVector[0], 8); + + key[0] = keys.at(lVersion).key[0]; + key[1] = keys.at(lVersion).key[1]; + key[2] = keys.at(lVersion).key[2]; + key[3] = keys.at(lVersion).key[3]; + key[4] = keys.at(lVersion).key[4]; + key[5] = keys.at(lVersion).key[5]; + key[6] = keys.at(lVersion).key[6]; + key[7] = keys.at(lVersion).key[7]; + memcpy(&key[8], &key[0], 8); + memcpy(&key[16], &key[6], 8); + memcpy(&key[24], &key[12], 8); +} + +/// @brief get proper licencename +/// @param licPostfix +/// @return +string LicenceELC21::getLicenceName() +{ + // note - bude stačit pouze měnit indexy nebo bude potřeba udělat novej rozcestnik? nyni necháno na indexech + string result = ""; + char prefixChar = 97; + int licType = (int)lIdentification.licLicenceType; + int lVersion = lIdentification.licenceVersion; + + unordered_map baseString; + baseString.insert(std::pair((int)LicenceType::EOS_EOV, "ezlic_eovosv")); + baseString.insert(std::pair((int)LicenceType::DDTS, "ezlic_ddts")); + baseString.insert(std::pair((int)LicenceType::DRT, "ezlic_drt")); + + struct Index + { + int index[11]; + }; + + std::unordered_map indexes; + Index indexes1 = {7, 16, 20, 23, 18, 4, 9, 11, 6, 9, 13}; + Index indexes2 = {12, 10, 22, 23, 24, 25, 9, 11, 2, 1, 3}; // puvodní indexy + Index indexes3 = {7, 16, 20, 23, 18, 4, 9, 11, 6, 9, 13}; + + indexes.insert(std::pair(1, indexes1)); + indexes.insert(std::pair(2, indexes2)); + indexes.insert(std::pair(3, indexes3)); + + result = baseString.at(licType) + to_string(lIdentification.licenceIndex) + "_"; + + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[0]] + (lIdentification.licenceIndex * 11)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[1]] + (lIdentification.licenceIndex * 39)) % 25); + + result += prefixChar + ((this->sdCard.cardData.CID_nibble[indexes.at(lVersion).index[2]] + (lIdentification.licenceIndex * 1)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID_nibble[indexes.at(lVersion).index[3]] * 2) % 25); + result += prefixChar + ((this->sdCard.cardData.CID_nibble[indexes.at(lVersion).index[4]] + (lIdentification.licenceIndex * 5)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID_nibble[indexes.at(lVersion).index[5]] * 3) % 25); + + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[6]] + (lIdentification.licenceIndex * 52)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[7]] + (lIdentification.licenceIndex * 34)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[8]] + (lIdentification.licenceIndex * 21)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[9]] + (lIdentification.licenceIndex * 47)) % 25); + result += prefixChar + ((this->sdCard.cardData.CID[indexes.at(lVersion).index[10]] + (lIdentification.licenceIndex * 7)) % 25); + + result += ".lic"; + return result; +} + +int LicenceELC21::getDataPointsCount(int protocolId) +{ + if (this->readLicence(nullptr) == false) + { + } + + for (auto item : this->licBody.privateContent.dataItems) + { + if (item.protoId == protocolId) + return item.licCount; + } + return 0; +} + +bool LicenceELC21::getLicenceItemInfo(int protocolId, void *returnItemStructure) +{ + if (returnItemStructure != nullptr) + { + LicenceItem21 *resultPtr = static_cast(returnItemStructure); + resultPtr->protocolId = protocolId; // protocolId; + if (this->licenceInfo.licences.count(protocolId)) resultPtr->dataPointsCount=this->licenceInfo.licences.at(protocolId); + else resultPtr->dataPointsCount = 0; + } + else + { + errorMessage.code = 1; + errorMessage.message = "Error: Null pointer!"; + return false; + } + + return true; +} + +bool LicenceELC21::getLicenceInfo(int protocolId, void *returnStructure) +{ + if (returnStructure != nullptr) + { + LicenceInfo21 *resultPtr = static_cast(returnStructure); + for (auto item : this->licBody.privateContent.dataItems) + { + resultPtr->licences.insert(pair(item.protoId, item.licCount)); + if (item.protoId == protocolId) resultPtr->reqDataPointsCount = item.licCount; + } + } + else + { + errorMessage.code = 1; + errorMessage.message = "Error: Null pointer!"; + return false; + } + + return true; +} + +LicenceELC21::~LicenceELC21() {} diff --git a/src/utils.cpp b/src/utils.cpp index 78e99d9..4f716fc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,4 +1,4 @@ -#include + #include #include #include @@ -11,7 +11,8 @@ #include #include #include -#include +#include +#include // #include // #include @@ -75,7 +76,10 @@ void getCharsFromString1(string source, char *charArray) void getCharsFromString(string &source, char *charArray, int length) { memset(charArray, 0, length); - for (int i = 0; i < length; i++) { charArray[i] = source[i]; } + for (int i = 0; i < length; i++) + { + charArray[i] = source[i]; + } } void getCharsFromString(string source, char *charArray) @@ -399,6 +403,14 @@ DATE getLicDate() return dateOnly; } +string getDate() +{ + auto r = std::chrono::system_clock::now(); + auto rp = std::chrono::system_clock::to_time_t(r); + std::string h(ctime(&rp)); // converting to c++ string + return h; +} + std::vector aes256_cbc_encrypt(const std::vector &plaintext, const std::vector &key, const std::vector &iv) { std::vector ciphertext; @@ -430,7 +442,7 @@ void handleErrors(void) abort(); } -int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, +int encrypt(const unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; @@ -475,7 +487,7 @@ int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, return ciphertext_len; } -int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, +int decrypt(const unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; @@ -725,10 +737,10 @@ std::string base64_encode_ai(const std::string &input) return encoded; } -map getArguments(int argc, char *argv[]) +unordered_map getArguments(int argc, char *argv[]) { const char splitChar = '='; - map result; + unordered_map result; if (argc <= 1) return result; @@ -762,10 +774,10 @@ map getArguments(int argc, char *argv[]) return result; } -map mapArguments(int argc, char *argv[]) +unordered_map mapArguments(int argc, char *argv[]) { const char splitChar = '='; - map result; + unordered_map result; if (argc <= 1) return result; @@ -804,11 +816,174 @@ map mapArguments(int argc, char *argv[]) string getCompletePath(string fileName) { - //std::filesystem::path executablePath = std::filesystem::canonical(std::filesystem::current_path()); // / std::filesystem::path(argv[0])); - std::filesystem::path exePath = std::filesystem::canonical("/proc/self/exe"); // / std::filesystem::path(argv[0])); - //std::filesystem::path fullPath = executablePath.parent_path() / "licenceData.xml"; +#ifdef WINDOWS + return fileName; +#else + std::filesystem::path exePath = std::filesystem::canonical("/proc/self/exe"); // / std::filesystem::path(argv[0])); std::filesystem::path fullPathOther = exePath.parent_path() / fileName; - //std::string fullPathStr = fullPath.string(); std::string fullPathStrOther = fullPathOther.string(); return fullPathStrOther; +#endif +} + +char *getFileContent(string fileName) +{ + FILE *file; + char ch; + long lSize; + size_t result; + + const int fileNameLength = fileName.length(); + char fileNameCh[fileNameLength] = {}; + for (int i = 0; i < fileName.length(); i++) + fileNameCh[i] = fileName[i]; + + file = fopen(fileNameCh, "rb"); // read mode + fseek(file, 0, SEEK_END); // seek to end of file + const int size = ftell(file); // get current file pointer + fseek(file, 0, SEEK_SET); + + if (file == NULL) + { + perror("Error while opening the file.\n"); + return nullptr; + } + + char licenceContent[size]; + + for (int i = 0; i < size; i++) + { + ch = fgetc(file); + licenceContent[i] = ch; + } + + fclose(file); + + return licenceContent; +} + +void appendStringToVector(const std::string &str, std::vector &charVector) +{ + // Get the length of the string + size_t strLength = str.length(); + + // Append each character of the string to the vector + for (size_t i = 0; i < strLength; ++i) + { + charVector.push_back(static_cast(str[i])); + } +} + +void coutVector(std::vector &charVector) +{ + for (const auto &elem : charVector) + { + std::cout << elem; + } +} + +uint16_t calculateCRC16(std::vector &charVector) +{ + const uint16_t polynomial = 0xA001; // CRC16-CCITT polynomial + uint16_t crc = 0xFFFF; // Initial value + + size_t length = charVector.size(); + + for (size_t i = 0; i < length; i++) + { + crc ^= charVector[i]; // XOR with the current data byte + + for (int j = 0; j < 8; j++) + { + if (crc & 0x0001) + { + crc = (crc >> 1) ^ polynomial; + } + else + { + crc = crc >> 1; + } + } + } + + return crc; +} + +uint32_t bytesToDword(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4) +{ + return static_cast(byte1) | + (static_cast(byte2) << 8) | + (static_cast(byte3) << 16) | + (static_cast(byte4) << 24); +} + +uint32_t bytesToWord(uint8_t byte1, uint8_t byte2) +{ + return static_cast(byte1) | (static_cast(byte2) << 8); +} + +std::vector joinVectors(const std::vector &vector1, const std::vector &vector2) +{ + std::vector result; + result.insert(result.end(), vector1.begin(), vector1.end()); + result.insert(result.end(), vector2.begin(), vector2.end()); + return result; +} + +string readFileToString(const std::string &filename, std::size_t sizeS) +{ + + std::ifstream file(filename, std::ios::binary); + + if (!file.is_open()) + { + std::cerr << "Error: Could not open file '" << filename << "'" << std::endl; + return ""; // Return an empty string to indicate an error + } + + // Read the file into a stringstream + std::stringstream buffer; + buffer << file.rdbuf(); + + // Get the content of the stringstream as a string + std::string fileContent = buffer.str(); + + // Ensure the string has at most sizeS characters + if (fileContent.size() > sizeS) + { + fileContent.resize(sizeS); + } + + return fileContent; +} + +bool readFile(string fileName, vector &output) +{ + std::ifstream file(fileName, std::ios::in | std::ios::binary); + + if (!file.is_open()) + { + return false; + } + + char byte; + while (file.get(byte)) + { + // Convert the char to unsigned char and push it into the vector + output.push_back(byte); + } + + +// Get the size of the file + // file.seekg(0, std::ios::end); + // streampos fileSize = file.tellg(); + // file.seekg(0, std::ios::beg); + + // Read the file into the buffer + // if (!file.read(reinterpret_cast(content.data()), fileSize)) + // { + // throw LicenceException((int)GeneralError::FileReadError, "Chyba otevření souboru."); + // } + + return true; }