diff --git a/cdoc/CDoc2Writer.cpp b/cdoc/CDoc2Writer.cpp index 5247d05e..377de316 100644 --- a/cdoc/CDoc2Writer.cpp +++ b/cdoc/CDoc2Writer.cpp @@ -419,7 +419,6 @@ CDoc2Writer::buildHeader(std::vector& header, const std::vector> transaction_ids(N_SHARES); for (int i = 0; i < N_SHARES; i++) { std::string send_url = urls[i]; - LOG_TRACE_KEY("Sending share: {} {} {}", i, send_url, libcdoc::toHex(kek_shares[i])); int result = network->sendShare(transaction_ids[i], send_url, RecipientInfo_i, kek_shares[i]); if (result < 0) FAIL(network->getLastErrorStr(result), result); @@ -479,6 +478,14 @@ CDoc2Writer::addRecipient(const libcdoc::Recipient& rcpt) if(!rcpt.validate()) FAIL("Invalid recipient parameters", libcdoc::WRONG_ARGUMENTS); break; +#ifdef HAS_KEYSHARES + case Recipient::KEYSHARE: + if (!network) + FAIL("KeyShares require NetworkBackend", libcdoc::WORKFLOW_ERROR); + if (!rcpt.validate()) + FAIL("Invalid recipient parameters", libcdoc::WRONG_ARGUMENTS); + break; +#endif default: FAIL("Invalid recipient type", WRONG_ARGUMENTS); } diff --git a/cdoc/CDocCipher.cpp b/cdoc/CDocCipher.cpp index b98b938e..89924b2d 100644 --- a/cdoc/CDocCipher.cpp +++ b/cdoc/CDocCipher.cpp @@ -73,7 +73,7 @@ struct ToolPKCS11 : public libcdoc::PKCS11Backend { ToolPKCS11(const std::string& library, const CipherInfo& info) : PKCS11Backend(library), c_info(info) {} libcdoc::result_t connectToKey(int idx, bool priv) override final { - const libcdoc::RcptInfo *rcpt = c_info.getRcpt(idx); + const libcdoc::RcptInfo *rcpt = c_info.getRcpt(idx); if (!rcpt) return libcdoc::INTERNAL_ERROR; if (!priv) { return useSecretKey(long(rcpt->p11.slot), rcpt->secret, rcpt->p11.key_id, rcpt->p11.key_label); diff --git a/cdoc/CMakeLists.txt b/cdoc/CMakeLists.txt index 44c87a68..d82d3c4f 100644 --- a/cdoc/CMakeLists.txt +++ b/cdoc/CMakeLists.txt @@ -50,6 +50,7 @@ add_library(cdoc CDoc2Writer.cpp CDoc2Writer.h DDocReader.cpp DDocReader.h DDocWriter.cpp DDocWriter.h + KeyShares.cpp KeyShares.h # KeyShares.cpp KeyShares.h XmlReader.cpp XmlReader.h XmlWriter.cpp XmlWriter.h @@ -79,6 +80,9 @@ target_include_directories(cdoc PUBLIC PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +# Enable SID/MID +target_compile_definitions(cdoc PRIVATE HAS_KEYSHARES) + if(NOT BUILD_SHARED_LIBS) target_compile_definitions(cdoc PUBLIC cdoc_STATIC) endif() @@ -102,6 +106,10 @@ target_link_libraries(cdoc PRIVATE if(BUILD_TOOLS) add_executable(cdoc-tool cdoc-tool.cpp) target_include_directories(cdoc-tool PRIVATE ${OPENSSL_INCLUDE_DIR}) + + # Enable SID/MID + target_compile_definitions(cdoc-tool PRIVATE HAS_KEYSHARES) + target_link_libraries(cdoc-tool cdoc_ver cdoc OpenSSL::SSL) target_link_options(cdoc-tool PRIVATE $<$: /MANIFEST:NO /MANIFEST:EMBED /MANIFESTINPUT:${CMAKE_CURRENT_SOURCE_DIR}/cdoc-tool.manifest> diff --git a/cdoc/NetworkBackend.cpp b/cdoc/NetworkBackend.cpp index 27ccbb7c..39eae5ad 100644 --- a/cdoc/NetworkBackend.cpp +++ b/cdoc/NetworkBackend.cpp @@ -463,6 +463,12 @@ libcdoc::NetworkBackend::fetchKey (std::vector& dst, const std::string& } #ifdef HAS_KEYSHARES +libcdoc::result_t +libcdoc::NetworkBackend::authenticateForShares(std::vector& dst) +{ + return NOT_IMPLEMENTED; +} + libcdoc::result_t libcdoc::NetworkBackend::fetchNonce(std::vector& dst, const std::string& url, const std::string& share_id) { @@ -608,9 +614,9 @@ rsa_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *si #ifdef HAS_KEYSHARES libcdoc::result_t -libcdoc::NetworkBackend::showVerificationCode(unsigned int code) +libcdoc::NetworkBackend::showFeedback(SIDMIDFeedback& feedback) { - LOG_INFO("Verification code: {:04d}", code); + LOG_INFO("Verification code: {:04d} url: {}", feedback.code, feedback.url); return OK; } @@ -836,8 +842,9 @@ libcdoc::NetworkBackend::signSID(std::vector& dst, std::vector // Generate code uint8_t b[32]; SHA256(digest.data(), digest.size(), b); - unsigned int code = ((b[30] << 8) | b[31]) % 10000; - result = showVerificationCode(code); + SIDMIDFeedback fb; + fb.code = ((b[30] << 8) | b[31]) % 10000; + result = showFeedback(fb); if (result != OK) return result; picojson::object aio1 = { @@ -962,8 +969,9 @@ libcdoc::NetworkBackend::signMID(std::vector& dst, std::vector } // Generate verification code. digest is guaranteed non-empty above. - unsigned int code = (((digest[0] & 0xfc) << 5) | (digest[digest.size() - 1] & 0x7f)); - result = showVerificationCode(code); + SIDMIDFeedback fb; + fb.code = (((digest[0] & 0xfc) << 5) | (digest[digest.size() - 1] & 0x7f)); + result = showFeedback(fb); if (result != OK) return result; picojson::object qobj = { @@ -991,7 +999,7 @@ libcdoc::NetworkBackend::signMID(std::vector& dst, std::vector LOG_DBG("Response: {}", rsp.body); picojson::value v; - parse_err = picojson::parse(v, rsp.body); + std::string parse_err = picojson::parse(v, rsp.body); if (!parse_err.empty()) { error = FORMAT("JSON parse error: {}", parse_err); LOG_ERROR("{}", error); diff --git a/cdoc/NetworkBackend.h b/cdoc/NetworkBackend.h index 8a3b8621..390c06f9 100644 --- a/cdoc/NetworkBackend.h +++ b/cdoc/NetworkBackend.h @@ -125,6 +125,11 @@ struct CDOC_EXPORT NetworkBackend { std::string_view password; }; + struct SIDMIDFeedback { + int code; + std::string url; + }; + NetworkBackend() = default; virtual ~NetworkBackend() noexcept = default; NetworkBackend(const NetworkBackend&) = delete; @@ -176,6 +181,7 @@ struct CDOC_EXPORT NetworkBackend { */ virtual result_t fetchKey (std::vector& dst, const std::string& url, const std::string& transaction_id); #ifdef HAS_KEYSHARES + virtual result_t authenticateForShares(std::vector& dst); /** * @brief fetch authentication nonce from share server * @param dst a destination container for nonce @@ -245,13 +251,14 @@ struct CDOC_EXPORT NetworkBackend { #ifdef HAS_KEYSHARES /** - * @brief show MID/SID verification code + * @brief show MID/SID verification code or QR code + * + * Show SID/MID verification code or QR code. The default implementation logs the content with level INFO. * - * Show SID/MID verification code. The default implementation logs it with level INFO. - * @param code verification code + * @param feedback SID/MID feedback data * @return error code or OK */ - virtual result_t showVerificationCode(unsigned int code); + virtual result_t showFeedback(SIDMIDFeedback& feedback); /** * @brief Sign digest with SmartID authentication key diff --git a/cdoc/Recipient.cpp b/cdoc/Recipient.cpp index 89e4f4c1..0274dc70 100644 --- a/cdoc/Recipient.cpp +++ b/cdoc/Recipient.cpp @@ -237,6 +237,11 @@ Recipient::validate() const case PUBLIC_KEY: // Public key should not be empty return !rcpt_key.empty(); +#ifdef HAS_KEYSHARES + case KEYSHARE: + // Server ID and recipient ID should not be empty + return !server_id.empty() && !id.empty(); +#endif default: return false; }