Add support for binary data to GStore
[platform/core/security/key-manager.git] / src / manager / service / ckm-logic.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  *
16  *
17  * @file        ckm-logic.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     1.0
20  * @brief       Sample service implementation.
21  */
22 #include <dpl/serialization.h>
23 #include <dpl/log/log.h>
24 #include <ckm/ckm-error.h>
25 #include <ckm/ckm-type.h>
26 #include <key-provider.h>
27 #include <file-system.h>
28 #include <ckm-logic.h>
29 #include <key-impl.h>
30 #include <key-aes-impl.h>
31 #include <certificate-config.h>
32 #include <certificate-store.h>
33 #include <dirent.h>
34 #include <algorithm>
35 #include <InitialValuesFile.h>
36 #include <sw-backend/store.h>
37 #include <generic-backend/exception.h>
38
39 namespace {
40 const char * const CERT_SYSTEM_DIR          = "/etc/ssl/certs";
41 const char * const INIT_VALUES_DIR          = "/opt/data/ckm/initial_values/";
42 const char * const INIT_VALUES_XSD          = "/usr/share/ckm/initial_values.xsd";
43 const char * const INIT_VALUES_FILE_SUFFIX  = ".xml";
44 const char * const SYSTEM_DB_PASSWD         = "cAtRugU7";
45
46 bool isLabelValid(const CKM::Label &label) {
47     // TODO: copy code from libprivilege control (for check smack label)
48     if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
49         return false;
50     return true;
51 }
52
53 bool isNameValid(const CKM::Name &name) {
54     if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
55         return false;
56     return true;
57 }
58 } // anonymous namespace
59
60 namespace CKM {
61
62 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
63
64 CKMLogic::CKMLogic()
65 {
66     CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR);
67
68     m_accessControl.updateCCMode();
69
70     // make initial file list
71     std::vector<std::string> filesToParse;
72     DIR *dp = opendir(INIT_VALUES_DIR);
73     if(dp)
74     {
75         struct dirent *entry;
76         while ((entry = readdir(dp)))
77         {
78             std::string filename = std::string(entry->d_name);
79
80             // check if XML file
81             std::string lowercaseFilename = filename;
82             std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower);
83             if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos)
84                 continue;
85
86             filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename);
87         }
88         closedir(dp);
89     }
90
91     // parse
92     for(const auto & file : filesToParse)
93     {
94         InitialValues::InitialValuesFile xmlFile(file.c_str(), *this);
95         int rc = xmlFile.Validate(INIT_VALUES_XSD);
96         if(rc == XML::Parser::PARSE_SUCCESS)
97         {
98             rc = xmlFile.Parse();
99             if(rc != XML::Parser::PARSE_SUCCESS)
100                 LogError("invalid initial values file: " << file << ", parsing code: " << rc);
101         }
102         else
103             LogError("invalid initial values file: " << file << ", validation code: " << rc);
104         unlink(file.c_str());
105     }
106 }
107
108 CKMLogic::~CKMLogic(){}
109
110 void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
111     auto &handle = m_userDataMap[user];
112
113     FileSystem fs(user);
114
115     auto wrappedDKEK = fs.getDKEK();
116
117     if (wrappedDKEK.empty()) {
118         wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
119         fs.saveDKEK(wrappedDKEK);
120     }
121
122     handle.keyProvider = KeyProvider(wrappedDKEK, password);
123 }
124
125 void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
126     auto &handle = m_userDataMap[user];
127
128     FileSystem fs(user);
129     fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
130 }
131
132 int CKMLogic::unlockDatabase(uid_t user, const Password & password)
133 {
134     if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
135         return CKM_API_SUCCESS;
136
137     int retCode = CKM_API_SUCCESS;
138     try
139     {
140         auto &handle = m_userDataMap[user];
141
142         FileSystem fs(user);
143         loadDKEKFile(user, password);
144
145         auto wrappedDatabaseDEK = fs.getDBDEK();
146         if (wrappedDatabaseDEK.empty()) {
147             wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
148             fs.saveDBDEK(wrappedDatabaseDEK);
149         }
150
151         RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
152
153         handle.database = DB::Crypto(fs.getDBPath(), key);
154         handle.crypto = CryptoLogic();
155
156         if ( !m_accessControl.isSystemService(user) )
157         {
158             // remove data of removed apps during locked state
159             AppLabelVector removedApps = fs.clearRemovedsApps();
160             for(auto& appSmackLabel : removedApps) {
161                 handle.crypto.removeKey(appSmackLabel);
162                 handle.database.deleteKey(appSmackLabel);
163             }
164         }
165     } catch (const Exc::Exception &e) {
166         retCode = e.error();
167     } catch (const CKM::Exception &e) {
168         LogError("CKM::Exception: " << e.GetMessage());
169         retCode = CKM_API_ERROR_SERVER_ERROR;
170     }
171
172     if (CKM_API_SUCCESS != retCode)
173         m_userDataMap.erase(user);
174
175     return retCode;
176 }
177
178 int CKMLogic::unlockSystemDB()
179 {
180     return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
181 }
182
183 UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
184 {
185     // if user trying to access system service - check:
186     //    * if user database is unlocked [mandatory]
187     //    * if not - proceed with regular user database
188     //    * if explicit system database label given -> switch to system DB
189     if ( !m_accessControl.isSystemService(cred) )
190     {
191         if (0 == m_userDataMap.count(cred.clientUid))
192             ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked");
193
194         if (0 != incoming_label.compare(OWNER_ID_SYSTEM))
195             return m_userDataMap[cred.clientUid];
196     }
197
198     // system database selected, modify the label
199     if (CKM_API_SUCCESS != unlockSystemDB() )
200         ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
201     return m_userDataMap[SYSTEM_DB_UID];
202 }
203
204 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
205 {
206     int retCode = CKM_API_SUCCESS;
207
208     if( !m_accessControl.isSystemService(user) )
209     {
210         retCode = unlockDatabase(user, password);
211     }
212     else
213     {
214         // do not allow lock/unlock operations for system users
215         retCode = CKM_API_ERROR_INPUT_PARAM;
216     }
217
218     return MessageBuffer::Serialize(retCode).Pop();
219 }
220
221 RawBuffer CKMLogic::updateCCMode() {
222     m_accessControl.updateCCMode();
223     return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
224 }
225
226 RawBuffer CKMLogic::lockUserKey(uid_t user)
227 {
228     int retCode = CKM_API_SUCCESS;
229     if( !m_accessControl.isSystemService(user) )
230     {
231         m_userDataMap.erase(user);
232     }
233     else
234     {
235         // do not allow lock/unlock operations for system users
236         retCode = CKM_API_ERROR_INPUT_PARAM;
237     }
238
239     return MessageBuffer::Serialize(retCode).Pop();
240
241 }
242
243 RawBuffer CKMLogic::removeUserData(uid_t user) {
244     int retCode = CKM_API_SUCCESS;
245
246     if (m_accessControl.isSystemService(user))
247         user = SYSTEM_DB_UID;
248
249     m_userDataMap.erase(user);
250
251     FileSystem fs(user);
252     fs.removeUserData();
253
254     return MessageBuffer::Serialize(retCode).Pop();
255 }
256
257 int CKMLogic::changeUserPasswordHelper(uid_t user,
258                                        const Password &oldPassword,
259                                        const Password &newPassword)
260 {
261     // do not allow to change system database password
262     if( m_accessControl.isSystemService(user) )
263         return CKM_API_ERROR_INPUT_PARAM;
264
265     loadDKEKFile(user, oldPassword);
266     saveDKEKFile(user, newPassword);
267
268     return CKM_API_SUCCESS;
269 }
270
271 RawBuffer CKMLogic::changeUserPassword(
272     uid_t user,
273     const Password &oldPassword,
274     const Password &newPassword)
275 {
276     int retCode = CKM_API_SUCCESS;
277     try
278     {
279         retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
280     } catch (const Exc::Exception &e) {
281         retCode = e.error();
282     } catch (const CKM::Exception &e) {
283         LogError("CKM::Exception: " << e.GetMessage());
284         retCode = CKM_API_ERROR_SERVER_ERROR;
285     }
286
287     return MessageBuffer::Serialize(retCode).Pop();
288 }
289
290 int CKMLogic::resetUserPasswordHelper(
291     uid_t user,
292     const Password &newPassword)
293 {
294     // do not allow to reset system database password
295     if( m_accessControl.isSystemService(user) )
296         return CKM_API_ERROR_INPUT_PARAM;
297
298     int retCode = CKM_API_SUCCESS;
299     if (0 == m_userDataMap.count(user))
300     {
301         // Check if key exists. If exists we must return error
302         FileSystem fs(user);
303         auto wrappedDKEKMain = fs.getDKEK();
304         if (!wrappedDKEKMain.empty())
305             retCode = CKM_API_ERROR_BAD_REQUEST;
306     } else {
307         saveDKEKFile(user, newPassword);
308     }
309
310     return retCode;
311 }
312
313 RawBuffer CKMLogic::resetUserPassword(
314     uid_t user,
315     const Password &newPassword)
316 {
317     int retCode = CKM_API_SUCCESS;
318     try {
319         retCode = resetUserPasswordHelper(user, newPassword);
320     } catch (const Exc::Exception &e) {
321         retCode = e.error();
322     } catch (const CKM::Exception &e) {
323         LogError("CKM::Exception: " << e.GetMessage());
324         retCode = CKM_API_ERROR_SERVER_ERROR;
325     }
326
327     return MessageBuffer::Serialize(retCode).Pop();
328 }
329
330 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
331     int retCode = CKM_API_SUCCESS;
332
333     try {
334
335         if (smackLabel.empty()) {
336             retCode = CKM_API_ERROR_INPUT_PARAM;
337         } else {
338             UidVector uids = FileSystem::getUIDsFromDBFile();
339             for (auto userId : uids) {
340                 if (0 == m_userDataMap.count(userId)) {
341                     FileSystem fs(userId);
342                     fs.addRemovedApp(smackLabel);
343                 } else {
344                     auto &handle = m_userDataMap[userId];
345                     handle.crypto.removeKey(smackLabel);
346                     handle.database.deleteKey(smackLabel);
347                 }
348             }
349         }
350
351     } catch (const DB::Crypto::Exception::InternalError &e) {
352         LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
353         retCode = CKM_API_ERROR_DB_ERROR;
354     } catch (const DB::Crypto::Exception::TransactionError &e) {
355         LogError("DB::Crypto transaction failed with message " << e.GetMessage());
356         retCode = CKM_API_ERROR_DB_ERROR;
357     } catch (const Exc::Exception &e) {
358         retCode = e.error();
359     } catch (const CKM::Exception &e) {
360         LogError("CKM::Exception: " << e.GetMessage());
361         retCode = CKM_API_ERROR_SERVER_ERROR;
362     }
363
364     return MessageBuffer::Serialize(retCode).Pop();
365 }
366
367 int CKMLogic::checkSaveConditions(
368     const Credentials &cred,
369     UserData &handler,
370     const Name &name,
371     const Label &ownerLabel)
372 {
373     // verify name and label are correct
374     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
375         LogDebug("Invalid parameter passed to key-manager");
376         return CKM_API_ERROR_INPUT_PARAM;
377     }
378
379     // check if allowed to save using ownerLabel
380     int access_ec = m_accessControl.canSave(cred, ownerLabel);
381     if( access_ec != CKM_API_SUCCESS)
382     {
383         LogDebug("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
384         return access_ec;
385     }
386
387     // check if not a duplicate
388     if( handler.database.isNameLabelPresent(name, ownerLabel))
389         return CKM_API_ERROR_DB_ALIAS_EXISTS;
390
391     // encryption section
392     if (!handler.crypto.haveKey(ownerLabel))
393     {
394         RawBuffer got_key;
395         auto key_optional = handler.database.getKey(ownerLabel);
396         if(!key_optional) {
397             LogDebug("No Key in database found. Generating new one for label: " << ownerLabel);
398             got_key = handler.keyProvider.generateDEK(ownerLabel);
399             handler.database.saveKey(ownerLabel, got_key);
400         } else {
401             LogDebug("Key from DB");
402             got_key = *key_optional;
403         }
404
405         got_key = handler.keyProvider.getPureDEK(got_key);
406         handler.crypto.pushKey(ownerLabel, got_key);
407     }
408
409     return CKM_API_SUCCESS;
410 }
411
412 DB::Row CKMLogic::createEncryptedRow(
413     CryptoLogic &crypto,
414     const Name &name,
415     const Label &label,
416     DataType dataType,
417     const RawBuffer &data,
418     const Policy &policy) const
419 {
420     Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable);
421     Token token = store.import(dataType, data);
422
423     DB::Row row(std::move(token), name, label, static_cast<int>(policy.extractable));
424
425     // do not encrypt data with password during cc_mode on
426     if(m_accessControl.isCCMode()) {
427         crypto.encryptRow("", row);
428     } else {
429         crypto.encryptRow(policy.password, row);
430     }
431     return row;
432 }
433
434 int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
435 {
436     RawBuffer dummy;
437     return toBinaryData(dataType, input_data, dummy);
438 }
439
440 int CKMLogic::toBinaryData(DataType dataType,
441                            const RawBuffer &input_data,
442                            RawBuffer &output_data) const
443 {
444     // verify the data integrity
445     if (dataType.isKey())
446     {
447         KeyShPtr output_key;
448         if(dataType.isSKey())
449             output_key = CKM::Key::createAES(input_data);
450         else
451             output_key = CKM::Key::create(input_data);
452         if(output_key.get() == NULL)
453         {
454             LogDebug("provided binary data is not valid key data");
455             return CKM_API_ERROR_INPUT_PARAM;
456         }
457         output_data = output_key->getDER();
458     }
459     else if (dataType.isCertificate() || dataType.isChainCert())
460     {
461         CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
462         if(cert.get() == NULL)
463         {
464             LogDebug("provided binary data is not valid certificate data");
465             return CKM_API_ERROR_INPUT_PARAM;
466         }
467         output_data = cert->getDER();
468     }
469     else
470         output_data = input_data;
471     // TODO: add here BINARY_DATA verification, i.e: max size etc.
472     return CKM_API_SUCCESS;
473 }
474
475 int CKMLogic::verifyAndSaveDataHelper(
476     const Credentials &cred,
477     const Name &name,
478     const Label &label,
479     const RawBuffer &data,
480     DataType dataType,
481     const PolicySerializable &policy)
482 {
483     int retCode = CKM_API_ERROR_UNKNOWN;
484
485     try {
486         // check if data is correct
487         RawBuffer binaryData;
488         retCode = toBinaryData(dataType, data, binaryData);
489         if(retCode == CKM_API_SUCCESS)
490         {
491             retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
492         }
493     } catch (const DB::Crypto::Exception::InternalError &e) {
494         LogError("DB::Crypto failed with message: " << e.GetMessage());
495         retCode = CKM_API_ERROR_DB_ERROR;
496     } catch (const DB::Crypto::Exception::TransactionError &e) {
497         LogError("DB::Crypto transaction failed with message " << e.GetMessage());
498         retCode = CKM_API_ERROR_DB_ERROR;
499     } catch (const Exc::Exception &e) {
500         retCode = e.error();
501     } catch (const CKM::Exception &e) {
502         LogError("CKM::Exception: " << e.GetMessage());
503         retCode = CKM_API_ERROR_SERVER_ERROR;
504     }
505     return retCode;
506 }
507
508 int CKMLogic::getKeyForService(
509         const Credentials &cred,
510         const Name &name,
511         const Label &label,
512         const Password &pass,
513         Crypto::GObjShPtr &key)
514 {
515     DB::Row row;
516     try {
517         // Key is for internal service use. It won't be exported to the client
518         int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, row);
519         if (retCode == CKM_API_SUCCESS)
520             key = m_decider.getStore(row).getObject(row);
521         return retCode;
522     } catch (const DB::Crypto::Exception::Base &e) {
523         LogError("DB::Crypto failed with message: " << e.GetMessage());
524         return CKM_API_ERROR_DB_ERROR;
525     } catch (const Exc::Exception &e) {
526         return e.error();
527     } catch (const CKM::Exception &e) {
528         LogError("CKM::Exception: " << e.GetMessage());
529         return CKM_API_ERROR_SERVER_ERROR;
530     }
531 }
532
533 RawBuffer CKMLogic::saveData(
534     const Credentials &cred,
535     int commandId,
536     const Name &name,
537     const Label &label,
538     const RawBuffer &data,
539     DataType dataType,
540     const PolicySerializable &policy)
541 {
542     int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
543     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
544                                              commandId,
545                                              retCode,
546                                              static_cast<int>(dataType));
547     return response.Pop();
548 }
549
550 int CKMLogic::extractPKCS12Data(
551     CryptoLogic &crypto,
552     const Name &name,
553     const Label &ownerLabel,
554     const PKCS12Serializable &pkcs,
555     const PolicySerializable &keyPolicy,
556     const PolicySerializable &certPolicy,
557     DB::RowVector &output) const
558 {
559     // private key is mandatory
560     if( !pkcs.getKey() )
561         return CKM_API_ERROR_INVALID_FORMAT;
562     Key* keyPtr = pkcs.getKey().get();
563     DataType keyType = DataType(keyPtr->getType());
564     RawBuffer keyData = keyPtr->getDER();
565     int retCode = verifyBinaryData(keyType, keyData);
566     if(retCode != CKM_API_SUCCESS)
567         return retCode;
568     output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
569
570     // certificate is mandatory
571     if( !pkcs.getCertificate() )
572         return CKM_API_ERROR_INVALID_FORMAT;
573     RawBuffer certData = pkcs.getCertificate().get()->getDER();
574     retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
575     if(retCode != CKM_API_SUCCESS)
576         return retCode;
577     output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
578
579     // CA cert chain
580     unsigned int cert_index = 0;
581     for(const auto & ca : pkcs.getCaCertificateShPtrVector())
582     {
583         DataType chainDataType = DataType::getChainDatatype(cert_index ++);
584         RawBuffer caCertData = ca->getDER();
585         int retCode = verifyBinaryData(chainDataType, caCertData);
586         if(retCode != CKM_API_SUCCESS)
587             return retCode;
588
589         output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
590     }
591
592     return CKM_API_SUCCESS;
593 }
594
595 RawBuffer CKMLogic::savePKCS12(
596     const Credentials &cred,
597     int commandId,
598     const Name &name,
599     const Label &label,
600     const PKCS12Serializable &pkcs,
601     const PolicySerializable &keyPolicy,
602     const PolicySerializable &certPolicy)
603 {
604     int retCode = CKM_API_ERROR_UNKNOWN;
605     try {
606         retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
607     } catch (const Exc::Exception &e) {
608         retCode = e.error();
609     } catch (const DB::Crypto::Exception::InternalError &e) {
610         LogError("DB::Crypto failed with message: " << e.GetMessage());
611         retCode = CKM_API_ERROR_DB_ERROR;
612     } catch (const DB::Crypto::Exception::TransactionError &e) {
613         LogError("DB::Crypto transaction failed with message " << e.GetMessage());
614         retCode = CKM_API_ERROR_DB_ERROR;
615     } catch (const CKM::Exception &e) {
616         LogError("CKM::Exception: " << e.GetMessage());
617         retCode = CKM_API_ERROR_SERVER_ERROR;
618     }
619
620     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
621                                              commandId,
622                                              retCode);
623     return response.Pop();
624 }
625
626
627 int CKMLogic::removeDataHelper(
628         const Credentials &cred,
629         const Name &name,
630         const Label &label)
631 {
632     auto &handler = selectDatabase(cred, label);
633
634     // use client label if not explicitly provided
635     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
636     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
637         LogDebug("Invalid label or name format");
638         return CKM_API_ERROR_INPUT_PARAM;
639     }
640
641     DB::Crypto::Transaction transaction(&handler.database);
642
643     // read and check permissions
644     PermissionMaskOptional permissionRowOpt =
645             handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
646     int retCode = m_accessControl.canDelete(cred,
647                         PermissionForLabel(cred.smackLabel, permissionRowOpt));
648     if(retCode != CKM_API_SUCCESS)
649     {
650         LogWarning("access control check result: " << retCode);
651         return retCode;
652     }
653
654     // get all matching rows
655     DB::RowVector rows;
656     handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows);
657     if (rows.empty()) {
658         LogDebug("No row for given name and label");
659         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
660     }
661
662     // load app key if needed
663     retCode = loadAppKey(handler, rows.front().ownerLabel);
664     if(CKM_API_SUCCESS != retCode)
665         return retCode;
666
667     // destroy it in store
668     for(auto& r : rows) {
669         /*
670          * TODO: If row is encrypted with user password we won't be able to decrypt it (tz id).
671          * Encryption/decryption with user password and with app key should both be done inside the
672          * store (import, getKey and generateXKey).
673          */
674         try {
675             handler.crypto.decryptRow(Password(), r);
676         } catch (const Exc::AuthenticationFailed&) {
677             LogDebug("Authentication failed when removing data. Ignored.");
678         }
679         m_decider.getStore(r.dataType, r.exportable).destroy(r);
680     }
681
682     // delete row in db
683     handler.database.deleteRow(name, ownerLabel);
684     transaction.commit();
685
686     return CKM_API_SUCCESS;
687 }
688
689 RawBuffer CKMLogic::removeData(
690     const Credentials &cred,
691     int commandId,
692     const Name &name,
693     const Label &label)
694 {
695     int retCode = CKM_API_ERROR_UNKNOWN;
696
697     try
698     {
699         retCode = removeDataHelper(cred, name, label);
700     }
701     catch (const Exc::Exception &e)
702     {
703         retCode = e.error();
704     }
705     catch (const CKM::Exception &)
706     {
707         LogError("Error in deleting row!");
708         retCode = CKM_API_ERROR_DB_ERROR;
709     }
710
711     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
712                                              commandId,
713                                              retCode);
714     return response.Pop();
715 }
716
717 int CKMLogic::readSingleRow(const Name &name,
718                             const Label &ownerLabel,
719                             DataType dataType,
720                             DB::Crypto & database,
721                             DB::Row &row)
722 {
723     DB::Crypto::RowOptional row_optional;
724     if (dataType.isKey())
725     {
726         // read all key types
727         row_optional = database.getRow(name,
728                                          ownerLabel,
729                                          DataType::DB_KEY_FIRST,
730                                          DataType::DB_KEY_LAST);
731     } else {
732         // read anything else
733         row_optional = database.getRow(name,
734                                          ownerLabel,
735                                          dataType);
736     }
737
738     if(!row_optional) {
739         LogDebug("No row for given name, label and type");
740         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
741     } else {
742         row = *row_optional;
743     }
744
745     return CKM_API_SUCCESS;
746 }
747
748
749 int CKMLogic::readMultiRow(const Name &name,
750                            const Label &ownerLabel,
751                            DataType dataType,
752                            DB::Crypto & database,
753                            DB::RowVector &output)
754 {
755     if (dataType.isKey())
756     {
757         // read all key types
758         database.getRows(name,
759                           ownerLabel,
760                           DataType::DB_KEY_FIRST,
761                           DataType::DB_KEY_LAST,
762                           output);
763     }
764     else if (dataType.isChainCert())
765     {
766         // read all key types
767         database.getRows(name,
768                          ownerLabel,
769                          DataType::DB_CHAIN_FIRST,
770                          DataType::DB_CHAIN_LAST,
771                          output);
772     }
773     else
774     {
775         // read anything else
776         database.getRows(name,
777                          ownerLabel,
778                          dataType,
779                          output);
780     }
781
782     if(!output.size()) {
783         LogDebug("No row for given name, label and type");
784         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
785     }
786
787     return CKM_API_SUCCESS;
788 }
789
790 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
791                                          const Name &name,
792                                          const Label &ownerLabel,
793                                          const Label &accessorLabel,
794                                          const DB::Row &row,
795                                          bool exportFlag,
796                                          DB::Crypto & database)
797 {
798     PermissionMaskOptional permissionRowOpt =
799             database.getPermissionRow(name, ownerLabel, accessorLabel);
800
801     if(exportFlag)
802         return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
803     return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
804 }
805
806 int CKMLogic::readDataHelper(
807     bool exportFlag,
808     const Credentials &cred,
809     DataType dataType,
810     const Name &name,
811     const Label &label,
812     const Password &password,
813     DB::RowVector &rows)
814 {
815     auto &handler = selectDatabase(cred, label);
816
817     // use client label if not explicitly provided
818     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
819
820     if (!isNameValid(name) || !isLabelValid(ownerLabel))
821         return CKM_API_ERROR_INPUT_PARAM;
822
823     // read rows
824     DB::Crypto::Transaction transaction(&handler.database);
825     int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
826     if(CKM_API_SUCCESS != retCode)
827         return retCode;
828
829     // all read rows belong to the same owner
830     DB::Row & firstRow = rows.at(0);
831
832     // check access rights
833     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
834     if(CKM_API_SUCCESS != retCode)
835         return retCode;
836
837     // load app key if needed
838     retCode = loadAppKey(handler, firstRow.ownerLabel);
839     if(CKM_API_SUCCESS != retCode)
840         return retCode;
841
842     // decrypt row
843     for(auto &row : rows)
844         handler.crypto.decryptRow(password, row);
845
846     return CKM_API_SUCCESS;
847 }
848
849 int CKMLogic::readDataHelper(
850     bool exportFlag,
851     const Credentials &cred,
852     DataType dataType,
853     const Name &name,
854     const Label &label,
855     const Password &password,
856     DB::Row &row)
857 {
858     auto &handler = selectDatabase(cred, label);
859
860     // use client label if not explicitly provided
861     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
862
863     if (!isNameValid(name) || !isLabelValid(ownerLabel))
864         return CKM_API_ERROR_INPUT_PARAM;
865
866     // read row
867     DB::Crypto::Transaction transaction(&handler.database);
868     int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
869     if(CKM_API_SUCCESS != retCode)
870         return retCode;
871
872     // check access rights
873     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
874     if(CKM_API_SUCCESS != retCode)
875         return retCode;
876
877     // load app key if needed
878     retCode = loadAppKey(handler, row.ownerLabel);
879     if(CKM_API_SUCCESS != retCode)
880         return retCode;
881
882     // decrypt row
883     handler.crypto.decryptRow(password, row);
884
885     return CKM_API_SUCCESS;
886 }
887
888 RawBuffer CKMLogic::getData(
889     const Credentials &cred,
890     int commandId,
891     DataType dataType,
892     const Name &name,
893     const Label &label,
894     const Password &password)
895 {
896     int retCode = CKM_API_SUCCESS;
897     DB::Row row;
898
899     try {
900         retCode = readDataHelper(true, cred, dataType, name, label, password, row);
901     } catch (const DB::Crypto::Exception::Base &e) {
902         LogError("DB::Crypto failed with message: " << e.GetMessage());
903         retCode = CKM_API_ERROR_DB_ERROR;
904     } catch (const Exc::Exception &e) {
905         retCode = e.error();
906     } catch (const CKM::Exception &e) {
907         LogError("CKM::Exception: " << e.GetMessage());
908         retCode = CKM_API_ERROR_SERVER_ERROR;
909     }
910
911     if (CKM_API_SUCCESS != retCode) {
912         row.data.clear();
913         row.dataType = dataType;
914     }
915
916     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
917                                              commandId,
918                                              retCode,
919                                              static_cast<int>(row.dataType),
920                                              row.data);
921     return response.Pop();
922 }
923
924 int CKMLogic::getPKCS12Helper(
925     const Credentials &cred,
926     const Name &name,
927     const Label &label,
928     const Password &keyPassword,
929     const Password &certPassword,
930     KeyShPtr & privKey,
931     CertificateShPtr & cert,
932     CertificateShPtrVector & caChain)
933 {
934     int retCode;
935
936     // read private key (mandatory)
937     DB::Row privKeyRow;
938     retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
939     if(retCode != CKM_API_SUCCESS)
940         return retCode;
941     privKey = CKM::Key::create(privKeyRow.data);
942
943     // read certificate (mandatory)
944     DB::Row certRow;
945     retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
946     if(retCode != CKM_API_SUCCESS)
947         return retCode;
948     cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
949
950     // read CA cert chain (optional)
951     DB::RowVector rawCaChain;
952     retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
953     if(retCode != CKM_API_SUCCESS &&
954        retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
955         return retCode;
956     for(auto &rawCaCert : rawCaChain)
957         caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
958
959     // if anything found, return it
960     if(privKey || cert || caChain.size()>0)
961         retCode = CKM_API_SUCCESS;
962
963     return retCode;
964 }
965
966 RawBuffer CKMLogic::getPKCS12(
967         const Credentials &cred,
968         int commandId,
969         const Name &name,
970         const Label &label,
971         const Password &keyPassword,
972         const Password &certPassword)
973 {
974     int retCode = CKM_API_ERROR_UNKNOWN;
975
976     PKCS12Serializable output;
977     try {
978         KeyShPtr privKey;
979         CertificateShPtr cert;
980         CertificateShPtrVector caChain;
981         retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
982
983         // prepare response
984         if(retCode == CKM_API_SUCCESS)
985             output = PKCS12Serializable(privKey, cert, caChain);
986     } catch (const DB::Crypto::Exception::Base &e) {
987         LogError("DB::Crypto failed with message: " << e.GetMessage());
988         retCode = CKM_API_ERROR_DB_ERROR;
989     } catch (const Exc::Exception &e) {
990         retCode = e.error();
991     } catch (const CKM::Exception &e) {
992         LogError("CKM::Exception: " << e.GetMessage());
993         retCode = CKM_API_ERROR_SERVER_ERROR;
994     }
995
996     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
997                                              commandId,
998                                              retCode,
999                                              output);
1000     return response.Pop();
1001 }
1002
1003 int CKMLogic::getDataListHelper(const Credentials &cred,
1004                                 const DataType dataType,
1005                                 LabelNameVector &labelNameVector)
1006 {
1007     int retCode = CKM_API_ERROR_DB_LOCKED;
1008     if (0 < m_userDataMap.count(cred.clientUid))
1009     {
1010         auto &database = m_userDataMap[cred.clientUid].database;
1011
1012         Try {
1013             LabelNameVector tmpVector;
1014             if (dataType.isKey()) {
1015                 // list all key types
1016                 database.listNames(cred.smackLabel,
1017                                    tmpVector,
1018                                    DataType::DB_KEY_FIRST,
1019                                    DataType::DB_KEY_LAST);
1020             } else {
1021                 // list anything else
1022                 database.listNames(cred.smackLabel,
1023                                    tmpVector,
1024                                    dataType);
1025             }
1026             labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1027             retCode = CKM_API_SUCCESS;
1028         }
1029         Catch (CKM::Exception) {
1030             LogError("Failed to get names");
1031             retCode = CKM_API_ERROR_DB_ERROR;
1032         }
1033     }
1034     return retCode;
1035 }
1036
1037 RawBuffer CKMLogic::getDataList(
1038     const Credentials &cred,
1039     int commandId,
1040     DataType dataType)
1041 {
1042     LabelNameVector systemVector;
1043     LabelNameVector userVector;
1044     LabelNameVector labelNameVector;
1045
1046     int retCode = unlockSystemDB();
1047     if (CKM_API_SUCCESS == retCode)
1048     {
1049         // system database
1050         if (m_accessControl.isSystemService(cred))
1051         {
1052             // lookup system DB
1053             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1054                                                     OWNER_ID_SYSTEM),
1055                                         dataType,
1056                                         systemVector);
1057         }
1058         else
1059         {
1060             // user - lookup system, then client DB
1061             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1062                                                     cred.smackLabel),
1063                                         dataType,
1064                                         systemVector);
1065
1066             // private database
1067             if(retCode == CKM_API_SUCCESS)
1068             {
1069                 retCode = getDataListHelper(cred,
1070                                             dataType,
1071                                             userVector);
1072             }
1073         }
1074     }
1075
1076     if(retCode == CKM_API_SUCCESS)
1077     {
1078         labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1079         labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1080     }
1081     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1082                                              commandId,
1083                                              retCode,
1084                                              static_cast<int>(dataType),
1085                                              labelNameVector);
1086     return response.Pop();
1087 }
1088
1089 int CKMLogic::saveDataHelper(
1090     const Credentials &cred,
1091     const Name &name,
1092     const Label &label,
1093     DataType dataType,
1094     const RawBuffer &data,
1095     const PolicySerializable &policy)
1096 {
1097     auto &handler = selectDatabase(cred, label);
1098
1099     // use client label if not explicitly provided
1100     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1101     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1102         return CKM_API_ERROR_INPUT_PARAM;
1103
1104     // check if save is possible
1105     DB::Crypto::Transaction transaction(&handler.database);
1106     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1107     if(retCode != CKM_API_SUCCESS)
1108         return retCode;
1109
1110     // save the data
1111     DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1112     handler.database.saveRow(encryptedRow);
1113
1114     transaction.commit();
1115     return CKM_API_SUCCESS;
1116 }
1117
1118 int CKMLogic::saveDataHelper(
1119     const Credentials &cred,
1120     const Name &name,
1121     const Label &label,
1122     const PKCS12Serializable &pkcs,
1123     const PolicySerializable &keyPolicy,
1124     const PolicySerializable &certPolicy)
1125 {
1126     auto &handler = selectDatabase(cred, label);
1127
1128     // use client label if not explicitly provided
1129     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1130     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1131         return CKM_API_ERROR_INPUT_PARAM;
1132
1133     // check if save is possible
1134     DB::Crypto::Transaction transaction(&handler.database);
1135     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1136     if(retCode != CKM_API_SUCCESS)
1137         return retCode;
1138
1139     // extract and encrypt the data
1140     DB::RowVector encryptedRows;
1141     retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1142     if(retCode != CKM_API_SUCCESS)
1143         return retCode;
1144
1145     // save the data
1146     handler.database.saveRows(name, ownerLabel, encryptedRows);
1147     transaction.commit();
1148
1149     return CKM_API_SUCCESS;
1150 }
1151
1152
1153 int CKMLogic::createKeyAESHelper(
1154     const Credentials &cred,
1155     const int size,
1156     const Name &name,
1157     const Label &label,
1158     const PolicySerializable &policy)
1159 {
1160     CryptoAlgorithm keyGenAlgorithm;
1161     keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1162     keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1163     Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);
1164
1165     return saveDataHelper(cred,
1166                           name,
1167                           label,
1168                           DataType::KEY_AES,
1169                           key.data,
1170                           policy);
1171 }
1172
1173
1174 int CKMLogic::createKeyPairHelper(
1175     const Credentials &cred,
1176     const CryptoAlgorithmSerializable & keyGenParams,
1177     const Name &namePrivate,
1178     const Label &labelPrivate,
1179     const Name &namePublic,
1180     const Label &labelPublic,
1181     const PolicySerializable &policyPrivate,
1182     const PolicySerializable &policyPublic)
1183 {
1184     auto &handlerPriv = selectDatabase(cred, labelPrivate);
1185     auto &handlerPub = selectDatabase(cred, labelPublic);
1186
1187     AlgoType keyType = AlgoType::RSA_GEN;
1188     if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1189         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1190     DataType dt(keyType);
1191     if(!dt.isKey())
1192         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1193
1194     bool exportable = policyPrivate.extractable || policyPublic.extractable;
1195     TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
1196
1197     DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1198     // in case the same database is used for private and public - the second
1199     // transaction will not be executed
1200     DB::Crypto::Transaction transactionPub(&handlerPub.database);
1201
1202     int retCode = saveDataHelper(cred,
1203                              namePrivate,
1204                              labelPrivate,
1205                              keys.first.dataType,
1206                              keys.first.data,
1207                              policyPrivate);
1208     if (CKM_API_SUCCESS != retCode)
1209         return retCode;
1210
1211     retCode = saveDataHelper(cred,
1212                              namePublic,
1213                              labelPublic,
1214                              keys.second.dataType,
1215                              keys.second.data,
1216                              policyPublic);
1217     if (CKM_API_SUCCESS != retCode)
1218         return retCode;
1219
1220     transactionPub.commit();
1221     transactionPriv.commit();
1222     return CKM_API_SUCCESS;
1223 }
1224
1225 RawBuffer CKMLogic::createKeyPair(
1226     const Credentials &cred,
1227     int commandId,
1228     const CryptoAlgorithmSerializable & keyGenParams,
1229     const Name &namePrivate,
1230     const Label &labelPrivate,
1231     const Name &namePublic,
1232     const Label &labelPublic,
1233     const PolicySerializable &policyPrivate,
1234     const PolicySerializable &policyPublic)
1235 {
1236     int retCode = CKM_API_SUCCESS;
1237
1238     try {
1239         retCode = createKeyPairHelper(
1240                         cred,
1241                         keyGenParams,
1242                         namePrivate,
1243                         labelPrivate,
1244                         namePublic,
1245                         labelPublic,
1246                         policyPrivate,
1247                         policyPublic);
1248     } catch(const Exc::Exception &e) {
1249         retCode = e.error();
1250     } catch (DB::Crypto::Exception::TransactionError &e) {
1251         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1252         retCode = CKM_API_ERROR_DB_ERROR;
1253     } catch (DB::Crypto::Exception::InternalError &e) {
1254         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1255         retCode = CKM_API_ERROR_DB_ERROR;
1256     } catch (const CKM::Exception &e) {
1257         LogError("CKM::Exception: " << e.GetMessage());
1258         retCode = CKM_API_ERROR_SERVER_ERROR;
1259     }
1260
1261     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1262                                     commandId, retCode).Pop();
1263 }
1264
1265 RawBuffer CKMLogic::createKeyAES(
1266     const Credentials &cred,
1267     int commandId,
1268     const int size,
1269     const Name &name,
1270     const Label &label,
1271     const PolicySerializable &policy)
1272 {
1273     int retCode = CKM_API_SUCCESS;
1274
1275     try {
1276         retCode = createKeyAESHelper(cred, size, name, label, policy);
1277     } catch (const Exc::Exception &e) {
1278         retCode = e.error();
1279     } catch (std::invalid_argument &e) {
1280         LogDebug("invalid argument error: " << e.what());
1281         retCode = CKM_API_ERROR_INPUT_PARAM;
1282     } catch (DB::Crypto::Exception::TransactionError &e) {
1283         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1284         retCode = CKM_API_ERROR_DB_ERROR;
1285     } catch (DB::Crypto::Exception::InternalError &e) {
1286         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1287         retCode = CKM_API_ERROR_DB_ERROR;
1288     } catch (const CKM::Exception &e) {
1289         LogError("CKM::Exception: " << e.GetMessage());
1290         retCode = CKM_API_ERROR_SERVER_ERROR;
1291     }
1292
1293     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1294                                     commandId, retCode).Pop();
1295 }
1296
1297 int CKMLogic::readCertificateHelper(
1298         const Credentials &cred,
1299         const LabelNameVector &labelNameVector,
1300         CertificateImplVector &certVector)
1301 {
1302     DB::Row row;
1303     for (auto &i: labelNameVector) {
1304         int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1305         if (ec != CKM_API_SUCCESS)
1306             return ec;
1307         certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1308
1309         // try to read chain certificates (if present)
1310         DB::RowVector rawCaChain;
1311         ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1312         if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1313             return ec;
1314         for(auto &rawCaCert : rawCaChain)
1315             certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1316     }
1317     return CKM_API_SUCCESS;
1318 }
1319
1320 int CKMLogic::getCertificateChainHelper(
1321         const CertificateImpl &cert,
1322         const RawBufferVector &untrustedCertificates,
1323         const RawBufferVector &trustedCertificates,
1324         bool useTrustedSystemCertificates,
1325         RawBufferVector &chainRawVector)
1326 {
1327     CertificateImplVector untrustedCertVector;
1328     CertificateImplVector trustedCertVector;
1329     CertificateImplVector chainVector;
1330
1331     if (cert.empty())
1332         return CKM_API_ERROR_INPUT_PARAM;
1333
1334     for (auto &e: untrustedCertificates) {
1335         CertificateImpl c(e, DataFormat::FORM_DER);
1336         if(c.empty())
1337             return CKM_API_ERROR_INPUT_PARAM;
1338         untrustedCertVector.push_back(std::move(c));
1339     }
1340     for (auto &e: trustedCertificates) {
1341         CertificateImpl c(e, DataFormat::FORM_DER);
1342         if(c.empty())
1343             return CKM_API_ERROR_INPUT_PARAM;
1344         trustedCertVector.push_back(std::move(c));
1345     }
1346
1347     CertificateStore store;
1348     int retCode = store.verifyCertificate(cert,
1349                                           untrustedCertVector,
1350                                           trustedCertVector,
1351                                           useTrustedSystemCertificates,
1352                                           m_accessControl.isCCMode(),
1353                                           chainVector);
1354     if (retCode != CKM_API_SUCCESS)
1355         return retCode;
1356
1357     for (auto &e : chainVector)
1358         chainRawVector.push_back(e.getDER());
1359     return CKM_API_SUCCESS;
1360 }
1361
1362 int CKMLogic::getCertificateChainHelper(
1363         const Credentials &cred,
1364         const CertificateImpl &cert,
1365         const LabelNameVector &untrusted,
1366         const LabelNameVector &trusted,
1367         bool useTrustedSystemCertificates,
1368         RawBufferVector &chainRawVector)
1369 {
1370     CertificateImplVector untrustedCertVector;
1371     CertificateImplVector trustedCertVector;
1372     CertificateImplVector chainVector;
1373     DB::Row row;
1374
1375     if (cert.empty())
1376         return CKM_API_ERROR_INPUT_PARAM;
1377
1378     int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1379     if (retCode != CKM_API_SUCCESS)
1380         return retCode;
1381     retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1382     if (retCode != CKM_API_SUCCESS)
1383         return retCode;
1384
1385     CertificateStore store;
1386     retCode = store.verifyCertificate(cert,
1387                                       untrustedCertVector,
1388                                       trustedCertVector,
1389                                       useTrustedSystemCertificates,
1390                                       m_accessControl.isCCMode(),
1391                                       chainVector);
1392     if (retCode != CKM_API_SUCCESS)
1393         return retCode;
1394
1395     for (auto &i: chainVector)
1396         chainRawVector.push_back(i.getDER());
1397
1398     return CKM_API_SUCCESS;
1399 }
1400
1401 RawBuffer CKMLogic::getCertificateChain(
1402     const Credentials & /*cred*/,
1403     int commandId,
1404     const RawBuffer &certificate,
1405     const RawBufferVector &untrustedCertificates,
1406     const RawBufferVector &trustedCertificates,
1407     bool useTrustedSystemCertificates)
1408 {
1409     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1410     RawBufferVector chainRawVector;
1411     int retCode = CKM_API_ERROR_UNKNOWN;
1412     try {
1413         retCode = getCertificateChainHelper(cert,
1414                                             untrustedCertificates,
1415                                             trustedCertificates,
1416                                             useTrustedSystemCertificates,
1417                                             chainRawVector);
1418     } catch (const Exc::Exception &e) {
1419         retCode = e.error();
1420     } catch (const DB::Crypto::Exception::Base &e) {
1421         LogError("DB::Crypto failed with message: " << e.GetMessage());
1422         retCode = CKM_API_ERROR_DB_ERROR;
1423     } catch (const std::exception& e) {
1424         LogError("STD exception " << e.what());
1425         retCode = CKM_API_ERROR_SERVER_ERROR;
1426     } catch (...) {
1427         LogError("Unknown error.");
1428     }
1429
1430     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1431                                              commandId,
1432                                              retCode,
1433                                              chainRawVector);
1434     return response.Pop();
1435 }
1436
1437 RawBuffer CKMLogic::getCertificateChain(
1438     const Credentials &cred,
1439     int commandId,
1440     const RawBuffer &certificate,
1441     const LabelNameVector &untrustedCertificates,
1442     const LabelNameVector &trustedCertificates,
1443     bool useTrustedSystemCertificates)
1444 {
1445     int retCode = CKM_API_ERROR_UNKNOWN;
1446     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1447     RawBufferVector chainRawVector;
1448     try {
1449         retCode = getCertificateChainHelper(cred,
1450                                             cert,
1451                                             untrustedCertificates,
1452                                             trustedCertificates,
1453                                             useTrustedSystemCertificates,
1454                                             chainRawVector);
1455     } catch (const DB::Crypto::Exception::Base &e) {
1456         LogError("DB::Crypto failed with message: " << e.GetMessage());
1457         retCode = CKM_API_ERROR_DB_ERROR;
1458     } catch (const Exc::Exception &e) {
1459         retCode = e.error();
1460     } catch (const std::exception& e) {
1461         LogError("STD exception " << e.what());
1462         retCode = CKM_API_ERROR_SERVER_ERROR;
1463     } catch (...) {
1464         LogError("Unknown error.");
1465     }
1466
1467     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1468                                              commandId,
1469                                              retCode,
1470                                              chainRawVector);
1471     return response.Pop();
1472 }
1473
1474 RawBuffer CKMLogic::createSignature(
1475         const Credentials &cred,
1476         int commandId,
1477         const Name &privateKeyName,
1478         const Label & ownerLabel,
1479         const Password &password,           // password for private_key
1480         const RawBuffer &message,
1481         const HashAlgorithm hash,
1482         const RSAPaddingAlgorithm padding)
1483 {
1484     DB::Row row;
1485     RawBuffer signature;
1486     CryptoAlgorithm cryptoAlg;
1487     cryptoAlg.setParam(ParamName::SV_HASH_ALGO, hash);
1488     cryptoAlg.setParam(ParamName::SV_RSA_PADDING, padding);
1489
1490     int retCode = CKM_API_SUCCESS;
1491
1492     try {
1493         retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1494         if(retCode == CKM_API_SUCCESS) {
1495             signature = m_decider.getStore(row).getObject(row)->sign(cryptoAlg, message);
1496         }
1497     } catch (const DB::Crypto::Exception::Base &e) {
1498         LogError("DB::Crypto failed with message: " << e.GetMessage());
1499         retCode = CKM_API_ERROR_DB_ERROR;
1500     } catch (const Exc::Exception &e) {
1501         retCode = e.error();
1502     } catch (const CKM::Exception &e) {
1503         LogError("Unknown CKM::Exception: " << e.GetMessage());
1504         retCode = CKM_API_ERROR_SERVER_ERROR;
1505     }
1506
1507     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1508                                              commandId,
1509                                              retCode,
1510                                              signature);
1511     return response.Pop();
1512 }
1513
1514 RawBuffer CKMLogic::verifySignature(
1515         const Credentials &cred,
1516         int commandId,
1517         const Name &publicKeyOrCertName,
1518         const Label & ownerLabel,
1519         const Password &password,           // password for public_key (optional)
1520         const RawBuffer &message,
1521         const RawBuffer &signature,
1522         const HashAlgorithm hash,
1523         const RSAPaddingAlgorithm padding)
1524 {
1525     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1526
1527     try {
1528         DB::Row row;
1529
1530         CryptoAlgorithm params;
1531         params.setParam(ParamName::SV_HASH_ALGO, hash);
1532         params.setParam(ParamName::SV_RSA_PADDING, padding);
1533
1534         // try certificate first - looking for a public key.
1535         // in case of PKCS, pub key from certificate will be found first
1536         // rather than private key from the same PKCS.
1537         retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1538         if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1539             retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1540         }
1541
1542         if (retCode == CKM_API_SUCCESS) {
1543             retCode = m_decider.getStore(row).getObject(row)->verify(params, message, signature);
1544         }
1545     } catch (const Exc::Exception &e) {
1546         retCode = e.error();
1547     } catch (const DB::Crypto::Exception::Base &e) {
1548         LogError("DB::Crypto failed with message: " << e.GetMessage());
1549         retCode = CKM_API_ERROR_DB_ERROR;
1550     } catch (const CKM::Exception &e) {
1551         LogError("Unknown CKM::Exception: " << e.GetMessage());
1552         retCode = CKM_API_ERROR_SERVER_ERROR;
1553     }
1554
1555     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1556                                              commandId,
1557                                              retCode);
1558     return response.Pop();
1559 }
1560
1561 int CKMLogic::setPermissionHelper(
1562         const Credentials &cred,                // who's the client
1563         const Name &name,
1564         const Label &label,                     // who's the owner
1565         const Label &accessorLabel,             // who will get the access
1566         const PermissionMask permissionMask)
1567 {
1568     auto &handler = selectDatabase(cred, label);
1569
1570     // we don't know the client
1571     if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1572         return CKM_API_ERROR_INPUT_PARAM;
1573
1574     // use client label if not explicitly provided
1575     const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1576
1577     // verify name and label are correct
1578     if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1579         return CKM_API_ERROR_INPUT_PARAM;
1580
1581     // currently we don't support modification of owner's permissions to his own rows
1582     if (ownerLabel==accessorLabel)
1583         return CKM_API_ERROR_INPUT_PARAM;
1584
1585     // system database does not support write/remove permissions
1586     if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1587         (permissionMask & Permission::REMOVE))
1588         return CKM_API_ERROR_INPUT_PARAM;
1589
1590     // can the client modify permissions to owner's row?
1591     int retCode = m_accessControl.canModify(cred, ownerLabel);
1592     if(retCode != CKM_API_SUCCESS)
1593         return retCode;
1594
1595     DB::Crypto::Transaction transaction(&handler.database);
1596
1597     if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1598         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1599
1600     // removing non-existing permissions: fail
1601     if(permissionMask == Permission::NONE)
1602     {
1603         if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1604             return CKM_API_ERROR_INPUT_PARAM;
1605     }
1606
1607     // set permissions to the row owned by ownerLabel for accessorLabel
1608     handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1609     transaction.commit();
1610
1611     return CKM_API_SUCCESS;
1612 }
1613
1614 RawBuffer CKMLogic::setPermission(
1615         const Credentials &cred,
1616         const int command,
1617         const int msgID,
1618         const Name &name,
1619         const Label &label,
1620         const Label &accessorLabel,
1621         const PermissionMask permissionMask)
1622 {
1623     int retCode;
1624     Try {
1625         retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1626     } catch (const Exc::Exception &e) {
1627         retCode = e.error();
1628     } Catch (CKM::Exception) {
1629         LogError("Error in set row!");
1630         retCode = CKM_API_ERROR_DB_ERROR;
1631     }
1632
1633     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1634 }
1635
1636 int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel)
1637 {
1638     if (!handle.crypto.haveKey(appLabel)) {
1639         RawBuffer key;
1640         auto key_optional = handle.database.getKey(appLabel);
1641         if(!key_optional) {
1642             LogError("No key for given label in database");
1643             return CKM_API_ERROR_DB_ERROR;
1644         }
1645         key = *key_optional;
1646         key = handle.keyProvider.getPureDEK(key);
1647         handle.crypto.pushKey(appLabel, key);
1648     }
1649     return CKM_API_SUCCESS;
1650 }
1651
1652 } // namespace CKM
1653