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