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