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