Revert "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 {
369     int retCode = CKM_API_SUCCESS;
370
371     if (0 < m_userDataMap.count(cred.uid)) {
372         Try {
373             auto erased = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
374             // check if the data existed or not
375             if(!erased) {
376                 LogError("No row for given alias and label");
377                 retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
378             }
379         } Catch (DBCrypto::Exception::PermissionDenied) {
380             LogError("Error: not enough permissions!");
381             retCode = CKM_API_ERROR_ACCESS_DENIED;
382         } Catch (CKM::Exception) {
383             LogError("Error in deleting row!");
384             retCode = CKM_API_ERROR_DB_ERROR;
385         }
386     } else {
387         retCode = CKM_API_ERROR_DB_LOCKED;
388     }
389
390     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
391                                              commandId,
392                                              retCode,
393                                              static_cast<int>(dataType));
394     return response.Pop();
395 }
396
397 int CKMLogic::getDataHelper(
398     Credentials &cred,
399     DBDataType dataType,
400     const Alias &alias,
401     const Password &password,
402     DBRow &row)
403 {
404     if (0 == m_userDataMap.count(cred.uid))
405         return CKM_API_ERROR_DB_LOCKED;
406
407     auto &handler = m_userDataMap[cred.uid];
408
409     DBCrypto::DBRowOptional row_optional;
410     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
411         row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
412     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
413             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
414     {
415         row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
416     } else {
417         LogError("Unknown type of requested data" << (int)dataType);
418         return CKM_API_ERROR_BAD_REQUEST;
419     }
420     if(!row_optional) {
421         LogError("No row for given alias, label and type");
422         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
423     } else {
424         row = *row_optional;
425     }
426
427     if (!handler.crypto.haveKey(row.smackLabel)) {
428         RawBuffer key;
429         auto key_optional = handler.database.getKey(row.smackLabel);
430         if(!key_optional) {
431             LogError("No key for given label in database");
432             return CKM_API_ERROR_DB_ERROR;
433         }
434         key = *key_optional;
435         key = handler.keyProvider.getPureDEK(key);
436         handler.crypto.pushKey(cred.smackLabel, key);
437     }
438     handler.crypto.decryptRow(password, row);
439
440     return CKM_API_SUCCESS;
441 }
442
443 RawBuffer CKMLogic::getData(
444     Credentials &cred,
445     int commandId,
446     DBDataType dataType,
447     const Alias &alias,
448     const Password &password)
449 {
450     int retCode = CKM_API_SUCCESS;
451     DBRow row;
452
453     try {
454         retCode = getDataHelper(cred, dataType, alias, password, row);
455     } catch (const KeyProvider::Exception::Base &e) {
456         LogError("KeyProvider failed with error: " << e.GetMessage());
457         retCode = CKM_API_ERROR_SERVER_ERROR;
458     } catch (const CryptoLogic::Exception::Base &e) {
459         LogError("CryptoLogic failed with message: " << e.GetMessage());
460         retCode = CKM_API_ERROR_SERVER_ERROR;
461     } catch (const DBCrypto::Exception::PermissionDenied &e) {
462         LogError("DBCrypto failed with message: " << e.GetMessage());
463         retCode = CKM_API_ERROR_ACCESS_DENIED;
464     } catch (const DBCrypto::Exception::Base &e) {
465         LogError("DBCrypto failed with message: " << e.GetMessage());
466         retCode = CKM_API_ERROR_DB_ERROR;
467     }
468
469     if (CKM_API_SUCCESS != retCode) {
470         row.data.clear();
471         row.dataType = dataType;
472     }
473
474     if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
475         row.data.clear();
476         retCode = CKM_API_ERROR_NOT_EXPORTABLE;
477     }
478
479     // Prevent extracting private keys during cc-mode on
480     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)) {
481         row.data.clear();
482         retCode = CKM_API_ERROR_BAD_REQUEST;
483     }
484
485     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
486                                              commandId,
487                                              retCode,
488                                              static_cast<int>(row.dataType),
489                                              row.data);
490     return response.Pop();
491 }
492
493 RawBuffer CKMLogic::getDataList(
494     Credentials &cred,
495     int commandId,
496     DBDataType dataType)
497 {
498     int retCode = CKM_API_SUCCESS;
499     AliasVector aliasVector;
500
501     if (0 < m_userDataMap.count(cred.uid)) {
502         auto &handler = m_userDataMap[cred.uid];
503         Try {
504             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
505                 handler.database.getAliases(cred.smackLabel, dataType, aliasVector);
506             } else {
507                 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
508             }
509         } Catch (CKM::Exception) {
510             LogError("Failed to get aliases");
511             retCode = CKM_API_ERROR_DB_ERROR;
512         }
513     } else {
514         retCode = CKM_API_ERROR_DB_LOCKED;
515     }
516
517     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
518                                              commandId,
519                                              retCode,
520                                              static_cast<int>(dataType),
521                                              aliasVector);
522     return response.Pop();
523 }
524
525
526 int CKMLogic::createKeyPairHelper(
527     Credentials &cred,
528     const KeyType key_type,
529     const int additional_param,
530     const Alias &aliasPrivate,
531     const Alias &aliasPublic,
532     const PolicySerializable &policyPrivate,
533     const PolicySerializable &policyPublic)
534 {
535     if (0 >= m_userDataMap.count(cred.uid))
536         return CKM_API_ERROR_DB_LOCKED;
537
538     auto &handler = m_userDataMap[cred.uid];
539     KeyImpl prv, pub;
540     int retCode;
541     switch(key_type)
542     {
543         case KeyType::KEY_RSA_PUBLIC:
544         case KeyType::KEY_RSA_PRIVATE:
545             retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
546             break;
547
548         case KeyType::KEY_DSA_PUBLIC:
549         case KeyType::KEY_DSA_PRIVATE:
550             retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
551             break;
552
553         case KeyType::KEY_ECDSA_PUBLIC:
554         case KeyType::KEY_ECDSA_PRIVATE:
555             retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
556             break;
557
558         default:
559             return CKM_API_ERROR_INPUT_PARAM;
560     }
561
562     if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
563     {
564         LogDebug("CryptoService error with code: " << retCode);
565         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
566     }
567
568     DBCrypto::Transaction transaction(&handler.database);
569     retCode = saveDataHelper(cred,
570                             toDBDataType(prv.getType()),
571                             aliasPrivate,
572                             prv.getDER(),
573                             policyPrivate);
574
575     if (CKM_API_SUCCESS != retCode)
576         return retCode;
577
578     retCode = saveDataHelper(cred,
579                             toDBDataType(pub.getType()),
580                             aliasPublic,
581                             pub.getDER(),
582                             policyPublic);
583
584     if (CKM_API_SUCCESS != retCode)
585         return retCode;
586
587     transaction.commit();
588
589     return retCode;
590 }
591
592 RawBuffer CKMLogic::createKeyPair(
593     Credentials &cred,
594     LogicCommand protocol_cmd,
595     int commandId,
596     const int additional_param,
597     const Alias &aliasPrivate,
598     const Alias &aliasPublic,
599     const PolicySerializable &policyPrivate,
600     const PolicySerializable &policyPublic)
601 {
602     int retCode = CKM_API_SUCCESS;
603
604     KeyType key_type = KeyType::KEY_NONE;
605     switch(protocol_cmd)
606     {
607         case LogicCommand::CREATE_KEY_PAIR_RSA:
608             key_type = KeyType::KEY_RSA_PUBLIC;
609             break;
610         case LogicCommand::CREATE_KEY_PAIR_DSA:
611             key_type = KeyType::KEY_DSA_PUBLIC;
612             break;
613         case LogicCommand::CREATE_KEY_PAIR_ECDSA:
614             key_type = KeyType::KEY_ECDSA_PUBLIC;
615             break;
616         default:
617             break;
618     }
619
620     try {
621         retCode = createKeyPairHelper(
622                         cred,
623                         key_type,
624                         additional_param,
625                         aliasPrivate,
626                         aliasPublic,
627                         policyPrivate,
628                         policyPublic);
629
630     } catch (DBCrypto::Exception::AliasExists &e) {
631         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
632         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
633     } catch (DBCrypto::Exception::TransactionError &e) {
634         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
635         retCode = CKM_API_ERROR_DB_ERROR;
636     } catch (CKM::CryptoLogic::Exception::Base &e) {
637         LogDebug("CryptoLogic error: " << e.GetMessage());
638         retCode = CKM_API_ERROR_SERVER_ERROR;
639     } catch (DBCrypto::Exception::InternalError &e) {
640         LogDebug("DBCrypto internal error: " << e.GetMessage());
641         retCode = CKM_API_ERROR_DB_ERROR;
642     }
643
644     return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
645 }
646
647 RawBuffer CKMLogic::getCertificateChain(
648     Credentials &cred,
649     int commandId,
650     const RawBuffer &certificate,
651     const RawBufferVector &untrustedRawCertVector)
652 {
653     (void)cred;
654
655     CertificateImpl cert(certificate, DataFormat::FORM_DER);
656     CertificateImplVector untrustedCertVector;
657     CertificateImplVector chainVector;
658     RawBufferVector chainRawVector;
659
660     for (auto &e: untrustedRawCertVector)
661         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
662
663     LogDebug("Cert is empty: " << cert.empty());
664
665     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
666
667     if (retCode == CKM_API_SUCCESS) {
668         for (auto &e : chainVector)
669             chainRawVector.push_back(e.getDER());
670     }
671
672     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
673                                              commandId,
674                                              retCode,
675                                              chainRawVector);
676     return response.Pop();
677 }
678
679 RawBuffer CKMLogic::getCertificateChain(
680     Credentials &cred,
681     int commandId,
682     const RawBuffer &certificate,
683     const AliasVector &aliasVector)
684 {
685     int retCode = CKM_API_SUCCESS;
686     RawBufferVector chainRawVector;
687     try {
688         CertificateImpl cert(certificate, DataFormat::FORM_DER);
689         CertificateImplVector untrustedCertVector;
690         CertificateImplVector chainVector;
691         DBRow row;
692
693         if (cert.empty()) {
694             retCode = CKM_API_ERROR_SERVER_ERROR;
695             goto senderror;
696         }
697
698         for (auto &i: aliasVector) {
699             retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row);
700
701             if (retCode != CKM_API_SUCCESS)
702                 goto senderror;
703
704             untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
705         }
706
707         retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
708
709         if (retCode != CKM_API_SUCCESS)
710             goto senderror;
711
712         for (auto &i: chainVector)
713             chainRawVector.push_back(i.getDER());
714
715     } catch (const CryptoLogic::Exception::Base &e) {
716         LogError("DBCyptorModule failed with message: " << e.GetMessage());
717         retCode = CKM_API_ERROR_SERVER_ERROR;
718     } catch (const DBCrypto::Exception::PermissionDenied &e) {
719         LogError("DBCrypto failed with message: " << e.GetMessage());
720         retCode = CKM_API_ERROR_ACCESS_DENIED;
721     } catch (const DBCrypto::Exception::Base &e) {
722         LogError("DBCrypto failed with message: " << e.GetMessage());
723         retCode = CKM_API_ERROR_DB_ERROR;
724     } catch (...) {
725         LogError("Unknown error.");
726     }
727
728 senderror:
729     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
730                                              commandId,
731                                              retCode,
732                                              chainRawVector);
733     return response.Pop();
734 }
735
736 RawBuffer CKMLogic::createSignature(
737         Credentials &cred,
738         int commandId,
739         const Alias &privateKeyAlias,
740         const Password &password,           // password for private_key
741         const RawBuffer &message,
742         const HashAlgorithm hash,
743         const RSAPaddingAlgorithm padding)
744 {
745     DBRow row;
746     CryptoService cs;
747     RawBuffer signature;
748
749     int retCode = CKM_API_SUCCESS;
750
751     try {
752         do {
753             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyAlias, password, row);
754             if (CKM_API_SUCCESS != retCode) {
755                 LogError("getDataHelper return error");
756                 break;
757             }
758
759             KeyImpl keyParsed(row.data, Password());
760             if (keyParsed.empty())
761                 retCode = CKM_API_ERROR_SERVER_ERROR;
762             else
763                 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
764         } while(0);
765     } catch (const KeyProvider::Exception::Base &e) {
766         LogError("KeyProvider failed with message: " << e.GetMessage());
767         retCode = CKM_API_ERROR_SERVER_ERROR;
768     } catch (const CryptoLogic::Exception::Base &e) {
769         LogError("CryptoLogic failed with message: " << e.GetMessage());
770         retCode = CKM_API_ERROR_SERVER_ERROR;
771     } catch (const DBCrypto::Exception::PermissionDenied &e) {
772         LogError("DBCrypto failed with message: " << e.GetMessage());
773         retCode = CKM_API_ERROR_ACCESS_DENIED;
774     } catch (const DBCrypto::Exception::Base &e) {
775         LogError("DBCrypto failed with message: " << e.GetMessage());
776         retCode = CKM_API_ERROR_DB_ERROR;
777     } catch (const CKM::Exception &e) {
778         LogError("Unknown CKM::Exception: " << e.GetMessage());
779         retCode = CKM_API_ERROR_SERVER_ERROR;
780     }
781
782     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
783                                              commandId,
784                                              retCode,
785                                              signature);
786     return response.Pop();
787 }
788
789 RawBuffer CKMLogic::verifySignature(
790         Credentials &cred,
791         int commandId,
792         const Alias &publicKeyOrCertAlias,
793         const Password &password,           // password for public_key (optional)
794         const RawBuffer &message,
795         const RawBuffer &signature,
796         const HashAlgorithm hash,
797         const RSAPaddingAlgorithm padding)
798 {
799     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
800
801     try {
802         do {
803             CryptoService cs;
804             DBRow row;
805             KeyImpl key;
806
807             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
808
809             if (retCode == CKM_API_SUCCESS) {
810                 key = KeyImpl(row.data);
811             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
812                 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
813                 if (retCode != CKM_API_SUCCESS)
814                     break;
815                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
816                 key = cert.getKeyImpl();
817             } else {
818                 break;
819             }
820
821             if (key.empty()) {
822                 retCode = CKM_API_ERROR_SERVER_ERROR;
823                 break;
824             }
825
826             retCode = cs.verifySignature(key, message, signature, hash, padding);
827         } while(0);
828     } catch (const CryptoService::Exception::Crypto_internal &e) {
829         LogError("KeyProvider failed with message: " << e.GetMessage());
830         retCode = CKM_API_ERROR_SERVER_ERROR;
831     } catch (const CryptoService::Exception::opensslError &e) {
832         LogError("KeyProvider failed with message: " << e.GetMessage());
833         retCode = CKM_API_ERROR_SERVER_ERROR;
834     } catch (const KeyProvider::Exception::Base &e) {
835         LogError("KeyProvider failed with error: " << e.GetMessage());
836         retCode = CKM_API_ERROR_SERVER_ERROR;
837     } catch (const CryptoLogic::Exception::Base &e) {
838         LogError("CryptoLogic failed with message: " << e.GetMessage());
839         retCode = CKM_API_ERROR_SERVER_ERROR;
840     } catch (const DBCrypto::Exception::PermissionDenied &e) {
841         LogError("DBCrypto failed with message: " << e.GetMessage());
842         retCode = CKM_API_ERROR_ACCESS_DENIED;
843     } catch (const DBCrypto::Exception::Base &e) {
844         LogError("DBCrypto failed with message: " << e.GetMessage());
845         retCode = CKM_API_ERROR_DB_ERROR;
846     } catch (const CKM::Exception &e) {
847         LogError("Unknown CKM::Exception: " << e.GetMessage());
848         retCode = CKM_API_ERROR_SERVER_ERROR;
849     }
850
851     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
852                                              commandId,
853                                              retCode);
854     return response.Pop();
855 }
856
857 RawBuffer CKMLogic::allowAccess(
858         Credentials &cred,
859         int command,
860         int msgID,
861         const Alias &item_alias,
862         const std::string &accessor_label,
863         const AccessRight req_rights)
864 {
865     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
866
867     if (0 < m_userDataMap.count(cred.uid))
868     {
869         Try {
870             retCode = m_userDataMap[cred.uid].database.setAccessRights(cred.smackLabel, item_alias, accessor_label, req_rights);
871         } Catch (DBCrypto::Exception::InvalidArgs) {
872             LogError("Error: invalid args!");
873             retCode = CKM_API_ERROR_INPUT_PARAM;
874         } Catch (DBCrypto::Exception::PermissionDenied) {
875             LogError("Error: not enough permissions!");
876             retCode = CKM_API_ERROR_ACCESS_DENIED;
877         } Catch (CKM::Exception) {
878             LogError("Error in set row!");
879             retCode = CKM_API_ERROR_DB_ERROR;
880         }
881     } else {
882         retCode = CKM_API_ERROR_DB_LOCKED;
883     }
884
885     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
886 }
887
888 RawBuffer CKMLogic::denyAccess(
889         Credentials &cred,
890         int command,
891         int msgID,
892         const Alias &item_alias,
893         const std::string &accessor_label)
894 {
895     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
896
897     if (0 < m_userDataMap.count(cred.uid))
898     {
899         Try {
900             retCode = m_userDataMap[cred.uid].database.clearAccessRights(cred.smackLabel, item_alias, accessor_label);
901         } Catch (DBCrypto::Exception::PermissionDenied) {
902             LogError("Error: not enough permissions!");
903             retCode = CKM_API_ERROR_ACCESS_DENIED;
904         } Catch (DBCrypto::Exception::InvalidArgs) {
905             LogError("Error: permission not found!");
906             retCode = CKM_API_ERROR_INPUT_PARAM;
907         } Catch (CKM::Exception) {
908             LogError("Error in deleting row!");
909             retCode = CKM_API_ERROR_DB_ERROR;
910         }
911     } else {
912         retCode = CKM_API_ERROR_DB_LOCKED;
913     }
914
915     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
916 }
917
918 } // namespace CKM
919