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