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