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