Fix implementation of sw-backend.
[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     try {
1102         // Inital values are always imported with root credentials. Label is not important.
1103         Credentials rootCred(0,"");
1104
1105         auto &handler = selectDatabase(rootCred, OWNER_ID_SYSTEM);
1106
1107         // check if save is possible
1108         DB::Crypto::Transaction transaction(&handler.database);
1109         int retCode = checkSaveConditions(rootCred, handler, name, OWNER_ID_SYSTEM);
1110         if(retCode != CKM_API_SUCCESS)
1111             return retCode;
1112
1113         Crypto::GStore& store =
1114           m_decider.getStore(data.type, policy.extractable, !enc.encryptedKey.empty());
1115
1116         Token token;
1117
1118         if (enc.encryptedKey.empty()) {
1119             Crypto::Data binaryData;
1120             if (CKM_API_SUCCESS != (retCode = toBinaryData(data, binaryData)))
1121                 return retCode;
1122             token = store.import(binaryData, m_accessControl.isCCMode() ? "" : policy.password);
1123         } else {
1124             token = store.importEncrypted(data, m_accessControl.isCCMode() ? "" : policy.password, enc);
1125         }
1126
1127         DB::Row row(std::move(token), name, OWNER_ID_SYSTEM, static_cast<int>(policy.extractable));
1128         handler.crypto.encryptRow(row);
1129
1130         handler.database.saveRow(row);
1131         transaction.commit();
1132     } catch (const Exc::Exception &e) {
1133         return e.error();
1134     } catch (const CKM::Exception &e) {
1135         LogError("CKM::Exception: " << e.GetMessage());
1136         return CKM_API_ERROR_SERVER_ERROR;
1137     } catch (const std::exception &e) {
1138         LogError("Std::exception: " << e.what());
1139         return CKM_API_ERROR_SERVER_ERROR;
1140     }
1141
1142     return CKM_API_SUCCESS;
1143 }
1144
1145 int CKMLogic::saveDataHelper(
1146     const Credentials &cred,
1147     const Name &name,
1148     const Label &label,
1149     const Crypto::Data &data,
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     // save the data
1166     DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, data, policy);
1167     handler.database.saveRow(encryptedRow);
1168
1169     transaction.commit();
1170     return CKM_API_SUCCESS;
1171 }
1172
1173 int CKMLogic::saveDataHelper(
1174     const Credentials &cred,
1175     const Name &name,
1176     const Label &label,
1177     const PKCS12Serializable &pkcs,
1178     const PolicySerializable &keyPolicy,
1179     const PolicySerializable &certPolicy)
1180 {
1181     auto &handler = selectDatabase(cred, label);
1182
1183     // use client label if not explicitly provided
1184     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1185     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1186         return CKM_API_ERROR_INPUT_PARAM;
1187
1188     // check if save is possible
1189     DB::Crypto::Transaction transaction(&handler.database);
1190     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1191     if(retCode != CKM_API_SUCCESS)
1192         return retCode;
1193
1194     // extract and encrypt the data
1195     DB::RowVector encryptedRows;
1196     retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows);
1197     if(retCode != CKM_API_SUCCESS)
1198         return retCode;
1199
1200     // save the data
1201     handler.database.saveRows(name, ownerLabel, encryptedRows);
1202     transaction.commit();
1203
1204     return CKM_API_SUCCESS;
1205 }
1206
1207
1208 int CKMLogic::createKeyAESHelper(
1209     const Credentials &cred,
1210     const int size,
1211     const Name &name,
1212     const Label &label,
1213     const PolicySerializable &policy)
1214 {
1215     auto &handler = selectDatabase(cred, label);
1216
1217     // use client label if not explicitly provided
1218     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
1219     if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
1220         return CKM_API_ERROR_INPUT_PARAM;
1221
1222     // check if save is possible
1223     DB::Crypto::Transaction transaction(&handler.database);
1224     int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
1225     if(retCode != CKM_API_SUCCESS)
1226         return retCode;
1227
1228     // create key in store
1229     CryptoAlgorithm keyGenAlgorithm;
1230     keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
1231     keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
1232     Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
1233
1234     // save the data
1235     DB::Row row(std::move(key), name, ownerLabel, static_cast<int>(policy.extractable));
1236     handler.crypto.encryptRow(row);
1237
1238     handler.database.saveRow(row);
1239
1240     transaction.commit();
1241     return CKM_API_SUCCESS;
1242 }
1243
1244 int CKMLogic::createKeyPairHelper(
1245     const Credentials &cred,
1246     const CryptoAlgorithmSerializable & keyGenParams,
1247     const Name &namePrivate,
1248     const Label &labelPrivate,
1249     const Name &namePublic,
1250     const Label &labelPublic,
1251     const PolicySerializable &policyPrivate,
1252     const PolicySerializable &policyPublic)
1253 {
1254     auto &handlerPriv = selectDatabase(cred, labelPrivate);
1255     auto &handlerPub = selectDatabase(cred, labelPublic);
1256
1257     AlgoType keyType = AlgoType::RSA_GEN;
1258     if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
1259         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
1260     DataType dt(keyType);
1261     if(!dt.isKey())
1262         ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
1263
1264     // use client label if not explicitly provided
1265     const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate;
1266     if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0)
1267         return CKM_API_ERROR_INPUT_PARAM;
1268     const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic;
1269     if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0)
1270         return CKM_API_ERROR_INPUT_PARAM;
1271
1272     bool exportable = policyPrivate.extractable || policyPublic.extractable;
1273     TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
1274                                                                      policyPrivate.password,
1275                                                                      policyPublic.password);
1276
1277     DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
1278     // in case the same database is used for private and public - the second
1279     // transaction will not be executed
1280     DB::Crypto::Transaction transactionPub(&handlerPub.database);
1281
1282     int retCode;
1283     retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
1284     if (CKM_API_SUCCESS != retCode)
1285         return retCode;
1286
1287     retCode = checkSaveConditions(cred, handlerPub, namePublic, ownerLabelPub);
1288     if (CKM_API_SUCCESS != retCode)
1289         return retCode;
1290
1291     // save the data
1292     DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast<int>(policyPrivate.extractable));
1293     handlerPriv.crypto.encryptRow(rowPrv);
1294     handlerPriv.database.saveRow(rowPrv);
1295
1296     DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast<int>(policyPublic.extractable));
1297     handlerPub.crypto.encryptRow(rowPub);
1298     handlerPub.database.saveRow(rowPub);
1299
1300     transactionPub.commit();
1301     transactionPriv.commit();
1302     return CKM_API_SUCCESS;
1303 }
1304
1305 RawBuffer CKMLogic::createKeyPair(
1306     const Credentials &cred,
1307     int commandId,
1308     const CryptoAlgorithmSerializable & keyGenParams,
1309     const Name &namePrivate,
1310     const Label &labelPrivate,
1311     const Name &namePublic,
1312     const Label &labelPublic,
1313     const PolicySerializable &policyPrivate,
1314     const PolicySerializable &policyPublic)
1315 {
1316     int retCode = CKM_API_SUCCESS;
1317
1318     try {
1319         retCode = createKeyPairHelper(
1320                         cred,
1321                         keyGenParams,
1322                         namePrivate,
1323                         labelPrivate,
1324                         namePublic,
1325                         labelPublic,
1326                         policyPrivate,
1327                         policyPublic);
1328     } catch(const Exc::Exception &e) {
1329         retCode = e.error();
1330     } catch (DB::Crypto::Exception::TransactionError &e) {
1331         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1332         retCode = CKM_API_ERROR_DB_ERROR;
1333     } catch (DB::Crypto::Exception::InternalError &e) {
1334         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1335         retCode = CKM_API_ERROR_DB_ERROR;
1336     } catch (const CKM::Exception &e) {
1337         LogError("CKM::Exception: " << e.GetMessage());
1338         retCode = CKM_API_ERROR_SERVER_ERROR;
1339     }
1340
1341     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
1342                                     commandId, retCode).Pop();
1343 }
1344
1345 RawBuffer CKMLogic::createKeyAES(
1346     const Credentials &cred,
1347     int commandId,
1348     const int size,
1349     const Name &name,
1350     const Label &label,
1351     const PolicySerializable &policy)
1352 {
1353     int retCode = CKM_API_SUCCESS;
1354
1355     try {
1356         retCode = createKeyAESHelper(cred, size, name, label, policy);
1357     } catch (const Exc::Exception &e) {
1358         retCode = e.error();
1359     } catch (std::invalid_argument &e) {
1360         LogDebug("invalid argument error: " << e.what());
1361         retCode = CKM_API_ERROR_INPUT_PARAM;
1362     } catch (DB::Crypto::Exception::TransactionError &e) {
1363         LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
1364         retCode = CKM_API_ERROR_DB_ERROR;
1365     } catch (DB::Crypto::Exception::InternalError &e) {
1366         LogDebug("DB::Crypto internal error: " << e.GetMessage());
1367         retCode = CKM_API_ERROR_DB_ERROR;
1368     } catch (const CKM::Exception &e) {
1369         LogError("CKM::Exception: " << e.GetMessage());
1370         retCode = CKM_API_ERROR_SERVER_ERROR;
1371     }
1372
1373     return MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_KEY_AES),
1374                                     commandId, retCode).Pop();
1375 }
1376
1377 int CKMLogic::readCertificateHelper(
1378         const Credentials &cred,
1379         const LabelNameVector &labelNameVector,
1380         CertificateImplVector &certVector)
1381 {
1382     DB::Row row;
1383     for (auto &i: labelNameVector) {
1384         // certificates can't be protected with custom user password
1385         Crypto::GObjUPtr obj;
1386         int ec;
1387         ec = readDataHelper(true,
1388                             cred,
1389                             DataType::CERTIFICATE,
1390                             i.second,
1391                             i.first,
1392                             Password(),
1393                             obj);
1394         if (ec != CKM_API_SUCCESS)
1395             return ec;
1396
1397         certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
1398
1399         // try to read chain certificates (if present)
1400         Crypto::GObjUPtrVector caChainObjs;
1401         ec = readDataHelper(true,
1402                             cred,
1403                             DataType::DB_CHAIN_FIRST,
1404                             i.second,
1405                             i.first,
1406                             CKM::Password(),
1407                             caChainObjs);
1408         if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
1409             return ec;
1410         for(auto &caCertObj : caChainObjs)
1411             certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
1412     }
1413     return CKM_API_SUCCESS;
1414 }
1415
1416 int CKMLogic::getCertificateChainHelper(
1417         const CertificateImpl &cert,
1418         const RawBufferVector &untrustedCertificates,
1419         const RawBufferVector &trustedCertificates,
1420         bool useTrustedSystemCertificates,
1421         RawBufferVector &chainRawVector)
1422 {
1423     CertificateImplVector untrustedCertVector;
1424     CertificateImplVector trustedCertVector;
1425     CertificateImplVector chainVector;
1426
1427     if (cert.empty())
1428         return CKM_API_ERROR_INPUT_PARAM;
1429
1430     for (auto &e: untrustedCertificates) {
1431         CertificateImpl c(e, DataFormat::FORM_DER);
1432         if(c.empty())
1433             return CKM_API_ERROR_INPUT_PARAM;
1434         untrustedCertVector.push_back(std::move(c));
1435     }
1436     for (auto &e: trustedCertificates) {
1437         CertificateImpl c(e, DataFormat::FORM_DER);
1438         if(c.empty())
1439             return CKM_API_ERROR_INPUT_PARAM;
1440         trustedCertVector.push_back(std::move(c));
1441     }
1442
1443     CertificateStore store;
1444     int retCode = store.verifyCertificate(cert,
1445                                           untrustedCertVector,
1446                                           trustedCertVector,
1447                                           useTrustedSystemCertificates,
1448                                           m_accessControl.isCCMode(),
1449                                           chainVector);
1450     if (retCode != CKM_API_SUCCESS)
1451         return retCode;
1452
1453     for (auto &e : chainVector)
1454         chainRawVector.push_back(e.getDER());
1455     return CKM_API_SUCCESS;
1456 }
1457
1458 int CKMLogic::getCertificateChainHelper(
1459         const Credentials &cred,
1460         const CertificateImpl &cert,
1461         const LabelNameVector &untrusted,
1462         const LabelNameVector &trusted,
1463         bool useTrustedSystemCertificates,
1464         RawBufferVector &chainRawVector)
1465 {
1466     CertificateImplVector untrustedCertVector;
1467     CertificateImplVector trustedCertVector;
1468     CertificateImplVector chainVector;
1469     DB::Row row;
1470
1471     if (cert.empty())
1472         return CKM_API_ERROR_INPUT_PARAM;
1473
1474     int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector);
1475     if (retCode != CKM_API_SUCCESS)
1476         return retCode;
1477     retCode = readCertificateHelper(cred, trusted, trustedCertVector);
1478     if (retCode != CKM_API_SUCCESS)
1479         return retCode;
1480
1481     CertificateStore store;
1482     retCode = store.verifyCertificate(cert,
1483                                       untrustedCertVector,
1484                                       trustedCertVector,
1485                                       useTrustedSystemCertificates,
1486                                       m_accessControl.isCCMode(),
1487                                       chainVector);
1488     if (retCode != CKM_API_SUCCESS)
1489         return retCode;
1490
1491     for (auto &i: chainVector)
1492         chainRawVector.push_back(i.getDER());
1493
1494     return CKM_API_SUCCESS;
1495 }
1496
1497 RawBuffer CKMLogic::getCertificateChain(
1498     const Credentials & /*cred*/,
1499     int commandId,
1500     const RawBuffer &certificate,
1501     const RawBufferVector &untrustedCertificates,
1502     const RawBufferVector &trustedCertificates,
1503     bool useTrustedSystemCertificates)
1504 {
1505     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1506     RawBufferVector chainRawVector;
1507     int retCode = CKM_API_ERROR_UNKNOWN;
1508     try {
1509         retCode = getCertificateChainHelper(cert,
1510                                             untrustedCertificates,
1511                                             trustedCertificates,
1512                                             useTrustedSystemCertificates,
1513                                             chainRawVector);
1514     } catch (const Exc::Exception &e) {
1515         retCode = e.error();
1516     } catch (const DB::Crypto::Exception::Base &e) {
1517         LogError("DB::Crypto failed with message: " << e.GetMessage());
1518         retCode = CKM_API_ERROR_DB_ERROR;
1519     } catch (const std::exception& e) {
1520         LogError("STD exception " << e.what());
1521         retCode = CKM_API_ERROR_SERVER_ERROR;
1522     } catch (...) {
1523         LogError("Unknown error.");
1524     }
1525
1526     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
1527                                              commandId,
1528                                              retCode,
1529                                              chainRawVector);
1530     return response.Pop();
1531 }
1532
1533 RawBuffer CKMLogic::getCertificateChain(
1534     const Credentials &cred,
1535     int commandId,
1536     const RawBuffer &certificate,
1537     const LabelNameVector &untrustedCertificates,
1538     const LabelNameVector &trustedCertificates,
1539     bool useTrustedSystemCertificates)
1540 {
1541     int retCode = CKM_API_ERROR_UNKNOWN;
1542     CertificateImpl cert(certificate, DataFormat::FORM_DER);
1543     RawBufferVector chainRawVector;
1544     try {
1545         retCode = getCertificateChainHelper(cred,
1546                                             cert,
1547                                             untrustedCertificates,
1548                                             trustedCertificates,
1549                                             useTrustedSystemCertificates,
1550                                             chainRawVector);
1551     } catch (const DB::Crypto::Exception::Base &e) {
1552         LogError("DB::Crypto failed with message: " << e.GetMessage());
1553         retCode = CKM_API_ERROR_DB_ERROR;
1554     } catch (const Exc::Exception &e) {
1555         retCode = e.error();
1556     } catch (const std::exception& e) {
1557         LogError("STD exception " << e.what());
1558         retCode = CKM_API_ERROR_SERVER_ERROR;
1559     } catch (...) {
1560         LogError("Unknown error.");
1561     }
1562
1563     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
1564                                              commandId,
1565                                              retCode,
1566                                              chainRawVector);
1567     return response.Pop();
1568 }
1569
1570 RawBuffer CKMLogic::createSignature(
1571         const Credentials &cred,
1572         int commandId,
1573         const Name &privateKeyName,
1574         const Label & ownerLabel,
1575         const Password &password,           // password for private_key
1576         const RawBuffer &message,
1577         const CryptoAlgorithm &cryptoAlg)
1578 {
1579     DB::Row row;
1580     RawBuffer signature;
1581
1582     int retCode = CKM_API_SUCCESS;
1583
1584     try {
1585         Crypto::GObjUPtr obj;
1586         retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj);
1587         if(retCode == CKM_API_SUCCESS) {
1588             signature = obj->sign(cryptoAlg, message);
1589         }
1590     } catch (const DB::Crypto::Exception::Base &e) {
1591         LogError("DB::Crypto failed with message: " << e.GetMessage());
1592         retCode = CKM_API_ERROR_DB_ERROR;
1593     } catch (const Exc::Exception &e) {
1594         retCode = e.error();
1595     } catch (const CKM::Exception &e) {
1596         LogError("Unknown CKM::Exception: " << e.GetMessage());
1597         retCode = CKM_API_ERROR_SERVER_ERROR;
1598     }
1599
1600     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
1601                                              commandId,
1602                                              retCode,
1603                                              signature);
1604     return response.Pop();
1605 }
1606
1607 RawBuffer CKMLogic::verifySignature(
1608         const Credentials &cred,
1609         int commandId,
1610         const Name &publicKeyOrCertName,
1611         const Label & ownerLabel,
1612         const Password &password,           // password for public_key (optional)
1613         const RawBuffer &message,
1614         const RawBuffer &signature,
1615         const CryptoAlgorithm &params)
1616 {
1617     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
1618
1619     try {
1620         DB::Row row;
1621
1622         // try certificate first - looking for a public key.
1623         // in case of PKCS, pub key from certificate will be found first
1624         // rather than private key from the same PKCS.
1625         Crypto::GObjUPtr obj;
1626         retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj);
1627         if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
1628             retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj);
1629         }
1630
1631         if (retCode == CKM_API_SUCCESS) {
1632             retCode = obj->verify(params, message, signature);
1633         }
1634     } catch (const Exc::Exception &e) {
1635         retCode = e.error();
1636     } catch (const DB::Crypto::Exception::Base &e) {
1637         LogError("DB::Crypto failed with message: " << e.GetMessage());
1638         retCode = CKM_API_ERROR_DB_ERROR;
1639     } catch (const CKM::Exception &e) {
1640         LogError("Unknown CKM::Exception: " << e.GetMessage());
1641         retCode = CKM_API_ERROR_SERVER_ERROR;
1642     }
1643
1644     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
1645                                              commandId,
1646                                              retCode);
1647     return response.Pop();
1648 }
1649
1650 int CKMLogic::setPermissionHelper(
1651         const Credentials &cred,                // who's the client
1652         const Name &name,
1653         const Label &label,                     // who's the owner
1654         const Label &accessorLabel,             // who will get the access
1655         const PermissionMask permissionMask)
1656 {
1657     auto &handler = selectDatabase(cred, label);
1658
1659     // we don't know the client
1660     if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel))
1661         return CKM_API_ERROR_INPUT_PARAM;
1662
1663     // use client label if not explicitly provided
1664     const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
1665
1666     // verify name and label are correct
1667     if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel))
1668         return CKM_API_ERROR_INPUT_PARAM;
1669
1670     // currently we don't support modification of owner's permissions to his own rows
1671     if (ownerLabel==accessorLabel)
1672         return CKM_API_ERROR_INPUT_PARAM;
1673
1674     // system database does not support write/remove permissions
1675     if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) &&
1676         (permissionMask & Permission::REMOVE))
1677         return CKM_API_ERROR_INPUT_PARAM;
1678
1679     // can the client modify permissions to owner's row?
1680     int retCode = m_accessControl.canModify(cred, ownerLabel);
1681     if(retCode != CKM_API_SUCCESS)
1682         return retCode;
1683
1684     DB::Crypto::Transaction transaction(&handler.database);
1685
1686     if( !handler.database.isNameLabelPresent(name, ownerLabel) )
1687         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
1688
1689     // removing non-existing permissions: fail
1690     if(permissionMask == Permission::NONE)
1691     {
1692         if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
1693             return CKM_API_ERROR_INPUT_PARAM;
1694     }
1695
1696     // set permissions to the row owned by ownerLabel for accessorLabel
1697     handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
1698     transaction.commit();
1699
1700     return CKM_API_SUCCESS;
1701 }
1702
1703 RawBuffer CKMLogic::setPermission(
1704         const Credentials &cred,
1705         const int command,
1706         const int msgID,
1707         const Name &name,
1708         const Label &label,
1709         const Label &accessorLabel,
1710         const PermissionMask permissionMask)
1711 {
1712     int retCode;
1713     Try {
1714         retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
1715     } catch (const Exc::Exception &e) {
1716         retCode = e.error();
1717     } Catch (CKM::Exception) {
1718         LogError("Error in set row!");
1719         retCode = CKM_API_ERROR_DB_ERROR;
1720     }
1721
1722     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1723 }
1724
1725 int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel)
1726 {
1727     if (!handle.crypto.haveKey(appLabel)) {
1728         RawBuffer key;
1729         auto key_optional = handle.database.getKey(appLabel);
1730         if(!key_optional) {
1731             LogError("No key for given label in database");
1732             return CKM_API_ERROR_DB_ERROR;
1733         }
1734         key = *key_optional;
1735         key = handle.keyProvider.getPureDEK(key);
1736         handle.crypto.pushKey(appLabel, key);
1737     }
1738     return CKM_API_SUCCESS;
1739 }
1740
1741 } // namespace CKM
1742