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