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