diff --git a/output/ezlic_eovosv0_jjacdgpdxpb.lic b/output/ezlic_eovosv0_jjacdgpdxpb.lic
index 4efdd87..f2eee96 100644
Binary files a/output/ezlic_eovosv0_jjacdgpdxpb.lic and b/output/ezlic_eovosv0_jjacdgpdxpb.lic differ
diff --git a/output/ezlic_eovosv0_wqxcyjpdxji.lic b/output/ezlic_eovosv0_wqxcyjpdxji.lic
index 6731e88..3d0a18f 100644
Binary files a/output/ezlic_eovosv0_wqxcyjpdxji.lic and b/output/ezlic_eovosv0_wqxcyjpdxji.lic differ
diff --git a/output/licData.xml b/output/licData.xml
index 47acd9a..1cfdec3 100644
--- a/output/licData.xml
+++ b/output/licData.xml
@@ -1,27 +1,29 @@
-EOV_OSV
-WAGO
+EOV_OSV
+wago
Licence pro EOV_OSV
-odb.zaluzi.drt.cz
-POZ8
-Projekt XXX stanice YYY
-
- -
- Položka licence 1
- 111
- 40000
-
- -
- Položka licence 2
- 222
- 51000
-
- -
- Položka licence 3
- 333
- 62000
-
-
-
+testovaci projekt
+
+-
+pt_Ez_iec104c
+5
+2500
+
+-
+pt_Ez_iec104s
+6
+15000
+
+-
+pt_Ez_mdbipc
+9
+250
+
+-
+pt_Ez_mdbips
+10
+400
+
+
\ No newline at end of file
diff --git a/output/licDataOld.xml b/output/licDataOld.xml
new file mode 100644
index 0000000..47acd9a
--- /dev/null
+++ b/output/licDataOld.xml
@@ -0,0 +1,27 @@
+
+
+EOV_OSV
+WAGO
+Licence pro EOV_OSV
+odb.zaluzi.drt.cz
+POZ8
+Projekt XXX stanice YYY
+
+ -
+ Položka licence 1
+ 111
+ 40000
+
+ -
+ Položka licence 2
+ 222
+ 51000
+
+ -
+ Položka licence 3
+ 333
+ 62000
+
+
+
+
\ No newline at end of file
diff --git a/output/licenceGenerator b/output/licenceGenerator
index fba0e59..9bd0a56 100644
Binary files a/output/licenceGenerator and b/output/licenceGenerator differ
diff --git a/output/temp/generate/licenceGenerator b/output/temp/generate/licenceGenerator
new file mode 100644
index 0000000..74d7d1c
Binary files /dev/null and b/output/temp/generate/licenceGenerator differ
diff --git a/output/temp/read/licenceGenerator b/output/temp/read/licenceGenerator
new file mode 100644
index 0000000..9bd0a56
Binary files /dev/null and b/output/temp/read/licenceGenerator differ
diff --git a/src/CreateLicence.cpp b/src/CreateLicence.cpp
index 4ce2ca9..9e7a44a 100644
--- a/src/CreateLicence.cpp
+++ b/src/CreateLicence.cpp
@@ -8,7 +8,7 @@
/// @param argc
/// @param argv parametry pro generování licence
/// @return
-int main6(int argc, char *argv[])
+int main(int argc, char *argv[])
{
unordered_map arguments = getArguments(argc, argv);
try
diff --git a/src/ReadLicence.cpp b/src/ReadLicence.cpp
index 775895a..99a8e68 100644
--- a/src/ReadLicence.cpp
+++ b/src/ReadLicence.cpp
@@ -7,7 +7,7 @@
/// @param argc
/// @param argv parametry pro generování licence
/// @return
-int main()
+int main6()
{
try
@@ -18,8 +18,8 @@ int main()
initStructure.licenceIndex = 0;
initStructure.licenceFilePath = ""; // cesta k licenčnímu souboru
// initStructure.compatibility = 0; v případě kompatibility 0 či nezadané je výstup defaultní.
- // pro ELC 1 LicenceELC1Info s výstupem isValid, pro ELC 2 strukura { int protocolId = -1; int dataPointsCount = 0; }
- initStructure.cid_csd_filePath = ""; // cesta k cidu/csd pro načtení a kontorlu licence
+ // pro ELC 1 LicenceELC1Info je to isValid, pro ELC 2 strukura { int protocolId = -1; int dataPointsCount = 0; }
+ initStructure.cid_csd_filePath = ""; // cesta k cidu/csd pro načtení a kontrolu licence
//verze původní ELC 1
LicenceReader licenceReaderELC1{};
@@ -46,7 +46,8 @@ int main()
if (licenceReaderELC2.initread(2, initStructure)) // iniciacni nacteni
{
// v případě kompatibility 0, či nezadané výstup nativně je defaultní.
- // v případně nenulové kompatibility, třeba 1, přidáme číslo kompatibility. Tedy pro ELC1 to bude LicenceELC1_1, pro ELC LicenceELC2_1
+ // v případně nenulové kompatibility, třeba 1, přidáme číslo kompatibility.
+ //Tedy pro ELC1 to bude LicenceELC1_1, pro ELC LicenceELC2_1
LicenceELC2Item info; // podle ELC a kompatibility určit strukuru (LicenceInfo11, LicenceInfo21, LicenceInfo31)
// if ()
int protocolId = 333;
@@ -77,7 +78,7 @@ int main()
//verze ELC 2 kompletní načtení
if (licenceReaderCompleteELC2.init(2, initStructure)) // iniciacni nacteni
{
- LicenceELC2Info info; // podle ELC a kompatibility určit strukuru (LicenceInfo11, LicenceInfo21, LicenceInfo31)
+ LicenceELC2Info info;
int protocolId = 333;
if (licenceReaderCompleteELC2.getLicenceInfo(&info))
@@ -106,17 +107,6 @@ int main()
{
cout << "Obecna chyba\n";
}
- // system("pause");
return SUCCES;
}
-/*
-CRC public size: 353
-CRC gen public: 27885
-
-CRC private size: 285
-CRC gen private: 18500
-
-CRC complete size: 638
-CRC gen complete: 42051
-*/
\ No newline at end of file
diff --git a/src/generator/LicenceGenerator.cpp b/src/generator/LicenceGenerator.cpp
index 3b1f27d..aca47d7 100644
--- a/src/generator/LicenceGenerator.cpp
+++ b/src/generator/LicenceGenerator.cpp
@@ -83,6 +83,7 @@ bool LicenceGenerator::processInputConfiguration()
}
else
{
+ cout << "file: " << fileName << "\n";
throw LicenceException((int)GeneralError::FileOpenError, "Unable to open the config file.");
}
@@ -118,15 +119,15 @@ void LicenceGenerator::createLicenceELC2()
switch (this->licIdentification.licCompatibility)
{
case 1:
+ {
Generator::Licence2 licence = Generator::Licence2(licData.cid,licData.csd,licData.doc);
licence.createLicence();
- /*
- licence.createLicence();
- // LicenceELC21 licence = LicenceELC21(this->licData);
- // licence.createLicence();
- */
- break;
+ break;
}
+ default: throw LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Compatibility not implemented.");
+
+ }
+
}
void LicenceGenerator::createLicenceELC3()
diff --git a/src/generator/LicenceGenerator.o b/src/generator/LicenceGenerator.o
index 06b6f48..912fb08 100644
Binary files a/src/generator/LicenceGenerator.o and b/src/generator/LicenceGenerator.o differ
diff --git a/src/generator/licGenELC2.cpp b/src/generator/licGenELC2.cpp
index 1801bda..8f5701f 100644
--- a/src/generator/licGenELC2.cpp
+++ b/src/generator/licGenELC2.cpp
@@ -23,7 +23,7 @@ namespace Generator
void Licence2::getHeader()
{
PublicHeader publicHeader;
- publicHeader.version = getVersion(7);
+ publicHeader.version = getVersion(lIdentification.revision);
publicHeader.projectDescription = projectDescription;
publicHeader.date = getDate();
publicHeader.licenceType = lIdentification.licTypeName;
@@ -98,7 +98,7 @@ namespace Generator
result.append(".");
result.append(to_string(middleVersion));
result.append(".");
- string tempLicenceCount = "3"; // TODO
+ string tempLicenceCount = "1"; // TODO
result.append(tempLicenceCount);
return result;
}
@@ -121,7 +121,7 @@ namespace Generator
}
this->lIdentification.licenceVersion = atoi(&xmlDoc->child(dataRootName).child("licenceType").attribute("licenceVersion").value()[0]);
- this->lIdentification.revision = xmlDoc->child(dataRootName).attribute("revision").value()[0];
+ this->lIdentification.revision = atoi(&xmlDoc->child(dataRootName).attribute("revision").value()[0]);
this->lIdentification.licenceIndex = atoi(&xmlDoc->child(dataRootName).child("licenceType").attribute("licenceIndex").value()[0]);
this->lIdentification.licElcType = (ELCType)atoi(&xmlDoc->child(dataRootName).attribute("elc").value()[0]);
diff --git a/src/generator/licGenELC2.o b/src/generator/licGenELC2.o
index a41ba6a..40a68ef 100644
Binary files a/src/generator/licGenELC2.o and b/src/generator/licGenELC2.o differ
diff --git a/src/reader/LicenceReader.cpp b/src/reader/LicenceReader.cpp
index c86ab44..21cecfd 100644
--- a/src/reader/LicenceReader.cpp
+++ b/src/reader/LicenceReader.cpp
@@ -64,7 +64,7 @@ bool LicenceReader::initread(int elcType, InitStructure &initStructure)
switch (this->licIdentification.licElcType)
{
case ELCType::ELC1:
- { // old eoseov
+ {
Reader::Licence1 licenceELC1 = Reader::Licence1(this->licIdentification);
this->licence1 = &licenceELC1;
licenceELC1.cid_cdsPath = initStructure.cid_csd_filePath;
@@ -143,7 +143,7 @@ bool LicenceReader::getLicenceItemInfo(int protocolId, void *returnItemStructure
if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
{
LicenceELC2Item *resultPtr = static_cast(returnItemStructure);
- resultPtr->protocolId = protocolId; // protocolId;
+ resultPtr->protocolId = protocolId;
if (this->licenceInfo.licences.count(protocolId))
resultPtr->dataPointsCount = this->licenceInfo.licences.at(protocolId);
else
diff --git a/src/reader/licReaderELC2.cpp b/src/reader/licReaderELC2.cpp
index 7ba21a6..1920220 100644
--- a/src/reader/licReaderELC2.cpp
+++ b/src/reader/licReaderELC2.cpp
@@ -62,10 +62,6 @@ namespace Reader
vector encryptedPart(content.begin() + licBody.licenceIdentHeader.publicHeaderLength + 18, content.begin() + content.size());
- // cout << "encryptedPart content length: " << encryptedPart.size() << "\n";
- // for (auto x : encryptedPart) cout << (int)x << "-";
- // cout << "\n";
-
vector privateContentDecrypted;
privateContentDecrypted = decryptPrivateContent(encryptedPart);
diff --git a/src/reader/licReaderELC2.o b/src/reader/licReaderELC2.o
index b532ae4..dcd1f62 100644
Binary files a/src/reader/licReaderELC2.o and b/src/reader/licReaderELC2.o differ
diff --git a/zdenda/Makefile b/zdenda/Makefile
new file mode 100644
index 0000000..1dffacf
--- /dev/null
+++ b/zdenda/Makefile
@@ -0,0 +1,100 @@
+#
+# 'make' build executable file 'main'
+# 'make clean' removes all .o and executable files
+#
+
+# define the Cpp compiler to use
+CXX = g++
+
+# define any compile-time flags
+# CXXFLAGS := -std=c++17 -Wall -Wextra -g -lssl -lcrypto -w
+CXXFLAGS := -Wall -Wextra -g -lssl -lcrypto
+
+# define library paths in addition to /usr/lib
+# if I wanted to include libraries not in /usr/lib I'd specify
+# their path using -Lpath, something like:
+LFLAGS =
+
+# define output directory
+OUTPUT := output
+
+# define source directory
+SRC := src src/common src/reader
+
+# define include directory
+INCLUDE := include include/common include/reader
+
+# define lib directory
+LIB := lib
+
+ifeq ($(OS),Windows_NT)
+MAIN := licenceGenerator.exe
+SOURCEDIRS := $(SRC)
+INCLUDEDIRS := $(INCLUDE)
+LIBDIRS := $(LIB)
+FIXPATH = $(subst /,\,$1)
+RM := del /q /f
+MD := mkdir
+else
+MAIN := licenceGenerator
+SOURCEDIRS := $(shell find $(SRC) -type d)
+INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
+LIBDIRS := $(shell find $(LIB) -type d)
+FIXPATH = $1
+RM = rm -f
+MD := mkdir -p
+endif
+
+# define any directories containing header files other than /usr/include
+INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
+
+# define the C libs
+LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
+
+# define the C source files
+SOURCES := $(wildcard $(patsubst %,%/*.cpp, $(SOURCEDIRS)))
+
+# define the C object files
+OBJECTS := $(SOURCES:.cpp=.o)
+
+# define the dependency output files
+DEPS := $(OBJECTS:.o=.d)
+
+#
+# The following part of the makefile is generic; it can be used to
+# build any executable just by changing the definitions above and by
+# deleting dependencies appended to the file from 'make depend'
+#
+
+OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
+
+all: $(OUTPUT) $(MAIN)
+ @echo Executing 'all' complete!
+
+$(OUTPUT):
+ $(MD) $(OUTPUT)
+
+$(MAIN): $(OBJECTS)
+ $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(OUTPUTMAIN) $(OBJECTS) $(LFLAGS) $(LIBS)
+
+# include all .d files
+-include $(DEPS)
+
+# this is a suffix replacement rule for building .o's and .d's from .c's
+# it uses automatic variables $<: the name of the prerequisite of
+# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
+# -MMD generates dependency output files same name as the .o file
+# (see the gnu make manual section about automatic variables)
+.cpp.o:
+ $(CXX) $(CXXFLAGS) $(INCLUDES) -c -MMD $< -o $@
+
+.PHONY: clean
+clean:
+ $(RM) $(OUTPUTMAIN)
+ $(RM) $(call FIXPATH,$(OBJECTS))
+ $(RM) $(call FIXPATH,$(DEPS))
+ @echo Cleanup complete!
+
+run: all
+ ./$(OUTPUTMAIN)
+ @echo Executing 'run: all' complete!
diff --git a/zdenda/src/ReadLicence.cpp b/zdenda/src/ReadLicence.cpp
new file mode 100644
index 0000000..9eea4bf
--- /dev/null
+++ b/zdenda/src/ReadLicence.cpp
@@ -0,0 +1,112 @@
+#define LINUX 1
+// #define WINDOWS 1
+
+#include "licenceReader.h"
+
+/// @brief hlavní funkce
+/// @param argc
+/// @param argv parametry pro generování licence
+/// @return
+int main()
+{
+
+ try
+ {
+ InitStructure initStructure;
+ initStructure.licenceType = (int)LicenceType::EOS_EOV;
+ initStructure.licenceVersion = 1;
+ initStructure.licenceIndex = 0;
+ initStructure.licenceFilePath = ""; // cesta k licenčnímu souboru
+ // initStructure.compatibility = 0; v případě kompatibility 0 či nezadané je výstup defaultní.
+ // pro ELC 1 LicenceELC1Info je to isValid, pro ELC 2 strukura { int protocolId = -1; int dataPointsCount = 0; }
+ initStructure.cid_csd_filePath = ""; // cesta k cidu/csd pro načtení a kontrolu licence
+
+ //verze původní ELC 1
+ LicenceReader licenceReaderELC1{};
+ if (licenceReaderELC1.initread(1, initStructure)) // iniciacni nacteni
+ {
+ LicenceELC1Info info; // struktura pro ELC1. Nemá tam asi nic jiného smysl nez true/false
+ if (licenceReaderELC1.getLicenceInfo(&info))
+ {
+ if (info.isValid)
+ cout << "Platna licence ELC1 \n";
+ else
+ cout << "Neplatna licence ELC1\n";
+ }
+ else
+ cout << "CHYBA: " << licenceReaderELC1.error.message;
+ }
+ else
+ {
+ cout << "CHYBA: " << licenceReaderELC1.error.message;
+ }
+
+ // verze ELC 2 pro jeden protokol
+ LicenceReader licenceReaderELC2{};
+ if (licenceReaderELC2.initread(2, initStructure)) // iniciacni nacteni
+ {
+ // v případě kompatibility 0, či nezadané výstup nativně je defaultní.
+ // v případně nenulové kompatibility, třeba 1, přidáme číslo kompatibility.
+ //Tedy pro ELC1 to bude LicenceELC1_1, pro ELC LicenceELC2_1
+ LicenceELC2Item info; // podle ELC a kompatibility určit strukuru (LicenceInfo11, LicenceInfo21, LicenceInfo31)
+ // if ()
+ int protocolId = 333;
+
+ // if (initStructure.compatibility == 1) //ukazka kompatibilita 1
+ // {
+ // LicenceELC2Item_1 info; //jiná struktura, zbytek stejný
+ // if (licenceReaderELC2.getLicenceItemInfo(protocolId, &info))
+ // {
+ // cout << "Pocet licencních bodu pro " << info.protocolId << ": " << info.dataPointsCount << std::endl;
+ // }
+ //...........
+ // }
+
+ if (licenceReaderELC2.getLicenceItemInfo(protocolId, &info))
+ {
+ cout << "Pocet licencních bodu pro " << info.protocolId << ": " << info.dataPointsCount << std::endl;
+ }
+ else
+ cout << "CHYBA: " << licenceReaderELC2.error.message;
+ }
+ else
+ {
+ cout << "CHYBA: " << licenceReaderELC2.error.message;
+ }
+
+ LicenceReader licenceReaderCompleteELC2{};
+ //verze ELC 2 kompletní načtení
+ if (licenceReaderCompleteELC2.init(2, initStructure)) // iniciacni nacteni
+ {
+ LicenceELC2Info info;
+ int protocolId = 333;
+
+ if (licenceReaderCompleteELC2.getLicenceInfo(&info))
+ {
+ if (info.licences.count(protocolId) > 0)
+ cout << "Pocet bodu z vectoru pro protokol : " << protocolId << ": " << info.licences.at(protocolId) << "\n";
+ else
+ cout << "Pro tento protokol nejsou definovay licencni body\n";
+ cout << "Vypis vsech licencnich bodu: " << endl;
+ for (const auto &pair : info.licences)
+ {
+ std::cout << "<" << pair.first << ", " << pair.second << ">" << endl;
+ }
+ }
+ else
+ cout << "CHYBA: " << licenceReaderCompleteELC2.error.message;
+
+ }
+ else
+ {
+ cout << "CHYBA: " << licenceReaderCompleteELC2.error.message;
+ }
+
+ }
+ catch (...)
+ {
+ cout << "Obecna chyba\n";
+ }
+ return SUCCES;
+}
+
diff --git a/zdenda/src/common/SDCard.cpp b/zdenda/src/common/SDCard.cpp
new file mode 100644
index 0000000..0f313f6
--- /dev/null
+++ b/zdenda/src/common/SDCard.cpp
@@ -0,0 +1,143 @@
+#include "utils.h"
+#include "SDCard.h"
+
+SDCard::SDCard()
+{
+}
+
+SDCard::SDCard(const string cds_cid_Path)
+{
+ this->filePath = cds_cid_Path;
+ if (getCIDFromFile() == false)
+ return;
+ if (getCSDFromFile() == false)
+ return;
+ this->isLoaded = SDCard::readSDCard();
+}
+
+SDCard::SDCard(string cid, string csd)
+{
+ for (unsigned int i = 0; i < cid.length(); i++)
+ this->cid[i] = cid[i];
+ for (unsigned 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];
+
+ // 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;
+ }
+
+ BYTE sdCrc = 0;
+ for (int i = 0; i <= 14; i++)
+ {
+ BYTE sdChar = this->cardData.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->cardData.CRCOK = ((sdCrc << 1) | 1) == this->cardData.CID[15];
+ this->cardData.crcCorrect = (int)this->cardData.CID[15] == (int)((sdCrc << 1) | 1);
+ return this->cardData.crcCorrect;
+}
+
+bool SDCard::getCIDFromFile()
+{
+ vector content;
+ if (readFile(this->filePath + "cid", content) == false)
+ {
+ return false;
+ }
+
+ if (content.size() >= CID_LENGTH)
+ {
+ for (int i = 0; i < 32; i++)
+ this->cid[i] = content[i];
+ }
+ else
+ return false;
+
+ return true;
+}
+
+bool SDCard::getCSDFromFile()
+{
+ vector content;
+ if (readFile(this->filePath + "csd", content) == false)
+ {
+ return false;
+ }
+ if (content.size() >= CSD_LENGTH)
+ {
+ for (int i = 0; i < 32; i++)
+ this->csd[i] = content[i];
+ }
+ else
+ return false;
+
+ return true;
+}
diff --git a/zdenda/src/common/licData.xml b/zdenda/src/common/licData.xml
new file mode 100644
index 0000000..6f67b1f
--- /dev/null
+++ b/zdenda/src/common/licData.xml
@@ -0,0 +1,37 @@
+
+
+EOV_OSV
+WAGO
+Licence pro EOV_OSV
+eov.ceskatrebova.ddts.cz
+eov2
+Projekt XXX stanice YYY
+
+ -
+ Položka licence 1
+ 111
+ 100
+
+ -
+ Položka licence 2
+ 222
+ 200
+
+ -
+ Položka licence 3
+ 333
+ 300
+
+ -
+ Položka licence 3
+ 444
+ 1600
+
+-
+ Položka licence 4
+ 555
+ 1999
+
+
+
+
\ No newline at end of file
diff --git a/zdenda/src/common/licenceELC1.cpp b/zdenda/src/common/licenceELC1.cpp
new file mode 100644
index 0000000..8edb22d
--- /dev/null
+++ b/zdenda/src/common/licenceELC1.cpp
@@ -0,0 +1,218 @@
+#include "licenceELC1.h"
+#include "utils.h"
+
+#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 cnibblescount1 = 32;
+std::string cSDMonthStr1[] = {"-", "I.", "II.", "III.", "IV.", "V.", "VI.", "VII.", "VIII.", "IX.", "X.", "XI.", "XII.", "-", "-", "-"};
+BYTE cHexNibble_to_No1[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 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";
+
+LicenceELC1::LicenceELC1() {}
+
+LicenceELC1::~LicenceELC1() {}
+
+LicenceELC1::LicenceELC1(LicenceIdentification &licIdentification) : lIdentification(licIdentification)
+{
+}
+
+bool LicenceELC1::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_No1[this->sdData.CID_nibble[2 * i]] << 4 | cHexNibble_to_No1[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_No1[this->sdData.CID[16]];
+ this->sdData.productRevision_sw = cHexNibble_to_No1[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_No1[this->sdData.CID_nibble[27]] * 10 + cHexNibble_to_No1[this->sdData.CID_nibble[28]] + 2000;
+ this->sdData.manufacturerDate_month = cHexNibble_to_No1[this->sdData.CID_nibble[29]];
+ string date = cSDMonthStr1[this->sdData.manufacturerDate_month] + std::to_string(this->sdData.manufacturerDate_year);
+
+ for (unsigned i = 0; i < date.length(); i++)
+ this->sdData.manufacturerDate[i] = date[i];
+
+ // CSD
+ for (unsigned int i = 0; i < CSD_LENGTH; i++) this->sdData.CSD_nibble[i] = (BYTE)csd[i];
+
+ for (unsigned int i = 0; i < cnibblescount / 2; i++)
+ {
+ this->sdData.CSD[i] = cHexNibble_to_No1[this->sdData.CSD_nibble[2 * i]] << 4 | cHexNibble_to_No1[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;
+ }
+
+ 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];
+
+ return (int)this->sdData.CID[15] == (int)((sdCrc << 1) | 1);
+
+}
+
+void LicenceELC1::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 LicenceELC1::getLicenceName()
+{
+ string result = "";
+ char prefixChar = 97;
+ 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 LicenceELC1::getLicenceName(BYTE licPostfix)
+{
+ string result = "";
+ char prefixChar = 97;
+
+ 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;
+}
diff --git a/zdenda/src/common/licenceELC2.cpp b/zdenda/src/common/licenceELC2.cpp
new file mode 100644
index 0000000..fa2b48d
--- /dev/null
+++ b/zdenda/src/common/licenceELC2.cpp
@@ -0,0 +1,172 @@
+#include "licenceELC2.h"
+#include "utils.h"
+
+
+ LicenceELC2::LicenceELC2(){}
+
+ LicenceELC2::~LicenceELC2(){}
+
+ LicenceELC2::LicenceELC2(LicenceIdentification &licIdentification): lIdentification(licIdentification)
+ {}
+
+ /// @brief get proper licencename
+/// @param licPostfix
+/// @return
+string LicenceELC2::getLicenceName()
+{
+ 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 = {8, 13, 11, 9, 7, 11, 10, 13, 5, 20, 19};
+
+ 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;
+}
+
+vector LicenceELC2::cryptPrivateContent(const std::vector &content)
+{
+
+ BYTE initVector[15] = {};
+ BYTE aesKey[32] = {};
+
+ LicenceELC2::initVector(initVector, aesKey);
+
+ unsigned char encrypted[10000] = {};
+ const unsigned char *plainTextArray = content.data();
+ int finalEncryptedLength = encrypt(plainTextArray, content.size(), aesKey, initVector, encrypted);
+
+ if (finalEncryptedLength <= 0) throw LicenceException((int)GeneralError::EncryptError, "Chyba při kryptování.");
+
+ std::vector result(encrypted, encrypted + finalEncryptedLength);
+
+ return result;
+}
+
+vector LicenceELC2::decryptPrivateContent(const std::vector &content)
+{
+
+ BYTE initVector[15] = {0};
+ BYTE aesKey[32] = {0};
+
+ LicenceELC2::initVector(initVector, aesKey);
+
+ const unsigned char *encryptedData = content.data();
+ unsigned char decrypted[10000] = {};
+
+ int decrypted_len = decrypt(encryptedData, content.size(), aesKey, initVector, decrypted);
+ if (decrypted_len <= 0) throw LicenceException((int)GeneralError::DecryptError, "Chyba při dekryptování.");
+
+ std::vector result(decrypted, decrypted + decrypted_len);
+
+ return result;
+}
+
+void LicenceELC2::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);
+}
+
+
diff --git a/zdenda/src/common/utils.cpp b/zdenda/src/common/utils.cpp
new file mode 100644
index 0000000..efbdf67
--- /dev/null
+++ b/zdenda/src/common/utils.cpp
@@ -0,0 +1,463 @@
+
+#include
+#include /* core library */
+#include "utils.h"
+
+using namespace std;
+
+const std::string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+const char base64_url_alphabet[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'};
+
+void getCharsFromString(string &source, char *charArray, size_t length)
+{
+ for (size_t i = 0; i < length; i++)
+ {
+ charArray[i] = source[i];
+ }
+}
+
+void getCharsFromString(string source, char *charArray)
+{
+ size_t length = source.length();
+ for (size_t i = 0; i < length; i++)
+ {
+ charArray[i] = source[i];
+ }
+}
+
+std::string right(const std::string &sourceString, size_t numChars)
+{
+ if (numChars >= sourceString.size())
+ {
+ return sourceString; // If numChars is greater or equal to the string size, return the whole string.
+ }
+ return sourceString.substr(sourceString.size() - numChars);
+}
+
+uint16_t calculateCRC16(const uint8_t *data, size_t length)
+{
+ const uint16_t polynomial = 0xA001; // CRC16-CCITT polynomial
+ uint16_t crc = 0xFFFF; // Initial value
+
+ for (size_t i = 0; i < length; i++)
+ {
+ crc ^= data[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;
+}
+
+uint16_t crc16(const unsigned char *data_p, unsigned char length)
+{
+ uint16_t x;
+ uint16_t crc = 0xFFFF;
+
+ while (length--)
+ {
+ x = crc >> 8 ^ *data_p++;
+ x ^= x >> 4;
+ crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
+ }
+ return crc;
+}
+
+DATE getLicDate()
+{
+ time_t ttime = time(0);
+ tm *local_time = localtime(&ttime);
+ int hoursSeconds = 3600 * local_time->tm_hour;
+ int minutesSeconds = 60 * local_time->tm_min;
+ int seconds = 1 * local_time->tm_sec;
+ int totalSeconds = hoursSeconds + minutesSeconds + seconds;
+
+#ifdef WINDOWS
+ DATE dateOnly = ttime - totalSeconds + 7200; // (pro windows); // 7200 + vteřina za dvě hodiny pro srování
+#else
+ DATE dateOnly = ttime - totalSeconds;
+#endif
+
+ 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;
+}
+
+int encrypt(const unsigned char *plaintext, int plaintext_len, unsigned char *key,
+ unsigned char *iv, unsigned char *ciphertext)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ int len;
+
+ int ciphertext_len;
+
+ /* Create and initialise the context */
+ if (!(ctx = EVP_CIPHER_CTX_new()))
+ return -1;
+
+ /*
+ * Initialise the encryption operation. IMPORTANT - ensure you use a key
+ * and IV size appropriate for your cipher
+ * In this example we are using 256 bit AES (i.e. a 256 bit key). The
+ * IV size for *most* modes is the same as the block size. For AES this
+ * is 128 bits
+ */
+ if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
+ return -1;
+
+ /*
+ * Provide the message to be encrypted, and obtain the encrypted output.
+ * EVP_EncryptUpdate can be called multiple times if necessary
+ */
+ if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
+ return -1;
+ ciphertext_len = len;
+
+ /*
+ * Finalise the encryption. Further ciphertext bytes may be written at
+ * this stage.
+ */
+ if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
+ return -1;
+ ciphertext_len += len;
+
+ /* Clean up */
+ EVP_CIPHER_CTX_free(ctx);
+
+ return ciphertext_len;
+}
+
+int decrypt(const unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
+ unsigned char *iv, unsigned char *plaintext)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ int len;
+
+ int plaintext_len;
+
+ /* Create and initialise the context */
+ if (!(ctx = EVP_CIPHER_CTX_new()))
+ return -1;
+
+ /*
+ * Initialise the decryption operation. IMPORTANT - ensure you use a key
+ * and IV size appropriate for your cipher
+ * In this example we are using 256 bit AES (i.e. a 256 bit key). The
+ * IV size for *most* modes is the same as the block size. For AES this
+ * is 128 bits
+ */
+ if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
+ return -1;
+
+ /*
+ * Provide the message to be decrypted, and obtain the plaintext output.
+ * EVP_DecryptUpdate can be called multiple times if necessary.
+ */
+ if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
+ return -1;
+ plaintext_len = len;
+
+ /*
+ * Finalise the decryption. Further plaintext bytes may be written at
+ * this stage.
+ */
+ if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
+ return -1;
+
+ plaintext_len += len;
+
+ /* Clean up */
+ EVP_CIPHER_CTX_free(ctx);
+
+ return plaintext_len;
+}
+
+// converts character array
+// to string and returns it
+string convertToString(char *a, int size)
+{
+ int i;
+ string s = "";
+ for (i = 0; i < size; i++)
+ {
+ s = s + a[i];
+ }
+ return s;
+}
+
+std::string base64_decode(const std::string &in)
+{
+ std::string out;
+ std::vector T(256, -1);
+ unsigned int i;
+ for (i = 0; i < 64; i++)
+ T[base64_url_alphabet[i]] = i;
+
+ int val = 0, valb = -8;
+ for (i = 0; i < in.length(); i++)
+ {
+ unsigned char c = in[i];
+ if (T[c] == -1)
+ break;
+ val = (val << 6) + T[c];
+ valb += 6;
+ if (valb >= 0)
+ {
+ out.push_back(char((val >> valb) & 0xFF));
+ valb -= 8;
+ }
+ }
+ return out;
+}
+
+std::string base64_encode_ai(const std::string &input)
+{
+ std::string encoded;
+
+ size_t input_length = input.length();
+ size_t i = 0;
+
+ while (i < input_length)
+ {
+ unsigned char input_chunk[3] = {0};
+ size_t chunk_size = 0;
+
+ // Fill the input chunk with up to 3 bytes from the input string
+ for (size_t j = 0; j < 3; ++j)
+ {
+ if (i < input_length)
+ {
+ input_chunk[j] = input[i++];
+ ++chunk_size;
+ }
+ }
+
+ // Encode the input chunk into 4 Base64 characters
+ encoded += base64_chars[(input_chunk[0] & 0xFC) >> 2];
+ encoded += base64_chars[((input_chunk[0] & 0x03) << 4) |
+ ((input_chunk[1] & 0xF0) >> 4)];
+ encoded += (chunk_size > 1)
+ ? base64_chars[((input_chunk[1] & 0x0F) << 2) |
+ ((input_chunk[2] & 0xC0) >> 6)]
+ : '=';
+ encoded += (chunk_size > 2)
+ ? base64_chars[input_chunk[2] & 0x3F]
+ : '=';
+ }
+
+ return encoded;
+}
+
+unordered_map getArguments(int argc, char *argv[])
+{
+ const char splitChar = '=';
+ unordered_map result;
+ if (argc <= 1)
+ return result;
+
+ for (int i = 1; i < argc; ++i)
+ {
+ bool isArgName = true;
+ int argLength = strlen(argv[i]);
+ string argName;
+ string argValue;
+
+ for (int j = 0; j < argLength; j++)
+ {
+ if (argv[i][j] == splitChar)
+ {
+ isArgName = false;
+ continue;
+ }
+
+ if (isArgName)
+ {
+ argName += argv[i][j];
+ }
+ else
+ {
+ argValue += argv[i][j];
+ }
+ }
+
+ result.insert(make_pair(argName, argValue));
+ }
+ return result;
+}
+
+string getCompletePath(string fileName)
+{
+#ifdef WINDOWS
+ return fileName;
+#else
+
+ char path[PATH_MAX + 1] = {};
+ ssize_t length = readlink("/proc/self/exe", path, PATH_MAX);
+ path[length] = '\0';
+ string result = string(dirname(path)) + "/" + fileName;
+ return result;
+ // return std::string( result, (count > 0) ? count : 0 );
+ // 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 fullPathStrOther = fullPathOther.string();
+ // return fullPathStrOther;
+#endif
+}
+
+void appendStringToVector(const std::string &str, std::vector &charVector)
+{
+ size_t strLength = str.length();
+ for (size_t i = 0; i < strLength; ++i)
+ {
+ charVector.push_back(static_cast(str[i]));
+ }
+}
+
+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;
+}
+
+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;
+}
+
+uint16_t calculateCRC16(std::vector &charVector, int removeCount)
+{
+ const uint16_t polynomial = 0xA001; // CRC16-CCITT polynomial
+ uint16_t crc = 0xFFFF; // Initial value
+
+ size_t length = charVector.size();
+ length = length-removeCount;
+
+ 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;
+}
+
+bool readFile(string fileName, vector &output)
+{
+ std::ifstream file(fileName, std::ios::in | std::ios::binary);
+
+ if (file.is_open() != 1)
+ {
+ return false;
+ }
+
+ char byte;
+ while (file.get(byte))
+ {
+ // Convert the char to unsigned char and push it into the vector
+ output.push_back(byte);
+ }
+
+ file.close();
+
+ return true;
+}
diff --git a/zdenda/src/output/cid b/zdenda/src/output/cid
new file mode 100644
index 0000000..9a70e3e
--- /dev/null
+++ b/zdenda/src/output/cid
@@ -0,0 +1,5 @@
+9f54495344434954615ad803c50171bf
+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/zdenda/src/output/csd b/zdenda/src/output/csd
new file mode 100644
index 0000000..609cf45
--- /dev/null
+++ b/zdenda/src/output/csd
@@ -0,0 +1,2 @@
+400e00325b5900003be77f800a400043
+
\ No newline at end of file
diff --git a/zdenda/src/output/ezlic_eovosv0_jjacdgpdxpb.lic b/zdenda/src/output/ezlic_eovosv0_jjacdgpdxpb.lic
new file mode 100644
index 0000000..4efdd87
Binary files /dev/null and b/zdenda/src/output/ezlic_eovosv0_jjacdgpdxpb.lic differ
diff --git a/zdenda/src/output/ezlic_eovosv0_wqxcyjpdxji.lic b/zdenda/src/output/ezlic_eovosv0_wqxcyjpdxji.lic
new file mode 100644
index 0000000..6731e88
Binary files /dev/null and b/zdenda/src/output/ezlic_eovosv0_wqxcyjpdxji.lic differ
diff --git a/zdenda/src/output/licData.xml b/zdenda/src/output/licData.xml
new file mode 100644
index 0000000..47acd9a
--- /dev/null
+++ b/zdenda/src/output/licData.xml
@@ -0,0 +1,27 @@
+
+
+EOV_OSV
+WAGO
+Licence pro EOV_OSV
+odb.zaluzi.drt.cz
+POZ8
+Projekt XXX stanice YYY
+
+ -
+ Položka licence 1
+ 111
+ 40000
+
+ -
+ Položka licence 2
+ 222
+ 51000
+
+ -
+ Položka licence 3
+ 333
+ 62000
+
+
+
+
\ No newline at end of file
diff --git a/zdenda/src/reader/LicenceReader.cpp b/zdenda/src/reader/LicenceReader.cpp
new file mode 100644
index 0000000..c86ab44
--- /dev/null
+++ b/zdenda/src/reader/LicenceReader.cpp
@@ -0,0 +1,265 @@
+#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
+
+LicenceReader::LicenceReader()
+{
+}
+
+/// @brief provede pouze inicialazaci čtecí třídy
+/// @param elcType
+/// @param initStructure
+/// @return
+bool LicenceReader::init(int elcType, InitStructure &initStructure)
+{
+ try
+ {
+ if (elcType > 3)
+ {
+ error.code = (int)GeneralError::ELCNotImplemented;
+ error.message = "ELC není implementováno.";
+ throw LicenceException((int)GeneralError::ELCNotImplemented, error.message);
+ }
+
+ this->licIdentification.licElcType = (ELCType)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 = elcType * 10 + licCompatibility;
+
+ return true;
+}
+
+/// @brief provede inicializaci čtecí třídy a zároveň načte licenční body do obecné struktury
+/// @param elcType
+/// @param licenceType
+/// @param licenceVersion
+/// @param licenceIndex
+/// @param compatibility
+/// @return
+bool LicenceReader::initread(int elcType, InitStructure &initStructure)
+{
+ try
+ {
+ elcSwitchType = elcType * 10 + initStructure.compatibility;
+
+ if (init(elcType, initStructure))
+ {
+ switch (this->licIdentification.licElcType)
+ {
+ case ELCType::ELC1:
+ { // old eoseov
+ Reader::Licence1 licenceELC1 = Reader::Licence1(this->licIdentification);
+ this->licence1 = &licenceELC1;
+ licenceELC1.cid_cdsPath = initStructure.cid_csd_filePath;
+ licenceELC1.licenceFilePath = initStructure.licenceFilePath;
+
+ try
+ {
+ this->licence1->readLicence(&this->licenceInfo);
+ }
+ catch (const LicenceException &ex)
+ {
+ error.code = ex.getErrorCode();
+ error.message = ex.getErrorMessage();
+ return false;
+ }
+ break;
+ }
+ case ELCType::ELC2:
+ {
+ Reader::Licence2 licenceELC2 = Reader::Licence2(this->licIdentification);
+ this->licence2 = &licenceELC2;
+ licenceELC2.cid_cdsPath = initStructure.cid_csd_filePath;
+ licenceELC2.licenceFilePath = initStructure.licenceFilePath;
+ this->licence2->readLicence(&this->licenceInfo);
+ break;
+ }
+ case ELCType::ELC3:
+ {
+ break;
+ }
+ default:
+ throw LicenceException((int)GeneralError::ELCNotImplemented, "Toto ELC není implementováno");
+ }
+ }
+ else
+ return false;
+ }
+ catch (const LicenceException &ex)
+ {
+ error.code = ex.getErrorCode();
+ error.message = ex.getErrorMessage();
+ return false;
+ }
+
+ return true; // TODO testy
+}
+
+/// @brief vrací informace o licenčím bodu na základě id protocolu a předané návratové struktury
+/// @param protocolId
+/// @param returnItemStructure
+/// @return
+bool LicenceReader::getLicenceItemInfo(int protocolId, void *returnItemStructure)
+{
+ try
+ {
+ switch (this->licIdentification.licElcType)
+ {
+ case ELCType::ELC1:
+ {
+ if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
+ {
+ LicenceELC1Info *resultPtr = static_cast(returnItemStructure);
+ if (this->licenceInfo.licences.count(1)) // stare eov má natvrdo "id" 1.
+ resultPtr->isValid = true;
+ else
+ resultPtr->isValid = false;
+ }
+ else
+ {
+ LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
+ }
+ break;
+ }
+ case ELCType::ELC2:
+ {
+ if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
+ {
+ LicenceELC2Item *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
+ {
+ switch (this->licIdentification.licCompatibility)
+ {
+ case 1:
+ // kod pro kompatibilitu 1
+ break;
+ default:
+ LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
+ break;
+ }
+ }
+ break;
+ }
+ case ELCType::ELC3:
+ {
+ 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;
+}
+
+/// @brief vrací informace o všech licenčních bodech základě předané návratové struktury
+/// @param returnStructure
+/// @return
+bool LicenceReader::getLicenceInfo(void *returnStructure)
+{
+ try
+ {
+ switch (this->licIdentification.licElcType)
+ {
+ case ELCType::ELC1:
+ { // old eoseov
+ if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
+ {
+ LicenceELC1Info *resultPtr = static_cast(returnStructure);
+
+ if (this->licenceInfo.licences.count(1)) // starý EOS má natvrdo "id" 1
+ {
+ resultPtr->isValid = true;
+ }
+ else
+ {
+ resultPtr->isValid = false;
+ }
+ }
+ else
+ {
+ switch (this->licIdentification.licCompatibility)
+ {
+ case 1:
+ // kod pro kompatibilitu 1
+ break;
+ default:
+ LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
+ break;
+ }
+ }
+ break;
+ }
+ case ELCType::ELC2:
+ {
+ if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
+ {
+ Reader::Licence2 licenceELC2 = Reader::Licence2(this->licIdentification);
+ licenceELC2.readLicence(&this->licenceInfo);
+ licenceELC2.getLicenceInfo(returnStructure);
+ }
+ else
+ {
+ switch (this->licIdentification.licCompatibility)
+ {
+ case 1:
+ // kod pro kompatibilitu 1
+ break;
+ default:
+ LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
+ break;
+ }
+ }
+ break;
+ }
+ case ELCType::ELC3:
+ {
+ break;
+ }
+ }
+ }
+ catch (const LicenceException &ex)
+ {
+ error.code = ex.getErrorCode();
+ error.message = ex.getErrorMessage();
+ return false;
+ }
+ return true;
+}
+
+LicenceReader::~LicenceReader()
+{
+}
diff --git a/zdenda/src/reader/licData.xml b/zdenda/src/reader/licData.xml
new file mode 100644
index 0000000..6f67b1f
--- /dev/null
+++ b/zdenda/src/reader/licData.xml
@@ -0,0 +1,37 @@
+
+
+EOV_OSV
+WAGO
+Licence pro EOV_OSV
+eov.ceskatrebova.ddts.cz
+eov2
+Projekt XXX stanice YYY
+
+ -
+ Položka licence 1
+ 111
+ 100
+
+ -
+ Položka licence 2
+ 222
+ 200
+
+ -
+ Položka licence 3
+ 333
+ 300
+
+ -
+ Položka licence 3
+ 444
+ 1600
+
+-
+ Položka licence 4
+ 555
+ 1999
+
+
+
+
\ No newline at end of file
diff --git a/zdenda/src/reader/licReaderELC1.cpp b/zdenda/src/reader/licReaderELC1.cpp
new file mode 100644
index 0000000..52ecad6
--- /dev/null
+++ b/zdenda/src/reader/licReaderELC1.cpp
@@ -0,0 +1,124 @@
+#include "licReaderELC1.h"
+
+namespace Reader
+{
+ Licence1::Licence1() {}
+
+ Licence1::~Licence1() {}
+
+ Licence1::Licence1(LicenceIdentification &licIdentification) : LicenceELC1(licIdentification)
+ {
+ }
+
+ /// @brief načte seznam licenčních bodů do obecné struktury
+ /// @param licences
+ /// @return
+ bool Licence1::readLicence(LicenceInfoGeneral *licences)
+ {
+ sdCard = SDCard(this->cid_cdsPath);
+ if (sdCard.isLoaded == false) throw LicenceException((int)GeneralError::SDCardReadError, "Chyba při čtení SD karty, cesta: " + cid_cdsPath);
+
+ for (unsigned int i = 0; i < CID_LENGTH;i++) this->cid[i] = sdCard.cid[i];
+ for (unsigned int i = 0; i < CSD_LENGTH;i++) this->csd[i] = sdCard.csd[i];
+
+ if (getSDData() == false) throw LicenceException((int)GeneralError::SDCardReadError, "Chyba při čtení SD karty, cesta: " + cid_cdsPath);
+
+ string licFileName = getLicenceName(0);
+ string licFilePath = this->licenceFilePath + licFileName;
+
+ char licFileNameToRead[licFilePath.length()+1] = {};
+ getCharsFromString(licFilePath, licFileNameToRead, licFilePath.length());
+
+ FILE *licenceFile;
+ char ch;
+
+ licenceFile = fopen(licFileNameToRead, "rb");
+
+ if (licenceFile == nullptr) throw LicenceException((int)GeneralError::LicenceReadError, "LicenceReadError: " + licFilePath);
+
+ fseek(licenceFile, 0, SEEK_END);
+ const int size = ftell(licenceFile);
+ fseek(licenceFile, 0, SEEK_SET);
+
+ if (size <= 0) throw LicenceException((int)GeneralError::LicenceSizeMismatch, "LicenceSizeMismatch: " + licFilePath);
+
+ int count = 0;
+
+ unsigned char licenceContent[size];
+
+ for (int i = 0; i < size; i++)
+ {
+ ch = fgetc(licenceFile);
+ licenceContent[i] = ch;
+ count++;
+ }
+
+ fclose(licenceFile);
+
+ LicenceDataMainELC licenceHeader{};
+ LicenceData licEncryptedData{};
+
+ 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)
+ {
+ if (licenceHeader.licHeader.licSubType == cEzLic_p78ou3_SubType_10_10)
+ {
+ initCrypto();
+
+ unsigned char decrypted[2000] = {};
+ int decrypted_len = decrypt(encryptedData, sizeof(encryptedData), cryptData.aesKey, cryptData.aesInitVector, decrypted);
+
+ if (sizeof(licEncryptedData) != decrypted_len)
+ {
+ throw LicenceException((int)GeneralError::LicenceSizeMismatch, "License size mismatch ");
+ }
+ else
+ {
+ 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)GeneralError::ItemsCountMismatch, "ItemsCountMismatch");
+ }
+ }
+ }
+ else
+ {
+ throw LicenceException((int)GeneralError::LicenceMismatch, "Licence mismatch");
+ }
+ }
+ }
+ }
+ else
+ {
+ throw LicenceException((int)GeneralError::LicenceMismatch, "Licence mismatch");
+ }
+ }
+ else
+ {
+ throw LicenceException((int)GeneralError::LicenceReadError, "Licence error");
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/zdenda/src/reader/licReaderELC2.cpp b/zdenda/src/reader/licReaderELC2.cpp
new file mode 100644
index 0000000..7ba21a6
--- /dev/null
+++ b/zdenda/src/reader/licReaderELC2.cpp
@@ -0,0 +1,136 @@
+#include "licReaderELC2.h"
+
+namespace Reader
+{
+
+ Licence2::Licence2() {}
+
+ Licence2::~Licence2() {}
+
+ Licence2::Licence2(LicenceIdentification &licIdentification) : LicenceELC2(licIdentification)
+ {
+ }
+
+ /// @brief načte seznam licenčních bodů do obecné struktury
+ /// @param licences
+ /// @return
+ bool Licence2::readLicence(LicenceInfoGeneral *licences)
+ {
+ sdCard = SDCard(this->cid_cdsPath);
+ if (sdCard.isLoaded == false)
+ throw LicenceException((int)GeneralError::SDCardReadError, "Nepodařilo se načíst SD kartu., cesta: " + cid_cdsPath);
+
+ string licFileName = getLicenceName();
+ string licFilePath = this->licenceFilePath + licFileName;
+
+ vector content;
+ if (readFile(licFilePath, content) == false)
+ {
+ throw LicenceException((int)GeneralError::FileOpenError, "Chyba otevření souboru licence: " + licFilePath);
+ }
+
+ 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]);
+
+ int elcVersion = (int)licBody.licId.licIdent[3] - 48; // verze je text, musí se odečíst 48
+
+ if (elcVersion != (int)this->lIdentification.licElcType)
+ {
+ throw LicenceException((int)GeneralError::ELCMismatch, "Nesouhlasí ELC.");
+ }
+
+ vector publicPart(content.begin(), content.begin() + 18 + this->licBody.licenceIdentHeader.publicHeaderLength);
+
+#ifdef CRCCHECK
+ cout << "CRC read public size: " << publicPart.size() << "\n";
+ cout << "CRC read public: " << calculateCRC16(publicPart) << "\n";
+#endif
+
+ vector encryptedPart(content.begin() + licBody.licenceIdentHeader.publicHeaderLength + 18, content.begin() + content.size());
+
+ // cout << "encryptedPart content length: " << encryptedPart.size() << "\n";
+ // for (auto x : encryptedPart) cout << (int)x << "-";
+ // cout << "\n";
+
+ vector privateContentDecrypted;
+ privateContentDecrypted = decryptPrivateContent(encryptedPart);
+
+#ifdef CRCCHECK
+ cout << "CRC read private size: " << privateContentDecrypted.size() << "\n";
+ cout << "CRC read private: " << calculateCRC16(privateContentDecrypted) << "\n";
+#endif
+
+ // cout << "privateContentDecrypted content length: " << privateContentDecrypted.size() << "\n";
+ // for (auto x : privateContentDecrypted) cout << (int)x << "-";
+ // cout << "\n";
+
+ 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]);
+
+ if (licBodyDecrypted.licenceIdentHeader.licItemCount != this->licBody.licenceIdentHeader.licItemCount)
+ {
+ throw LicenceException((int)GeneralError::ItemsCountMismatch, "Nesouhlasí počet položek licence.");
+ }
+
+ 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 += 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));
+ }
+
+ uint16_t crcComplete = bytesToWord(privateContentDecrypted[index], privateContentDecrypted[index + 1]);
+
+ vector completeVector = joinVectors(publicPart, privateContentDecrypted);
+ if (calculateCRC16(completeVector, 2) != crcComplete) throw LicenceException((int)GeneralError::LicenceCRCMismatch, "Nesouhlasí CRC.");
+
+ return true;
+ }
+
+ bool Licence2::getLicenceInfo(void *returnStructure)
+ {
+ if (returnStructure != nullptr)
+ {
+ LicenceELC2Info *resultPtr = static_cast(returnStructure);
+ for (auto item : this->licBody.privateContent.dataItems)
+ {
+ resultPtr->licences.insert(pair(item.protoId, item.licCount));
+ }
+ }
+ else
+ {
+ errorMessage.code = 1;
+ errorMessage.message = "Error: Null pointer!";
+ return false;
+ }
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/zdenda/src/reader/licReaderELC3.cpp b/zdenda/src/reader/licReaderELC3.cpp
new file mode 100644
index 0000000..6c0e341
--- /dev/null
+++ b/zdenda/src/reader/licReaderELC3.cpp
@@ -0,0 +1,7 @@
+#include "licReaderELC3.h"
+
+namespace Reader
+{
+}
+
+
diff --git a/zdenda_reader.zip b/zdenda_reader.zip
new file mode 100644
index 0000000..f57b083
Binary files /dev/null and b/zdenda_reader.zip differ