0a6893fd887c4c634cb2a915a311c602bc3019fa
[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(LABEL_SYSTEM_DB))
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         LogWarning("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         LogWarning("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     DB::Row row(name, label, static_cast<int>(policy.extractable), dataType, data, static_cast<int>(data.size()));
421     row.backendId = m_decider.chooseCryptoBackend(dataType, policy.extractable);
422
423     // do not encrypt data with password during cc_mode on
424     if(m_accessControl.isCCMode()) {
425         crypto.encryptRow("", row);
426     } else {
427         crypto.encryptRow(policy.password, row);
428     }
429     return row;
430 }
431
432 int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
433 {
434     RawBuffer dummy;
435     return toBinaryData(dataType, input_data, dummy);
436 }
437
438 int CKMLogic::toBinaryData(DataType dataType,
439                            const RawBuffer &input_data,
440                            RawBuffer &output_data) const
441 {
442     // verify the data integrity
443     if (dataType.isKey())
444     {
445         KeyShPtr output_key;
446         if(dataType.isSKey())
447             output_key = CKM::Key::createAES(input_data);
448         else
449             output_key = CKM::Key::create(input_data);
450         if(output_key.get() == NULL)
451         {
452             LogError("provided binary data is not valid key data");
453             return CKM_API_ERROR_INPUT_PARAM;
454         }
455         output_data = output_key->getDER();
456     }
457     else if (dataType.isCertificate() || dataType.isChainCert())
458     {
459         CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
460         if(cert.get() == NULL)
461         {
462             LogError("provided binary data is not valid certificate data");
463             return CKM_API_ERROR_INPUT_PARAM;
464         }
465         output_data = cert->getDER();
466     }
467     else
468         output_data = input_data;
469     // TODO: add here BINARY_DATA verification, i.e: max size etc.
470     return CKM_API_SUCCESS;
471 }
472
473 int CKMLogic::verifyAndSaveDataHelper(
474     const Credentials &cred,
475     const Name &name,
476     const Label &label,
477     const RawBuffer &data,
478     DataType dataType,
479     const PolicySerializable &policy)
480 {
481     int retCode = CKM_API_ERROR_UNKNOWN;
482
483     try {
484         // check if data is correct
485         RawBuffer binaryData;
486         retCode = toBinaryData(dataType, data, binaryData);
487         if(retCode == CKM_API_SUCCESS)
488         {
489             retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
490         }
491     } catch (const DB::Crypto::Exception::InternalError &e) {
492         LogError("DB::Crypto failed with message: " << e.GetMessage());
493         retCode = CKM_API_ERROR_DB_ERROR;
494     } catch (const DB::Crypto::Exception::TransactionError &e) {
495         LogError("DB::Crypto transaction failed with message " << e.GetMessage());
496         retCode = CKM_API_ERROR_DB_ERROR;
497     } catch (const Exc::Exception &e) {
498         retCode = e.error();
499     } catch (const CKM::Exception &e) {
500         LogError("CKM::Exception: " << e.GetMessage());
501         retCode = CKM_API_ERROR_SERVER_ERROR;
502     }
503     return retCode;
504 }
505
506 int CKMLogic::getKeyForService(
507         const Credentials &cred,
508         const Name &name,
509         const Label &label,
510         const Password &pass,
511         Crypto::GKeyShPtr &key)
512 {
513     DB::Row row;
514     try {
515         // Key is for internal service use. It won't be exported to the client
516         int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, row);
517         if (retCode == CKM_API_SUCCESS)
518             key = m_decider.getStore(row).getKey(row);
519         return retCode;
520     } catch (const DB::Crypto::Exception::Base &e) {
521         LogError("DB::Crypto failed with message: " << e.GetMessage());
522         return CKM_API_ERROR_DB_ERROR;
523     } catch (const Exc::Exception &e) {
524         return e.error();
525     } catch (const CKM::Exception &e) {
526         LogError("CKM::Exception: " << e.GetMessage());
527         return CKM_API_ERROR_SERVER_ERROR;
528     }
529 }
530
531 RawBuffer CKMLogic::saveData(
532     const Credentials &cred,
533     int commandId,
534     const Name &name,
535     const Label &label,
536     const RawBuffer &data,
537     DataType dataType,
538     const PolicySerializable &policy)
539 {
540     int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy);
541     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
542                                              commandId,
543                                              retCode,
544                                              static_cast<int>(dataType));
545     return response.Pop();
546 }
547
548 int CKMLogic::extractPKCS12Data(
549     CryptoLogic &crypto,
550     const Name &name,
551     const Label &ownerLabel,
552     const PKCS12Serializable &pkcs,
553     const PolicySerializable &keyPolicy,
554     const PolicySerializable &certPolicy,
555     DB::RowVector &output) const
556 {
557     // private key is mandatory
558     if( !pkcs.getKey() )
559         return CKM_API_ERROR_INVALID_FORMAT;
560     Key* keyPtr = pkcs.getKey().get();
561     DataType keyType = DataType(keyPtr->getType());
562     RawBuffer keyData = keyPtr->getDER();
563     int retCode = verifyBinaryData(keyType, keyData);
564     if(retCode != CKM_API_SUCCESS)
565         return retCode;
566     output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy));
567
568     // certificate is mandatory
569     if( !pkcs.getCertificate() )
570         return CKM_API_ERROR_INVALID_FORMAT;
571     RawBuffer certData = pkcs.getCertificate().get()->getDER();
572     retCode = verifyBinaryData(DataType::CERTIFICATE, certData);
573     if(retCode != CKM_API_SUCCESS)
574         return retCode;
575     output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy));
576
577     // CA cert chain
578     unsigned int cert_index = 0;
579     for(const auto & ca : pkcs.getCaCertificateShPtrVector())
580     {
581         DataType chainDataType = DataType::getChainDatatype(cert_index ++);
582         RawBuffer caCertData = ca->getDER();
583         int retCode = verifyBinaryData(chainDataType, caCertData);
584         if(retCode != CKM_API_SUCCESS)
585             return retCode;
586
587         output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
588     }
589
590     return CKM_API_SUCCESS;
591 }
592
593 RawBuffer CKMLogic::savePKCS12(
594     const Credentials &cred,
595     int commandId,
596     const Name &name,
597     const Label &label,
598     const PKCS12Serializable &pkcs,
599     const PolicySerializable &keyPolicy,
600     const PolicySerializable &certPolicy)
601 {
602     int retCode = CKM_API_ERROR_UNKNOWN;
603     try {
604         retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
605     } catch (const Exc::Exception &e) {
606         retCode = e.error();
607     } catch (const DB::Crypto::Exception::InternalError &e) {
608         LogError("DB::Crypto failed with message: " << e.GetMessage());
609         retCode = CKM_API_ERROR_DB_ERROR;
610     } catch (const DB::Crypto::Exception::TransactionError &e) {
611         LogError("DB::Crypto transaction failed with message " << e.GetMessage());
612         retCode = CKM_API_ERROR_DB_ERROR;
613     } catch (const CKM::Exception &e) {
614         LogError("CKM::Exception: " << e.GetMessage());
615         retCode = CKM_API_ERROR_SERVER_ERROR;
616     }
617
618     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
619                                              commandId,
620                                              retCode);
621     return response.Pop();
622 }
623
624
625 int CKMLogic::removeDataHelper(
626         const Credentials &cred,
627         const Name &name,
628         const Label &label)
629 {
630     auto &handler = selectDatabase(cred, label);
631
632     // use client label if not explicitly provided
633     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
634     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
635         LogError("Invalid label or name format");
636         return CKM_API_ERROR_INPUT_PARAM;
637     }
638
639     DB::Crypto::Transaction transaction(&handler.database);
640
641     // read and check permissions
642     PermissionMaskOptional permissionRowOpt =
643             handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
644     int retCode = m_accessControl.canDelete(cred,
645                         PermissionForLabel(cred.smackLabel, permissionRowOpt));
646     if(retCode != CKM_API_SUCCESS)
647     {
648         LogWarning("access control check result: " << retCode);
649         return retCode;
650     }
651
652     auto erased = handler.database.deleteRow(name, ownerLabel);
653     // check if the data existed or not
654     if(erased)
655         transaction.commit();
656     else {
657         LogError("No row for given name and label");
658         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
659     }
660
661     return CKM_API_SUCCESS;
662 }
663
664 RawBuffer CKMLogic::removeData(
665     const Credentials &cred,
666     int commandId,
667     const Name &name,
668     const Label &label)
669 {
670     int retCode = CKM_API_ERROR_UNKNOWN;
671
672     try
673     {
674         retCode = removeDataHelper(cred, name, label);
675     }
676     catch (const Exc::Exception &e)
677     {
678         retCode = e.error();
679     }
680     catch (const CKM::Exception &)
681     {
682         LogError("Error in deleting row!");
683         retCode = CKM_API_ERROR_DB_ERROR;
684     }
685
686     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
687                                              commandId,
688                                              retCode);
689     return response.Pop();
690 }
691
692 int CKMLogic::readSingleRow(const Name &name,
693                             const Label &ownerLabel,
694                             DataType dataType,
695                             DB::Crypto & database,
696                             DB::Row &row)
697 {
698     DB::Crypto::RowOptional row_optional;
699     if (dataType.isKey())
700     {
701         // read all key types
702         row_optional = database.getRow(name,
703                                          ownerLabel,
704                                          DataType::DB_KEY_FIRST,
705                                          DataType::DB_KEY_LAST);
706     } else {
707         // read anything else
708         row_optional = database.getRow(name,
709                                          ownerLabel,
710                                          dataType);
711     }
712
713     if(!row_optional) {
714         LogError("No row for given name, label and type");
715         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
716     } else {
717         row = *row_optional;
718     }
719
720     return CKM_API_SUCCESS;
721 }
722
723
724 int CKMLogic::readMultiRow(const Name &name,
725                            const Label &ownerLabel,
726                            DataType dataType,
727                            DB::Crypto & database,
728                            DB::RowVector &output)
729 {
730     if (dataType.isKey())
731     {
732         // read all key types
733         database.getRows(name,
734                           ownerLabel,
735                           DataType::DB_KEY_FIRST,
736                           DataType::DB_KEY_LAST,
737                           output);
738     }
739     else if (dataType.isChainCert())
740     {
741         // read all key types
742         database.getRows(name,
743                          ownerLabel,
744                          DataType::DB_CHAIN_FIRST,
745                          DataType::DB_CHAIN_LAST,
746                          output);
747     }
748     else
749     {
750         // read anything else
751         database.getRows(name,
752                          ownerLabel,
753                          dataType,
754                          output);
755     }
756
757     if(!output.size()) {
758         LogError("No row for given name, label and type");
759         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
760     }
761
762     return CKM_API_SUCCESS;
763 }
764
765 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
766                                          const Name &name,
767                                          const Label &ownerLabel,
768                                          const Label &accessorLabel,
769                                          const DB::Row &row,
770                                          bool exportFlag,
771                                          DB::Crypto & database)
772 {
773     PermissionMaskOptional permissionRowOpt =
774             database.getPermissionRow(name, ownerLabel, accessorLabel);
775
776     if(exportFlag)
777         return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
778     return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
779 }
780
781 int CKMLogic::readDataHelper(
782     bool exportFlag,
783     const Credentials &cred,
784     DataType dataType,
785     const Name &name,
786     const Label &label,
787     const Password &password,
788     DB::RowVector &rows)
789 {
790     auto &handler = selectDatabase(cred, label);
791
792     // use client label if not explicitly provided
793     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
794
795     if (!isNameValid(name) || !isLabelValid(ownerLabel))
796         return CKM_API_ERROR_INPUT_PARAM;
797
798     // read rows
799     DB::Crypto::Transaction transaction(&handler.database);
800     int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
801     if(CKM_API_SUCCESS != retCode)
802         return retCode;
803
804     // all read rows belong to the same owner
805     DB::Row & firstRow = rows.at(0);
806
807     // check access rights
808     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
809     if(CKM_API_SUCCESS != retCode)
810         return retCode;
811
812     // decrypt row
813     if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
814         RawBuffer key;
815         auto key_optional = handler.database.getKey(firstRow.ownerLabel);
816         if(!key_optional) {
817             LogError("No key for given label in database");
818             return CKM_API_ERROR_DB_ERROR;
819         }
820         key = *key_optional;
821         key = handler.keyProvider.getPureDEK(key);
822         handler.crypto.pushKey(firstRow.ownerLabel, key);
823     }
824     for(auto &row : rows)
825         handler.crypto.decryptRow(password, row);
826
827     return CKM_API_SUCCESS;
828 }
829
830 int CKMLogic::readDataHelper(
831     bool exportFlag,
832     const Credentials &cred,
833     DataType dataType,
834     const Name &name,
835     const Label &label,
836     const Password &password,
837     DB::Row &row)
838 {
839     auto &handler = selectDatabase(cred, label);
840
841     // use client label if not explicitly provided
842     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
843
844     if (!isNameValid(name) || !isLabelValid(ownerLabel))
845         return CKM_API_ERROR_INPUT_PARAM;
846
847     // read row
848     DB::Crypto::Transaction transaction(&handler.database);
849     int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
850     if(CKM_API_SUCCESS != retCode)
851         return retCode;
852
853     // check access rights
854     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
855     if(CKM_API_SUCCESS != retCode)
856         return retCode;
857
858     // decrypt row
859     if (!handler.crypto.haveKey(row.ownerLabel)) {
860         RawBuffer key;
861         auto key_optional = handler.database.getKey(row.ownerLabel);
862         if(!key_optional) {
863             LogError("No key for given label in database");
864             return CKM_API_ERROR_DB_ERROR;
865         }
866         key = *key_optional;
867         key = handler.keyProvider.getPureDEK(key);
868         handler.crypto.pushKey(row.ownerLabel, key);
869     }
870     handler.crypto.decryptRow(password, row);
871
872     return CKM_API_SUCCESS;
873 }
874
875 RawBuffer CKMLogic::getData(
876     const Credentials &cred,
877     int commandId,
878     DataType dataType,
879     const Name &name,
880     const Label &label,
881     const Password &password)
882 {
883     int retCode = CKM_API_SUCCESS;
884     DB::Row row;
885
886     try {
887         retCode = readDataHelper(true, cred, dataType, name, label, password, row);
888     } catch (const DB::Crypto::Exception::Base &e) {
889         LogError("DB::Crypto failed with message: " << e.GetMessage());
890         retCode = CKM_API_ERROR_DB_ERROR;
891     } catch (const Exc::Exception &e) {
892         retCode = e.error();
893     } catch (const CKM::Exception &e) {
894         LogError("CKM::Exception: " << e.GetMessage());
895         retCode = CKM_API_ERROR_SERVER_ERROR;
896     }
897
898     if (CKM_API_SUCCESS != retCode) {
899         row.data.clear();
900         row.dataType = dataType;
901     }
902
903     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
904                                              commandId,
905                                              retCode,
906                                              static_cast<int>(row.dataType),
907                                              row.data);
908     return response.Pop();
909 }
910
911 int CKMLogic::getPKCS12Helper(
912     const Credentials &cred,
913     const Name &name,
914     const Label &label,
915     const Password &keyPassword,
916     const Password &certPassword,
917     KeyShPtr & privKey,
918     CertificateShPtr & cert,
919     CertificateShPtrVector & caChain)
920 {
921     int retCode;
922
923     // read private key (mandatory)
924     DB::Row privKeyRow;
925     retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
926     if(retCode != CKM_API_SUCCESS)
927         return retCode;
928     privKey = CKM::Key::create(privKeyRow.data);
929
930     // read certificate (mandatory)
931     DB::Row certRow;
932     retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
933     if(retCode != CKM_API_SUCCESS)
934         return retCode;
935     cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
936
937     // read CA cert chain (optional)
938     DB::RowVector rawCaChain;
939     retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
940     if(retCode != CKM_API_SUCCESS &&
941        retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
942         return retCode;
943     for(auto &rawCaCert : rawCaChain)
944         caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
945
946     // if anything found, return it
947     if(privKey || cert || caChain.size()>0)
948         retCode = CKM_API_SUCCESS;
949
950     return retCode;
951 }
952
953 RawBuffer CKMLogic::getPKCS12(
954         const Credentials &cred,
955         int commandId,
956         const Name &name,
957         const Label &label,
958         const Password &keyPassword,
959         const Password &certPassword)
960 {
961     int retCode = CKM_API_ERROR_UNKNOWN;
962
963     PKCS12Serializable output;
964     try {
965         KeyShPtr privKey;
966         CertificateShPtr cert;
967         CertificateShPtrVector caChain;
968         retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
969
970         // prepare response
971         if(retCode == CKM_API_SUCCESS)
972             output = PKCS12Serializable(privKey, cert, caChain);
973     } catch (const DB::Crypto::Exception::Base &e) {
974         LogError("DB::Crypto failed with message: " << e.GetMessage());
975         retCode = CKM_API_ERROR_DB_ERROR;
976     } catch (const Exc::Exception &e) {
977         retCode = e.error();
978     } catch (const CKM::Exception &e) {
979         LogError("CKM::Exception: " << e.GetMessage());
980         retCode = CKM_API_ERROR_SERVER_ERROR;
981     }
982
983     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
984                                              commandId,
985                                              retCode,
986                                              output);
987     return response.Pop();
988 }
989
990 int CKMLogic::getDataListHelper(const Credentials &cred,
991                                 const DataType dataType,
992                                 LabelNameVector &labelNameVector)
993 {
994     int retCode = CKM_API_ERROR_DB_LOCKED;
995     if (0 < m_userDataMap.count(cred.clientUid))
996     {
997         auto &database = m_userDataMap[cred.clientUid].database;
998
999         Try {
1000             LabelNameVector tmpVector;
1001             if (dataType.isKey()) {
1002                 // list all key types
1003                 database.listNames(cred.smackLabel,
1004                                    tmpVector,
1005                                    DataType::DB_KEY_FIRST,
1006                                    DataType::DB_KEY_LAST);
1007             } else {
1008                 // list anything else
1009                 database.listNames(cred.smackLabel,
1010                                    tmpVector,
1011                                    dataType);
1012             }
1013             labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
1014             retCode = CKM_API_SUCCESS;
1015         }
1016         Catch (CKM::Exception) {
1017             LogError("Failed to get names");
1018             retCode = CKM_API_ERROR_DB_ERROR;
1019         }
1020     }
1021     return retCode;
1022 }
1023
1024 RawBuffer CKMLogic::getDataList(
1025     const Credentials &cred,
1026     int commandId,
1027     DataType dataType)
1028 {
1029     LabelNameVector systemVector;
1030     LabelNameVector userVector;
1031     LabelNameVector labelNameVector;
1032
1033     int retCode = unlockSystemDB();
1034     if (CKM_API_SUCCESS == retCode)
1035     {
1036         // system database
1037         if (m_accessControl.isSystemService(cred))
1038         {
1039             // lookup system DB
1040             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1041                                                     LABEL_SYSTEM_DB),
1042                                         dataType,
1043                                         systemVector);
1044         }
1045         else
1046         {
1047             // user - lookup system, then client DB
1048             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1049                                                     cred.smackLabel),
1050                                         dataType,
1051                                         systemVector);
1052
1053             // private database
1054             if(retCode == CKM_API_SUCCESS)
1055             {
1056                 retCode = getDataListHelper(cred,
1057                                             dataType,
1058                                             userVector);
1059             }
1060         }
1061     }
1062
1063     if(retCode == CKM_API_SUCCESS)
1064     {
1065         labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1066         labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1067     }
1068     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1069                                              commandId,
1070                                              retCode,
1071                                              static_cast<int>(dataType),
1072                                              labelNameVector);
1073     return response.Pop();
1074 }
1075
1076 int CKMLogic::saveDataHelper(
1077     const Credentials &cred,
1078     const Name &name,
1079     const Label &label,
1080     DataType dataType,
1081     const RawBuffer &data,
1082     const PolicySerializable &policy)
1083 {
1084     auto &handler = selectDatabase(cred, label);
1085
1086     // use client label if not explicitly provided
1087     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1088     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1089         return CKM_API_ERROR_INPUT_PARAM;
1090
1091     // check if save is possible
1092     DB::Crypto::Transaction transaction(&handler.database);
1093     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1094     if(retCode != CKM_API_SUCCESS)
1095         return retCode;
1096
1097     // save the data
1098     DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
1099     handler.database.saveRow(encryptedRow);
1100
1101     transaction.commit();
1102     return CKM_API_SUCCESS;
1103 }
1104
1105 int CKMLogic::saveDataHelper(
1106     const Credentials &cred,
1107     const Name &name,
1108     const Label &label,
1109     const PKCS12Serializable &pkcs,
1110     const PolicySerializable &keyPolicy,
1111     const PolicySerializable &certPolicy)
1112 {
1113     auto &handler = selectDatabase(cred, label);
1114
1115     // use client label if not explicitly provided
1116     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1117     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
1118         return CKM_API_ERROR_INPUT_PARAM;
1119
1120     // check if save is possible
1121     DB::Crypto::Transaction transaction(&handler.database);
1122     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1123     if(retCode != CKM_API_SUCCESS)
1124         return retCode;
1125
1126     // extract and encrypt the data
1127     DB::RowVector encryptedRows;
1128     retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1129     if(retCode != CKM_API_SUCCESS)
1130         return retCode;
1131
1132     // save the data
1133     handler.database.saveRows(name, ownerLabel, encryptedRows);
1134     transaction.commit();
1135
1136     return CKM_API_SUCCESS;
1137 }
1138
1139
1140 int CKMLogic::createKeyAESHelper(
1141     const Credentials &cred,
1142     const int size,
1143     const Name &name,
1144     const Label &label,
1145     const PolicySerializable &policy)
1146 {
1147     CryptoAlgorithm keyGenAlgorithm;
1148     keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1149     keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1150     Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);
1151
1152     return saveDataHelper(cred,
1153                           name,
1154                           label,
1155                           DataType::KEY_AES,
1156                           key.data,
1157                           policy);
1158 }
1159
1160
1161 int CKMLogic::createKeyPairHelper(
1162     const Credentials &cred,
1163     const CryptoAlgorithmSerializable & keyGenParams,
1164     const Name &namePrivate,
1165     const Label &labelPrivate,
1166     const Name &namePublic,
1167     const Label &labelPublic,
1168     const PolicySerializable &policyPrivate,
1169     const PolicySerializable &policyPublic)
1170 {
1171     auto &handlerPriv = selectDatabase(cred, labelPrivate);
1172     auto &handlerPub = selectDatabase(cred, labelPublic);
1173
1174     AlgoType keyType = AlgoType::RSA_GEN;
1175     if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1176         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1177     DataType dt(keyType);
1178     if(!dt.isKey())
1179         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1180
1181     bool exportable = policyPrivate.extractable || policyPublic.extractable;
1182     TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
1183
1184     DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1185     // in case the same database is used for private and public - the second
1186     // transaction will not be executed
1187     DB::Crypto::Transaction transactionPub(&handlerPub.database);
1188
1189     int retCode = saveDataHelper(cred,
1190                              namePrivate,
1191                              labelPrivate,
1192                              keys.first.dataType,
1193                              keys.first.data,
1194                              policyPrivate);
1195     if (CKM_API_SUCCESS != retCode)
1196         return retCode;
1197
1198     retCode = saveDataHelper(cred,
1199                              namePublic,
1200                              labelPublic,
1201                              keys.second.dataType,
1202                              keys.second.data,
1203                              policyPublic);
1204     if (CKM_API_SUCCESS != retCode)
1205         return retCode;
1206
1207     transactionPub.commit();
1208     transactionPriv.commit();
1209     return CKM_API_SUCCESS;
1210 }
1211
1212 RawBuffer CKMLogic::createKeyPair(
1213     const Credentials &cred,
1214     int commandId,
1215     const CryptoAlgorithmSerializable & keyGenParams,
1216     const Name &namePrivate,
1217     const Label &labelPrivate,
1218     const Name &namePublic,
1219     const Label &labelPublic,
1220     const PolicySerializable &policyPrivate,
1221     const PolicySerializable &policyPublic)
1222 {
1223     int retCode = CKM_API_SUCCESS;
1224
1225     try {
1226         retCode = createKeyPairHelper(
1227                         cred,
1228                         keyGenParams,
1229                         namePrivate,
1230                         labelPrivate,
1231                         namePublic,
1232                         labelPublic,
1233                         policyPrivate,
1234                         policyPublic);
1235     } catch(const Exc::Exception &e) {
1236         retCode = e.error();
1237     } catch (DB::Crypto::Exception::TransactionError &e) {
1238         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1239         retCode = CKM_API_ERROR_DB_ERROR;
1240     } catch (DB::Crypto::Exception::InternalError &e) {
1241         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1242         retCode = CKM_API_ERROR_DB_ERROR;
1243     } catch (const CKM::Exception &e) {
1244         LogError("CKM::Exception: " << e.GetMessage());
1245         retCode = CKM_API_ERROR_SERVER_ERROR;
1246     }
1247
1248     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1249                                     commandId, retCode).Pop();
1250 }
1251
1252 RawBuffer CKMLogic::createKeyAES(
1253     const Credentials &cred,
1254     int commandId,
1255     const int size,
1256     const Name &name,
1257     const Label &label,
1258     const PolicySerializable &policy)
1259 {
1260     int retCode = CKM_API_SUCCESS;
1261
1262     try {
1263         retCode = createKeyAESHelper(cred, size, name, label, policy);
1264     } catch (const Exc::Exception &e) {
1265         retCode = e.error();
1266     } catch (std::invalid_argument &e) {
1267         LogDebug("invalid argument error: " << e.what());
1268         retCode = CKM_API_ERROR_INPUT_PARAM;
1269     } catch (DB::Crypto::Exception::TransactionError &e) {
1270         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1271         retCode = CKM_API_ERROR_DB_ERROR;
1272     } catch (DB::Crypto::Exception::InternalError &e) {
1273         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1274         retCode = CKM_API_ERROR_DB_ERROR;
1275     } catch (const CKM::Exception &e) {
1276         LogError("CKM::Exception: " << e.GetMessage());
1277         retCode = CKM_API_ERROR_SERVER_ERROR;
1278     }
1279
1280     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1281                                     commandId, retCode).Pop();
1282 }
1283
1284 int CKMLogic::readCertificateHelper(
1285         const Credentials &cred,
1286         const LabelNameVector &labelNameVector,
1287         CertificateImplVector &certVector)
1288 {
1289     DB::Row row;
1290     for (auto &i: labelNameVector) {
1291         int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
1292         if (ec != CKM_API_SUCCESS)
1293             return ec;
1294         certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
1295
1296         // try to read chain certificates (if present)
1297         DB::RowVector rawCaChain;
1298         ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
1299         if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1300             return ec;
1301         for(auto &rawCaCert : rawCaChain)
1302             certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
1303     }
1304     return CKM_API_SUCCESS;
1305 }
1306
1307 int CKMLogic::getCertificateChainHelper(
1308         const CertificateImpl &cert,
1309         const RawBufferVector &untrustedCertificates,
1310         const RawBufferVector &trustedCertificates,
1311         bool useTrustedSystemCertificates,
1312         RawBufferVector &chainRawVector)
1313 {
1314     CertificateImplVector untrustedCertVector;
1315     CertificateImplVector trustedCertVector;
1316     CertificateImplVector chainVector;
1317
1318     if (cert.empty())
1319         return CKM_API_ERROR_INPUT_PARAM;
1320
1321     for (auto &e: untrustedCertificates)
1322         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1323     for (auto &e: trustedCertificates)
1324         trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
1325
1326     CertificateStore store;
1327     int retCode = store.verifyCertificate(cert,
1328                                           untrustedCertVector,
1329                                           trustedCertVector,
1330                                           useTrustedSystemCertificates,
1331                                           m_accessControl.isCCMode(),
1332                                           chainVector);
1333     if (retCode != CKM_API_SUCCESS)
1334         return retCode;
1335
1336     for (auto &e : chainVector)
1337         chainRawVector.push_back(e.getDER());
1338     return CKM_API_SUCCESS;
1339 }
1340
1341 int CKMLogic::getCertificateChainHelper(
1342         const Credentials &cred,
1343         const CertificateImpl &cert,
1344         const LabelNameVector &untrusted,
1345         const LabelNameVector &trusted,
1346         bool useTrustedSystemCertificates,
1347         RawBufferVector &chainRawVector)
1348 {
1349     CertificateImplVector untrustedCertVector;
1350     CertificateImplVector trustedCertVector;
1351     CertificateImplVector chainVector;
1352     DB::Row row;
1353
1354     if (cert.empty())
1355         return CKM_API_ERROR_INPUT_PARAM;
1356
1357     int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1358     if (retCode != CKM_API_SUCCESS)
1359         return retCode;
1360     retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1361     if (retCode != CKM_API_SUCCESS)
1362         return retCode;
1363
1364     CertificateStore store;
1365     retCode = store.verifyCertificate(cert,
1366                                       untrustedCertVector,
1367                                       trustedCertVector,
1368                                       useTrustedSystemCertificates,
1369                                       m_accessControl.isCCMode(),
1370                                       chainVector);
1371     if (retCode != CKM_API_SUCCESS)
1372         return retCode;
1373
1374     for (auto &i: chainVector)
1375         chainRawVector.push_back(i.getDER());
1376
1377     return CKM_API_SUCCESS;
1378 }
1379
1380 RawBuffer CKMLogic::getCertificateChain(
1381     const Credentials & /*cred*/,
1382     int commandId,
1383     const RawBuffer &certificate,
1384     const RawBufferVector &untrustedCertificates,
1385     const RawBufferVector &trustedCertificates,
1386     bool useTrustedSystemCertificates)
1387 {
1388     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1389     RawBufferVector chainRawVector;
1390     int retCode = CKM_API_ERROR_UNKNOWN;
1391     try {
1392         retCode = getCertificateChainHelper(cert,
1393                                             untrustedCertificates,
1394                                             trustedCertificates,
1395                                             useTrustedSystemCertificates,
1396                                             chainRawVector);
1397     } catch (const Exc::Exception &e) {
1398         retCode = e.error();
1399     } catch (const DB::Crypto::Exception::Base &e) {
1400         LogError("DB::Crypto failed with message: " << e.GetMessage());
1401         retCode = CKM_API_ERROR_DB_ERROR;
1402     } catch (const std::exception& e) {
1403         LogError("STD exception " << e.what());
1404         retCode = CKM_API_ERROR_SERVER_ERROR;
1405     } catch (...) {
1406         LogError("Unknown error.");
1407     }
1408
1409     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1410                                              commandId,
1411                                              retCode,
1412                                              chainRawVector);
1413     return response.Pop();
1414 }
1415
1416 RawBuffer CKMLogic::getCertificateChain(
1417     const Credentials &cred,
1418     int commandId,
1419     const RawBuffer &certificate,
1420     const LabelNameVector &untrustedCertificates,
1421     const LabelNameVector &trustedCertificates,
1422     bool useTrustedSystemCertificates)
1423 {
1424     int retCode = CKM_API_ERROR_UNKNOWN;
1425     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1426     RawBufferVector chainRawVector;
1427     try {
1428         retCode = getCertificateChainHelper(cred,
1429                                             cert,
1430                                             untrustedCertificates,
1431                                             trustedCertificates,
1432                                             useTrustedSystemCertificates,
1433                                             chainRawVector);
1434     } catch (const DB::Crypto::Exception::Base &e) {
1435         LogError("DB::Crypto failed with message: " << e.GetMessage());
1436         retCode = CKM_API_ERROR_DB_ERROR;
1437     } catch (const Exc::Exception &e) {
1438         retCode = e.error();
1439     } catch (const std::exception& e) {
1440         LogError("STD exception " << e.what());
1441         retCode = CKM_API_ERROR_SERVER_ERROR;
1442     } catch (...) {
1443         LogError("Unknown error.");
1444     }
1445
1446     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1447                                              commandId,
1448                                              retCode,
1449                                              chainRawVector);
1450     return response.Pop();
1451 }
1452
1453 RawBuffer CKMLogic::createSignature(
1454         const Credentials &cred,
1455         int commandId,
1456         const Name &privateKeyName,
1457         const Label & ownerLabel,
1458         const Password &password,           // password for private_key
1459         const RawBuffer &message,
1460         const HashAlgorithm hash,
1461         const RSAPaddingAlgorithm padding)
1462 {
1463     DB::Row row;
1464     RawBuffer signature;
1465     CryptoAlgorithm cryptoAlg;
1466     cryptoAlg.setParam(ParamName::SV_HASH_ALGO, hash);
1467     cryptoAlg.setParam(ParamName::SV_RSA_PADDING, padding);
1468
1469     int retCode = CKM_API_SUCCESS;
1470
1471     try {
1472         retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
1473         if(retCode == CKM_API_SUCCESS) {
1474             signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
1475         }
1476     } catch (const DB::Crypto::Exception::Base &e) {
1477         LogError("DB::Crypto failed with message: " << e.GetMessage());
1478         retCode = CKM_API_ERROR_DB_ERROR;
1479     } catch (const Exc::Exception &e) {
1480         retCode = e.error();
1481     } catch (const CKM::Exception &e) {
1482         LogError("Unknown CKM::Exception: " << e.GetMessage());
1483         retCode = CKM_API_ERROR_SERVER_ERROR;
1484     }
1485
1486     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1487                                              commandId,
1488                                              retCode,
1489                                              signature);
1490     return response.Pop();
1491 }
1492
1493 RawBuffer CKMLogic::verifySignature(
1494         const Credentials &cred,
1495         int commandId,
1496         const Name &publicKeyOrCertName,
1497         const Label & ownerLabel,
1498         const Password &password,           // password for public_key (optional)
1499         const RawBuffer &message,
1500         const RawBuffer &signature,
1501         const HashAlgorithm hash,
1502         const RSAPaddingAlgorithm padding)
1503 {
1504     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1505
1506     try {
1507         DB::Row row;
1508
1509         CryptoAlgorithm params;
1510         params.setParam(ParamName::SV_HASH_ALGO, hash);
1511         params.setParam(ParamName::SV_RSA_PADDING, padding);
1512
1513         // try certificate first - looking for a public key.
1514         // in case of PKCS, pub key from certificate will be found first
1515         // rather than private key from the same PKCS.
1516         retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
1517         if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1518             retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
1519         }
1520
1521         if (retCode == CKM_API_SUCCESS) {
1522             retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
1523         }
1524     } catch (const Exc::Exception &e) {
1525         retCode = e.error();
1526     } catch (const DB::Crypto::Exception::Base &e) {
1527         LogError("DB::Crypto failed with message: " << e.GetMessage());
1528         retCode = CKM_API_ERROR_DB_ERROR;
1529     } catch (const CKM::Exception &e) {
1530         LogError("Unknown CKM::Exception: " << e.GetMessage());
1531         retCode = CKM_API_ERROR_SERVER_ERROR;
1532     }
1533
1534     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1535                                              commandId,
1536                                              retCode);
1537     return response.Pop();
1538 }
1539
1540 int CKMLogic::setPermissionHelper(
1541         const Credentials &cred,                // who's the client
1542         const Name &name,
1543         const Label &label,                     // who's the owner
1544         const Label &accessorLabel,             // who will get the access
1545         const PermissionMask permissionMask)
1546 {
1547     auto &handler = selectDatabase(cred, label);
1548
1549     // we don't know the client
1550     if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1551         return CKM_API_ERROR_INPUT_PARAM;
1552
1553     // use client label if not explicitly provided
1554     const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1555
1556     // verify name and label are correct
1557     if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1558         return CKM_API_ERROR_INPUT_PARAM;
1559
1560     // currently we don't support modification of owner's permissions to his own rows
1561     if (ownerLabel==accessorLabel)
1562         return CKM_API_ERROR_INPUT_PARAM;
1563
1564     // system database does not support write/remove permissions
1565     if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) &&
1566         (permissionMask & Permission::REMOVE))
1567         return CKM_API_ERROR_INPUT_PARAM;
1568
1569     // can the client modify permissions to owner's row?
1570     int retCode = m_accessControl.canModify(cred, ownerLabel);
1571     if(retCode != CKM_API_SUCCESS)
1572         return retCode;
1573
1574     DB::Crypto::Transaction transaction(&handler.database);
1575
1576     if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1577         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1578
1579     // removing non-existing permissions: fail
1580     if(permissionMask == Permission::NONE)
1581     {
1582         if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1583             return CKM_API_ERROR_INPUT_PARAM;
1584     }
1585
1586     // set permissions to the row owned by ownerLabel for accessorLabel
1587     handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1588     transaction.commit();
1589
1590     return CKM_API_SUCCESS;
1591 }
1592
1593 RawBuffer CKMLogic::setPermission(
1594         const Credentials &cred,
1595         const int command,
1596         const int msgID,
1597         const Name &name,
1598         const Label &label,
1599         const Label &accessorLabel,
1600         const PermissionMask permissionMask)
1601 {
1602     int retCode;
1603     Try {
1604         retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1605     } catch (const Exc::Exception &e) {
1606         retCode = e.error();
1607     } Catch (CKM::Exception) {
1608         LogError("Error in set row!");
1609         retCode = CKM_API_ERROR_DB_ERROR;
1610     }
1611
1612     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1613 }
1614
1615 } // namespace CKM
1616