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