29a70623f2500b19fed76c136540a2003d90c257
[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     MessageBuffer response;
112     Serialization::Serialize(response, retCode);
113     return response.Pop();
114 }
115
116 RawBuffer CKMLogic::setCCModeStatus(CCModeState mode_status) {
117
118     int retCode = CKM_API_SUCCESS;
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
126     MessageBuffer response;
127     Serialization::Serialize(response, retCode);
128     return response.Pop();
129 }
130
131 RawBuffer CKMLogic::lockUserKey(uid_t user) {
132     int retCode = CKM_API_SUCCESS;
133     // TODO try catch for all errors that should be supported by error code
134     m_userDataMap.erase(user);
135
136     MessageBuffer response;
137     Serialization::Serialize(response, retCode);
138     return response.Pop();
139 }
140
141 RawBuffer CKMLogic::removeUserData(uid_t user) {
142     int retCode = CKM_API_SUCCESS;
143     // TODO try catch for all errors that should be supported by error code
144     m_userDataMap.erase(user);
145
146     FileSystem fs(user);
147     fs.removeUserData();
148
149     MessageBuffer response;
150     Serialization::Serialize(response, retCode);
151     return response.Pop();
152 }
153
154 RawBuffer CKMLogic::changeUserPassword(
155     uid_t user,
156     const Password &oldPassword,
157     const Password &newPassword)
158 {
159     int retCode = CKM_API_SUCCESS;
160     try {
161         FileSystem fs(user);
162         auto wrappedDomainKEK = fs.getDKEK();
163         if (wrappedDomainKEK.empty()) {
164             retCode = CKM_API_ERROR_BAD_REQUEST;
165         } else {
166             wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
167             fs.saveDKEK(wrappedDomainKEK);
168         }
169     } catch (const KeyProvider::Exception::PassWordError &e) {
170         LogError("Incorrect Password " << e.GetMessage());
171         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
172     } catch (const KeyProvider::Exception::Base &e) {
173         LogError("Error in KeyProvider " << e.GetMessage());
174         retCode = CKM_API_ERROR_SERVER_ERROR;
175     } catch (const CKM::Exception &e) {
176         LogError("CKM::Exception: " << e.GetMessage());
177         retCode = CKM_API_ERROR_SERVER_ERROR;
178     }
179
180     MessageBuffer response;
181     Serialization::Serialize(response, retCode);
182     return response.Pop();
183 }
184
185 RawBuffer CKMLogic::resetUserPassword(
186     uid_t user,
187     const Password &newPassword)
188 {
189     int retCode = CKM_API_SUCCESS;
190     // TODO try-catch
191     if (0 == m_userDataMap.count(user)) {
192         retCode = CKM_API_ERROR_BAD_REQUEST;
193     } else {
194         auto &handler = m_userDataMap[user];
195         FileSystem fs(user);
196         fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
197     }
198
199     MessageBuffer response;
200     Serialization::Serialize(response, retCode);
201     return response.Pop();
202 }
203
204 RawBuffer CKMLogic::removeApplicationData(const std::string &smackLabel) {
205     int retCode = CKM_API_SUCCESS;
206
207     try {
208
209         if (smackLabel.empty()) {
210             retCode = CKM_API_ERROR_INPUT_PARAM;
211         } else {
212             UidVector uids = FileSystem::getUIDsFromDBFile();
213             for (auto userId : uids) {
214                 if (0 == m_userDataMap.count(userId)) {
215                     FileSystem fs(userId);
216                     fs.addRemovedApp(smackLabel);
217                 } else {
218                     auto &handle = m_userDataMap[userId];
219                     handle.database.deleteKey(smackLabel);
220                 }
221             }
222         }
223
224     } catch (const DBCrypto::Exception::InternalError &e) {
225         LogError("DBCrypto couldn't remove data: " << e.GetMessage());
226         retCode = CKM_API_ERROR_DB_ERROR;
227     } catch (const DBCrypto::Exception::TransactionError &e) {
228         LogError("DBCrypto transaction failed with message " << e.GetMessage());
229         retCode = CKM_API_ERROR_DB_ERROR;
230     }
231
232     MessageBuffer response;
233     Serialization::Serialize(response, retCode);
234     return response.Pop();
235 }
236
237 int CKMLogic::saveDataHelper(
238     Credentials &cred,
239     DBDataType dataType,
240     const Alias &alias,
241     const RawBuffer &key,
242     const PolicySerializable &policy)
243 {
244     if (0 == m_userDataMap.count(cred.uid))
245         return CKM_API_ERROR_DB_LOCKED;
246
247     DBRow row = { alias, cred.smackLabel,
248          policy.extractable, dataType, DBCMAlgType::NONE,
249          0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
250
251     auto &handler = m_userDataMap[cred.uid];
252     DBCrypto::Transaction transaction(&handler.database);
253     if (!handler.crypto.haveKey(cred.smackLabel)) {
254         RawBuffer key;
255         auto key_optional = handler.database.getKey(cred.smackLabel);
256         if(!key_optional) {
257             LogDebug("No Key in database found. Generating new one for label: "
258                     << cred.smackLabel);
259             key = handler.keyProvider.generateDEK(cred.smackLabel);
260             handler.database.saveKey(cred.smackLabel, key);
261         } else {
262             LogDebug("Key from DB");
263             key = *key_optional;
264         }
265
266         key = handler.keyProvider.getPureDEK(key);
267         handler.crypto.pushKey(cred.smackLabel, key);
268     }
269
270     // Do not encrypt data with password during cc_mode on
271     if(cc_mode_status == CCModeState::CC_MODE_ON) {
272         handler.crypto.encryptRow("", row);
273     } else {
274         handler.crypto.encryptRow(policy.password, row);
275     }
276
277     handler.database.saveDBRow(row);
278     transaction.commit();
279     return CKM_API_SUCCESS;
280 }
281
282 RawBuffer CKMLogic::saveData(
283     Credentials &cred,
284     int commandId,
285     DBDataType dataType,
286     const Alias &alias,
287     const RawBuffer &key,
288     const PolicySerializable &policy)
289 {
290     int retCode = CKM_API_SUCCESS;
291     try {
292         retCode = saveDataHelper(cred, dataType, alias, key, policy);
293         LogDebug("SaveDataHelper returned: " << retCode);
294     } catch (const KeyProvider::Exception::Base &e) {
295         LogError("KeyProvider failed with message: " << e.GetMessage());
296         retCode = CKM_API_ERROR_SERVER_ERROR;
297     } catch (const CryptoLogic::Exception::Base &e) {
298         LogError("CryptoLogic failed with message: " << e.GetMessage());
299         retCode = CKM_API_ERROR_SERVER_ERROR;
300     } catch (const DBCrypto::Exception::InternalError &e) {
301         LogError("DBCrypto failed with message: " << e.GetMessage());
302         retCode = CKM_API_ERROR_DB_ERROR;
303     } catch (const DBCrypto::Exception::AliasExists &e) {
304         LogError("DBCrypto couldn't save duplicate alias");
305         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
306     } catch (const DBCrypto::Exception::TransactionError &e) {
307         LogError("DBCrypto transaction failed with message " << e.GetMessage());
308         retCode = CKM_API_ERROR_DB_ERROR;
309     }
310
311     MessageBuffer response;
312     Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
313     Serialization::Serialize(response, commandId);
314     Serialization::Serialize(response, retCode);
315     Serialization::Serialize(response, static_cast<int>(dataType));
316
317     return response.Pop();
318 }
319
320 RawBuffer CKMLogic::removeData(
321     Credentials &cred,
322     int commandId,
323     DBDataType dataType,
324     const Alias &alias)
325 {
326     int retCode = CKM_API_SUCCESS;
327
328     if (0 < m_userDataMap.count(cred.uid)) {
329         Try {
330             auto erased = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
331             // check if the data existed or not
332             if(!erased) {
333                 LogError("No row for given alias and label");
334                 retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
335             }
336         } Catch (DBCrypto::Exception::PermissionDenied) {
337             LogError("Error: not enough permissions!");
338             retCode = CKM_API_ERROR_ACCESS_DENIED;
339         } Catch (CKM::Exception) {
340             LogError("Error in deleting row!");
341             retCode = CKM_API_ERROR_DB_ERROR;
342         }
343     } else {
344         retCode = CKM_API_ERROR_DB_LOCKED;
345     }
346
347     MessageBuffer response;
348     Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
349     Serialization::Serialize(response, commandId);
350     Serialization::Serialize(response, retCode);
351     Serialization::Serialize(response, static_cast<int>(dataType));
352
353     return response.Pop();
354 }
355
356 int CKMLogic::getDataHelper(
357     Credentials &cred,
358     DBDataType dataType,
359     const Alias &alias,
360     const Password &password,
361     DBRow &row)
362 {
363     if (0 == m_userDataMap.count(cred.uid))
364         return CKM_API_ERROR_DB_LOCKED;
365
366     auto &handler = m_userDataMap[cred.uid];
367
368     DBCrypto::DBRowOptional row_optional;
369     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
370         row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
371     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
372             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
373     {
374         row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
375     } else {
376         LogError("Unknown type of requested data" << (int)dataType);
377         return CKM_API_ERROR_BAD_REQUEST;
378     }
379     if(!row_optional) {
380         LogError("No row for given alias, label and type");
381         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
382     } else {
383         row = *row_optional;
384     }
385
386     if (!handler.crypto.haveKey(row.smackLabel)) {
387         RawBuffer key;
388         auto key_optional = handler.database.getKey(row.smackLabel);
389         if(!key_optional) {
390             LogError("No key for given label in database");
391             return CKM_API_ERROR_DB_ERROR;
392         }
393         key = *key_optional;
394         key = handler.keyProvider.getPureDEK(key);
395         handler.crypto.pushKey(cred.smackLabel, key);
396     }
397     handler.crypto.decryptRow(password, row);
398
399     return CKM_API_SUCCESS;
400 }
401
402 RawBuffer CKMLogic::getData(
403     Credentials &cred,
404     int commandId,
405     DBDataType dataType,
406     const Alias &alias,
407     const Password &password)
408 {
409     int retCode = CKM_API_SUCCESS;
410     DBRow row;
411
412     try {
413         retCode = getDataHelper(cred, dataType, alias, password, row);
414     } catch (const KeyProvider::Exception::Base &e) {
415         LogError("KeyProvider failed with error: " << e.GetMessage());
416         retCode = CKM_API_ERROR_SERVER_ERROR;
417     } catch (const CryptoLogic::Exception::Base &e) {
418         LogError("CryptoLogic failed with message: " << e.GetMessage());
419         retCode = CKM_API_ERROR_SERVER_ERROR;
420     } catch (const DBCrypto::Exception::PermissionDenied &e) {
421         LogError("DBCrypto failed with message: " << e.GetMessage());
422         retCode = CKM_API_ERROR_ACCESS_DENIED;
423     } catch (const DBCrypto::Exception::Base &e) {
424         LogError("DBCrypto failed with message: " << e.GetMessage());
425         retCode = CKM_API_ERROR_DB_ERROR;
426     }
427
428     if (CKM_API_SUCCESS != retCode) {
429         row.data.clear();
430         row.dataType = dataType;
431     }
432
433     if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
434         row.data.clear();
435         retCode = CKM_API_ERROR_NOT_EXPORTABLE;
436     }
437
438     // Prevent extracting private keys during cc-mode on
439     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)) {
440         row.data.clear();
441         retCode = CKM_API_ERROR_BAD_REQUEST;
442     }
443
444     MessageBuffer response;
445     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
446     Serialization::Serialize(response, commandId);
447     Serialization::Serialize(response, retCode);
448     Serialization::Serialize(response, static_cast<int>(row.dataType));
449     Serialization::Serialize(response, row.data);
450     return response.Pop();
451 }
452
453 RawBuffer CKMLogic::getDataList(
454     Credentials &cred,
455     int commandId,
456     DBDataType dataType)
457 {
458     int retCode = CKM_API_SUCCESS;
459     AliasVector aliasVector;
460
461     if (0 < m_userDataMap.count(cred.uid)) {
462         auto &handler = m_userDataMap[cred.uid];
463         Try {
464             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
465                 handler.database.getAliases(dataType, aliasVector);
466             } else {
467                 handler.database.getKeyAliases(aliasVector);
468             }
469         } Catch (CKM::Exception) {
470             LogError("Failed to get aliases");
471             retCode = CKM_API_ERROR_DB_ERROR;
472         }
473     } else {
474         retCode = CKM_API_ERROR_DB_LOCKED;
475     }
476
477     MessageBuffer response;
478     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
479     Serialization::Serialize(response, commandId);
480     Serialization::Serialize(response, retCode);
481     Serialization::Serialize(response, static_cast<int>(dataType));
482     Serialization::Serialize(response, 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     MessageBuffer response;
606     Serialization::Serialize(response, static_cast<int>(protocol_cmd));
607     Serialization::Serialize(response, commandId);
608     Serialization::Serialize(response, retCode);
609
610     return response.Pop();
611 }
612
613 RawBuffer CKMLogic::getCertificateChain(
614     Credentials &cred,
615     int commandId,
616     const RawBuffer &certificate,
617     const RawBufferVector &untrustedRawCertVector)
618 {
619     (void)cred;
620
621     CertificateImpl cert(certificate, DataFormat::FORM_DER);
622     CertificateImplVector untrustedCertVector;
623     CertificateImplVector chainVector;
624     RawBufferVector chainRawVector;
625
626     for (auto &e: untrustedRawCertVector)
627         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
628
629     LogDebug("Cert is empty: " << cert.empty());
630
631     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
632
633     if (retCode == CKM_API_SUCCESS) {
634         for (auto &e : chainVector)
635             chainRawVector.push_back(e.getDER());
636     }
637
638     MessageBuffer response;
639     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
640     Serialization::Serialize(response, commandId);
641     Serialization::Serialize(response, retCode);
642     Serialization::Serialize(response, chainRawVector);
643     return response.Pop();
644 }
645
646 RawBuffer CKMLogic::getCertificateChain(
647     Credentials &cred,
648     int commandId,
649     const RawBuffer &certificate,
650     const AliasVector &aliasVector)
651 {
652     int retCode = CKM_API_SUCCESS;
653     RawBufferVector chainRawVector;
654     try {
655         CertificateImpl cert(certificate, DataFormat::FORM_DER);
656         CertificateImplVector untrustedCertVector;
657         CertificateImplVector chainVector;
658         DBRow row;
659
660         if (cert.empty()) {
661             retCode = CKM_API_ERROR_SERVER_ERROR;
662             goto senderror;
663         }
664
665         for (auto &i: aliasVector) {
666             retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row);
667
668             if (retCode != CKM_API_SUCCESS)
669                 goto senderror;
670
671             untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
672         }
673
674         retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
675
676         if (retCode != CKM_API_SUCCESS)
677             goto senderror;
678
679         for (auto &i: chainVector)
680             chainRawVector.push_back(i.getDER());
681
682     } catch (const CryptoLogic::Exception::Base &e) {
683         LogError("DBCyptorModule failed with message: " << e.GetMessage());
684         retCode = CKM_API_ERROR_SERVER_ERROR;
685     } catch (const DBCrypto::Exception::PermissionDenied &e) {
686         LogError("DBCrypto failed with message: " << e.GetMessage());
687         retCode = CKM_API_ERROR_ACCESS_DENIED;
688     } catch (const DBCrypto::Exception::Base &e) {
689         LogError("DBCrypto failed with message: " << e.GetMessage());
690         retCode = CKM_API_ERROR_DB_ERROR;
691     } catch (...) {
692         LogError("Unknown error.");
693     }
694
695 senderror:
696     MessageBuffer response;
697     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
698     Serialization::Serialize(response, commandId);
699     Serialization::Serialize(response, retCode);
700     Serialization::Serialize(response, chainRawVector);
701     return response.Pop();
702 }
703
704 RawBuffer CKMLogic::createSignature(
705         Credentials &cred,
706         int commandId,
707         const Alias &privateKeyAlias,
708         const Password &password,           // password for private_key
709         const RawBuffer &message,
710         const HashAlgorithm hash,
711         const RSAPaddingAlgorithm padding)
712 {
713     DBRow row;
714     CryptoService cs;
715     RawBuffer signature;
716
717     int retCode = CKM_API_SUCCESS;
718
719     try {
720         do {
721             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyAlias, password, row);
722             if (CKM_API_SUCCESS != retCode) {
723                 LogError("getDataHelper return error");
724                 break;
725             }
726
727             KeyImpl keyParsed(row.data, Password());
728             if (keyParsed.empty())
729                 retCode = CKM_API_ERROR_SERVER_ERROR;
730             else
731                 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
732         } while(0);
733     } catch (const KeyProvider::Exception::Base &e) {
734         LogError("KeyProvider failed with message: " << e.GetMessage());
735         retCode = CKM_API_ERROR_SERVER_ERROR;
736     } catch (const CryptoLogic::Exception::Base &e) {
737         LogError("CryptoLogic failed with message: " << e.GetMessage());
738         retCode = CKM_API_ERROR_SERVER_ERROR;
739     } catch (const DBCrypto::Exception::PermissionDenied &e) {
740         LogError("DBCrypto failed with message: " << e.GetMessage());
741         retCode = CKM_API_ERROR_ACCESS_DENIED;
742     } catch (const DBCrypto::Exception::Base &e) {
743         LogError("DBCrypto failed with message: " << e.GetMessage());
744         retCode = CKM_API_ERROR_DB_ERROR;
745     } catch (const CKM::Exception &e) {
746         LogError("Unknown CKM::Exception: " << e.GetMessage());
747         retCode = CKM_API_ERROR_SERVER_ERROR;
748     }
749
750     MessageBuffer response;
751     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
752     Serialization::Serialize(response, commandId);
753     Serialization::Serialize(response, retCode);
754     Serialization::Serialize(response, signature);
755     return response.Pop();
756 }
757
758 RawBuffer CKMLogic::verifySignature(
759         Credentials &cred,
760         int commandId,
761         const Alias &publicKeyOrCertAlias,
762         const Password &password,           // password for public_key (optional)
763         const RawBuffer &message,
764         const RawBuffer &signature,
765         const HashAlgorithm hash,
766         const RSAPaddingAlgorithm padding)
767 {
768     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
769
770     try {
771         do {
772             CryptoService cs;
773             DBRow row;
774             KeyImpl key;
775
776             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
777
778             if (retCode == CKM_API_SUCCESS) {
779                 key = KeyImpl(row.data);
780             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
781                 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
782                 if (retCode != CKM_API_SUCCESS)
783                     break;
784                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
785                 key = cert.getKeyImpl();
786             } else {
787                 break;
788             }
789
790             if (key.empty()) {
791                 retCode = CKM_API_ERROR_SERVER_ERROR;
792                 break;
793             }
794
795             retCode = cs.verifySignature(key, message, signature, hash, padding);
796         } while(0);
797     } catch (const CryptoService::Exception::Crypto_internal &e) {
798         LogError("KeyProvider failed with message: " << e.GetMessage());
799         retCode = CKM_API_ERROR_SERVER_ERROR;
800     } catch (const CryptoService::Exception::opensslError &e) {
801         LogError("KeyProvider failed with message: " << e.GetMessage());
802         retCode = CKM_API_ERROR_SERVER_ERROR;
803     } catch (const KeyProvider::Exception::Base &e) {
804         LogError("KeyProvider failed with error: " << e.GetMessage());
805         retCode = CKM_API_ERROR_SERVER_ERROR;
806     } catch (const CryptoLogic::Exception::Base &e) {
807         LogError("CryptoLogic failed with message: " << e.GetMessage());
808         retCode = CKM_API_ERROR_SERVER_ERROR;
809     } catch (const DBCrypto::Exception::PermissionDenied &e) {
810         LogError("DBCrypto failed with message: " << e.GetMessage());
811         retCode = CKM_API_ERROR_ACCESS_DENIED;
812     } catch (const DBCrypto::Exception::Base &e) {
813         LogError("DBCrypto failed with message: " << e.GetMessage());
814         retCode = CKM_API_ERROR_DB_ERROR;
815     } catch (const CKM::Exception &e) {
816         LogError("Unknown CKM::Exception: " << e.GetMessage());
817         retCode = CKM_API_ERROR_SERVER_ERROR;
818     }
819
820     MessageBuffer response;
821     Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
822     Serialization::Serialize(response, commandId);
823     Serialization::Serialize(response, retCode);
824
825     return response.Pop();
826 }
827
828 RawBuffer CKMLogic::allowAccess(
829         Credentials &cred,
830         int commandId,
831         const Alias &item_alias,
832         const std::string &accessor_label,
833         const AccessRight req_rights)
834 {
835     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
836
837     if (0 < m_userDataMap.count(cred.uid))
838     {
839         Try {
840             retCode = m_userDataMap[cred.uid].database.setAccessRights(cred.smackLabel, item_alias, accessor_label, req_rights);
841         } Catch (DBCrypto::Exception::InvalidArgs) {
842             LogError("Error: invalid args!");
843             retCode = CKM_API_ERROR_INPUT_PARAM;
844         } Catch (DBCrypto::Exception::PermissionDenied) {
845             LogError("Error: not enough permissions!");
846             retCode = CKM_API_ERROR_ACCESS_DENIED;
847         } Catch (CKM::Exception) {
848             LogError("Error in set row!");
849             retCode = CKM_API_ERROR_DB_ERROR;
850         }
851     } else {
852         retCode = CKM_API_ERROR_DB_LOCKED;
853     }
854
855     MessageBuffer response;
856     Serialization::Serialize(response, static_cast<int>(LogicCommand::ALLOW_ACCESS));
857     Serialization::Serialize(response, commandId);
858     Serialization::Serialize(response, retCode);
859
860     return response.Pop();
861 }
862
863 RawBuffer CKMLogic::denyAccess(
864         Credentials &cred,
865         int commandId,
866         const Alias &item_alias,
867         const std::string &accessor_label)
868 {
869     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
870
871     if (0 < m_userDataMap.count(cred.uid))
872     {
873         Try {
874             retCode = m_userDataMap[cred.uid].database.clearAccessRights(cred.smackLabel, item_alias, accessor_label);
875         } Catch (DBCrypto::Exception::PermissionDenied) {
876             LogError("Error: not enough permissions!");
877             retCode = CKM_API_ERROR_ACCESS_DENIED;
878         } Catch (DBCrypto::Exception::InvalidArgs) {
879             LogError("Error: permission not found!");
880             retCode = CKM_API_ERROR_INPUT_PARAM;
881         } Catch (CKM::Exception) {
882             LogError("Error in deleting row!");
883             retCode = CKM_API_ERROR_DB_ERROR;
884         }
885     } else {
886         retCode = CKM_API_ERROR_DB_LOCKED;
887     }
888
889     MessageBuffer response;
890     Serialization::Serialize(response, static_cast<int>(LogicCommand::DENY_ACCESS));
891     Serialization::Serialize(response, commandId);
892     Serialization::Serialize(response, retCode);
893
894     return response.Pop();
895 }
896
897 } // namespace CKM
898