Ods::pag* CryptoManager::encrypt(ISC_STATUS* sv, Ods::pag* from, Ods::pag* to) { // Code calling us is not ready to process exceptions correctly // Therefore use old (status vector based) method try { if (crypt && cryptPlugin && Ods::pag_crypt_page[from->pag_type % (pag_max + 1)]) { to[0] = from[0]; LocalStatus status; cryptPlugin->encrypt(&status, dbb.dbb_page_size - sizeof(Ods::pag), &from[1], &to[1]); if (!status.isSuccess()) { memcpy(sv, status.get(), sizeof(ISC_STATUS_ARRAY)); return NULL; } to->pag_flags |= Ods::crypted_page; return to; } else { from->pag_flags &= ~Ods::crypted_page; return from; } } catch (const Exception& ex) { ex.stuff_exception(sv); } return NULL; }
bool CryptoManager::decrypt(ISC_STATUS* sv, Ods::pag* page) { // Code calling us is not ready to process exceptions correctly // Therefore use old (status vector based) method try { if (page->pag_flags & Ods::crypted_page) { if (!cryptPlugin) { // We are invoked from shared cache manager, i.e. no valid attachment in tdbb // Therefore create system temporary attachment like in crypt thread to be able to work with locks UserId user; user.usr_user_name = "(Crypt plugin loader)"; Jrd::Attachment* const attachment = Jrd::Attachment::create(&dbb); RefPtr<SysAttachment> jAtt(new SysAttachment(attachment)); attachment->att_interface = jAtt; attachment->att_filename = dbb.dbb_filename; attachment->att_user = &user; BackgroundContextHolder tdbb(&dbb, attachment, sv, FB_FUNCTION); // Lock crypt state takeStateLock(tdbb); Header hdr(tdbb, LCK_read); crypt = hdr->hdr_flags & Ods::hdr_encrypted; process = hdr->hdr_flags & Ods::hdr_crypt_process; if (crypt || process) { loadPlugin(hdr->hdr_crypt_plugin); } if (!cryptPlugin) { (Arg::Gds(isc_decrypt_error)).raise(); return false; } } LocalStatus status; cryptPlugin->decrypt(&status, dbb.dbb_page_size - sizeof(Ods::pag), &page[1], &page[1]); if (!status.isSuccess()) { memcpy(sv, status.get(), sizeof(ISC_STATUS_ARRAY)); return false; } } return true; } catch (const Exception& ex) { ex.stuff_exception(sv); } return false; }
void CryptoManager::KeyHolderPlugins::init(IDbCryptPlugin* crypt) { MutexLockGuard g(holdersMutex, FB_FUNCTION); Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 64> holdersVector; unsigned int length = knownHolders.getCount(); IKeyHolderPlugin** vector = holdersVector.getBuffer(length); for (unsigned i = 0; i < length; ++i) { vector[i] = knownHolders[i].getPlugin(); } LocalStatus st; crypt->setKey(&st, length, vector); if (!st.isSuccess()) { status_exception::raise(st.get()); } }
void CryptoManager::KeyHolderPlugins::attach(Attachment* att, Config* config) { MutexLockGuard g(holdersMutex, FB_FUNCTION); for (GetPlugins<IKeyHolderPlugin> keyControl(PluginType::KeyHolder, FB_KEYHOLDER_PLUGIN_VERSION, upInfo, config); keyControl.hasData(); keyControl.next()) { IKeyHolderPlugin* keyPlugin = keyControl.plugin(); LocalStatus st; if (keyPlugin->keyCallback(&st, att->att_crypt_callback) == 1) { // holder accepted attachment's key HolderAttachments* ha = NULL; for (unsigned i = 0; i < knownHolders.getCount(); ++i) { if (knownHolders[i] == keyPlugin) { ha = &knownHolders[i]; break; } } if (!ha) { ha = &(knownHolders.add()); ha->setPlugin(keyPlugin); } ha->registerAttachment(att); break; // Do not need >1 key from attachment to single DB } else if (!st.isSuccess()) { status_exception::raise(st.get()); } } }