Fix file permissions.
[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          = "/etc/ssl/certs";
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             retCode = saveDataHelper(cred, name, label, binaryData, policy);
419     } catch (const Exc::Exception &e) {
420         retCode = e.error();
421     } catch (const CKM::Exception &e) {
422         LogError("CKM::Exception: " << e.GetMessage());
423         retCode = CKM_API_ERROR_SERVER_ERROR;
424     }
425     return retCode;
426 }
427
428 int CKMLogic::getKeyForService(
429         const Credentials &cred,
430         const Name &name,
431         const Label &label,
432         const Password &pass,
433         Crypto::GObjShPtr &key)
434 {
435     DB::Row row;
436     try {
437         // Key is for internal service use. It won't be exported to the client
438         Crypto::GObjUPtr obj;
439         int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj);
440         if (retCode == CKM_API_SUCCESS)
441             key = std::move(obj);
442         return retCode;
443     } catch (const Exc::Exception &e) {
444         return e.error();
445     } catch (const CKM::Exception &e) {
446         LogError("CKM::Exception: " << e.GetMessage());
447         return CKM_API_ERROR_SERVER_ERROR;
448     }
449 }
450
451 RawBuffer CKMLogic::saveData(
452     const Credentials &cred,
453     int commandId,
454     const Name &name,
455     const Label &label,
456     const Crypto::Data &data,
457     const PolicySerializable &policy)
458 {
459     int retCode = verifyAndSaveDataHelper(cred, name, label, data, policy);
460     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
461                                              commandId,
462                                              retCode,
463                                              static_cast<int>(data.type));
464     return response.Pop();
465 }
466
467 int CKMLogic::extractPKCS12Data(
468     CryptoLogic &crypto,
469     const Name &name,
470     const Label &ownerLabel,
471     const PKCS12Serializable &pkcs,
472     const PolicySerializable &keyPolicy,
473     const PolicySerializable &certPolicy,
474     DB::RowVector &output) const
475 {
476     // private key is mandatory
477     if (!pkcs.getKey())
478         return CKM_API_ERROR_INVALID_FORMAT;
479     Key* keyPtr = pkcs.getKey().get();
480     Crypto::Data keyData(DataType(keyPtr->getType()), keyPtr->getDER());
481     int retCode = verifyBinaryData(keyData);
482     if (retCode != CKM_API_SUCCESS)
483         return retCode;
484     output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyData, keyPolicy));
485
486     // certificate is mandatory
487     if (!pkcs.getCertificate())
488         return CKM_API_ERROR_INVALID_FORMAT;
489     Crypto::Data certData(DataType::CERTIFICATE, pkcs.getCertificate().get()->getDER());
490     retCode = verifyBinaryData(certData);
491     if (retCode != CKM_API_SUCCESS)
492         return retCode;
493     output.push_back(createEncryptedRow(crypto, name, ownerLabel, certData, certPolicy));
494
495     // CA cert chain
496     unsigned int cert_index = 0;
497     for (const auto & ca : pkcs.getCaCertificateShPtrVector()) {
498         Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++), ca->getDER());
499         int retCode = verifyBinaryData(caCertData);
500         if (retCode != CKM_API_SUCCESS)
501             return retCode;
502
503         output.push_back(createEncryptedRow(crypto, name, ownerLabel, caCertData, certPolicy));
504     }
505
506     return CKM_API_SUCCESS;
507 }
508
509 RawBuffer CKMLogic::savePKCS12(
510     const Credentials &cred,
511     int commandId,
512     const Name &name,
513     const Label &label,
514     const PKCS12Serializable &pkcs,
515     const PolicySerializable &keyPolicy,
516     const PolicySerializable &certPolicy)
517 {
518     int retCode = CKM_API_ERROR_UNKNOWN;
519     try {
520         retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
521     } catch (const Exc::Exception &e) {
522         retCode = e.error();
523     } catch (const CKM::Exception &e) {
524         LogError("CKM::Exception: " << e.GetMessage());
525         retCode = CKM_API_ERROR_SERVER_ERROR;
526     }
527
528     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
529                                              commandId,
530                                              retCode);
531     return response.Pop();
532 }
533
534
535 int CKMLogic::removeDataHelper(
536         const Credentials &cred,
537         const Name &name,
538         const Label &label)
539 {
540     auto &handler = selectDatabase(cred, label);
541
542     // use client label if not explicitly provided
543     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
544     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
545         LogDebug("Invalid label or name format");
546         return CKM_API_ERROR_INPUT_PARAM;
547     }
548
549     DB::Crypto::Transaction transaction(&handler.database);
550
551     // read and check permissions
552     PermissionMaskOptional permissionRowOpt =
553             handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel);
554     int retCode = m_accessControl.canDelete(cred,
555                         PermissionForLabel(cred.smackLabel, permissionRowOpt));
556     if (retCode != CKM_API_SUCCESS) {
557         LogWarning("access control check result: " << retCode);
558         return retCode;
559     }
560
561     // get all matching rows
562     DB::RowVector rows;
563     handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows);
564     if (rows.empty()) {
565         LogDebug("No row for given name and label");
566         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
567     }
568
569     // load app key if needed
570     retCode = loadAppKey(handler, rows.front().ownerLabel);
571     if (CKM_API_SUCCESS != retCode)
572         return retCode;
573
574     // destroy it in store
575     for (auto& r : rows) {
576         try {
577             handler.crypto.decryptRow(Password(), r);
578             m_decider.getStore(r).destroy(r);
579         } catch (const Exc::AuthenticationFailed&) {
580             LogDebug("Authentication failed when removing data. Ignored.");
581         }
582     }
583
584     // delete row in db
585     handler.database.deleteRow(name, ownerLabel);
586     transaction.commit();
587
588     return CKM_API_SUCCESS;
589 }
590
591 RawBuffer CKMLogic::removeData(
592     const Credentials &cred,
593     int commandId,
594     const Name &name,
595     const Label &label)
596 {
597     int retCode = CKM_API_ERROR_UNKNOWN;
598
599     try {
600         retCode = removeDataHelper(cred, name, label);
601     } catch (const Exc::Exception &e) {
602         retCode = e.error();
603     } catch (const CKM::Exception &e) {
604         LogError("Error: " << e.GetMessage());
605         retCode = CKM_API_ERROR_DB_ERROR;
606     }
607
608     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
609                                              commandId,
610                                              retCode);
611     return response.Pop();
612 }
613
614 int CKMLogic::readSingleRow(const Name &name,
615                             const Label &ownerLabel,
616                             DataType dataType,
617                             DB::Crypto & database,
618                             DB::Row &row)
619 {
620     DB::Crypto::RowOptional row_optional;
621     if (dataType.isKey()) {
622         // read all key types
623         row_optional = database.getRow(name,
624                                          ownerLabel,
625                                          DataType::DB_KEY_FIRST,
626                                          DataType::DB_KEY_LAST);
627     } else {
628         // read anything else
629         row_optional = database.getRow(name,
630                                          ownerLabel,
631                                          dataType);
632     }
633
634     if (!row_optional) {
635         LogDebug("No row for given name, label and type");
636         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
637     } else {
638         row = *row_optional;
639     }
640
641     return CKM_API_SUCCESS;
642 }
643
644
645 int CKMLogic::readMultiRow(const Name &name,
646                            const Label &ownerLabel,
647                            DataType dataType,
648                            DB::Crypto & database,
649                            DB::RowVector &output)
650 {
651     if (dataType.isKey())
652         // read all key types
653         database.getRows(name,
654                           ownerLabel,
655                           DataType::DB_KEY_FIRST,
656                           DataType::DB_KEY_LAST,
657                           output);
658     else if (dataType.isChainCert())
659         // read all key types
660         database.getRows(name,
661                          ownerLabel,
662                          DataType::DB_CHAIN_FIRST,
663                          DataType::DB_CHAIN_LAST,
664                          output);
665     else
666         // read anything else
667         database.getRows(name,
668                          ownerLabel,
669                          dataType,
670                          output);
671
672     if (!output.size()) {
673         LogDebug("No row for given name, label and type");
674         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
675     }
676
677     return CKM_API_SUCCESS;
678 }
679
680 int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
681                                          const Name &name,
682                                          const Label &ownerLabel,
683                                          const Label &accessorLabel,
684                                          const DB::Row &row,
685                                          bool exportFlag,
686                                          DB::Crypto & database)
687 {
688     PermissionMaskOptional permissionRowOpt =
689             database.getPermissionRow(name, ownerLabel, accessorLabel);
690
691     if (exportFlag)
692         return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt));
693     return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
694 }
695
696 Crypto::GObjUPtr CKMLogic::rowToObject(
697     UserData& handler,
698     DB::Row row,
699     const Password& password)
700 {
701     Crypto::GStore& store = m_decider.getStore(row);
702
703     Password pass = m_accessControl.isCCMode() ? "" : password;
704
705     // decrypt row
706     Crypto::GObjUPtr obj;
707     if (CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) {
708         handler.crypto.decryptRow(Password(), row);
709
710         obj = store.getObject(row, pass);
711     } else {
712         // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
713         handler.crypto.decryptRow(pass, row);
714         // destroy it in store
715         store.destroy(row);
716
717         // import it to store with new scheme: data -> pass(data)
718         Token token = store.import(Crypto::Data(row.dataType, row.data), pass);
719
720         // get it from the store (it can be different than the data we imported into store)
721         obj = store.getObject(token, pass);
722
723         // update row with new token
724         *static_cast<Token*>(&row) = std::move(token);
725
726         // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
727         handler.crypto.encryptRow(row);
728
729         // update it in db
730         handler.database.updateRow(row);
731     }
732     return obj;
733 }
734
735 int CKMLogic::readDataHelper(
736     bool exportFlag,
737     const Credentials &cred,
738     DataType dataType,
739     const Name &name,
740     const Label &label,
741     const Password &password,
742     Crypto::GObjUPtrVector &objs)
743 {
744     auto &handler = selectDatabase(cred, label);
745
746     // use client label if not explicitly provided
747     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
748
749     if (!isNameValid(name) || !isLabelValid(ownerLabel))
750         return CKM_API_ERROR_INPUT_PARAM;
751
752     // read rows
753     DB::Crypto::Transaction transaction(&handler.database);
754     DB::RowVector rows;
755     int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
756     if (CKM_API_SUCCESS != retCode)
757         return retCode;
758
759     // all read rows belong to the same owner
760     DB::Row & firstRow = rows.at(0);
761
762     // check access rights
763     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database);
764     if (CKM_API_SUCCESS != retCode)
765         return retCode;
766
767     // load app key if needed
768     retCode = loadAppKey(handler, firstRow.ownerLabel);
769     if (CKM_API_SUCCESS != retCode)
770         return retCode;
771
772     // decrypt row
773     for (auto &row : rows)
774         objs.push_back(rowToObject(handler, std::move(row), password));
775     // rowToObject may modify db
776     transaction.commit();
777
778     return CKM_API_SUCCESS;
779 }
780
781 int CKMLogic::readDataHelper(
782     bool exportFlag,
783     const Credentials &cred,
784     DataType dataType,
785     const Name &name,
786     const Label &label,
787     const Password &password,
788     Crypto::GObjUPtr &obj)
789 {
790     DataType objDataType;
791     return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType);
792 }
793
794 int CKMLogic::readDataHelper(
795     bool exportFlag,
796     const Credentials &cred,
797     DataType dataType,
798     const Name &name,
799     const Label &label,
800     const Password &password,
801     Crypto::GObjUPtr &obj,
802     DataType& objDataType)
803 {
804     auto &handler = selectDatabase(cred, label);
805
806     // use client label if not explicitly provided
807     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
808
809     if (!isNameValid(name) || !isLabelValid(ownerLabel))
810         return CKM_API_ERROR_INPUT_PARAM;
811
812     // read row
813     DB::Crypto::Transaction transaction(&handler.database);
814     DB::Row row;
815     int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
816     if (CKM_API_SUCCESS != retCode)
817         return retCode;
818
819     objDataType = row.dataType;
820
821     // check access rights
822     retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
823     if (CKM_API_SUCCESS != retCode)
824         return retCode;
825
826     // load app key if needed
827     retCode = loadAppKey(handler, row.ownerLabel);
828     if (CKM_API_SUCCESS != retCode)
829         return retCode;
830
831     obj = rowToObject(handler, std::move(row), password);
832     // rowToObject may modify db
833     transaction.commit();
834
835     return CKM_API_SUCCESS;
836 }
837
838 RawBuffer CKMLogic::getData(
839     const Credentials &cred,
840     int commandId,
841     DataType dataType,
842     const Name &name,
843     const Label &label,
844     const Password &password)
845 {
846     int retCode = CKM_API_SUCCESS;
847     DB::Row row;
848     DataType objDataType;
849
850     try {
851         Crypto::GObjUPtr obj;
852         retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType);
853         if (retCode == CKM_API_SUCCESS)
854             row.data = std::move(obj->getBinary());
855     } catch (const Exc::Exception &e) {
856         retCode = e.error();
857     } catch (const CKM::Exception &e) {
858         LogError("CKM::Exception: " << e.GetMessage());
859         retCode = CKM_API_ERROR_SERVER_ERROR;
860     }
861
862     if (CKM_API_SUCCESS != retCode) {
863         row.data.clear();
864         row.dataType = dataType;
865     }
866
867     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
868                                              commandId,
869                                              retCode,
870                                              static_cast<int>(objDataType),
871                                              row.data);
872     return response.Pop();
873 }
874
875 int CKMLogic::getPKCS12Helper(
876     const Credentials &cred,
877     const Name &name,
878     const Label &label,
879     const Password &keyPassword,
880     const Password &certPassword,
881     KeyShPtr & privKey,
882     CertificateShPtr & cert,
883     CertificateShPtrVector & caChain)
884 {
885     int retCode;
886
887     // read private key (mandatory)
888     Crypto::GObjUPtr keyObj;
889     retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, keyObj);
890     if (retCode != CKM_API_SUCCESS)
891         return retCode;
892     privKey = CKM::Key::create(keyObj->getBinary());
893
894     // read certificate (mandatory)
895     Crypto::GObjUPtr certObj;
896     retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj);
897     if (retCode != CKM_API_SUCCESS)
898         return retCode;
899     cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
900
901     // read CA cert chain (optional)
902     Crypto::GObjUPtrVector caChainObjs;
903     retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs);
904     if (retCode != CKM_API_SUCCESS &&
905        retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
906         return retCode;
907     for (auto &caCertObj : caChainObjs)
908         caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER));
909
910     // if anything found, return it
911     if (privKey || cert || caChain.size() > 0)
912         retCode = CKM_API_SUCCESS;
913
914     return retCode;
915 }
916
917 RawBuffer CKMLogic::getPKCS12(
918         const Credentials &cred,
919         int commandId,
920         const Name &name,
921         const Label &label,
922         const Password &keyPassword,
923         const Password &certPassword)
924 {
925     int retCode = CKM_API_ERROR_UNKNOWN;
926
927     PKCS12Serializable output;
928     try {
929         KeyShPtr privKey;
930         CertificateShPtr cert;
931         CertificateShPtrVector caChain;
932         retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain);
933
934         // prepare response
935         if (retCode == CKM_API_SUCCESS)
936             output = PKCS12Serializable(privKey, cert, caChain);
937     } catch (const Exc::Exception &e) {
938         retCode = e.error();
939     } catch (const CKM::Exception &e) {
940         LogError("CKM::Exception: " << e.GetMessage());
941         retCode = CKM_API_ERROR_SERVER_ERROR;
942     }
943
944     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
945                                              commandId,
946                                              retCode,
947                                              output);
948     return response.Pop();
949 }
950
951 int CKMLogic::getDataListHelper(const Credentials &cred,
952                                 const DataType dataType,
953                                 LabelNameVector &labelNameVector)
954 {
955     int retCode = CKM_API_ERROR_DB_LOCKED;
956     if (0 < m_userDataMap.count(cred.clientUid)) {
957         auto &database = m_userDataMap[cred.clientUid].database;
958
959         try {
960             LabelNameVector tmpVector;
961             if (dataType.isKey()) {
962                 // list all key types
963                 database.listNames(cred.smackLabel,
964                                    tmpVector,
965                                    DataType::DB_KEY_FIRST,
966                                    DataType::DB_KEY_LAST);
967             } else {
968                 // list anything else
969                 database.listNames(cred.smackLabel,
970                                    tmpVector,
971                                    dataType);
972             }
973             labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
974             retCode = CKM_API_SUCCESS;
975         } catch (const CKM::Exception &e) {
976             LogError("Error: " << e.GetMessage());
977             retCode = CKM_API_ERROR_DB_ERROR;
978         } catch (const Exc::Exception &e) {
979             retCode = e.error();
980         }
981     }
982     return retCode;
983 }
984
985 RawBuffer CKMLogic::getDataList(
986     const Credentials &cred,
987     int commandId,
988     DataType dataType)
989 {
990     LabelNameVector systemVector;
991     LabelNameVector userVector;
992     LabelNameVector labelNameVector;
993
994     int retCode = unlockSystemDB();
995     if (CKM_API_SUCCESS == retCode) {
996         // system database
997         if (m_accessControl.isSystemService(cred)) {
998             // lookup system DB
999             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1000                                                     OWNER_ID_SYSTEM),
1001                                         dataType,
1002                                         systemVector);
1003         } else {
1004             // user - lookup system, then client DB
1005             retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
1006                                                     cred.smackLabel),
1007                                         dataType,
1008                                         systemVector);
1009
1010             // private database
1011             if (retCode == CKM_API_SUCCESS) {
1012                 retCode = getDataListHelper(cred,
1013                                             dataType,
1014                                             userVector);
1015             }
1016         }
1017     }
1018
1019     if (retCode == CKM_API_SUCCESS) {
1020         labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end());
1021         labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end());
1022     }
1023
1024     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
1025                                              commandId,
1026                                              retCode,
1027                                              static_cast<int>(dataType),
1028                                              labelNameVector);
1029     return response.Pop();
1030 }
1031
1032 int CKMLogic::importInitialData(
1033     const Name &name,
1034     const Crypto::Data &data,
1035     const Crypto::DataEncryption &enc,
1036     const Policy &policy)
1037 {
1038     try {
1039         // Inital values are always imported with root credentials. Label is not important.
1040         Credentials rootCred(0, "");
1041
1042         auto &handler = selectDatabase(rootCred, OWNER_ID_SYSTEM);
1043
1044         // check if save is possible
1045         DB::Crypto::Transaction transaction(&handler.database);
1046         int retCode = checkSaveConditions(rootCred, handler, name, OWNER_ID_SYSTEM);
1047         if (retCode != CKM_API_SUCCESS)
1048             return retCode;
1049
1050         Crypto::GStore& store =
1051             m_decider.getStore(data.type, policy.extractable, !enc.encryptedKey.empty());
1052
1053         Token token;
1054
1055         if (enc.encryptedKey.empty()) {
1056             Crypto::Data binaryData;
1057             if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1058                 return retCode;
1059             token = store.import(binaryData, m_accessControl.isCCMode() ? "" : policy.password);
1060         } else {
1061             token = store.importEncrypted(data, m_accessControl.isCCMode() ? "" : policy.password, enc);
1062         }
1063
1064         DB::Row row(std::move(token), name, OWNER_ID_SYSTEM, static_cast<int>(policy.extractable));
1065         handler.crypto.encryptRow(row);
1066
1067         handler.database.saveRow(row);
1068         transaction.commit();
1069     } catch (const Exc::Exception &e) {
1070         return e.error();
1071     } catch (const CKM::Exception &e) {
1072         LogError("CKM::Exception: " << e.GetMessage());
1073         return CKM_API_ERROR_SERVER_ERROR;
1074     } catch (const std::exception &e) {
1075         LogError("Std::exception: " << e.what());
1076         return CKM_API_ERROR_SERVER_ERROR;
1077     }
1078
1079     return CKM_API_SUCCESS;
1080 }
1081
1082 int CKMLogic::saveDataHelper(
1083     const Credentials &cred,
1084     const Name &name,
1085     const Label &label,
1086     const Crypto::Data &data,
1087     const PolicySerializable &policy)
1088 {
1089     auto &handler = selectDatabase(cred, label);
1090
1091     // use client label if not explicitly provided
1092     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1093     if (m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1094         return CKM_API_ERROR_INPUT_PARAM;
1095
1096     // check if save is possible
1097     DB::Crypto::Transaction transaction(&handler.database);
1098     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1099     if (retCode != CKM_API_SUCCESS)
1100         return retCode;
1101
1102     // save the data
1103     DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, data, policy);
1104     handler.database.saveRow(encryptedRow);
1105
1106     transaction.commit();
1107     return CKM_API_SUCCESS;
1108 }
1109
1110 int CKMLogic::saveDataHelper(
1111     const Credentials &cred,
1112     const Name &name,
1113     const Label &label,
1114     const PKCS12Serializable &pkcs,
1115     const PolicySerializable &keyPolicy,
1116     const PolicySerializable &certPolicy)
1117 {
1118     auto &handler = selectDatabase(cred, label);
1119
1120     // use client label if not explicitly provided
1121     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1122     if (m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1123         return CKM_API_ERROR_INPUT_PARAM;
1124
1125     // check if save is possible
1126     DB::Crypto::Transaction transaction(&handler.database);
1127     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1128     if (retCode != CKM_API_SUCCESS)
1129         return retCode;
1130
1131     // extract and encrypt the data
1132     DB::RowVector encryptedRows;
1133     retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1134     if (retCode != CKM_API_SUCCESS)
1135         return retCode;
1136
1137     // save the data
1138     handler.database.saveRows(name, ownerLabel, encryptedRows);
1139     transaction.commit();
1140
1141     return CKM_API_SUCCESS;
1142 }
1143
1144
1145 int CKMLogic::createKeyAESHelper(
1146     const Credentials &cred,
1147     const int size,
1148     const Name &name,
1149     const Label &label,
1150     const PolicySerializable &policy)
1151 {
1152     auto &handler = selectDatabase(cred, label);
1153
1154     // use client label if not explicitly provided
1155     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1156     if (m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM) != 0)
1157         return CKM_API_ERROR_INPUT_PARAM;
1158
1159     // check if save is possible
1160     DB::Crypto::Transaction transaction(&handler.database);
1161     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1162     if (retCode != CKM_API_SUCCESS)
1163         return retCode;
1164
1165     // create key in store
1166     CryptoAlgorithm keyGenAlgorithm;
1167     keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1168     keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1169     Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1170
1171     // save the data
1172     DB::Row row(std::move(key), name, ownerLabel, static_cast<int>(policy.extractable));
1173     handler.crypto.encryptRow(row);
1174
1175     handler.database.saveRow(row);
1176
1177     transaction.commit();
1178     return CKM_API_SUCCESS;
1179 }
1180
1181 int CKMLogic::createKeyPairHelper(
1182     const Credentials &cred,
1183     const CryptoAlgorithmSerializable & keyGenParams,
1184     const Name &namePrivate,
1185     const Label &labelPrivate,
1186     const Name &namePublic,
1187     const Label &labelPublic,
1188     const PolicySerializable &policyPrivate,
1189     const PolicySerializable &policyPublic)
1190 {
1191     auto &handlerPriv = selectDatabase(cred, labelPrivate);
1192     auto &handlerPub = selectDatabase(cred, labelPublic);
1193
1194     AlgoType keyType = AlgoType::RSA_GEN;
1195     if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1196         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1197
1198     DataType dt(keyType);
1199     if (!dt.isKey())
1200         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1201
1202     // use client label if not explicitly provided
1203     const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate;
1204     if (m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM) != 0)
1205         return CKM_API_ERROR_INPUT_PARAM;
1206
1207     const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic;
1208     if (m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM) != 0)
1209         return CKM_API_ERROR_INPUT_PARAM;
1210
1211     bool exportable = policyPrivate.extractable || policyPublic.extractable;
1212     TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1213                                                                      policyPrivate.password,
1214                                                                      policyPublic.password);
1215
1216     DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1217     // in case the same database is used for private and public - the second
1218     // transaction will not be executed
1219     DB::Crypto::Transaction transactionPub(&handlerPub.database);
1220
1221     int retCode;
1222     retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1223     if (CKM_API_SUCCESS != retCode)
1224         return retCode;
1225
1226     retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerLabelPub);
1227     if (CKM_API_SUCCESS != retCode)
1228         return retCode;
1229
1230     // save the data
1231     DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast<int>(policyPrivate.extractable));
1232     handlerPriv.crypto.encryptRow(rowPrv);
1233     handlerPriv.database.saveRow(rowPrv);
1234
1235     DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast<int>(policyPublic.extractable));
1236     handlerPub.crypto.encryptRow(rowPub);
1237     handlerPub.database.saveRow(rowPub);
1238
1239     transactionPub.commit();
1240     transactionPriv.commit();
1241     return CKM_API_SUCCESS;
1242 }
1243
1244 RawBuffer CKMLogic::createKeyPair(
1245     const Credentials &cred,
1246     int commandId,
1247     const CryptoAlgorithmSerializable & keyGenParams,
1248     const Name &namePrivate,
1249     const Label &labelPrivate,
1250     const Name &namePublic,
1251     const Label &labelPublic,
1252     const PolicySerializable &policyPrivate,
1253     const PolicySerializable &policyPublic)
1254 {
1255     int retCode = CKM_API_SUCCESS;
1256
1257     try {
1258         retCode = createKeyPairHelper(
1259                         cred,
1260                         keyGenParams,
1261                         namePrivate,
1262                         labelPrivate,
1263                         namePublic,
1264                         labelPublic,
1265                         policyPrivate,
1266                         policyPublic);
1267     } catch(const Exc::Exception &e) {
1268         retCode = e.error();
1269     } catch (const CKM::Exception &e) {
1270         LogError("CKM::Exception: " << e.GetMessage());
1271         retCode = CKM_API_ERROR_SERVER_ERROR;
1272     }
1273
1274     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1275                                     commandId, retCode).Pop();
1276 }
1277
1278 RawBuffer CKMLogic::createKeyAES(
1279     const Credentials &cred,
1280     int commandId,
1281     const int size,
1282     const Name &name,
1283     const Label &label,
1284     const PolicySerializable &policy)
1285 {
1286     int retCode = CKM_API_SUCCESS;
1287
1288     try {
1289         retCode = createKeyAESHelper(cred, size, name, label, policy);
1290     } catch (const Exc::Exception &e) {
1291         retCode = e.error();
1292     } catch (std::invalid_argument &e) {
1293         LogDebug("invalid argument error: " << e.what());
1294         retCode = CKM_API_ERROR_INPUT_PARAM;
1295     } catch (const CKM::Exception &e) {
1296         LogError("CKM::Exception: " << e.GetMessage());
1297         retCode = CKM_API_ERROR_SERVER_ERROR;
1298     }
1299
1300     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1301                                     commandId, retCode).Pop();
1302 }
1303
1304 int CKMLogic::readCertificateHelper(
1305         const Credentials &cred,
1306         const LabelNameVector &labelNameVector,
1307         CertificateImplVector &certVector)
1308 {
1309     DB::Row row;
1310     for (auto &i: labelNameVector) {
1311         // certificates can't be protected with custom user password
1312         Crypto::GObjUPtr obj;
1313         int ec;
1314         ec = readDataHelper(true,
1315                             cred,
1316                             DataType::CERTIFICATE,
1317                             i.second,
1318                             i.first,
1319                             Password(),
1320                             obj);
1321         if (ec != CKM_API_SUCCESS)
1322             return ec;
1323
1324         certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1325
1326         // try to read chain certificates (if present)
1327         Crypto::GObjUPtrVector caChainObjs;
1328         ec = readDataHelper(true,
1329                             cred,
1330                             DataType::DB_CHAIN_FIRST,
1331                             i.second,
1332                             i.first,
1333                             CKM::Password(),
1334                             caChainObjs);
1335         if (ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1336             return ec;
1337         for (auto &caCertObj : caChainObjs)
1338             certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1339     }
1340     return CKM_API_SUCCESS;
1341 }
1342
1343 int CKMLogic::getCertificateChainHelper(
1344         const CertificateImpl &cert,
1345         const RawBufferVector &untrustedCertificates,
1346         const RawBufferVector &trustedCertificates,
1347         bool useTrustedSystemCertificates,
1348         RawBufferVector &chainRawVector)
1349 {
1350     CertificateImplVector untrustedCertVector;
1351     CertificateImplVector trustedCertVector;
1352     CertificateImplVector chainVector;
1353
1354     if (cert.empty())
1355         return CKM_API_ERROR_INPUT_PARAM;
1356
1357     for (auto &e: untrustedCertificates) {
1358         CertificateImpl c(e, DataFormat::FORM_DER);
1359         if (c.empty())
1360             return CKM_API_ERROR_INPUT_PARAM;
1361         untrustedCertVector.push_back(std::move(c));
1362     }
1363     for (auto &e: trustedCertificates) {
1364         CertificateImpl c(e, DataFormat::FORM_DER);
1365         if (c.empty())
1366             return CKM_API_ERROR_INPUT_PARAM;
1367         trustedCertVector.push_back(std::move(c));
1368     }
1369
1370     CertificateStore store;
1371     int retCode = store.verifyCertificate(cert,
1372                                           untrustedCertVector,
1373                                           trustedCertVector,
1374                                           useTrustedSystemCertificates,
1375                                           m_accessControl.isCCMode(),
1376                                           chainVector);
1377     if (retCode != CKM_API_SUCCESS)
1378         return retCode;
1379
1380     for (auto &e : chainVector)
1381         chainRawVector.push_back(e.getDER());
1382     return CKM_API_SUCCESS;
1383 }
1384
1385 int CKMLogic::getCertificateChainHelper(
1386         const Credentials &cred,
1387         const CertificateImpl &cert,
1388         const LabelNameVector &untrusted,
1389         const LabelNameVector &trusted,
1390         bool useTrustedSystemCertificates,
1391         RawBufferVector &chainRawVector)
1392 {
1393     CertificateImplVector untrustedCertVector;
1394     CertificateImplVector trustedCertVector;
1395     CertificateImplVector chainVector;
1396     DB::Row row;
1397
1398     if (cert.empty())
1399         return CKM_API_ERROR_INPUT_PARAM;
1400
1401     int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1402     if (retCode != CKM_API_SUCCESS)
1403         return retCode;
1404     retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1405     if (retCode != CKM_API_SUCCESS)
1406         return retCode;
1407
1408     CertificateStore store;
1409     retCode = store.verifyCertificate(cert,
1410                                       untrustedCertVector,
1411                                       trustedCertVector,
1412                                       useTrustedSystemCertificates,
1413                                       m_accessControl.isCCMode(),
1414                                       chainVector);
1415     if (retCode != CKM_API_SUCCESS)
1416         return retCode;
1417
1418     for (auto &i: chainVector)
1419         chainRawVector.push_back(i.getDER());
1420
1421     return CKM_API_SUCCESS;
1422 }
1423
1424 RawBuffer CKMLogic::getCertificateChain(
1425     const Credentials & /*cred*/,
1426     int commandId,
1427     const RawBuffer &certificate,
1428     const RawBufferVector &untrustedCertificates,
1429     const RawBufferVector &trustedCertificates,
1430     bool useTrustedSystemCertificates)
1431 {
1432     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1433     RawBufferVector chainRawVector;
1434     int retCode = CKM_API_ERROR_UNKNOWN;
1435     try {
1436         retCode = getCertificateChainHelper(cert,
1437                                             untrustedCertificates,
1438                                             trustedCertificates,
1439                                             useTrustedSystemCertificates,
1440                                             chainRawVector);
1441     } catch (const Exc::Exception &e) {
1442         retCode = e.error();
1443     } catch (const std::exception& e) {
1444         LogError("STD exception " << e.what());
1445         retCode = CKM_API_ERROR_SERVER_ERROR;
1446     } catch (...) {
1447         LogError("Unknown error.");
1448     }
1449
1450     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1451                                              commandId,
1452                                              retCode,
1453                                              chainRawVector);
1454     return response.Pop();
1455 }
1456
1457 RawBuffer CKMLogic::getCertificateChain(
1458     const Credentials &cred,
1459     int commandId,
1460     const RawBuffer &certificate,
1461     const LabelNameVector &untrustedCertificates,
1462     const LabelNameVector &trustedCertificates,
1463     bool useTrustedSystemCertificates)
1464 {
1465     int retCode = CKM_API_ERROR_UNKNOWN;
1466     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1467     RawBufferVector chainRawVector;
1468     try {
1469         retCode = getCertificateChainHelper(cred,
1470                                             cert,
1471                                             untrustedCertificates,
1472                                             trustedCertificates,
1473                                             useTrustedSystemCertificates,
1474                                             chainRawVector);
1475     } catch (const Exc::Exception &e) {
1476         retCode = e.error();
1477     } catch (const std::exception& e) {
1478         LogError("STD exception " << e.what());
1479         retCode = CKM_API_ERROR_SERVER_ERROR;
1480     } catch (...) {
1481         LogError("Unknown error.");
1482     }
1483
1484     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1485                                              commandId,
1486                                              retCode,
1487                                              chainRawVector);
1488     return response.Pop();
1489 }
1490
1491 RawBuffer CKMLogic::createSignature(
1492         const Credentials &cred,
1493         int commandId,
1494         const Name &privateKeyName,
1495         const Label & ownerLabel,
1496         const Password &password,           // password for private_key
1497         const RawBuffer &message,
1498         const CryptoAlgorithm &cryptoAlg)
1499 {
1500     DB::Row row;
1501     RawBuffer signature;
1502
1503     int retCode = CKM_API_SUCCESS;
1504
1505     try {
1506         Crypto::GObjUPtr obj;
1507         retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj);
1508         if (retCode == CKM_API_SUCCESS)
1509             signature = obj->sign(cryptoAlg, message);
1510     } catch (const Exc::Exception &e) {
1511         retCode = e.error();
1512     } catch (const CKM::Exception &e) {
1513         LogError("Unknown CKM::Exception: " << e.GetMessage());
1514         retCode = CKM_API_ERROR_SERVER_ERROR;
1515     } catch (const std::exception &e) {
1516         LogError("STD exception " << e.what());
1517         retCode = CKM_API_ERROR_SERVER_ERROR;
1518     }
1519
1520     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1521                                              commandId,
1522                                              retCode,
1523                                              signature);
1524     return response.Pop();
1525 }
1526
1527 RawBuffer CKMLogic::verifySignature(
1528         const Credentials &cred,
1529         int commandId,
1530         const Name &publicKeyOrCertName,
1531         const Label & ownerLabel,
1532         const Password &password,           // password for public_key (optional)
1533         const RawBuffer &message,
1534         const RawBuffer &signature,
1535         const CryptoAlgorithm &params)
1536 {
1537     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1538
1539     try {
1540         DB::Row row;
1541
1542         // try certificate first - looking for a public key.
1543         // in case of PKCS, pub key from certificate will be found first
1544         // rather than private key from the same PKCS.
1545         Crypto::GObjUPtr obj;
1546         retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj);
1547         if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1548             retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj);
1549
1550         if (retCode == CKM_API_SUCCESS)
1551             retCode = obj->verify(params, message, signature);
1552     } catch (const Exc::Exception &e) {
1553         retCode = e.error();
1554     } catch (const CKM::Exception &e) {
1555         LogError("Unknown CKM::Exception: " << e.GetMessage());
1556         retCode = CKM_API_ERROR_SERVER_ERROR;
1557     }
1558
1559     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1560                                              commandId,
1561                                              retCode);
1562     return response.Pop();
1563 }
1564
1565 int CKMLogic::setPermissionHelper(
1566         const Credentials &cred,                // who's the client
1567         const Name &name,
1568         const Label &label,                     // who's the owner
1569         const Label &accessorLabel,             // who will get the access
1570         const PermissionMask permissionMask)
1571 {
1572     auto &handler = selectDatabase(cred, label);
1573
1574     // we don't know the client
1575     if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1576         return CKM_API_ERROR_INPUT_PARAM;
1577
1578     // use client label if not explicitly provided
1579     const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1580
1581     // verify name and label are correct
1582     if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1583         return CKM_API_ERROR_INPUT_PARAM;
1584
1585     // currently we don't support modification of owner's permissions to his own rows
1586     if (ownerLabel == accessorLabel)
1587         return CKM_API_ERROR_INPUT_PARAM;
1588
1589     // system database does not support write/remove permissions
1590     if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1591         (permissionMask & Permission::REMOVE))
1592         return CKM_API_ERROR_INPUT_PARAM;
1593
1594     // can the client modify permissions to owner's row?
1595     int retCode = m_accessControl.canModify(cred, ownerLabel);
1596     if (retCode != CKM_API_SUCCESS)
1597         return retCode;
1598
1599     DB::Crypto::Transaction transaction(&handler.database);
1600
1601     if (!handler.database.isNameLabelPresent(name, ownerLabel))
1602         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1603
1604     // removing non-existing permissions: fail
1605     if (permissionMask == Permission::NONE) {
1606         if (!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1607             return CKM_API_ERROR_INPUT_PARAM;
1608     }
1609
1610     // set permissions to the row owned by ownerLabel for accessorLabel
1611     handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1612     transaction.commit();
1613
1614     return CKM_API_SUCCESS;
1615 }
1616
1617 RawBuffer CKMLogic::setPermission(
1618         const Credentials &cred,
1619         const int command,
1620         const int msgID,
1621         const Name &name,
1622         const Label &label,
1623         const Label &accessorLabel,
1624         const PermissionMask permissionMask)
1625 {
1626     int retCode;
1627     try {
1628         retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1629     } catch (const Exc::Exception &e) {
1630         retCode = e.error();
1631     } catch (const CKM::Exception &e) {
1632         LogError("Error: " << e.GetMessage());
1633         retCode = CKM_API_ERROR_DB_ERROR;
1634     }
1635
1636     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1637 }
1638
1639 int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel)
1640 {
1641     if (!handle.crypto.haveKey(appLabel)) {
1642         RawBuffer key;
1643         auto key_optional = handle.database.getKey(appLabel);
1644         if (!key_optional) {
1645             LogError("No key for given label in database");
1646             return CKM_API_ERROR_DB_ERROR;
1647         }
1648         key = *key_optional;
1649         key = handle.keyProvider.getPureDEK(key);
1650         handle.crypto.pushKey(appLabel, key);
1651     }
1652     return CKM_API_SUCCESS;
1653 }
1654
1655 } // namespace CKM
1656