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