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