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