|
23 | 23 | #include "CryptoBackend.h" |
24 | 24 | #include "CDoc2.h" |
25 | 25 | #include "ILogger.h" |
| 26 | +#include "KeyShares.h" |
26 | 27 | #include "Lock.h" |
27 | 28 | #include "NetworkBackend.h" |
28 | 29 | #include "Tar.h" |
@@ -111,8 +112,10 @@ libcdoc::result_t |
111 | 112 | CDoc2Reader::getLockForCert(const std::vector<uint8_t>& cert){ |
112 | 113 | libcdoc::Certificate cc(cert); |
113 | 114 | std::vector<uint8_t> other_key = cc.getPublicKey(); |
| 115 | + LOG_DBG("Cert public key: {}", toHex(other_key)); |
114 | 116 | for (int lock_idx = 0; lock_idx < priv->locks.size(); lock_idx++) { |
115 | 117 | const libcdoc::Lock *ll = priv->locks.at(lock_idx); |
| 118 | + LOG_DBG("Lock {} type {}", lock_idx, (int) ll->type); |
116 | 119 | if (ll->hasTheSameKey(other_key)) { |
117 | 120 | return lock_idx; |
118 | 121 | } |
@@ -152,7 +155,7 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx) |
152 | 155 | LOG_TRACE_KEY("kek: {}", kek); |
153 | 156 |
|
154 | 157 | if (kek.empty()) return libcdoc::CRYPTO_ERROR; |
155 | | - } else { |
| 158 | + } else if ((lock.type == libcdoc::Lock::Type::PUBLIC_KEY) || (lock.type == libcdoc::Lock::Type::SERVER)) { |
156 | 159 | // Public/private key |
157 | 160 | std::vector<uint8_t> key_material; |
158 | 161 | if(lock.type == libcdoc::Lock::Type::SERVER) { |
@@ -210,6 +213,88 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx) |
210 | 213 |
|
211 | 214 | kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), libcdoc::CDoc2::KEY_LEN); |
212 | 215 | } |
| 216 | + } else if (lock.type == libcdoc::Lock::Type::SHARE_SERVER) { |
| 217 | + /* SALT */ |
| 218 | + std::vector<uint8_t> salt = lock.getBytes(Lock::SALT); |
| 219 | + /* RECIPIENT_ID */ |
| 220 | + std::string rcpt_id = lock.getString(Lock::RECIPIENT_ID); |
| 221 | + /* SHARE_URLS */ |
| 222 | + /* url,share_id;url,share_id... */ |
| 223 | + std::string all = lock.getString(Lock::SHARE_URLS); |
| 224 | + std::vector<std::string> strs = split(all, ';'); |
| 225 | + if (strs.empty()) return libcdoc::DATA_FORMAT_ERROR; |
| 226 | + std::vector<ShareData> shares; |
| 227 | + for (auto& str : strs) { |
| 228 | + std::vector<std::string> parts = split(str, ','); |
| 229 | + if (parts.size() != 2) return libcdoc::DATA_FORMAT_ERROR; |
| 230 | + std::string url = parts[0]; |
| 231 | + std::string id = parts[1]; |
| 232 | + LOG_DBG("Share {} url {}", id, url); |
| 233 | + |
| 234 | + std::vector<uint8_t> nonce; |
| 235 | + int64_t result = network->fetchNonce(nonce, url, id); |
| 236 | + if (result != libcdoc::OK) { |
| 237 | + setLastError(t_("Cannot fetch nonce from server")); |
| 238 | + LOG_ERROR("Cannot fetch nonce from server {}", url); |
| 239 | + return result; |
| 240 | + } |
| 241 | + LOG_DBG("Nonce: {}", std::string(nonce.cbegin(), nonce.cend())); |
| 242 | + ShareData acc(url, id, std::string(nonce.cbegin(), nonce.cend())); |
| 243 | + shares.push_back(std::move(acc)); |
| 244 | + } |
| 245 | + /* Create tickets from shares */ |
| 246 | + std::vector<std::string> tickets; |
| 247 | + std::vector<uint8_t> cert; |
| 248 | + result_t result = NOT_IMPLEMENTED; |
| 249 | + if (conf->getValue(Configuration::SHARE_SIGNER) == "SMART_ID") { |
| 250 | + // "https://sid.demo.sk.ee/smart-id-rp/v2" |
| 251 | + std::string url = conf->getValue(Configuration::SID_DOMAIN, Configuration::BASE_URL); |
| 252 | + // "00000000-0000-0000-0000-000000000000" |
| 253 | + std::string relyingPartyUUID = conf->getValue(Configuration::SID_DOMAIN, Configuration::RP_UUID); |
| 254 | + // "DEMO" |
| 255 | + std::string relyingPartyName = conf->getValue(Configuration::SID_DOMAIN, Configuration::RP_NAME); |
| 256 | + SIDSigner signer(url, relyingPartyUUID, relyingPartyName, rcpt_id, network); |
| 257 | + result = signer.generateTickets(tickets, shares); |
| 258 | + if (result == OK) cert = std::move(signer.cert); |
| 259 | + } else if (conf->getValue(Configuration::SHARE_SIGNER) == "MOBILE_ID") { |
| 260 | + // "https://sid.demo.sk.ee/smart-id-rp/v2" |
| 261 | + std::string url = conf->getValue(Configuration::MID_DOMAIN, Configuration::BASE_URL); |
| 262 | + // "00000000-0000-0000-0000-000000000000" |
| 263 | + std::string relyingPartyUUID = conf->getValue(Configuration::MID_DOMAIN, Configuration::RP_UUID); |
| 264 | + // "DEMO" |
| 265 | + std::string relyingPartyName = conf->getValue(Configuration::MID_DOMAIN, Configuration::RP_NAME); |
| 266 | + // "37200000566" |
| 267 | + std::string phone = conf->getValue(Configuration::MID_DOMAIN, Configuration::PHONE_NUMBER); |
| 268 | + MIDSigner signer(url, relyingPartyUUID, relyingPartyName, phone, rcpt_id, network); |
| 269 | + result = signer.generateTickets(tickets, shares); |
| 270 | + if (result == OK) cert = std::move(signer.cert); |
| 271 | + } else { |
| 272 | + setLastError(t_("Unknown or missing signer type")); |
| 273 | + LOG_ERROR("Unknown or missing signer type"); |
| 274 | + return result; |
| 275 | + } |
| 276 | + if (result != libcdoc::OK) { |
| 277 | + setLastError(t_("Cannot generate share tickets")); |
| 278 | + LOG_ERROR("Cannot generate share tickets"); |
| 279 | + return result; |
| 280 | + } |
| 281 | + kek.resize(32); |
| 282 | + std::fill(kek.begin(), kek.end(), 0); |
| 283 | + for (unsigned int i = 0; i < tickets.size(); i++) { |
| 284 | + NetworkBackend::ShareInfo share; |
| 285 | + result = network->fetchShare(share, shares[i].base_url, shares[i].share_id, tickets[i], cert); |
| 286 | + if (result != libcdoc::OK) { |
| 287 | + setLastError(t_("Cannot fetch share")); |
| 288 | + LOG_ERROR("Cannot fetch share {}", i); |
| 289 | + return result; |
| 290 | + } |
| 291 | + Crypto::xor_data(kek, kek, share.share); |
| 292 | + } |
| 293 | + LOG_INFO("Fetched all shares"); |
| 294 | + } else { |
| 295 | + setLastError(t_("Unknown lock type")); |
| 296 | + LOG_ERROR("Unknown lock type: %d", (int) lock.type); |
| 297 | + return libcdoc::UNSPECIFIED_ERROR; |
213 | 298 | } |
214 | 299 |
|
215 | 300 | LOG_TRACE_KEY("KEK: {}", kek); |
@@ -524,6 +609,40 @@ CDoc2Reader::CDoc2Reader(libcdoc::DataSource *src, bool take_ownership) |
524 | 609 | priv->locks.push_back(key); |
525 | 610 | } |
526 | 611 | break; |
| 612 | + case Capsule::recipients_KeySharesCapsule: |
| 613 | + if (const auto *capsule = recipient->capsule_as_recipients_KeySharesCapsule()) { |
| 614 | + if (capsule->recipient_type() != cdoc20::recipients::KeyShareRecipientType::SID_MID) { |
| 615 | + LOG_ERROR("Invalid keyshare recipient type: {}", (int) capsule->recipient_type()); |
| 616 | + continue; |
| 617 | + } |
| 618 | + if (capsule->shares_scheme() != cdoc20::recipients::SharesScheme::N_OF_N) { |
| 619 | + LOG_ERROR("Invalid keyshare scheme type: {}", (int) capsule->shares_scheme()); |
| 620 | + continue; |
| 621 | + } |
| 622 | + /* url,share_id;url,share_id... */ |
| 623 | + std::vector<std::string> strs; |
| 624 | + for (auto cshare = capsule->shares()->cbegin(); cshare != capsule->shares()->cend(); ++cshare) { |
| 625 | + std::string id = cshare->share_id()->str(); |
| 626 | + std::string url = cshare->server_base_url()->str(); |
| 627 | + std::string str = url + "," + id; |
| 628 | + LOG_DBG("Keyshare: {}", str); |
| 629 | + strs.push_back(str); |
| 630 | + } |
| 631 | + std::string urls = join(strs, ";"); |
| 632 | + LOG_DBG("Keyshare urls: {}", urls); |
| 633 | + std::vector<uint8_t> salt(capsule->salt()->cbegin(), capsule->salt()->cend()); |
| 634 | + LOG_DBG("Keyshare salt: {}", toHex(salt)); |
| 635 | + std::string recipient_id = capsule->recipient_id()->str(); |
| 636 | + LOG_DBG("Keyshare recipient id: {}", recipient_id); |
| 637 | + libcdoc::Lock *lock = new libcdoc::Lock(libcdoc::Lock::SHARE_SERVER); |
| 638 | + lock->label = recipient->key_label()->str(); |
| 639 | + lock->encrypted_fmk.assign(recipient->encrypted_fmk()->cbegin(), recipient->encrypted_fmk()->cend()); |
| 640 | + lock->setString(libcdoc::Lock::SHARE_URLS, urls); |
| 641 | + lock->setBytes(libcdoc::Lock::SALT, salt); |
| 642 | + lock->setString(libcdoc::Lock::RECIPIENT_ID, recipient_id); |
| 643 | + priv->locks.push_back(std::move(lock)); |
| 644 | + } |
| 645 | + break; |
527 | 646 | default: |
528 | 647 | LOG_ERROR("Unsupported Key Details: skipping"); |
529 | 648 | } |
|
0 commit comments