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