Split alias at server side into pair name and label.
[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 <vconf/vconf.h>
23 #include <dpl/serialization.h>
24 #include <dpl/log/log.h>
25 #include <ckm/ckm-error.h>
26 #include <ckm/ckm-type.h>
27 #include <key-provider.h>
28 #include <file-system.h>
29 #include <CryptoService.h>
30 #include <ckm-logic.h>
31 #include <key-impl.h>
32
33 #ifndef VCONFKEY_SECURITY_MDPP_STATE
34 #define VCONFKEY_SECURITY_MDPP_STATE = "file/security_mdpp/security_mdpp_state";
35 #endif
36
37 namespace {
38 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
39
40 const char* const MDPP_MODE_ENFORCING = "Enforcing";
41 const char* const MDPP_MODE_ENABLED = "Enabled";
42
43 } // anonymous namespace
44
45 namespace CKM {
46
47 CKMLogic::CKMLogic() : m_ccMode(false)
48 {
49     int retCode = FileSystem::init();
50     // TODO what can I do when init went wrong? exit(-1) ??
51     if (retCode) {
52         LogError("Fatal error in FileSystem::init()");
53     }
54
55     if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
56         LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
57     }
58
59     updateCCMode_internal();
60 }
61
62 CKMLogic::~CKMLogic(){}
63
64 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) {
65     // TODO try catch for all errors that should be supported by error code
66     int retCode = CKM_API_SUCCESS;
67
68     try {
69         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
70             auto &handle = m_userDataMap[user];
71             FileSystem fs(user);
72             auto wrappedDomainKEK = fs.getDKEK();
73
74             if (wrappedDomainKEK.empty()) {
75                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
76                 fs.saveDKEK(wrappedDomainKEK);
77             }
78
79             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
80
81             auto wrappedDatabaseDEK = fs.getDBDEK();
82
83             if (wrappedDatabaseDEK.empty()) {
84                 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
85                 fs.saveDBDEK(wrappedDatabaseDEK);
86             }
87
88             RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
89             handle.database = DBCrypto(fs.getDBPath(), key);
90             handle.crypto = CryptoLogic();
91
92             // remove data of removed apps during locked state
93             AppLabelVector removedApps = fs.clearRemovedsApps();
94             for(auto& appSmackLabel : removedApps) {
95                 handle.database.deleteKey(appSmackLabel);
96             }
97
98             // TODO wipe key
99         }
100     } catch (const KeyProvider::Exception::PassWordError &e) {
101         LogError("Incorrect Password " << e.GetMessage());
102         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
103     } catch (const KeyProvider::Exception::Base &e) {
104         LogError("Error in KeyProvider " << e.GetMessage());
105         retCode = CKM_API_ERROR_SERVER_ERROR;
106     } catch (const CryptoLogic::Exception::Base &e) {
107         LogError("CryptoLogic error: " << e.GetMessage());
108         retCode = CKM_API_ERROR_SERVER_ERROR;
109     } catch (const CKM::Exception &e) {
110         LogError("CKM::Exception: " << e.GetMessage());
111         retCode = CKM_API_ERROR_SERVER_ERROR;
112     }
113
114     if(retCode != CKM_API_SUCCESS) {
115         // When not successful, UserData in m_userDataMap should be erased.
116         // Because other operations make decision based on the existence of UserData in m_userDataMap.
117         m_userDataMap.erase(user);
118     }
119
120     return MessageBuffer::Serialize(retCode).Pop();
121 }
122
123 void CKMLogic::updateCCMode_internal() {
124     int fipsModeStatus = 0;
125     int rc = 0;
126     bool newMode;
127
128     char *mdppState = vconf_get_str(VCONFKEY_SECURITY_MDPP_STATE);
129     newMode = ( mdppState && (!strcmp(mdppState, MDPP_MODE_ENABLED) ||
130                               !strcmp(mdppState, MDPP_MODE_ENFORCING)) );
131     if (newMode == m_ccMode)
132         return;
133
134     m_ccMode = newMode;
135
136     fipsModeStatus = FIPS_mode();
137
138     if(m_ccMode) {
139         if(fipsModeStatus == 0) { // If FIPS mode off
140             rc = FIPS_mode_set(1); // Change FIPS_mode from off to on
141             if(rc == 0) {
142                 LogError("Error in FIPS_mode_set function");
143             }
144         }
145     } else {
146         if(fipsModeStatus == 1) { // If FIPS mode on
147             rc = FIPS_mode_set(0); // Change FIPS_mode from on to off
148             if(rc == 0) {
149                 LogError("Error in FIPS_mode_set function");
150             }
151         }
152     }
153 }
154
155 RawBuffer CKMLogic::updateCCMode() {
156     updateCCMode_internal();
157     return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
158 }
159
160 RawBuffer CKMLogic::lockUserKey(uid_t user) {
161     int retCode = CKM_API_SUCCESS;
162     // TODO try catch for all errors that should be supported by error code
163     m_userDataMap.erase(user);
164
165     return MessageBuffer::Serialize(retCode).Pop();
166
167 }
168
169 RawBuffer CKMLogic::removeUserData(uid_t user) {
170     int retCode = CKM_API_SUCCESS;
171     // TODO try catch for all errors that should be supported by error code
172     m_userDataMap.erase(user);
173
174     FileSystem fs(user);
175     fs.removeUserData();
176
177     return MessageBuffer::Serialize(retCode).Pop();
178 }
179
180 RawBuffer CKMLogic::changeUserPassword(
181     uid_t user,
182     const Password &oldPassword,
183     const Password &newPassword)
184 {
185     int retCode = CKM_API_SUCCESS;
186     try {
187         FileSystem fs(user);
188         auto wrappedDomainKEK = fs.getDKEK();
189         if (wrappedDomainKEK.empty()) {
190             retCode = CKM_API_ERROR_BAD_REQUEST;
191         } else {
192             wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
193             fs.saveDKEK(wrappedDomainKEK);
194         }
195     } catch (const KeyProvider::Exception::PassWordError &e) {
196         LogError("Incorrect Password " << e.GetMessage());
197         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
198     } catch (const KeyProvider::Exception::Base &e) {
199         LogError("Error in KeyProvider " << e.GetMessage());
200         retCode = CKM_API_ERROR_SERVER_ERROR;
201     } catch (const CKM::Exception &e) {
202         LogError("CKM::Exception: " << e.GetMessage());
203         retCode = CKM_API_ERROR_SERVER_ERROR;
204     }
205
206     return MessageBuffer::Serialize(retCode).Pop();
207 }
208
209 RawBuffer CKMLogic::resetUserPassword(
210     uid_t user,
211     const Password &newPassword)
212 {
213     int retCode = CKM_API_SUCCESS;
214     // TODO try-catch
215     if (0 == m_userDataMap.count(user)) {
216         retCode = CKM_API_ERROR_BAD_REQUEST;
217     } else {
218         auto &handler = m_userDataMap[user];
219         FileSystem fs(user);
220         fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
221     }
222
223     return MessageBuffer::Serialize(retCode).Pop();
224 }
225
226 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
227     int retCode = CKM_API_SUCCESS;
228
229     try {
230
231         if (smackLabel.empty()) {
232             retCode = CKM_API_ERROR_INPUT_PARAM;
233         } else {
234             UidVector uids = FileSystem::getUIDsFromDBFile();
235             for (auto userId : uids) {
236                 if (0 == m_userDataMap.count(userId)) {
237                     FileSystem fs(userId);
238                     fs.addRemovedApp(smackLabel);
239                 } else {
240                     auto &handle = m_userDataMap[userId];
241                     handle.database.deleteKey(smackLabel);
242                 }
243             }
244         }
245
246     } catch (const DBCrypto::Exception::InternalError &e) {
247         LogError("DBCrypto couldn't remove data: " << e.GetMessage());
248         retCode = CKM_API_ERROR_DB_ERROR;
249     } catch (const DBCrypto::Exception::TransactionError &e) {
250         LogError("DBCrypto transaction failed with message " << e.GetMessage());
251         retCode = CKM_API_ERROR_DB_ERROR;
252     }
253
254     return MessageBuffer::Serialize(retCode).Pop();
255 }
256
257 int CKMLogic::saveDataHelper(
258     Credentials &cred,
259     DBDataType dataType,
260     const Name &name,
261     const RawBuffer &key,
262     const PolicySerializable &policy)
263 {
264     if (0 == m_userDataMap.count(cred.uid))
265         return CKM_API_ERROR_DB_LOCKED;
266
267     // proceed to data save
268     DBRow row = { name, cred.smackLabel,
269          policy.extractable, dataType, DBCMAlgType::NONE,
270          0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
271
272     auto &handler = m_userDataMap[cred.uid];
273     DBCrypto::Transaction transaction(&handler.database);
274     if (!handler.crypto.haveKey(cred.smackLabel)) {
275         RawBuffer key;
276         auto key_optional = handler.database.getKey(cred.smackLabel);
277         if(!key_optional) {
278             LogDebug("No Key in database found. Generating new one for label: "
279                     << cred.smackLabel);
280             key = handler.keyProvider.generateDEK(cred.smackLabel);
281             handler.database.saveKey(cred.smackLabel, key);
282         } else {
283             LogDebug("Key from DB");
284             key = *key_optional;
285         }
286
287         key = handler.keyProvider.getPureDEK(key);
288         handler.crypto.pushKey(cred.smackLabel, key);
289     }
290
291     // Do not encrypt data with password during cc_mode on
292     if(m_ccMode) {
293         handler.crypto.encryptRow("", row);
294     } else {
295         handler.crypto.encryptRow(policy.password, row);
296     }
297
298     handler.database.saveDBRow(row);
299     transaction.commit();
300     return CKM_API_SUCCESS;
301 }
302
303 void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const
304 {
305     // verify the data integrity
306     switch(dataType)
307     {
308         case DBDataType::KEY_RSA_PUBLIC:
309         case DBDataType::KEY_RSA_PRIVATE:
310         case DBDataType::KEY_ECDSA_PUBLIC:
311         case DBDataType::KEY_ECDSA_PRIVATE:
312         case DBDataType::KEY_DSA_PUBLIC:
313         case DBDataType::KEY_DSA_PRIVATE:
314         case DBDataType::KEY_AES:
315         {
316             KeyShPtr output_key = CKM::Key::create(input_data);
317             if(output_key.get() == NULL)
318                 ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data");
319             break;
320         }
321
322         case DBDataType::CERTIFICATE:
323         {
324             CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
325             if(cert.get() == NULL)
326                 ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data");
327             break;
328         }
329
330         // TODO: add here BINARY_DATA verification, i.e: max size etc.
331
332         default: break;
333     }
334 }
335
336 RawBuffer CKMLogic::saveData(
337     Credentials &cred,
338     int commandId,
339     DBDataType dataType,
340     const Name &name,
341     const RawBuffer &key,
342     const PolicySerializable &policy)
343 {
344     int retCode = CKM_API_SUCCESS;
345     try {
346         verifyBinaryData(dataType, key);
347
348         retCode = saveDataHelper(cred, dataType, name, key, policy);
349         LogDebug("SaveDataHelper returned: " << retCode);
350     } catch (const CKMLogic::Exception::InputDataInvalid &e) {
351         LogError("Provided data invalid: " << e.GetMessage());
352         retCode = CKM_API_ERROR_INPUT_PARAM;
353     } catch (const KeyProvider::Exception::Base &e) {
354         LogError("KeyProvider failed with message: " << e.GetMessage());
355         retCode = CKM_API_ERROR_SERVER_ERROR;
356     } catch (const CryptoLogic::Exception::Base &e) {
357         LogError("CryptoLogic failed with message: " << e.GetMessage());
358         retCode = CKM_API_ERROR_SERVER_ERROR;
359     } catch (const DBCrypto::Exception::InternalError &e) {
360         LogError("DBCrypto failed with message: " << e.GetMessage());
361         retCode = CKM_API_ERROR_DB_ERROR;
362     } catch (const DBCrypto::Exception::NameExists &e) {
363         LogError("DBCrypto couldn't save duplicate name");
364         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
365     } catch (const DBCrypto::Exception::TransactionError &e) {
366         LogError("DBCrypto transaction failed with message " << e.GetMessage());
367         retCode = CKM_API_ERROR_DB_ERROR;
368     }
369
370     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
371                                              commandId,
372                                              retCode,
373                                              static_cast<int>(dataType));
374     return response.Pop();
375 }
376
377 RawBuffer CKMLogic::removeData(
378     Credentials &cred,
379     int commandId,
380     DBDataType dataType,
381     const Name &name,
382     const Label &label)
383 {
384     int retCode = CKM_API_SUCCESS;
385
386     if (0 < m_userDataMap.count(cred.uid)) {
387         Try {
388             // use client label if not explicitly provided
389             const Label & ownerLabel = label.empty() ? cred.smackLabel : label;
390
391             // verify name and label are correct
392             if (true == checkNameAndLabelValid(name, ownerLabel))
393             {
394                 auto erased = m_userDataMap[cred.uid].database.deleteDBRow(name, ownerLabel, cred.smackLabel);
395                 // check if the data existed or not
396                 if(!erased) {
397                     LogError("No row for given name and label");
398                     retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
399                 }
400             }
401             else
402             {
403                 LogError("Invalid label or name format");
404                 retCode = CKM_API_ERROR_INPUT_PARAM;
405             }
406         } Catch (DBCrypto::Exception::PermissionDenied) {
407             LogError("Error: not enough permissions!");
408             retCode = CKM_API_ERROR_ACCESS_DENIED;
409         } Catch (CKM::Exception) {
410             LogError("Error in deleting row!");
411             retCode = CKM_API_ERROR_DB_ERROR;
412         }
413     } else {
414         retCode = CKM_API_ERROR_DB_LOCKED;
415     }
416
417     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
418                                              commandId,
419                                              retCode,
420                                              static_cast<int>(dataType));
421     return response.Pop();
422 }
423
424 bool CKMLogic::checkNameAndLabelValid(const Name &name, const Label &label)
425 {
426     // verify the name is valid
427     if(name.find(':') != Label::npos)
428         return false;
429
430     // verify the label is valid
431     if(label.find(LABEL_NAME_SEPARATOR) != Label::npos)
432         return false;
433
434     return true;
435 }
436
437 int CKMLogic::getDataHelper(
438     Credentials &cred,
439     DBDataType dataType,
440     const Name &name,
441     const Label &label,
442     const Password &password,
443     DBRow &row)
444 {
445     if (0 == m_userDataMap.count(cred.uid))
446         return CKM_API_ERROR_DB_LOCKED;
447
448     auto &handler = m_userDataMap[cred.uid];
449
450     // use client label if not explicitly provided
451     const Label ownerLabel = label.empty() ? cred.smackLabel : label;
452
453     // verify name and label are correct
454     if (true != checkNameAndLabelValid(name, ownerLabel))
455         return CKM_API_ERROR_INPUT_PARAM;
456
457     DBCrypto::DBRowOptional row_optional;
458     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA)
459     {
460         row_optional = handler.database.getDBRow(name, ownerLabel, cred.smackLabel, dataType);
461     }
462     else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST)) &&
463              (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
464     {
465         row_optional = handler.database.getKeyDBRow(name, ownerLabel, cred.smackLabel);
466     }
467     else
468     {
469         LogError("Unknown type of requested data" << (int)dataType);
470         return CKM_API_ERROR_BAD_REQUEST;
471     }
472     if(!row_optional) {
473         LogError("No row for given name, label and type");
474         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
475     } else {
476         row = *row_optional;
477     }
478
479     if (!handler.crypto.haveKey(row.smackLabel)) {
480         RawBuffer key;
481         auto key_optional = handler.database.getKey(row.smackLabel);
482         if(!key_optional) {
483             LogError("No key for given label in database");
484             return CKM_API_ERROR_DB_ERROR;
485         }
486         key = *key_optional;
487         key = handler.keyProvider.getPureDEK(key);
488         handler.crypto.pushKey(cred.smackLabel, key);
489     }
490     handler.crypto.decryptRow(password, row);
491
492     return CKM_API_SUCCESS;
493 }
494
495 RawBuffer CKMLogic::getData(
496     Credentials &cred,
497     int commandId,
498     DBDataType dataType,
499     const Name &name,
500     const Label &label,
501     const Password &password)
502 {
503     int retCode = CKM_API_SUCCESS;
504     DBRow row;
505
506     try {
507         retCode = getDataHelper(cred, dataType, name, label, password, row);
508     } catch (const KeyProvider::Exception::Base &e) {
509         LogError("KeyProvider failed with error: " << e.GetMessage());
510         retCode = CKM_API_ERROR_SERVER_ERROR;
511     } catch (const CryptoLogic::Exception::Base &e) {
512         LogError("CryptoLogic failed with message: " << e.GetMessage());
513         retCode = CKM_API_ERROR_SERVER_ERROR;
514     } catch (const DBCrypto::Exception::PermissionDenied &e) {
515         LogError("DBCrypto failed with message: " << e.GetMessage());
516         retCode = CKM_API_ERROR_ACCESS_DENIED;
517     } catch (const DBCrypto::Exception::Base &e) {
518         LogError("DBCrypto failed with message: " << e.GetMessage());
519         retCode = CKM_API_ERROR_DB_ERROR;
520     }
521
522     if (CKM_API_SUCCESS != retCode) {
523         row.data.clear();
524         row.dataType = dataType;
525     }
526
527     if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
528         row.data.clear();
529         retCode = CKM_API_ERROR_NOT_EXPORTABLE;
530     }
531
532     // Prevent extracting private keys during cc-mode on
533     if((m_ccMode) && (row.dataType == DBDataType::KEY_RSA_PRIVATE ||
534                       row.dataType == DBDataType::KEY_ECDSA_PRIVATE ||
535                       row.dataType == DBDataType::KEY_DSA_PRIVATE))
536     {
537         row.data.clear();
538         retCode = CKM_API_ERROR_BAD_REQUEST;
539     }
540
541     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
542                                              commandId,
543                                              retCode,
544                                              static_cast<int>(row.dataType),
545                                              row.data);
546     return response.Pop();
547 }
548
549 RawBuffer CKMLogic::getDataList(
550     Credentials &cred,
551     int commandId,
552     DBDataType dataType)
553 {
554     int retCode = CKM_API_SUCCESS;
555     LabelNameVector labelNameVector;
556
557     if (0 < m_userDataMap.count(cred.uid)) {
558         auto &handler = m_userDataMap[cred.uid];
559         Try {
560             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
561                 handler.database.getNames(cred.smackLabel, dataType, labelNameVector);
562             } else {
563                 handler.database.getKeyNames(cred.smackLabel, labelNameVector);
564             }
565         } Catch (CKM::Exception) {
566             LogError("Failed to get names");
567             retCode = CKM_API_ERROR_DB_ERROR;
568         }
569     } else {
570         retCode = CKM_API_ERROR_DB_LOCKED;
571     }
572
573     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
574                                              commandId,
575                                              retCode,
576                                              static_cast<int>(dataType),
577                                              labelNameVector);
578     return response.Pop();
579 }
580
581
582 int CKMLogic::createKeyPairHelper(
583     Credentials &cred,
584     const KeyType key_type,
585     const int additional_param,
586     const Name &namePrivate,
587     const Name &namePublic,
588     const PolicySerializable &policyPrivate,
589     const PolicySerializable &policyPublic)
590 {
591     if (0 >= m_userDataMap.count(cred.uid))
592         return CKM_API_ERROR_DB_LOCKED;
593
594     auto &handler = m_userDataMap[cred.uid];
595     KeyImpl prv, pub;
596     int retCode;
597     switch(key_type)
598     {
599         case KeyType::KEY_RSA_PUBLIC:
600         case KeyType::KEY_RSA_PRIVATE:
601             retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
602             break;
603
604         case KeyType::KEY_DSA_PUBLIC:
605         case KeyType::KEY_DSA_PRIVATE:
606             retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
607             break;
608
609         case KeyType::KEY_ECDSA_PUBLIC:
610         case KeyType::KEY_ECDSA_PRIVATE:
611             retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
612             break;
613
614         default:
615             return CKM_API_ERROR_INPUT_PARAM;
616     }
617
618     if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
619     {
620         LogDebug("CryptoService error with code: " << retCode);
621         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
622     }
623
624     DBCrypto::Transaction transaction(&handler.database);
625     retCode = saveDataHelper(cred,
626                             toDBDataType(prv.getType()),
627                             namePrivate,
628                             prv.getDER(),
629                             policyPrivate);
630
631     if (CKM_API_SUCCESS != retCode)
632         return retCode;
633
634     retCode = saveDataHelper(cred,
635                             toDBDataType(pub.getType()),
636                             namePublic,
637                             pub.getDER(),
638                             policyPublic);
639
640     if (CKM_API_SUCCESS != retCode)
641         return retCode;
642
643     transaction.commit();
644
645     return retCode;
646 }
647
648 RawBuffer CKMLogic::createKeyPair(
649     Credentials &cred,
650     LogicCommand protocol_cmd,
651     int commandId,
652     const int additional_param,
653     const Name &namePrivate,
654     const Name &namePublic,
655     const PolicySerializable &policyPrivate,
656     const PolicySerializable &policyPublic)
657 {
658     int retCode = CKM_API_SUCCESS;
659
660     KeyType key_type = KeyType::KEY_NONE;
661     switch(protocol_cmd)
662     {
663         case LogicCommand::CREATE_KEY_PAIR_RSA:
664             key_type = KeyType::KEY_RSA_PUBLIC;
665             break;
666         case LogicCommand::CREATE_KEY_PAIR_DSA:
667             key_type = KeyType::KEY_DSA_PUBLIC;
668             break;
669         case LogicCommand::CREATE_KEY_PAIR_ECDSA:
670             key_type = KeyType::KEY_ECDSA_PUBLIC;
671             break;
672         default:
673             break;
674     }
675
676     try {
677         retCode = createKeyPairHelper(
678                         cred,
679                         key_type,
680                         additional_param,
681                         namePrivate,
682                         namePublic,
683                         policyPrivate,
684                         policyPublic);
685
686     } catch (DBCrypto::Exception::NameExists &e) {
687         LogDebug("DBCrypto error: name exists: " << e.GetMessage());
688         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
689     } catch (DBCrypto::Exception::TransactionError &e) {
690         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
691         retCode = CKM_API_ERROR_DB_ERROR;
692     } catch (CKM::CryptoLogic::Exception::Base &e) {
693         LogDebug("CryptoLogic error: " << e.GetMessage());
694         retCode = CKM_API_ERROR_SERVER_ERROR;
695     } catch (DBCrypto::Exception::InternalError &e) {
696         LogDebug("DBCrypto internal error: " << e.GetMessage());
697         retCode = CKM_API_ERROR_DB_ERROR;
698     }
699
700     return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
701 }
702
703 RawBuffer CKMLogic::getCertificateChain(
704     Credentials &cred,
705     int commandId,
706     const RawBuffer &certificate,
707     const RawBufferVector &untrustedRawCertVector)
708 {
709     (void)cred;
710
711     CertificateImpl cert(certificate, DataFormat::FORM_DER);
712     CertificateImplVector untrustedCertVector;
713     CertificateImplVector chainVector;
714     RawBufferVector chainRawVector;
715
716     for (auto &e: untrustedRawCertVector)
717         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
718
719     LogDebug("Cert is empty: " << cert.empty());
720
721     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
722
723     if (retCode == CKM_API_SUCCESS) {
724         for (auto &e : chainVector)
725             chainRawVector.push_back(e.getDER());
726     }
727
728     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
729                                              commandId,
730                                              retCode,
731                                              chainRawVector);
732     return response.Pop();
733 }
734
735 RawBuffer CKMLogic::getCertificateChain(
736     Credentials &cred,
737     int commandId,
738     const RawBuffer &certificate,
739     const AliasVector &aliasVector)
740 {
741     int retCode = CKM_API_SUCCESS;
742     RawBufferVector chainRawVector;
743     try {
744         CertificateImpl cert(certificate, DataFormat::FORM_DER);
745         CertificateImplVector untrustedCertVector;
746         CertificateImplVector chainVector;
747         DBRow row;
748
749         if (cert.empty()) {
750             retCode = CKM_API_ERROR_SERVER_ERROR;
751             goto senderror;
752         }
753
754         for (auto &i: aliasVector) {
755             retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Label(), Password(), row);
756
757             if (retCode != CKM_API_SUCCESS)
758                 goto senderror;
759
760             untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
761         }
762
763         retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
764
765         if (retCode != CKM_API_SUCCESS)
766             goto senderror;
767
768         for (auto &i: chainVector)
769             chainRawVector.push_back(i.getDER());
770
771     } catch (const CryptoLogic::Exception::Base &e) {
772         LogError("DBCyptorModule failed with message: " << e.GetMessage());
773         retCode = CKM_API_ERROR_SERVER_ERROR;
774     } catch (const DBCrypto::Exception::PermissionDenied &e) {
775         LogError("DBCrypto failed with message: " << e.GetMessage());
776         retCode = CKM_API_ERROR_ACCESS_DENIED;
777     } catch (const DBCrypto::Exception::Base &e) {
778         LogError("DBCrypto failed with message: " << e.GetMessage());
779         retCode = CKM_API_ERROR_DB_ERROR;
780     } catch (...) {
781         LogError("Unknown error.");
782     }
783
784 senderror:
785     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
786                                              commandId,
787                                              retCode,
788                                              chainRawVector);
789     return response.Pop();
790 }
791
792 RawBuffer CKMLogic::createSignature(
793         Credentials &cred,
794         int commandId,
795         const Name &privateKeyName,
796         const Label & ownerLabel,
797         const Password &password,           // password for private_key
798         const RawBuffer &message,
799         const HashAlgorithm hash,
800         const RSAPaddingAlgorithm padding)
801 {
802     DBRow row;
803     CryptoService cs;
804     RawBuffer signature;
805
806     int retCode = CKM_API_SUCCESS;
807
808     try {
809         do {
810             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
811             if (CKM_API_SUCCESS != retCode) {
812                 LogError("getDataHelper return error");
813                 break;
814             }
815
816             KeyImpl keyParsed(row.data, Password());
817             if (keyParsed.empty())
818                 retCode = CKM_API_ERROR_SERVER_ERROR;
819             else
820                 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
821         } while(0);
822     } catch (const KeyProvider::Exception::Base &e) {
823         LogError("KeyProvider failed with message: " << e.GetMessage());
824         retCode = CKM_API_ERROR_SERVER_ERROR;
825     } catch (const CryptoLogic::Exception::Base &e) {
826         LogError("CryptoLogic failed with message: " << e.GetMessage());
827         retCode = CKM_API_ERROR_SERVER_ERROR;
828     } catch (const DBCrypto::Exception::PermissionDenied &e) {
829         LogError("DBCrypto failed with message: " << e.GetMessage());
830         retCode = CKM_API_ERROR_ACCESS_DENIED;
831     } catch (const DBCrypto::Exception::Base &e) {
832         LogError("DBCrypto failed with message: " << e.GetMessage());
833         retCode = CKM_API_ERROR_DB_ERROR;
834     } catch (const CKM::Exception &e) {
835         LogError("Unknown CKM::Exception: " << e.GetMessage());
836         retCode = CKM_API_ERROR_SERVER_ERROR;
837     }
838
839     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
840                                              commandId,
841                                              retCode,
842                                              signature);
843     return response.Pop();
844 }
845
846 RawBuffer CKMLogic::verifySignature(
847         Credentials &cred,
848         int commandId,
849         const Name &publicKeyOrCertName,
850         const Label & ownerLabel,
851         const Password &password,           // password for public_key (optional)
852         const RawBuffer &message,
853         const RawBuffer &signature,
854         const HashAlgorithm hash,
855         const RSAPaddingAlgorithm padding)
856 {
857     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
858
859     try {
860         do {
861             CryptoService cs;
862             DBRow row;
863             KeyImpl key;
864
865             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
866
867             if (retCode == CKM_API_SUCCESS) {
868                 key = KeyImpl(row.data);
869             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
870                 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
871                 if (retCode != CKM_API_SUCCESS)
872                     break;
873                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
874                 key = cert.getKeyImpl();
875             } else {
876                 break;
877             }
878
879             if (key.empty()) {
880                 retCode = CKM_API_ERROR_SERVER_ERROR;
881                 break;
882             }
883
884             retCode = cs.verifySignature(key, message, signature, hash, padding);
885         } while(0);
886     } catch (const CryptoService::Exception::Crypto_internal &e) {
887         LogError("KeyProvider failed with message: " << e.GetMessage());
888         retCode = CKM_API_ERROR_SERVER_ERROR;
889     } catch (const CryptoService::Exception::opensslError &e) {
890         LogError("KeyProvider failed with message: " << e.GetMessage());
891         retCode = CKM_API_ERROR_SERVER_ERROR;
892     } catch (const KeyProvider::Exception::Base &e) {
893         LogError("KeyProvider failed with error: " << e.GetMessage());
894         retCode = CKM_API_ERROR_SERVER_ERROR;
895     } catch (const CryptoLogic::Exception::Base &e) {
896         LogError("CryptoLogic failed with message: " << e.GetMessage());
897         retCode = CKM_API_ERROR_SERVER_ERROR;
898     } catch (const DBCrypto::Exception::PermissionDenied &e) {
899         LogError("DBCrypto failed with message: " << e.GetMessage());
900         retCode = CKM_API_ERROR_ACCESS_DENIED;
901     } catch (const DBCrypto::Exception::Base &e) {
902         LogError("DBCrypto failed with message: " << e.GetMessage());
903         retCode = CKM_API_ERROR_DB_ERROR;
904     } catch (const CKM::Exception &e) {
905         LogError("Unknown CKM::Exception: " << e.GetMessage());
906         retCode = CKM_API_ERROR_SERVER_ERROR;
907     }
908
909     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
910                                              commandId,
911                                              retCode);
912     return response.Pop();
913 }
914
915 RawBuffer CKMLogic::allowAccess(
916         Credentials &cred,
917         int command,
918         int msgID,
919         const Name &name,
920         const Label &accessorLabel,
921         const AccessRight reqRights)
922 {
923     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
924
925     if (cred.smackLabel.empty()) {
926         retCode = CKM_API_ERROR_INPUT_PARAM;
927     } else if (0 < m_userDataMap.count(cred.uid) && !cred.smackLabel.empty()) {
928         Try {
929             retCode = m_userDataMap[cred.uid].database.setAccessRights(
930                 name,
931                 cred.smackLabel,
932                 accessorLabel,
933                 reqRights);
934         } Catch (DBCrypto::Exception::InvalidArgs) {
935             LogError("Error: invalid args!");
936             retCode = CKM_API_ERROR_INPUT_PARAM;
937         } Catch (DBCrypto::Exception::PermissionDenied) {
938             LogError("Error: not enough permissions!");
939             retCode = CKM_API_ERROR_ACCESS_DENIED;
940         } Catch (CKM::Exception) {
941             LogError("Error in set row!");
942             retCode = CKM_API_ERROR_DB_ERROR;
943         }
944     } else {
945         retCode = CKM_API_ERROR_DB_LOCKED;
946     }
947
948     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
949 }
950
951 RawBuffer CKMLogic::denyAccess(
952         Credentials &cred,
953         int command,
954         int msgID,
955         const Name &name,
956         const Label &accessorLabel)
957 {
958     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
959
960     if (cred.smackLabel.empty()) {
961         retCode = CKM_API_ERROR_INPUT_PARAM;
962     } else if (0 < m_userDataMap.count(cred.uid)) {
963         Try {
964             retCode = m_userDataMap[cred.uid].database.clearAccessRights(name, cred.smackLabel, accessorLabel);
965         } Catch (DBCrypto::Exception::PermissionDenied) {
966             LogError("Error: not enough permissions!");
967             retCode = CKM_API_ERROR_ACCESS_DENIED;
968         } Catch (DBCrypto::Exception::InvalidArgs) {
969             LogError("Error: permission not found!");
970             retCode = CKM_API_ERROR_INPUT_PARAM;
971         } Catch (CKM::Exception) {
972             LogError("Error in deleting row!");
973             retCode = CKM_API_ERROR_DB_ERROR;
974         }
975     } else {
976         retCode = CKM_API_ERROR_DB_LOCKED;
977     }
978
979     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
980 }
981
982 } // namespace CKM
983