diff --git a/cdoc/CDocCipher.cpp b/cdoc/CDocCipher.cpp index 7d0fe9c7..b1f3230d 100644 --- a/cdoc/CDocCipher.cpp +++ b/cdoc/CDocCipher.cpp @@ -43,46 +43,43 @@ using namespace libcdoc; static string GenerateRandomSequence(); struct ToolPKCS11 : public libcdoc::PKCS11Backend { - const RecipientInfoIdMap& rcpts; + const std::map& rcpts; - ToolPKCS11(const std::string& library, const RecipientInfoIdMap& vec) : libcdoc::PKCS11Backend(library), rcpts(vec) {} + ToolPKCS11(const std::string& library, const std::map& vec) : libcdoc::PKCS11Backend(library), rcpts(vec) {} libcdoc::result_t connectToKey(int idx, bool priv) override final { if (!rcpts.contains(idx)) return libcdoc::CRYPTO_ERROR; - const RcptInfo& rcpt = rcpts.at(idx); - int result = libcdoc::CRYPTO_ERROR; + libcdoc::RcptInfo rcpt = rcpts.at(idx); if (!priv) { - result = useSecretKey(rcpt.slot, rcpt.secret, rcpt.key_id, rcpt.key_label); + return useSecretKey(rcpt.p11.slot, rcpt.secret, rcpt.p11.key_id, rcpt.p11.key_label); } else { - result = usePrivateKey(rcpt.slot, rcpt.secret, rcpt.key_id, rcpt.key_label); + return usePrivateKey(rcpt.p11.slot, rcpt.secret, rcpt.p11.key_id, rcpt.p11.key_label); } - if (result != libcdoc::OK) return result; - return libcdoc::OK; } }; #ifdef _WIN32 struct ToolWin : public libcdoc::WinBackend { - const RecipientInfoIdMap& rcpts; + const std::map& rcpts; - ToolWin(const std::string& provider, const RecipientInfoIdMap& vec) : libcdoc::WinBackend(provider), rcpts(vec) {} + ToolWin(const std::string& provider, const std::map& vec) : libcdoc::WinBackend(provider), rcpts(vec) {} result_t connectToKey(int idx, bool priv) { - const RcptInfo& rcpt = rcpts.at(idx); - return useKey(rcpt.key_label, std::string(rcpt.secret.cbegin(), rcpt.secret.cend())); + if (!rcpts.contains(idx)) return libcdoc::CRYPTO_ERROR; + const libcdoc::RcptInfo &rcpt = rcpts.at(idx); + return useKey(rcpt.p11.key_label, std::string(rcpt.secret.cbegin(), rcpt.secret.cend())); } - }; #endif struct ToolCrypto : public libcdoc::CryptoBackend { - const RecipientInfoIdMap& rcpts; + const std::map& rcpts; std::unique_ptr p11; #ifdef _WIN32 std::unique_ptr ncrypt; #endif - ToolCrypto(const RecipientInfoIdMap& recipients) : rcpts(recipients) { + ToolCrypto(const std::map& recipients) : rcpts(recipients) { } bool connectLibrary(const std::string& library) { @@ -102,7 +99,7 @@ struct ToolCrypto : public libcdoc::CryptoBackend { libcdoc::result_t decryptRSA(std::vector& dst, const std::vector &data, bool oaep, unsigned int idx) override final { if (p11) return p11->decryptRSA(dst, data, oaep, idx); if (!rcpts.contains(idx)) return libcdoc::CRYPTO_ERROR; - const RcptInfo& rcpt = rcpts.at(idx); + const libcdoc::RcptInfo &rcpt = rcpts.at(idx); if (rcpt.secret.empty()) return libcdoc::CRYPTO_ERROR; const uint8_t *p = rcpt.secret.data(); @@ -134,7 +131,7 @@ struct ToolCrypto : public libcdoc::CryptoBackend { libcdoc::result_t deriveECDH1(std::vector& dst, const std::vector &public_key, unsigned int idx) override final { if (!rcpts.contains(idx)) return libcdoc::CRYPTO_ERROR; - const RcptInfo& rcpt = rcpts.at(idx); + const libcdoc::RcptInfo &rcpt = rcpts.at(idx); if (rcpt.secret.empty()) return libcdoc::CRYPTO_ERROR; const uint8_t *p = rcpt.secret.data(); @@ -151,7 +148,7 @@ struct ToolCrypto : public libcdoc::CryptoBackend { (EVP_PKEY_paramgen(ctx.get(), ¶ms) < 0)) return libcdoc::CRYPTO_ERROR; - p = public_key.data(); + p = public_key.data(); auto pubkey = make_unique_ptr(d2i_PublicKey(EVP_PKEY_EC, ¶ms, &p, long(public_key.size()))); if (!pubkey) return libcdoc::CRYPTO_ERROR; @@ -187,7 +184,7 @@ struct ToolCrypto : public libcdoc::CryptoBackend { libcdoc::result_t getSecret(std::vector& secret, unsigned int idx) override final { if (!rcpts.contains(idx)) return libcdoc::CRYPTO_ERROR; - const RcptInfo& rcpt = rcpts.at(idx); + const libcdoc::RcptInfo &rcpt = rcpts.at(idx); secret = rcpt.secret; return secret.empty() ? INVALID_PARAMS : libcdoc::OK; } @@ -212,7 +209,7 @@ struct ToolNetwork : public libcdoc::NetworkBackend { if (!crypto->rcpts.contains(rcpt_idx)) return libcdoc::CRYPTO_ERROR; const RcptInfo& rcpt = crypto->rcpts.at(rcpt_idx); bool rsa = false; - return crypto->p11->getCertificate(dst, rsa, rcpt.slot, rcpt.secret, rcpt.key_id, rcpt.key_label); + return crypto->p11->getCertificate(dst, rsa, rcpt.p11.slot, rcpt.secret, rcpt.p11.key_id, rcpt.p11.key_label); } libcdoc::result_t getPeerTLSCertificates(std::vector> &dst) override final { @@ -227,9 +224,9 @@ struct ToolNetwork : public libcdoc::NetworkBackend { }; -int CDocCipher::writer_push(CDocWriter& writer, const vector& keys, const vector& files) +int CDocCipher::writer_push(CDocWriter& writer, const vector& rcpts, const vector& files) { - for (const libcdoc::Recipient& rcpt : keys) { + for (const libcdoc::Recipient& rcpt : rcpts) { int64_t result = writer.addRecipient(rcpt); if (result != libcdoc::OK) return result; } @@ -262,7 +259,7 @@ int CDocCipher::writer_push(CDocWriter& writer, const vector& keys, c #define PUSH true static bool -fill_recipients_from_rcpt_info(ToolConf& conf, ToolCrypto& crypto, std::vector& rcpts, RecipientInfoIdMap& crypto_rcpts, const RecipientInfoVector& recipients) +fill_recipients_from_rcpt_info(ToolConf& conf, ToolCrypto& crypto, std::vector& rcpts, std::map& crypto_rcpts, const std::vector& recipients) { int idx = 0; for (const auto& rcpt : recipients) { @@ -305,9 +302,9 @@ fill_recipients_from_rcpt_info(ToolConf& conf, ToolCrypto& crypto, std::vector val; bool rsa; ToolPKCS11* p11 = dynamic_cast(crypto.p11.get()); - int result = p11->getPublicKey(val, rsa, rcpt.slot, rcpt.secret, rcpt.key_id, rcpt.key_label); + int result = p11->getPublicKey(val, rsa, rcpt.p11.slot, rcpt.secret, rcpt.p11.key_id, rcpt.p11.key_label); if (result != libcdoc::OK) { - LOG_ERROR("No such public key: {}", rcpt.key_label); + LOG_ERROR("No such public key: {}", rcpt.p11.key_label); continue; } LOG_DBG("Public key ({}): {}", rsa ? "rsa" : "ecc", toHex(val)); @@ -329,9 +326,9 @@ fill_recipients_from_rcpt_info(ToolConf& conf, ToolCrypto& crypto, std::vector& recipients) { - RecipientInfoIdMap crypto_rcpts; + std::map crypto_rcpts; ToolCrypto crypto(crypto_rcpts); ToolNetwork network(&crypto); network.certs = std::move(conf.accept_certs); @@ -372,48 +369,9 @@ int CDocCipher::Encrypt(ToolConf& conf, RecipientInfoVector& recipients) return result; } -int CDocCipher::Decrypt(ToolConf& conf, int idx_base_1, const RcptInfo& recipient) +int CDocCipher::Decrypt(ToolConf& conf, const RcptInfo& recipient) { - RecipientInfoIdMap rcpts; - ToolCrypto crypto(rcpts); - ToolNetwork network(&crypto); - network.certs = std::move(conf.accept_certs); - - unique_ptr rdr(CDocReader::createReader(conf.input_files[0], &conf, &crypto, &network)); - if (rdr) { - LOG_DBG("Reader created"); - } else { - LOG_ERROR("Cannot create reader (invalid file?)"); - return 1; - } - - // Acquire the locks and get the labels according to the index - const vector &locks = rdr->getLocks(); - int lock_idx = idx_base_1 - 1; - if (lock_idx < 0) { - LOG_ERROR("Indexing of labels starts from 1"); - return 1; - } - if (lock_idx >= locks.size()) { - LOG_ERROR("Label index is out of range"); - return 1; - } - rcpts[lock_idx] = recipient; - - const Lock& lock = locks[lock_idx]; - LOG_INFO("Found matching label: {}", lock.label); - network.rcpt_idx = lock_idx; - //rcpts[idx_base_1] = recipient; - - if (!conf.library.empty()) - crypto.connectLibrary(conf.library); - - return Decrypt(rdr, lock_idx, conf.out); -} - -int CDocCipher::Decrypt(ToolConf& conf, const std::string& label, const RcptInfo& recipient) -{ - RecipientInfoIdMap rcpts; + std::map rcpts; ToolCrypto crypto(rcpts); ToolNetwork network(&crypto); network.certs = std::move(conf.accept_certs); @@ -428,39 +386,45 @@ int CDocCipher::Decrypt(ToolConf& conf, const std::string& label, const RcptInfo } LOG_DBG("Reader created"); - // Acquire the locks and get the labels according to the index + // Find lock by label/index/certificate int lock_idx = -1; const vector& locks = rdr->getLocks(); - if (!label.empty()) { + if (!recipient.label.empty()) { LOG_DBG("Looking for lock by label"); for (unsigned int i = 0; i < locks.size(); i++) { - if (locks[i].label == label) { + if (locks[i].label == recipient.label) { lock_idx = i; break; } } + } else if (recipient.lock_idx >= 0) { + if (recipient.lock_idx >= locks.size()) { + LOG_ERROR("Label index is out of range"); + return 1; + } + lock_idx = recipient.lock_idx; } else if (crypto.p11) { bool isRsa; vector cert_bytes; ToolPKCS11* p11 = dynamic_cast(crypto.p11.get()); - int64_t result = p11->getCertificate(cert_bytes, isRsa, (int) recipient.slot, recipient.secret, recipient.key_id, recipient.key_label); + int64_t result = p11->getCertificate(cert_bytes, isRsa, (int) recipient.p11.slot, recipient.secret, recipient.p11.key_id, recipient.p11.key_label); if (result != libcdoc::OK) { - LOG_ERROR("Certificate reading from SC card failed. Key label: {}", recipient.key_label); + LOG_ERROR("Certificate reading from SC card failed. Key label: {}", recipient.p11.key_label); return 1; } LOG_DBG("Got certificate from P11 module"); result = rdr->getLockForCert(cert_bytes); if (result < 0) { - LOG_ERROR("No lock for certificate {}", recipient.key_label); + LOG_ERROR("No lock for certificate {}", recipient.p11.key_label); return 1; } lock_idx = (int) result; } if (lock_idx < 0) { - LOG_ERROR("Lock not found: {}", label); + LOG_ERROR("Lock not found: {}", recipient.label); return 1; } - LOG_INFO("Found matching label: {}", label); + LOG_INFO("Found matching lock: {}", recipient.label); rcpts[lock_idx] = recipient; network.rcpt_idx = lock_idx; @@ -550,10 +514,10 @@ int CDocCipher::Decrypt(const unique_ptr& rdr, unsigned int lock_idx } int -CDocCipher::ReEncrypt(ToolConf& conf, int lock_idx_base_1, const std::string& lock_label, const RcptInfo& lock_info, RecipientInfoVector& recipients) +CDocCipher::ReEncrypt(ToolConf& conf, const RcptInfo& lock_info, std::vector& recipients) { // Decryption part - RecipientInfoIdMap dec_info; + std::map dec_info; ToolCrypto crypto(dec_info); ToolNetwork network(&crypto); network.certs = std::move(conf.accept_certs); @@ -571,26 +535,32 @@ CDocCipher::ReEncrypt(ToolConf& conf, int lock_idx_base_1, const std::string& lo const vector& locks = rdr->getLocks(); - int lock_idx = lock_idx_base_1 - 1; - if (lock_idx < 0) { + int lock_idx = -1; + if (!lock_info.label.empty()) { for (unsigned int i = 0; i < locks.size(); i++) { - if (locks[i].label == lock_label) { + if (locks[i].label == lock_info.label) { lock_idx = i; break; } } - if (lock_idx < 0) { - LOG_ERROR("Lock not found: {}", lock_label); + } else if (lock_info.lock_idx >= 0) { + if (lock_info.lock_idx >= locks.size()) { + LOG_ERROR("Label index is out of range"); return 1; } - LOG_INFO("Found matching label: {}", lock_label); + lock_idx = lock_info.lock_idx; } + if (lock_idx < 0) { + LOG_ERROR("Lock not found: {}", lock_info.label); + return 1; + } + dec_info[lock_idx] = lock_info; network.rcpt_idx = lock_idx; // Encryption part - RecipientInfoIdMap crypto_rcpts; + std::map crypto_rcpts; ToolCrypto enc_crypto(crypto_rcpts); ToolNetwork enc_network(&enc_crypto); enc_network.certs = std::move(conf.accept_certs); diff --git a/cdoc/CDocCipher.h b/cdoc/CDocCipher.h index 84614bb4..42b76cfb 100644 --- a/cdoc/CDocCipher.h +++ b/cdoc/CDocCipher.h @@ -30,8 +30,6 @@ namespace libcdoc { -typedef typename std::map RecipientInfoIdMap; -typedef typename std::vector RecipientInfoVector; class CDocCipher { @@ -40,12 +38,11 @@ class CDocCipher CDocCipher(const CDocCipher&) = delete; CDocCipher(CDocCipher&&) = delete; - int Encrypt(ToolConf& conf, RecipientInfoVector& recipients); + int Encrypt(ToolConf& conf, std::vector& recipients); - int Decrypt(ToolConf& conf, int idx_base_1, const RcptInfo& recipient); - int Decrypt(ToolConf& conf, const std::string& label, const RcptInfo& recipient); + int Decrypt(ToolConf& conf, const RcptInfo& recipient); - int ReEncrypt(ToolConf& conf, int lock_idx_base_1, const std::string& lock_label, const RcptInfo& lock_info, RecipientInfoVector& recipients); + int ReEncrypt(ToolConf& conf, const RcptInfo& lock_info, std::vector& recipients); void Locks(const char* file) const; diff --git a/cdoc/RcptInfo.h b/cdoc/RcptInfo.h index 86168c6a..e4142553 100644 --- a/cdoc/RcptInfo.h +++ b/cdoc/RcptInfo.h @@ -24,10 +24,19 @@ namespace libcdoc { struct RcptInfo { + // PKCS11/NCrypt data + // NB! PIN is stored in secret + struct PKCS11Info { + long slot = 0; + std::vector key_id; + std::string key_label; + }; + enum Type { - // Detect type from container - ANY, + // For decryption (use the lock type) + LOCK, + // For encryption // Certificate from file CERT, // Password from command line @@ -47,17 +56,21 @@ struct RcptInfo { }; Type type; + // Locks label + std::string label; + // Certificate for encryption std::vector cert; // Pin or password std::vector secret; - long slot = 0; - std::vector key_id; - std::string key_label; + // PKCS11-specific info + PKCS11Info p11; + + // Keyfile name for automatic labels std::string key_file_name; // ID code for shares server std::string id; - // Locks label - std::string label; + // Lock index + int lock_idx = -1; }; } diff --git a/cdoc/cdoc-tool.cpp b/cdoc/cdoc-tool.cpp index 12adf66d..c00495fb 100644 --- a/cdoc/cdoc-tool.cpp +++ b/cdoc/cdoc-tool.cpp @@ -44,7 +44,7 @@ static void print_usage(ostream& ofs) ofs << "cdoc-tool encrypt --rcpt RECIPIENT [--rcpt...] [-v1] [--genlabel] --out OUTPUTFILE FILE [FILE...]" << endl; ofs << " Encrypt files for one or more recipients" << endl; ofs << " RECIPIENT has to be one of the following:" << endl; - ofs << " [label]:cert:CERTIFICATE_HEX - public key from certificate" << endl; + ofs << " [label]:cert:CERTIFICATE_FILE - public key from certificate" << endl; ofs << " [label]:pkey:SECRET_KEY_HEX - public key" << endl; ofs << " [label]:pfkey:PUB_KEY_FILE - path to DER file with EC (secp384r1 curve) public key" << endl; ofs << " [label]:skey:SECRET_KEY_HEX - AES key" << endl; @@ -140,7 +140,7 @@ parse_common(ToolConf& conf, int arg_idx, int argc, char *argv[]) } static int -parse_rcpt(ToolConf& conf, RecipientInfoVector& rcpts, int& arg_idx, int argc, char *argv[]) +parse_rcpt(ToolConf& conf, std::vector& rcpts, int& arg_idx, int argc, char *argv[]) { string_view arg(argv[arg_idx]); if ((arg != "--rcpt") || ((arg_idx + 1) >= argc)) return 0; @@ -202,10 +202,10 @@ parse_rcpt(ToolConf& conf, RecipientInfoVector& rcpts, int& arg_idx, int argc, c size_t last_char_idx; if (parts[2].starts_with("0x")) { - rcpt.slot = std::stoul(parts[2].substr(2), &last_char_idx, 16); + rcpt.p11.slot = std::stoul(parts[2].substr(2), &last_char_idx, 16); last_char_idx += 2; } else { - rcpt.slot = std::stoul(parts[2], &last_char_idx); + rcpt.p11.slot = std::stoul(parts[2], &last_char_idx); } if (last_char_idx < parts[2].size()) { LOG_ERROR("Slot is not a number"); @@ -215,31 +215,31 @@ parse_rcpt(ToolConf& conf, RecipientInfoVector& rcpts, int& arg_idx, int argc, c if (parts.size() > 3) { rcpt.secret.assign(parts[3].cbegin(), parts[3].cend()); if (parts.size() > 4) { - if (!parts[4].empty()) rcpt.key_id = fromHex(parts[4]); + if (!parts[4].empty()) rcpt.p11.key_id = fromHex(parts[4]); if (parts.size() > 5) - rcpt.key_label = parts[5]; + rcpt.p11.key_label = parts[5]; } } #ifndef NDEBUG // For debugging LOG_DBG("Method: {}", method); - LOG_DBG("Slot: {}", rcpt.slot); + LOG_DBG("Slot: {}", rcpt.p11.slot); if (!rcpt.secret.empty()) { string str(rcpt.secret.cbegin(), rcpt.secret.cend()); LOG_TRACE("Pin: {}", str); } - if (!rcpt.key_id.empty()) - LOG_DBG("Key ID: {}", toHex(rcpt.key_id)); - if (!rcpt.key_label.empty()) - LOG_DBG("Key label: {}", rcpt.key_label); + if (!rcpt.p11.key_id.empty()) + LOG_DBG("Key ID: {}", toHex(rcpt.p11.key_id)); + if (!rcpt.p11.key_label.empty()) + LOG_DBG("Key label: {}", rcpt.p11.key_label); #endif } else if (method == "ncrypt") { // label:ncrypt:key_label[:pin] rcpt.type = RcptInfo::NCRYPT; if (parts.size() > 2) { - rcpt.key_label = parts[2]; + rcpt.p11.key_label = parts[2]; if (parts.size() > 3) { rcpt.secret.assign(parts[3].cbegin(), parts[3].cend()); } @@ -248,13 +248,13 @@ parse_rcpt(ToolConf& conf, RecipientInfoVector& rcpts, int& arg_idx, int argc, c #ifndef NDEBUG // For debugging cout << "Method: " << method << endl; - cout << "Slot: " << rcpt.slot << endl; + cout << "Slot: " << rcpt.p11.slot << endl; if (!rcpt.secret.empty()) cout << "Pin: " << string(rcpt.secret.cbegin(), rcpt.secret.cend()) << endl; - if (!rcpt.key_id.empty()) - cout << "Key ID: " << toHex(rcpt.key_id) << endl; - if (!rcpt.key_label.empty()) - cout << "Key label: " << rcpt.key_label << endl; + if (!rcpt.p11.key_id.empty()) + cout << "Key ID: " << toHex(rcpt.p11.key_id) << endl; + if (!rcpt.p11.key_label.empty()) + cout << "Key label: " << rcpt.p11.key_label << endl; #endif } else if (method == "share") { // label:share:RECIPIENT_ID @@ -285,7 +285,7 @@ static int ParseAndEncrypt(int argc, char *argv[]) LOG_INFO("Encrypting"); ToolConf conf; - RecipientInfoVector rcpts; + std::vector rcpts; // // Parse all arguments into ToolConf structure @@ -325,7 +325,7 @@ static int ParseAndEncrypt(int argc, char *argv[]) } if (!conf.gen_label) { // If labels must not be generated then is there any Recipient without provided label? - auto rcpt_wo_label{ find_if(rcpts.cbegin(), rcpts.cend(), [](RecipientInfoVector::const_reference rcpt) -> bool {return rcpt.label.empty();}) }; + auto rcpt_wo_label{ find_if(rcpts.cbegin(), rcpts.cend(), [](const libcdoc::RcptInfo &rcpt) -> bool {return rcpt.label.empty();}) }; if (rcpt_wo_label != rcpts.cend()) { if (rcpts.size() > 1) { LOG_ERROR("Not all Recipients have label"); @@ -352,7 +352,7 @@ static int ParseAndEncrypt(int argc, char *argv[]) // CDOC1 is supported only for encryption with certificate. if (conf.cdocVersion == 1) { - auto rcpt_type_non_cert{ find_if(rcpts.cbegin(), rcpts.cend(), [](RecipientInfoVector::const_reference rcpt) -> bool {return rcpt.type != RcptInfo::CERT;}) }; + auto rcpt_type_non_cert{ find_if(rcpts.cbegin(), rcpts.cend(), [](const libcdoc::RcptInfo &rcpt) -> bool {return rcpt.type != RcptInfo::CERT;}) }; if (rcpt_type_non_cert != rcpts.cend()) { LOG_ERROR("CDOC version 1 container can be used for encryption with certificate only."); return 1; @@ -539,18 +539,14 @@ static int ParseAndDecrypt(int argc, char *argv[]) } CDocCipher cipher; - RcptInfo rcpt {RcptInfo::ANY, {}, ldata.secret, ldata.slot, ldata.key_id, ldata.key_label}; - if (ldata.lock_idx != -1) { - return cipher.Decrypt(conf, ldata.lock_idx, rcpt); - } else { - return cipher.Decrypt(conf, ldata.lock_label, rcpt); - } + RcptInfo rcpt {.type=RcptInfo::LOCK, .label=ldata.lock_label, .secret=ldata.secret, .p11={ldata.slot, ldata.key_id, ldata.key_label}, .lock_idx=ldata.lock_idx - 1}; + return cipher.Decrypt(conf, rcpt); } static int ParseAndReEncrypt(int argc, char *argv[]) { ToolConf conf; - RecipientInfoVector rcpts; + std::vector rcpts; LockData ldata; int arg_idx = 0; @@ -596,7 +592,7 @@ static int ParseAndReEncrypt(int argc, char *argv[]) if (!conf.gen_label) { // If labels must not be generated then is there any Recipient without provided label? - auto rcpt_wo_label{ find_if(rcpts.cbegin(), rcpts.cend(), [](RecipientInfoVector::const_reference rcpt) -> bool {return rcpt.label.empty();}) }; + auto rcpt_wo_label{ find_if(rcpts.cbegin(), rcpts.cend(), [](const libcdoc::RcptInfo &rcpt) -> bool {return rcpt.label.empty();}) }; if (rcpt_wo_label != rcpts.cend()) { if (rcpts.size() > 1) { LOG_ERROR("Not all Recipients have label"); @@ -619,7 +615,7 @@ static int ParseAndReEncrypt(int argc, char *argv[]) // CDOC1 is supported only for encryption with certificate. if (conf.cdocVersion == 1) { - auto rcpt_type_non_cert{ find_if(rcpts.cbegin(), rcpts.cend(), [](RecipientInfoVector::const_reference rcpt) -> bool {return rcpt.type != RcptInfo::CERT;}) }; + auto rcpt_type_non_cert{ find_if(rcpts.cbegin(), rcpts.cend(), [](const libcdoc::RcptInfo &rcpt) -> bool {return rcpt.type != RcptInfo::CERT;}) }; if (rcpt_type_non_cert != rcpts.cend()) { LOG_ERROR("CDOC version 1 container can be used for encryption with certificate only."); return 1; @@ -627,9 +623,9 @@ static int ParseAndReEncrypt(int argc, char *argv[]) } CDocCipher cipher; - RcptInfo rcpt {RcptInfo::ANY, {}, ldata.secret, ldata.slot, ldata.key_id, ldata.key_label}; + RcptInfo rcpt {.type=RcptInfo::LOCK, .label=ldata.lock_label, .secret=ldata.secret, .p11={ldata.slot, ldata.key_id, ldata.key_label}, .lock_idx=ldata.lock_idx}; if (ldata.lock_idx != -1) { - return cipher.ReEncrypt(conf, ldata.lock_idx, ldata.lock_label, rcpt, rcpts); + return cipher.ReEncrypt(conf, rcpt, rcpts); } return true; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4b60ec69..1e9f06c1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,9 +3,6 @@ add_executable(unittests ../cdoc/CDocCipher.cpp ../cdoc/Crypto.cpp) -target_compile_definitions(unittests PRIVATE - DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") - target_link_libraries(unittests OpenSSL::SSL cdoc @@ -13,7 +10,7 @@ target_link_libraries(unittests add_test(NAME runtest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/unittests --build_info=YES --logger=HRF,all,stdout - WORKING_DIRECTORY $ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test ) add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS unittests) diff --git a/test/data/ec-secp384r1-cert.der b/test/data/ec-secp384r1-cert.der new file mode 100644 index 00000000..b806ac8b Binary files /dev/null and b/test/data/ec-secp384r1-cert.der differ diff --git a/test/data/rsa_2048_cert.der b/test/data/rsa_2048_cert.der new file mode 100644 index 00000000..4c0463f8 Binary files /dev/null and b/test/data/rsa_2048_cert.der differ diff --git a/test/data/test_data2.txt b/test/data/test_data2.txt new file mode 100644 index 00000000..ff3bb639 --- /dev/null +++ b/test/data/test_data2.txt @@ -0,0 +1 @@ +The quick brown fox jumps over the lazy dog \ No newline at end of file diff --git a/test/data/test_data3.txt b/test/data/test_data3.txt new file mode 100644 index 00000000..85c30401 --- /dev/null +++ b/test/data/test_data3.txt @@ -0,0 +1,3 @@ +alpha +beta +gamma diff --git a/test/libcdoc_boost.cpp b/test/libcdoc_boost.cpp index d9ff9eab..78e3ce4a 100644 --- a/test/libcdoc_boost.cpp +++ b/test/libcdoc_boost.cpp @@ -32,7 +32,7 @@ #include "pipe.h" #ifndef DATA_DIR -#define DATA_DIR "." +#define DATA_DIR "data" #endif namespace btools = boost::test_tools; @@ -45,6 +45,8 @@ using namespace std; * @brief Unencrypted file name. */ constexpr string_view SourceFile("test_data.txt"); +constexpr string_view SourceFile2("test_data2.txt"); +constexpr string_view SourceFile3("test_data3.txt"); /** * @brief Encrypted file name. @@ -52,8 +54,10 @@ constexpr string_view SourceFile("test_data.txt"); constexpr string_view TargetFile("test_data.txt.cdoc"); constexpr string_view ECPrivKeyFile("ec-secp384r1-priv.der"); constexpr string_view ECPubKeyFile("ec-secp384r1-pub.der"); +constexpr string_view ECCertFile("ec-secp384r1-cert.der"); constexpr string_view RSAPrivKeyFile("rsa_2048_priv.der"); constexpr string_view RSAPubKeyFile("rsa_2048_pub.der"); +constexpr string_view RSACertFile("rsa_2048_cert.der"); const string Label("Proov"); @@ -97,6 +101,14 @@ class FixtureBase max_filesize = std::stoull(utf::framework::master_test_suite().argv[i]); } } + if (!fs::exists(testDataPath)) { + std::cerr << "Path " << testDataPath << " does not exist!" << std::endl; + ::exit(1); + } + tmpDataPath = fs::path(DATA_DIR) / "tmp"; + if (!fs::exists(tmpDataPath)) { + fs::create_directories(tmpDataPath); + } } /** @@ -110,34 +122,46 @@ class FixtureBase target /= fileName; } - /** - * @brief Checks if the file exists in the test data path. - * - * The method prepends the fileName with the test data path and checks its existence. If the file does not - * exist then appropriate message is appended to returned predicate_result object and the value of the object - * is set to false. - * @param fileName the name of the file thats existence has to be checked. - * @return predicate_result object with the check result. - */ - boost::test_tools::predicate_result DoesFileExist(const string& fileName) const + std::string formTargetFile(const std::string_view name) const { - fs::path file(testDataPath); - file /= fileName; - if (fs::exists(file)) - { - return true; - } - else - { - btools::predicate_result res(false); - res.message() << "File " << file << " does not exist"; - return res; + fs::path path(fs::path(tmpDataPath) / name); + if (fs::exists(path)) { + error_code e; + fs::remove(path, e); + if(e) BOOST_TEST_MESSAGE("Failed to remove file"); } + return path.string(); + } + + std::string checkDataFile(const std::string_view name) const + { + fs::path path(fs::path(testDataPath) / name); + BOOST_TEST_REQUIRE(fs::exists(path), "file " << name << " does not exist"); + return path.string(); + } + + std::string checkTargetFile(const std::string_view name) const + { + fs::path path(fs::path(tmpDataPath) / name); + BOOST_TEST_REQUIRE(fs::exists(path), "file " << name << " does not exist"); + return path.string(); + } + + std::vector fetchDataFile(const std::string_view name) const + { + fs::path path(fs::path(testDataPath) / name); + BOOST_TEST_REQUIRE(fs::exists(path), "file " << name << " does not exist"); + return libcdoc::readAllBytes(path.string()); } fs::path testDataPath = DATA_DIR; + fs::path tmpDataPath; fs::path sourceFilePath; - fs::path targetFilePath; + fs::path sourceFilePath2; + fs::path sourceFilePath3; + + std::vector sources = {"test_data.txt", "test_data2.txt", "test_data3.txt"}; + size_t max_filesize = 100000000; }; @@ -153,18 +177,8 @@ class EncryptFixture : public FixtureBase // Setup source, unencrypted file path FormFilePath(SourceFile, sourceFilePath); - - // Setup target, encrypted file path - FormFilePath(TargetFile, targetFilePath); - - // Remove target file if it exists - if (fs::exists(targetFilePath)) - { - error_code e; - fs::remove(targetFilePath, e); - if(e) - BOOST_TEST_MESSAGE("Failed to remove file"); - } + FormFilePath(SourceFile2, sourceFilePath2); + FormFilePath(SourceFile3, sourceFilePath3); } ~EncryptFixture() { BOOST_TEST_MESSAGE("Encrypt fixture deardown"); } @@ -218,9 +232,6 @@ class DecryptFixture : public FixtureBase // Setup source, encrypted file path FormFilePath(TargetFile, sourceFilePath); - - // Setup target, unencrypted file path - FormFilePath(SourceFile, targetFilePath); } ~DecryptFixture() @@ -229,6 +240,66 @@ class DecryptFixture : public FixtureBase } }; +static void +encrypt(unsigned int version, const std::vector& files, const std::string& container, std::vector& rcpts) { + libcdoc::ToolConf conf; + for (auto file : files) { + conf.input_files.push_back(file); + } + conf.out = container; + conf.cdocVersion = version; + + libcdoc::CDocCipher cipher; + BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); + + BOOST_TEST(fs::exists(fs::path(container)), "File " << container << " does not exist"); +} + +static void +encryptV1(const std::vector& files, const std::string& container, const std::vector& cert) { + std::vector rcpts { + {libcdoc::RcptInfo::CERT, {}, cert} + }; + encrypt(1, files, container, rcpts); +} + +static void +encryptV2(const std::vector& files, const std::string& container, const std::vector& cert) { + std::vector rcpts { + {libcdoc::RcptInfo::CERT, {}, cert} + }; + encrypt(2, files, container, rcpts); +} + +static void +decrypt(const std::vector& files, const std::string& container, const std::string& dir, libcdoc::RcptInfo& rcpt) +{ + libcdoc::ToolConf conf; + conf.input_files.push_back(container); + conf.out = dir; + + libcdoc::CDocCipher cipher; + BOOST_CHECK_EQUAL(cipher.Decrypt(conf, rcpt), 0); + + fs::path path(dir); + for (auto file : files) { + BOOST_TEST(fs::exists(path / fs::path(file).filename()), "File " << file << " does not exist"); + } + + path = fs::path(container); + if (fs::exists(path)) { + error_code e; + fs::remove(path, e); + if(e) + BOOST_TEST_MESSAGE("Failed to remove file"); } +} + +static void +decrypt(const std::vector& files, const std::string& container, const std::string& dir, const std::vector& key) +{ + libcdoc::RcptInfo rcpt {.type=libcdoc::RcptInfo::LOCK, .secret=key, .lock_idx=0}; + decrypt(files, container, dir, rcpt); +} static int unicode_to_utf8 (unsigned int uval, uint8_t *d, uint64_t size) { @@ -344,258 +415,148 @@ BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithPasswordAndLabel, FixtureBase, * u BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(PasswordUsageWithLabel) +// CDoc2 password and label -BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithPasswordAndLabel, EncryptFixture, * utf::description("Encrypting a file with password and given label")) +BOOST_AUTO_TEST_SUITE(PasswordUsageWithLabel) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithPasswordAndLabel, EncryptFixture, + * utf::description("Encrypting a file with password and given label")) { - // Check if the source, unecrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = targetFilePath.string(); - - libcdoc::RcptInfo rcpt; - rcpt.type = libcdoc::RcptInfo::PASSWORD; - rcpt.secret.assign(Password.cbegin(), Password.cend()); - rcpt.label = Label; - - libcdoc::RecipientInfoVector rcpts {rcpt}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); - - // Validate the encrypted file - BOOST_TEST(ValidateEncryptedFile(targetFilePath)); + std::vector rcpts { + {libcdoc::RcptInfo::PASSWORD, Label, {}, std::vector(Password.cbegin(), Password.cend())} + }; + encrypt(2, {checkDataFile(sources[0])}, formTargetFile("PasswordUsageWithoutLabel.cdoc"), rcpts); } - BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithPasswordAndLabel, DecryptFixture, * utf::depends_on("PasswordUsageWithLabel/EncryptWithPasswordAndLabel") * utf::description("Decrypting a file with password and given label")) { - // Check if the source, encrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - - auto tmp = testDataPath / "tmp"; - fs::remove_all(tmp); - fs::create_directory(tmp); - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = tmp.string(); - - libcdoc::RcptInfo rcpt {libcdoc::RcptInfo::ANY, {}, vector(Password.cbegin(), Password.cend())}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Decrypt(conf, Label, rcpt), 0); - - // Check if the encrypted file exists - BOOST_TEST(fs::exists(targetFilePath), "File " << targetFilePath << " exists"); + libcdoc::RcptInfo rcpt {.type=libcdoc::RcptInfo::LOCK, .label=Label, .secret=std::vector(Password.cbegin(), Password.cend())}; + decrypt({checkDataFile(sources[0])}, checkTargetFile("PasswordUsageWithoutLabel.cdoc"), tmpDataPath, rcpt); } - BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(PasswordUsageWithoutLabel) +// CDoc2 password and label -BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithPasswordWithoutLabel, EncryptFixture, * utf::description("Encrypting a file with password and without label")) +BOOST_AUTO_TEST_SUITE(PasswordUsageWithoutLabel) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithPasswordWithoutLabel, EncryptFixture, + * utf::description("Encrypting a file with password and without label")) { - // Check if the source, unecrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - - libcdoc::ToolConf conf; - conf.gen_label = true; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = targetFilePath.string(); - - libcdoc::RcptInfo rcpt; - rcpt.type = libcdoc::RcptInfo::PASSWORD; - rcpt.secret.assign(Password.cbegin(), Password.cend()); - - libcdoc::RecipientInfoVector rcpts {rcpt}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); - - // Validate the encrypted file - BOOST_TEST(ValidateEncryptedFile(targetFilePath)); + std::vector rcpts { + {libcdoc::RcptInfo::PASSWORD, {}, {}, std::vector(Password.cbegin(), Password.cend())} + }; + encrypt(2, {checkDataFile(sources[0])}, formTargetFile("PasswordUsageWithoutLabel.cdoc"), rcpts); } - BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithPasswordLabelIndex, DecryptFixture, * utf::depends_on("PasswordUsageWithoutLabel/EncryptWithPasswordWithoutLabel") * utf::description("Decrypting a file with password and label index")) { - // Check if the source, encrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = testDataPath.string(); - - libcdoc::RcptInfo rcpt {libcdoc::RcptInfo::ANY, {}, vector(Password.cbegin(), Password.cend())}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Decrypt(conf, 1, rcpt), 0); - - // Check if the encrypted file exists - BOOST_TEST(fs::exists(targetFilePath), "File " << targetFilePath << " exists"); + decrypt({checkDataFile(sources[0])}, checkTargetFile("PasswordUsageWithoutLabel.cdoc"), tmpDataPath.string(), std::vector(Password.cbegin(), Password.cend())); } - BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(AESKeyUsage) +// CDoc2 AES key -BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithAESKey, EncryptFixture, * utf::description("Encrypting a file with symmetric AES key")) +BOOST_AUTO_TEST_SUITE(AESKeyUsage) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithAESKey, EncryptFixture, + * utf::description("Encrypting a file with symmetric AES key")) { - // Check if the source, unecrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = targetFilePath.string(); - - libcdoc::RcptInfo rcpt; - rcpt.type = libcdoc::RcptInfo::SKEY; - rcpt.secret = std::move(libcdoc::fromHex(AESKey)); - rcpt.label = Label; - - libcdoc::RecipientInfoVector rcpts {rcpt}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); - - // Validate the encrypted file - BOOST_TEST(ValidateEncryptedFile(targetFilePath)); + std::vector rcpts { + {libcdoc::RcptInfo::SKEY, {}, {}, libcdoc::fromHex(AESKey)} + }; + encrypt(2, {checkDataFile(sources[0])}, formTargetFile("AESKeyUsage.cdoc"), rcpts); } - BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithAESKey, DecryptFixture, * utf::depends_on("AESKeyUsage/EncryptWithAESKey") * utf::description("Decrypting a file with with symmetric AES key")) { - // Check if the source, encrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = testDataPath.string(); - - libcdoc::RcptInfo rcpt {libcdoc::RcptInfo::ANY, {}, libcdoc::fromHex(AESKey)}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Decrypt(conf, Label, rcpt), 0); - - // Check if the encrypted file exists - BOOST_TEST(fs::exists(targetFilePath), "File " << targetFilePath << " exists"); + decrypt({checkDataFile(sources[0])}, checkTargetFile("AESKeyUsage.cdoc"), tmpDataPath.string(), libcdoc::fromHex(AESKey)); } - BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(ECKeyUsage) +// CDoc2 EC public/private key -BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithECKey, EncryptFixture, * utf::description("Encrypting a file with EC key")) +BOOST_AUTO_TEST_SUITE(ECKeyUsage) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithECKey, EncryptFixture, + * utf::description("Encrypting a file with EC key")) { - // Check if the source and public key file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - fs::path keyPath; - FormFilePath(ECPubKeyFile, keyPath); - BOOST_TEST_REQUIRE(fs::exists(keyPath), "File " << keyPath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = targetFilePath.string(); - - libcdoc::RcptInfo rcpt; - rcpt.type = libcdoc::RcptInfo::PKEY; - rcpt.secret = libcdoc::readAllBytes(keyPath.string()); - rcpt.label = Label; - - libcdoc::RecipientInfoVector rcpts {rcpt}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); - - // Validate the encrypted file - BOOST_TEST(ValidateEncryptedFile(targetFilePath)); + std::vector rcpts { + {libcdoc::RcptInfo::PKEY, {}, {}, fetchDataFile(ECPubKeyFile)} + }; + encrypt(2, {checkDataFile(sources[0])}, formTargetFile("ECKeyUsage.cdoc"), rcpts); } - BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithECKey, DecryptFixture, * utf::depends_on("ECKeyUsage/EncryptWithECKey") * utf::description("Decrypting a file with with EC private key")) { - // Check if the source, encrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - fs::path keyPath; - FormFilePath(ECPrivKeyFile, keyPath); - BOOST_TEST_REQUIRE(fs::exists(keyPath), "File " << keyPath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = testDataPath.string(); - - libcdoc::RcptInfo rcpt {libcdoc::RcptInfo::ANY, {}, libcdoc::readAllBytes(keyPath.string())}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Decrypt(conf, Label, rcpt), 0); - - // Check if the encrypted file exists - BOOST_TEST(fs::exists(targetFilePath), "File " << targetFilePath << " exists"); + decrypt({checkDataFile(sources[0])}, checkTargetFile("ECKeyUsage.cdoc"), tmpDataPath.string(), fetchDataFile(ECPrivKeyFile)); } - BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(RSAKeyUsage) +// CDoc2 RSA public/private key -BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithRSAKey, EncryptFixture, * utf::description("Encrypting a file with RSA key")) +BOOST_AUTO_TEST_SUITE(RSAKeyUsage) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithRSAKey, EncryptFixture, + * utf::description("Encrypting a file with RSA key")) { - // Check if the source and public key file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - fs::path keyPath; - FormFilePath(RSAPubKeyFile, keyPath); - BOOST_TEST_REQUIRE(fs::exists(keyPath), "File " << keyPath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = targetFilePath.string(); - - libcdoc::RcptInfo rcpt; - rcpt.type = libcdoc::RcptInfo::PKEY; - rcpt.secret = libcdoc::readAllBytes(keyPath.string()); - rcpt.label = Label; - - libcdoc::RecipientInfoVector rcpts {rcpt}; - - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Encrypt(conf, rcpts), 0); - - // Validate the encrypted file - BOOST_TEST(ValidateEncryptedFile(targetFilePath)); + std::vector rcpts { + {libcdoc::RcptInfo::PKEY, {}, {}, fetchDataFile(RSAPubKeyFile)} + }; + encrypt(2, {checkDataFile(sources[0])}, formTargetFile("RSAKeyUsage.cdoc"), rcpts); } - BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithRSAKey, DecryptFixture, * utf::depends_on("RSAKeyUsage/EncryptWithRSAKey") * utf::description("Decrypting a file with with RSA private key")) { - // Check if the source, encrypted file exists - BOOST_TEST_REQUIRE(fs::exists(sourceFilePath), "File " << sourceFilePath << " must exists"); - fs::path keyPath; - FormFilePath(RSAPrivKeyFile, keyPath); - BOOST_TEST_REQUIRE(fs::exists(keyPath), "File " << keyPath << " must exists"); - - libcdoc::ToolConf conf; - conf.input_files.push_back(sourceFilePath.string()); - conf.out = testDataPath.string(); + decrypt({checkDataFile(sources[0])}, checkTargetFile("RSAKeyUsage.cdoc"), tmpDataPath.string(), fetchDataFile(RSAPrivKeyFile)); +} +BOOST_AUTO_TEST_SUITE_END() - libcdoc::RcptInfo rcpt {libcdoc::RcptInfo::ANY, {}, libcdoc::readAllBytes(keyPath.string())}; +// CDoc1 tests - libcdoc::CDocCipher cipher; - BOOST_CHECK_EQUAL(cipher.Decrypt(conf, Label, rcpt), 0); +BOOST_AUTO_TEST_SUITE(CDoc1ECKeySingle) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithECKeyV1, EncryptFixture, + * utf::description("Encrypting a file with EC key in CDoc1 format")) +{ + encryptV1({checkDataFile(sources[0])}, formTargetFile("ECKeyUsageV1.cdoc"), fetchDataFile(ECCertFile)); +} +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithECKeyV1, DecryptFixture, + * utf::depends_on("CDoc1ECKeySingle/EncryptWithECKeyV1") + * utf::description("Decrypting a file in CDoc1 format with with EC private key")) +{ + decrypt({checkDataFile(sources[0])}, checkTargetFile("ECKeyUsageV1.cdoc"), tmpDataPath.string(), fetchDataFile(ECPrivKeyFile)); +} +BOOST_AUTO_TEST_SUITE_END() - // Check if the encrypted file exists - BOOST_TEST(fs::exists(targetFilePath), "File " << targetFilePath << " exists"); +BOOST_AUTO_TEST_SUITE(CDoc1ECKeyMulti) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithECKeyV1Multi, EncryptFixture, + * utf::description("Encrypting multiple files with EC key in CDoc1 format")) +{ + encryptV1({checkDataFile(sources[0]), checkDataFile(sources[1]), checkDataFile(sources[2])}, formTargetFile("ECKeyUsageV1Multi.cdoc"), fetchDataFile(ECCertFile)); +} +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithECKeyV1Multi, DecryptFixture, + * utf::depends_on("CDoc1ECKeyMulti/EncryptWithECKeyV1Multi") + * utf::description("Decrypting multiple files in CDoc1 format with with EC private key")) +{ + decrypt({checkDataFile(sources[0]), checkDataFile(sources[1]), checkDataFile(sources[2])}, checkTargetFile("ECKeyUsageV1Multi.cdoc"), tmpDataPath.string(), fetchDataFile(ECPrivKeyFile)); } +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE(CDoc1RSAKeySingle) +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(EncryptWithRSAKeyV1, EncryptFixture, * utf::description("Encrypting a file with RSA key in CDoc1 format")) +{ + encryptV1({checkDataFile(sources[0])}, formTargetFile("RSAKeyUsageV1.cdoc"), fetchDataFile(RSACertFile)); +} +BOOST_FIXTURE_TEST_CASE_WITH_DECOR(DecryptWithRSAKeyV1, DecryptFixture, + * utf::depends_on("CDoc1RSAKeySingle/EncryptWithRSAKeyV1") + * utf::description("Decrypting a file in CDoc1 format with with RSA private key")) +{ + decrypt({checkDataFile(sources[0])}, checkTargetFile("RSAKeyUsageV1.cdoc"), tmpDataPath.string(), fetchDataFile(RSAPrivKeyFile)); +} BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(MachineLabelParsing) +// Label parsing +BOOST_AUTO_TEST_SUITE(MachineLabelParsing) BOOST_AUTO_TEST_CASE(PlainLabelParsing) { const string label("data:v=1&type=ID-card&serial_number=PNOEE-38001085718&cn=J%C3%95EORG%2CJAAK-KRISTJAN%2C38001085718"); @@ -643,11 +604,9 @@ BOOST_AUTO_TEST_CASE(Base64LabelParsingWithMediaType) } } } - BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(StreamingDecryption) - using BufTypes = std::tuple, std::array, std::array, std::array>; BOOST_AUTO_TEST_CASE_TEMPLATE(constructor, Buf, BufTypes) {