#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) { // 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: " + 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]); #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)); } 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() {}