X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmanager%2Fservice%2Fckm-logic.cpp;h=8736fd50bfc27fcdb6d0fae0b534c3c52db06909;hb=51a5e9cfe81d0374a02c1e28375a482b68afd879;hp=728bfc5efc9f430dbff1941186c6c496299f7ac4;hpb=b2d277acd0398562a7e9968c1d6c59517178c0f8;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 728bfc5..8736fd5 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -418,16 +418,11 @@ DB::Row CKMLogic::createEncryptedRow( const Policy &policy) const { Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable); - Token token = store.import(dataType, data); - - DB::Row row(std::move(token), name, label, static_cast(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; } @@ -515,9 +510,10 @@ int CKMLogic::getKeyForService( 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).getObject(row); + key = std::move(obj); return retCode; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); @@ -666,17 +662,12 @@ int CKMLogic::removeDataHelper( // destroy it in store for(auto& r : rows) { - /* - * TODO: If row is encrypted with user password we won't be able to decrypt it (tz id). - * Encryption/decryption with user password and with app key should both be done inside the - * store (import, getKey and generateXKey). - */ try { handler.crypto.decryptRow(Password(), r); + m_decider.getStore(r).destroy(r); } catch (const Exc::AuthenticationFailed&) { LogDebug("Authentication failed when removing data. Ignored."); } - m_decider.getStore(r.dataType, r.exportable).destroy(r); } // delete row in db @@ -803,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, @@ -810,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); @@ -822,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; @@ -841,7 +872,9 @@ int CKMLogic::readDataHelper( // decrypt row 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; } @@ -853,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); @@ -865,10 +912,13 @@ 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) @@ -879,8 +929,9 @@ int CKMLogic::readDataHelper( if(CKM_API_SUCCESS != retCode) return retCode; - // decrypt row - handler.crypto.decryptRow(password, row); + obj = rowToObject(handler, std::move(row), password); + // rowToObject may modify db + transaction.commit(); return CKM_API_SUCCESS; } @@ -895,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; @@ -916,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(); } @@ -934,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) @@ -1157,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; } @@ -1191,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; @@ -1301,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; } @@ -1490,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).getObject(row)->sign(cryptoAlg, message); + signature = obj->sign(cryptoAlg, message); } } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); @@ -1534,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).getObject(row)->verify(params, message, signature); + retCode = obj->verify(params, message, signature); } } catch (const Exc::Exception &e) { retCode = e.error();