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