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