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