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