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