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