X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmanager%2Fservice%2Fckm-logic.cpp;h=8736fd50bfc27fcdb6d0fae0b534c3c52db06909;hb=51a5e9cfe81d0374a02c1e28375a482b68afd879;hp=3ce1e1c60469591d4044ba87923da755d3e8673e;hpb=0df8f4ec79a11de5bf82ce472801467aa70defa8;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 3ce1e1c..8736fd5 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -191,7 +191,7 @@ UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incomi if (0 == m_userDataMap.count(cred.clientUid)) ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked"); - if (0 != incoming_label.compare(LABEL_SYSTEM_DB)) + if (0 != incoming_label.compare(OWNER_ID_SYSTEM)) return m_userDataMap[cred.clientUid]; } @@ -417,15 +417,12 @@ DB::Row CKMLogic::createEncryptedRow( const RawBuffer &data, const Policy &policy) const { - DB::Row row(name, label, static_cast(policy.extractable), dataType, data, static_cast(data.size())); - row.backendId = m_decider.chooseCryptoBackend(dataType, policy.extractable); + Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable); // do not encrypt data with password during cc_mode on - if(m_accessControl.isCCMode()) { - crypto.encryptRow("", row); - } else { - crypto.encryptRow(policy.password, row); - } + Token token = store.import(dataType, data, m_accessControl.isCCMode() ? "" : policy.password); + DB::Row row(std::move(token), name, label, static_cast(policy.extractable)); + crypto.encryptRow(row); return row; } @@ -508,14 +505,15 @@ int CKMLogic::getKeyForService( const Name &name, const Label &label, const Password &pass, - Crypto::GKeyShPtr &key) + Crypto::GObjShPtr &key) { DB::Row row; try { // Key is for internal service use. It won't be exported to the client - int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, row); + Crypto::GObjUPtr obj; + int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj); if (retCode == CKM_API_SUCCESS) - key = m_decider.getStore(row).getKey(row); + key = std::move(obj); return retCode; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); @@ -649,15 +647,33 @@ int CKMLogic::removeDataHelper( return retCode; } - auto erased = handler.database.deleteRow(name, ownerLabel); - // check if the data existed or not - if(erased) - transaction.commit(); - else { + // get all matching rows + DB::RowVector rows; + handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows); + if (rows.empty()) { LogDebug("No row for given name and label"); return CKM_API_ERROR_DB_ALIAS_UNKNOWN; } + // load app key if needed + retCode = loadAppKey(handler, rows.front().ownerLabel); + if(CKM_API_SUCCESS != retCode) + return retCode; + + // destroy it in store + for(auto& r : rows) { + try { + handler.crypto.decryptRow(Password(), r); + m_decider.getStore(r).destroy(r); + } catch (const Exc::AuthenticationFailed&) { + LogDebug("Authentication failed when removing data. Ignored."); + } + } + + // delete row in db + handler.database.deleteRow(name, ownerLabel); + transaction.commit(); + return CKM_API_SUCCESS; } @@ -778,6 +794,45 @@ int CKMLogic::checkDataPermissionsHelper(const Credentials &cred, return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt)); } +Crypto::GObjUPtr CKMLogic::rowToObject( + UserData& handler, + DB::Row row, + const Password& password) +{ + Crypto::GStore& store = m_decider.getStore(row); + + Password pass = m_accessControl.isCCMode() ? "" : password; + + // decrypt row + Crypto::GObjUPtr obj; + if(CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) { + handler.crypto.decryptRow(Password(), row); + + obj = store.getObject(row, pass); + } else { + // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data + handler.crypto.decryptRow(pass, row); + // destroy it in store + store.destroy(row); + + // import it to store with new scheme: data -> pass(data) + Token token = store.import(row.dataType,row.data, pass); + + // get it from the store (it can be different than the data we imported into store) + obj = store.getObject(token, pass); + + // update row with new token + *static_cast(&row) = std::move(token); + + // encrypt it with app key: pass(data) -> b64(appkey(pass(data)) + handler.crypto.encryptRow(row); + + // update it in db + handler.database.updateRow(row); + } + return obj; +} + int CKMLogic::readDataHelper( bool exportFlag, const Credentials &cred, @@ -785,7 +840,7 @@ int CKMLogic::readDataHelper( const Name &name, const Label &label, const Password &password, - DB::RowVector &rows) + Crypto::GObjUPtrVector &objs) { auto &handler = selectDatabase(cred, label); @@ -797,6 +852,7 @@ int CKMLogic::readDataHelper( // read rows DB::Crypto::Transaction transaction(&handler.database); + DB::RowVector rows; int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows); if(CKM_API_SUCCESS != retCode) return retCode; @@ -809,20 +865,16 @@ int CKMLogic::readDataHelper( if(CKM_API_SUCCESS != retCode) return retCode; + // load app key if needed + retCode = loadAppKey(handler, firstRow.ownerLabel); + if(CKM_API_SUCCESS != retCode) + return retCode; + // decrypt row - if (!handler.crypto.haveKey(firstRow.ownerLabel)) { - RawBuffer key; - auto key_optional = handler.database.getKey(firstRow.ownerLabel); - if(!key_optional) { - LogError("No key for given label in database"); - return CKM_API_ERROR_DB_ERROR; - } - key = *key_optional; - key = handler.keyProvider.getPureDEK(key); - handler.crypto.pushKey(firstRow.ownerLabel, key); - } for(auto &row : rows) - handler.crypto.decryptRow(password, row); + objs.push_back(rowToObject(handler, std::move(row), password)); + // rowToObject may modify db + transaction.commit(); return CKM_API_SUCCESS; } @@ -834,7 +886,21 @@ int CKMLogic::readDataHelper( const Name &name, const Label &label, const Password &password, - DB::Row &row) + Crypto::GObjUPtr &obj) +{ + DataType objDataType; + return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType); +} + +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const Label &label, + const Password &password, + Crypto::GObjUPtr &obj, + DataType& objDataType) { auto &handler = selectDatabase(cred, label); @@ -846,28 +912,26 @@ int CKMLogic::readDataHelper( // read row DB::Crypto::Transaction transaction(&handler.database); + DB::Row row; int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row); if(CKM_API_SUCCESS != retCode) return retCode; + objDataType = row.dataType; + // check access rights retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database); if(CKM_API_SUCCESS != retCode) return retCode; - // decrypt row - if (!handler.crypto.haveKey(row.ownerLabel)) { - RawBuffer key; - auto key_optional = handler.database.getKey(row.ownerLabel); - if(!key_optional) { - LogError("No key for given label in database"); - return CKM_API_ERROR_DB_ERROR; - } - key = *key_optional; - key = handler.keyProvider.getPureDEK(key); - handler.crypto.pushKey(row.ownerLabel, key); - } - handler.crypto.decryptRow(password, row); + // load app key if needed + retCode = loadAppKey(handler, row.ownerLabel); + if(CKM_API_SUCCESS != retCode) + return retCode; + + obj = rowToObject(handler, std::move(row), password); + // rowToObject may modify db + transaction.commit(); return CKM_API_SUCCESS; } @@ -882,9 +946,13 @@ RawBuffer CKMLogic::getData( { int retCode = CKM_API_SUCCESS; DB::Row row; + DataType objDataType; try { - retCode = readDataHelper(true, cred, dataType, name, label, password, row); + Crypto::GObjUPtr obj; + retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType); + if(retCode == CKM_API_SUCCESS) + row.data = std::move(obj->getBinary()); } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -903,7 +971,7 @@ RawBuffer CKMLogic::getData( auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET), commandId, retCode, - static_cast(row.dataType), + static_cast(objDataType), row.data); return response.Pop(); } @@ -921,27 +989,27 @@ int CKMLogic::getPKCS12Helper( int retCode; // read private key (mandatory) - DB::Row privKeyRow; - retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow); + Crypto::GObjUPtr keyObj; + retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, keyObj); if(retCode != CKM_API_SUCCESS) return retCode; - privKey = CKM::Key::create(privKeyRow.data); + privKey = CKM::Key::create(keyObj->getBinary()); // read certificate (mandatory) - DB::Row certRow; - retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow); + Crypto::GObjUPtr certObj; + retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj); if(retCode != CKM_API_SUCCESS) return retCode; - cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER); + cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER); // read CA cert chain (optional) - DB::RowVector rawCaChain; - retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain); + Crypto::GObjUPtrVector caChainObjs; + retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs); if(retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) return retCode; - for(auto &rawCaCert : rawCaChain) - caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER)); + for(auto &caCertObj : caChainObjs) + caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER)); // if anything found, return it if(privKey || cert || caChain.size()>0) @@ -1038,7 +1106,7 @@ RawBuffer CKMLogic::getDataList( { // lookup system DB retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, - LABEL_SYSTEM_DB), + OWNER_ID_SYSTEM), dataType, systemVector); } @@ -1085,7 +1153,7 @@ int CKMLogic::saveDataHelper( // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; - if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0) + if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0) return CKM_API_ERROR_INPUT_PARAM; // check if save is possible @@ -1114,7 +1182,7 @@ int CKMLogic::saveDataHelper( // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; - if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0) + if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0) return CKM_API_ERROR_INPUT_PARAM; // check if save is possible @@ -1144,17 +1212,33 @@ int CKMLogic::createKeyAESHelper( const Label &label, const PolicySerializable &policy) { + auto &handler = selectDatabase(cred, label); + + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + + // check if save is possible + DB::Crypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // create key in store CryptoAlgorithm keyGenAlgorithm; keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN); keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size); - Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm); - - return saveDataHelper(cred, - name, - label, - DataType::KEY_AES, - key.data, - policy); + Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password); + + // save the data + DB::Row row(std::move(key), name, ownerLabel, static_cast(policy.extractable)); + handler.crypto.encryptRow(row); + + handler.database.saveRow(row); + + transaction.commit(); + return CKM_API_SUCCESS; } @@ -1178,32 +1262,41 @@ int CKMLogic::createKeyPairHelper( if(!dt.isKey()) ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value."); + // use client label if not explicitly provided + const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate; + if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic; + if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + bool exportable = policyPrivate.extractable || policyPublic.extractable; - TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams); + TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams, + policyPrivate.password, + policyPublic.password); DB::Crypto::Transaction transactionPriv(&handlerPriv.database); // in case the same database is used for private and public - the second // transaction will not be executed DB::Crypto::Transaction transactionPub(&handlerPub.database); - int retCode = saveDataHelper(cred, - namePrivate, - labelPrivate, - keys.first.dataType, - keys.first.data, - policyPrivate); - if (CKM_API_SUCCESS != retCode) + int retCode; + retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv); + if(retCode != CKM_API_SUCCESS) return retCode; - - retCode = saveDataHelper(cred, - namePublic, - labelPublic, - keys.second.dataType, - keys.second.data, - policyPublic); - if (CKM_API_SUCCESS != retCode) + retCode = checkSaveConditions(cred, handlerPub, namePrivate, ownerLabelPub); + if(retCode != CKM_API_SUCCESS) return retCode; + // save the data + DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast(policyPrivate.extractable)); + handlerPriv.crypto.encryptRow(rowPrv); + handlerPriv.database.saveRow(rowPrv); + + DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast(policyPublic.extractable)); + handlerPub.crypto.encryptRow(rowPub); + handlerPub.database.saveRow(rowPub); + transactionPub.commit(); transactionPriv.commit(); return CKM_API_SUCCESS; @@ -1288,18 +1381,21 @@ int CKMLogic::readCertificateHelper( { DB::Row row; for (auto &i: labelNameVector) { - int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row); + // certificates can't be protected with custom user password + Crypto::GObjUPtr obj; + int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), obj); if (ec != CKM_API_SUCCESS) return ec; - certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER)); + + certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER); // try to read chain certificates (if present) - DB::RowVector rawCaChain; - ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain); + Crypto::GObjUPtrVector caChainObjs; + ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), caChainObjs); if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN) return ec; - for(auto &rawCaCert : rawCaChain) - certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER)); + for(auto &caCertObj : caChainObjs) + certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER); } return CKM_API_SUCCESS; } @@ -1477,9 +1573,10 @@ RawBuffer CKMLogic::createSignature( int retCode = CKM_API_SUCCESS; try { - retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row); + Crypto::GObjUPtr obj; + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj); if(retCode == CKM_API_SUCCESS) { - signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message); + signature = obj->sign(cryptoAlg, message); } } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); @@ -1521,13 +1618,14 @@ RawBuffer CKMLogic::verifySignature( // try certificate first - looking for a public key. // in case of PKCS, pub key from certificate will be found first // rather than private key from the same PKCS. - retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row); + Crypto::GObjUPtr obj; + retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj); if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { - retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row); + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj); } if (retCode == CKM_API_SUCCESS) { - retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature); + retCode = obj->verify(params, message, signature); } } catch (const Exc::Exception &e) { retCode = e.error(); @@ -1570,7 +1668,7 @@ int CKMLogic::setPermissionHelper( return CKM_API_ERROR_INPUT_PARAM; // system database does not support write/remove permissions - if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) && + if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) && (permissionMask & Permission::REMOVE)) return CKM_API_ERROR_INPUT_PARAM; @@ -1620,5 +1718,21 @@ RawBuffer CKMLogic::setPermission( return MessageBuffer::Serialize(command, msgID, retCode).Pop(); } +int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel) +{ + if (!handle.crypto.haveKey(appLabel)) { + RawBuffer key; + auto key_optional = handle.database.getKey(appLabel); + if(!key_optional) { + LogError("No key for given label in database"); + return CKM_API_ERROR_DB_ERROR; + } + key = *key_optional; + key = handle.keyProvider.getPureDEK(key); + handle.crypto.pushKey(appLabel, key); + } + return CKM_API_SUCCESS; +} + } // namespace CKM