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