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