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