Add additional functions related to CC mode
[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 (CKM::Exception) {
337             LogError("Error in deleting row!");
338             retCode = CKM_API_ERROR_DB_ERROR;
339         }
340     } else {
341         retCode = CKM_API_ERROR_DB_LOCKED;
342     }
343
344     MessageBuffer response;
345     Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
346     Serialization::Serialize(response, commandId);
347     Serialization::Serialize(response, retCode);
348     Serialization::Serialize(response, static_cast<int>(dataType));
349
350     return response.Pop();
351 }
352
353 int CKMLogic::getDataHelper(
354     Credentials &cred,
355     DBDataType dataType,
356     const Alias &alias,
357     const Password &password,
358     DBRow &row)
359 {
360
361     if (0 == m_userDataMap.count(cred.uid))
362         return CKM_API_ERROR_DB_LOCKED;
363
364     auto &handler = m_userDataMap[cred.uid];
365
366     DBCrypto::DBRowOptional row_optional;
367     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
368         row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
369     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
370             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
371     {
372         row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
373     } else {
374         LogError("Unknown type of requested data" << (int)dataType);
375         return CKM_API_ERROR_BAD_REQUEST;
376     }
377     if(!row_optional) {
378         LogError("No row for given alias, label and type");
379         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
380     } else {
381         row = *row_optional;
382     }
383
384     if (!handler.crypto.haveKey(row.smackLabel)) {
385         RawBuffer key;
386         auto key_optional = handler.database.getKey(row.smackLabel);
387         if(!key_optional) {
388             LogError("No key for given label in database");
389             return CKM_API_ERROR_DB_ERROR;
390         }
391         key = *key_optional;
392         key = handler.keyProvider.getPureDEK(key);
393         handler.crypto.pushKey(cred.smackLabel, key);
394     }
395     handler.crypto.decryptRow(password, row);
396
397     return CKM_API_SUCCESS;
398 }
399
400 RawBuffer CKMLogic::getData(
401     Credentials &cred,
402     int commandId,
403     DBDataType dataType,
404     const Alias &alias,
405     const Password &password)
406 {
407     int retCode = CKM_API_SUCCESS;
408     DBRow row;
409
410     try {
411         retCode = getDataHelper(cred, dataType, alias, password, row);
412     } catch (const KeyProvider::Exception::Base &e) {
413         LogError("KeyProvider failed with error: " << e.GetMessage());
414         retCode = CKM_API_ERROR_SERVER_ERROR;
415     } catch (const CryptoLogic::Exception::Base &e) {
416         LogError("CryptoLogic failed with message: " << e.GetMessage());
417         retCode = CKM_API_ERROR_SERVER_ERROR;
418     } catch (const DBCrypto::Exception::Base &e) {
419         LogError("DBCrypto failed with message: " << e.GetMessage());
420         retCode = CKM_API_ERROR_DB_ERROR;
421     }
422
423     if (CKM_API_SUCCESS != retCode) {
424         row.data.clear();
425         row.dataType = dataType;
426     }
427
428     if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
429         row.data.clear();
430         retCode = CKM_API_ERROR_NOT_EXPORTABLE;
431     }
432
433     // Prevent extracting private keys during cc-mode on
434     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)) {
435         row.data.clear();
436         retCode = CKM_API_ERROR_BAD_REQUEST;
437     }
438
439     MessageBuffer response;
440     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
441     Serialization::Serialize(response, commandId);
442     Serialization::Serialize(response, retCode);
443     Serialization::Serialize(response, static_cast<int>(row.dataType));
444     Serialization::Serialize(response, row.data);
445     return response.Pop();
446 }
447
448 RawBuffer CKMLogic::getDataList(
449     Credentials &cred,
450     int commandId,
451     DBDataType dataType)
452 {
453     int retCode = CKM_API_SUCCESS;
454     AliasVector aliasVector;
455
456     if (0 < m_userDataMap.count(cred.uid)) {
457         auto &handler = m_userDataMap[cred.uid];
458         Try {
459             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
460                 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
461             } else {
462                 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
463             }
464         } Catch (CKM::Exception) {
465             LogError("Failed to get aliases");
466             retCode = CKM_API_ERROR_DB_ERROR;
467         }
468     } else {
469         retCode = CKM_API_ERROR_DB_LOCKED;
470     }
471
472     MessageBuffer response;
473     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
474     Serialization::Serialize(response, commandId);
475     Serialization::Serialize(response, retCode);
476     Serialization::Serialize(response, static_cast<int>(dataType));
477     Serialization::Serialize(response, aliasVector);
478     return response.Pop();
479 }
480
481
482 int CKMLogic::createKeyPairHelper(
483     Credentials &cred,
484     const KeyType key_type,
485     const int additional_param,
486     const Alias &aliasPrivate,
487     const Alias &aliasPublic,
488     const PolicySerializable &policyPrivate,
489     const PolicySerializable &policyPublic)
490 {
491     if (0 >= m_userDataMap.count(cred.uid))
492         return CKM_API_ERROR_DB_LOCKED;
493
494     auto &handler = m_userDataMap[cred.uid];
495     KeyImpl prv, pub;
496     int retCode;
497     switch(key_type)
498     {
499         case KeyType::KEY_RSA_PUBLIC:
500         case KeyType::KEY_RSA_PRIVATE:
501             retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
502             break;
503
504         case KeyType::KEY_DSA_PUBLIC:
505         case KeyType::KEY_DSA_PRIVATE:
506             retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
507             break;
508
509         case KeyType::KEY_ECDSA_PUBLIC:
510         case KeyType::KEY_ECDSA_PRIVATE:
511             retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
512             break;
513
514         default:
515             return CKM_API_ERROR_INPUT_PARAM;
516     }
517
518     if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
519     {
520         LogDebug("CryptoService error with code: " << retCode);
521         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
522     }
523
524     DBCrypto::Transaction transaction(&handler.database);
525     retCode = saveDataHelper(cred,
526                             toDBDataType(prv.getType()),
527                             aliasPrivate,
528                             prv.getDER(),
529                             policyPrivate);
530
531     if (CKM_API_SUCCESS != retCode)
532         return retCode;
533
534     retCode = saveDataHelper(cred,
535                             toDBDataType(pub.getType()),
536                             aliasPublic,
537                             pub.getDER(),
538                             policyPublic);
539
540     if (CKM_API_SUCCESS != retCode)
541         return retCode;
542
543     transaction.commit();
544
545     return retCode;
546 }
547
548 RawBuffer CKMLogic::createKeyPair(
549     Credentials &cred,
550     LogicCommand protocol_cmd,
551     int commandId,
552     const int additional_param,
553     const Alias &aliasPrivate,
554     const Alias &aliasPublic,
555     const PolicySerializable &policyPrivate,
556     const PolicySerializable &policyPublic)
557 {
558     int retCode = CKM_API_SUCCESS;
559
560     KeyType key_type = KeyType::KEY_NONE;
561     switch(protocol_cmd)
562     {
563         case LogicCommand::CREATE_KEY_PAIR_RSA:
564             key_type = KeyType::KEY_RSA_PUBLIC;
565             break;
566         case LogicCommand::CREATE_KEY_PAIR_DSA:
567             key_type = KeyType::KEY_DSA_PUBLIC;
568             break;
569         case LogicCommand::CREATE_KEY_PAIR_ECDSA:
570             key_type = KeyType::KEY_ECDSA_PUBLIC;
571             break;
572         default:
573             break;
574     }
575
576     try {
577         retCode = createKeyPairHelper(
578                         cred,
579                         key_type,
580                         additional_param,
581                         aliasPrivate,
582                         aliasPublic,
583                         policyPrivate,
584                         policyPublic);
585
586     } catch (DBCrypto::Exception::AliasExists &e) {
587         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
588         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
589     } catch (DBCrypto::Exception::TransactionError &e) {
590         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
591         retCode = CKM_API_ERROR_DB_ERROR;
592     } catch (CKM::CryptoLogic::Exception::Base &e) {
593         LogDebug("CryptoLogic error: " << e.GetMessage());
594         retCode = CKM_API_ERROR_SERVER_ERROR;
595     } catch (DBCrypto::Exception::InternalError &e) {
596         LogDebug("DBCrypto internal error: " << e.GetMessage());
597         retCode = CKM_API_ERROR_DB_ERROR;
598     }
599
600     MessageBuffer response;
601     Serialization::Serialize(response, static_cast<int>(protocol_cmd));
602     Serialization::Serialize(response, commandId);
603     Serialization::Serialize(response, retCode);
604
605     return response.Pop();
606 }
607
608 RawBuffer CKMLogic::getCertificateChain(
609     Credentials &cred,
610     int commandId,
611     const RawBuffer &certificate,
612     const RawBufferVector &untrustedRawCertVector)
613 {
614     (void)cred;
615
616     CertificateImpl cert(certificate, DataFormat::FORM_DER);
617     CertificateImplVector untrustedCertVector;
618     CertificateImplVector chainVector;
619     RawBufferVector chainRawVector;
620
621     for (auto &e: untrustedRawCertVector)
622         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
623
624     LogDebug("Cert is empty: " << cert.empty());
625
626     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
627
628     if (retCode == CKM_API_SUCCESS) {
629         for (auto &e : chainVector)
630             chainRawVector.push_back(e.getDER());
631     }
632
633     MessageBuffer response;
634     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
635     Serialization::Serialize(response, commandId);
636     Serialization::Serialize(response, retCode);
637     Serialization::Serialize(response, chainRawVector);
638     return response.Pop();
639 }
640
641 RawBuffer CKMLogic::getCertificateChain(
642     Credentials &cred,
643     int commandId,
644     const RawBuffer &certificate,
645     const AliasVector &aliasVector)
646 {
647     int retCode = CKM_API_SUCCESS;
648     RawBufferVector chainRawVector;
649     try {
650         CertificateImpl cert(certificate, DataFormat::FORM_DER);
651         CertificateImplVector untrustedCertVector;
652         CertificateImplVector chainVector;
653         DBRow row;
654
655         if (cert.empty()) {
656             retCode = CKM_API_ERROR_SERVER_ERROR;
657             goto senderror;
658         }
659
660         for (auto &i: aliasVector) {
661             retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row);
662
663             if (retCode != CKM_API_SUCCESS)
664                 goto senderror;
665
666             untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
667         }
668
669         retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
670
671         if (retCode != CKM_API_SUCCESS)
672             goto senderror;
673
674         for (auto &i: chainVector)
675             chainRawVector.push_back(i.getDER());
676
677     } catch (const CryptoLogic::Exception::Base &e) {
678         LogError("DBCyptorModule failed with message: " << e.GetMessage());
679         retCode = CKM_API_ERROR_SERVER_ERROR;
680     } catch (const DBCrypto::Exception::Base &e) {
681         LogError("DBCrypto failed with message: " << e.GetMessage());
682         retCode = CKM_API_ERROR_DB_ERROR;
683     } catch (...) {
684         LogError("Unknown error.");
685     }
686
687 senderror:
688     MessageBuffer response;
689     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
690     Serialization::Serialize(response, commandId);
691     Serialization::Serialize(response, retCode);
692     Serialization::Serialize(response, chainRawVector);
693     return response.Pop();
694 }
695
696 RawBuffer CKMLogic::createSignature(
697         Credentials &cred,
698         int commandId,
699         const Alias &privateKeyAlias,
700         const Password &password,           // password for private_key
701         const RawBuffer &message,
702         const HashAlgorithm hash,
703         const RSAPaddingAlgorithm padding)
704 {
705     DBRow row;
706     CryptoService cs;
707     RawBuffer signature;
708
709     int retCode = CKM_API_SUCCESS;
710
711     try {
712         do {
713             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyAlias, password, row);
714             if (CKM_API_SUCCESS != retCode) {
715                 LogError("getDataHelper return error");
716                 break;
717             }
718
719             KeyImpl keyParsed(row.data, Password());
720             if (keyParsed.empty())
721                 retCode = CKM_API_ERROR_SERVER_ERROR;
722             else
723                 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
724         } while(0);
725     } catch (const KeyProvider::Exception::Base &e) {
726         LogError("KeyProvider failed with message: " << e.GetMessage());
727         retCode = CKM_API_ERROR_SERVER_ERROR;
728     } catch (const CryptoLogic::Exception::Base &e) {
729         LogError("CryptoLogic failed with message: " << e.GetMessage());
730         retCode = CKM_API_ERROR_SERVER_ERROR;
731     } catch (const DBCrypto::Exception::Base &e) {
732         LogError("DBCrypto failed with message: " << e.GetMessage());
733         retCode = CKM_API_ERROR_DB_ERROR;
734     } catch (const CKM::Exception &e) {
735         LogError("Unknown CKM::Exception: " << e.GetMessage());
736         retCode = CKM_API_ERROR_SERVER_ERROR;
737     }
738
739     MessageBuffer response;
740     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
741     Serialization::Serialize(response, commandId);
742     Serialization::Serialize(response, retCode);
743     Serialization::Serialize(response, signature);
744     return response.Pop();
745 }
746
747 RawBuffer CKMLogic::verifySignature(
748         Credentials &cred,
749         int commandId,
750         const Alias &publicKeyOrCertAlias,
751         const Password &password,           // password for public_key (optional)
752         const RawBuffer &message,
753         const RawBuffer &signature,
754         const HashAlgorithm hash,
755         const RSAPaddingAlgorithm padding)
756 {
757     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
758
759     try {
760         do {
761             CryptoService cs;
762             DBRow row;
763             KeyImpl key;
764
765             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
766
767             if (retCode == CKM_API_SUCCESS) {
768                 key = KeyImpl(row.data);
769             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
770                 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
771                 if (retCode != CKM_API_SUCCESS)
772                     break;
773                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
774                 key = cert.getKeyImpl();
775             } else {
776                 break;
777             }
778
779             if (key.empty()) {
780                 retCode = CKM_API_ERROR_SERVER_ERROR;
781                 break;
782             }
783
784             retCode = cs.verifySignature(key, message, signature, hash, padding);
785         } while(0);
786     } catch (const CryptoService::Exception::Crypto_internal &e) {
787         LogError("KeyProvider failed with message: " << e.GetMessage());
788         retCode = CKM_API_ERROR_SERVER_ERROR;
789     } catch (const CryptoService::Exception::opensslError &e) {
790         LogError("KeyProvider failed with message: " << e.GetMessage());
791         retCode = CKM_API_ERROR_SERVER_ERROR;
792     } catch (const KeyProvider::Exception::Base &e) {
793         LogError("KeyProvider failed with error: " << e.GetMessage());
794         retCode = CKM_API_ERROR_SERVER_ERROR;
795     } catch (const CryptoLogic::Exception::Base &e) {
796         LogError("CryptoLogic failed with message: " << e.GetMessage());
797         retCode = CKM_API_ERROR_SERVER_ERROR;
798     } catch (const DBCrypto::Exception::Base &e) {
799         LogError("DBCrypto failed with message: " << e.GetMessage());
800         retCode = CKM_API_ERROR_DB_ERROR;
801     } catch (const CKM::Exception &e) {
802         LogError("Unknown CKM::Exception: " << e.GetMessage());
803         retCode = CKM_API_ERROR_SERVER_ERROR;
804     }
805
806     MessageBuffer response;
807     Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
808     Serialization::Serialize(response, commandId);
809     Serialization::Serialize(response, retCode);
810
811     return response.Pop();
812 }
813 } // namespace CKM
814