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