Remove restrict mechanism.
[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
51 CKMLogic::~CKMLogic(){}
52
53 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) {
54     // TODO try catch for all errors that should be supported by error code
55     int retCode = CKM_API_SUCCESS;
56
57     try {
58         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
59             auto &handle = m_userDataMap[user];
60             FileSystem fs(user);
61             auto wrappedDomainKEK = fs.getDKEK();
62
63             if (wrappedDomainKEK.empty()) {
64                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
65                 fs.saveDKEK(wrappedDomainKEK);
66             }
67
68             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
69
70             auto wrappedDatabaseDEK = fs.getDBDEK();
71
72             if (wrappedDatabaseDEK.empty()) {
73                 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
74                 fs.saveDBDEK(wrappedDatabaseDEK);
75             }
76
77             RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
78             handle.database = DBCrypto(fs.getDBPath(), key);
79             handle.crypto = CryptoLogic();
80             // TODO wipe key
81         }
82     } catch (const KeyProvider::Exception::PassWordError &e) {
83         LogError("Incorrect Password " << e.GetMessage());
84         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
85     } catch (const KeyProvider::Exception::Base &e) {
86         LogError("Error in KeyProvider " << e.GetMessage());
87         retCode = CKM_API_ERROR_SERVER_ERROR;
88     } catch (const CryptoLogic::Exception::Base &e) {
89         LogError("CryptoLogic error: " << e.GetMessage());
90         retCode = CKM_API_ERROR_SERVER_ERROR;
91     } catch (const CKM::Exception &e) {
92         LogError("CKM::Exception: " << e.GetMessage());
93         retCode = CKM_API_ERROR_SERVER_ERROR;
94     }
95
96     if(retCode != CKM_API_SUCCESS) {
97         // When not successful, UserData in m_userDataMap should be erased.
98         // Because other operations make decision based on the existence of UserData in m_userDataMap.
99         m_userDataMap.erase(user);
100     }
101
102     MessageBuffer response;
103     Serialization::Serialize(response, retCode);
104     return response.Pop();
105 }
106
107 RawBuffer CKMLogic::lockUserKey(uid_t user) {
108     int retCode = CKM_API_SUCCESS;
109     // TODO try catch for all errors that should be supported by error code
110     m_userDataMap.erase(user);
111
112     MessageBuffer response;
113     Serialization::Serialize(response, retCode);
114     return response.Pop();
115 }
116
117 RawBuffer CKMLogic::removeUserData(uid_t user) {
118     int retCode = CKM_API_SUCCESS;
119     // TODO try catch for all errors that should be supported by error code
120     m_userDataMap.erase(user);
121
122     FileSystem fs(user);
123     fs.removeUserData();
124
125     MessageBuffer response;
126     Serialization::Serialize(response, retCode);
127     return response.Pop();
128 }
129
130 RawBuffer CKMLogic::changeUserPassword(
131     uid_t user,
132     const Password &oldPassword,
133     const Password &newPassword)
134 {
135     int retCode = CKM_API_SUCCESS;
136     try {
137         FileSystem fs(user);
138         auto wrappedDomainKEK = fs.getDKEK();
139         if (wrappedDomainKEK.empty()) {
140             retCode = CKM_API_ERROR_BAD_REQUEST;
141         } else {
142             wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
143             fs.saveDKEK(wrappedDomainKEK);
144         }
145     } catch (const KeyProvider::Exception::PassWordError &e) {
146         LogError("Incorrect Password " << e.GetMessage());
147         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
148     } catch (const KeyProvider::Exception::Base &e) {
149         LogError("Error in KeyProvider " << e.GetMessage());
150         retCode = CKM_API_ERROR_SERVER_ERROR;
151     } catch (const CKM::Exception &e) {
152         LogError("CKM::Exception: " << e.GetMessage());
153         retCode = CKM_API_ERROR_SERVER_ERROR;
154     }
155
156     MessageBuffer response;
157     Serialization::Serialize(response, retCode);
158     return response.Pop();
159 }
160
161 RawBuffer CKMLogic::resetUserPassword(
162     uid_t user,
163     const Password &newPassword)
164 {
165     int retCode = CKM_API_SUCCESS;
166     // TODO try-catch
167     if (0 == m_userDataMap.count(user)) {
168         retCode = CKM_API_ERROR_BAD_REQUEST;
169     } else {
170         auto &handler = m_userDataMap[user];
171         FileSystem fs(user);
172         fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
173     }
174
175     MessageBuffer response;
176     Serialization::Serialize(response, retCode);
177     return response.Pop();
178 }
179
180 RawBuffer CKMLogic::removeApplicationData(const std::string &smackLabel) {
181     int retCode = CKM_API_SUCCESS;
182
183     try {
184
185         if (smackLabel.empty()) {
186             retCode = CKM_API_ERROR_INPUT_PARAM;
187         } else {
188             for(auto &handler: m_userDataMap) {
189                 handler.second.database.deleteKey(smackLabel);
190             }
191         }
192
193     } catch (const DBCrypto::Exception::InternalError &e) {
194         LogError("DBCrypto couldn't remove data: " << e.GetMessage());
195         retCode = CKM_API_ERROR_DB_ERROR;
196     } catch (const DBCrypto::Exception::TransactionError &e) {
197         LogError("DBCrypto transaction failed with message " << e.GetMessage());
198         retCode = CKM_API_ERROR_DB_ERROR;
199     }
200
201     MessageBuffer response;
202     Serialization::Serialize(response, retCode);
203     return response.Pop();
204 }
205
206 int CKMLogic::saveDataHelper(
207     Credentials &cred,
208     DBDataType dataType,
209     const Alias &alias,
210     const RawBuffer &key,
211     const PolicySerializable &policy)
212 {
213     if (0 == m_userDataMap.count(cred.uid))
214         return CKM_API_ERROR_DB_LOCKED;
215
216     DBRow row = { alias, cred.smackLabel,
217          policy.extractable, dataType, DBCMAlgType::NONE,
218          0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
219
220     auto &handler = m_userDataMap[cred.uid];
221     DBCrypto::Transaction transaction(&handler.database);
222     if (!handler.crypto.haveKey(cred.smackLabel)) {
223         RawBuffer key;
224         auto key_optional = handler.database.getKey(cred.smackLabel);
225         if(!key_optional) {
226             LogDebug("No Key in database found. Generating new one for label: "
227                     << cred.smackLabel);
228             key = handler.keyProvider.generateDEK(cred.smackLabel);
229             handler.database.saveKey(cred.smackLabel, key);
230         } else {
231             LogDebug("Key from DB");
232             key = *key_optional;
233         }
234
235         key = handler.keyProvider.getPureDEK(key);
236         handler.crypto.pushKey(cred.smackLabel, key);
237     }
238     handler.crypto.encryptRow(policy.password, row);
239     handler.database.saveDBRow(row);
240     transaction.commit();
241     return CKM_API_SUCCESS;
242 }
243
244 RawBuffer CKMLogic::saveData(
245     Credentials &cred,
246     int commandId,
247     DBDataType dataType,
248     const Alias &alias,
249     const RawBuffer &key,
250     const PolicySerializable &policy)
251 {
252     int retCode = CKM_API_SUCCESS;
253     try {
254         retCode = saveDataHelper(cred, dataType, alias, key, policy);
255         LogDebug("SaveDataHelper returned: " << retCode);
256     } catch (const KeyProvider::Exception::Base &e) {
257         LogError("KeyProvider failed with message: " << e.GetMessage());
258         retCode = CKM_API_ERROR_SERVER_ERROR;
259     } catch (const CryptoLogic::Exception::Base &e) {
260         LogError("CryptoLogic failed with message: " << e.GetMessage());
261         retCode = CKM_API_ERROR_SERVER_ERROR;
262     } catch (const DBCrypto::Exception::InternalError &e) {
263         LogError("DBCrypto failed with message: " << e.GetMessage());
264         retCode = CKM_API_ERROR_DB_ERROR;
265     } catch (const DBCrypto::Exception::AliasExists &e) {
266         LogError("DBCrypto couldn't save duplicate alias");
267         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
268     } catch (const DBCrypto::Exception::TransactionError &e) {
269         LogError("DBCrypto transaction failed with message " << e.GetMessage());
270         retCode = CKM_API_ERROR_DB_ERROR;
271     }
272
273     MessageBuffer response;
274     Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
275     Serialization::Serialize(response, commandId);
276     Serialization::Serialize(response, retCode);
277     Serialization::Serialize(response, static_cast<int>(dataType));
278
279     return response.Pop();
280 }
281
282 RawBuffer CKMLogic::removeData(
283     Credentials &cred,
284     int commandId,
285     DBDataType dataType,
286     const Alias &alias)
287 {
288     int retCode = CKM_API_SUCCESS;
289
290     if (0 < m_userDataMap.count(cred.uid)) {
291         Try {
292             auto erased = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
293             // check if the data existed or not
294             if(!erased) {
295                 LogError("No row for given alias and label");
296                 retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
297             }
298         } Catch (CKM::Exception) {
299             LogError("Error in deleting row!");
300             retCode = CKM_API_ERROR_DB_ERROR;
301         }
302     } else {
303         retCode = CKM_API_ERROR_DB_LOCKED;
304     }
305
306     MessageBuffer response;
307     Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
308     Serialization::Serialize(response, commandId);
309     Serialization::Serialize(response, retCode);
310     Serialization::Serialize(response, static_cast<int>(dataType));
311
312     return response.Pop();
313 }
314
315 int CKMLogic::getDataHelper(
316     Credentials &cred,
317     DBDataType dataType,
318     const Alias &alias,
319     const Password &password,
320     DBRow &row)
321 {
322
323     if (0 == m_userDataMap.count(cred.uid))
324         return CKM_API_ERROR_DB_LOCKED;
325
326     auto &handler = m_userDataMap[cred.uid];
327
328     DBCrypto::DBRowOptional row_optional;
329     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
330         row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
331     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
332             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
333     {
334         row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
335     } else {
336         LogError("Unknown type of requested data" << (int)dataType);
337         return CKM_API_ERROR_BAD_REQUEST;
338     }
339     if(!row_optional) {
340         LogError("No row for given alias, label and type");
341         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
342     } else {
343         row = *row_optional;
344     }
345
346     if (!handler.crypto.haveKey(row.smackLabel)) {
347         RawBuffer key;
348         auto key_optional = handler.database.getKey(row.smackLabel);
349         if(!key_optional) {
350             LogError("No key for given label in database");
351             return CKM_API_ERROR_DB_ERROR;
352         }
353         key = *key_optional;
354         key = handler.keyProvider.getPureDEK(key);
355         handler.crypto.pushKey(cred.smackLabel, key);
356     }
357     handler.crypto.decryptRow(password, row);
358
359     return CKM_API_SUCCESS;
360 }
361
362 RawBuffer CKMLogic::getData(
363     Credentials &cred,
364     int commandId,
365     DBDataType dataType,
366     const Alias &alias,
367     const Password &password)
368 {
369     int retCode = CKM_API_SUCCESS;
370     DBRow row;
371
372     try {
373         retCode = getDataHelper(cred, dataType, alias, password, row);
374     } catch (const KeyProvider::Exception::Base &e) {
375         LogError("KeyProvider failed with error: " << e.GetMessage());
376         retCode = CKM_API_ERROR_SERVER_ERROR;
377     } catch (const CryptoLogic::Exception::Base &e) {
378         LogError("CryptoLogic failed with message: " << e.GetMessage());
379         retCode = CKM_API_ERROR_SERVER_ERROR;
380     } catch (const DBCrypto::Exception::Base &e) {
381         LogError("DBCrypto failed with message: " << e.GetMessage());
382         retCode = CKM_API_ERROR_DB_ERROR;
383     }
384
385     if (CKM_API_SUCCESS != retCode) {
386         row.data.clear();
387         row.dataType = dataType;
388     }
389
390     if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
391         row.data.clear();
392         retCode = CKM_API_ERROR_NOT_EXPORTABLE;
393     }
394
395     MessageBuffer response;
396     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
397     Serialization::Serialize(response, commandId);
398     Serialization::Serialize(response, retCode);
399     Serialization::Serialize(response, static_cast<int>(row.dataType));
400     Serialization::Serialize(response, row.data);
401     return response.Pop();
402 }
403
404 RawBuffer CKMLogic::getDataList(
405     Credentials &cred,
406     int commandId,
407     DBDataType dataType)
408 {
409     int retCode = CKM_API_SUCCESS;
410     AliasVector aliasVector;
411
412     if (0 < m_userDataMap.count(cred.uid)) {
413         auto &handler = m_userDataMap[cred.uid];
414         Try {
415             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
416                 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
417             } else {
418                 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
419             }
420         } Catch (CKM::Exception) {
421             LogError("Failed to get aliases");
422             retCode = CKM_API_ERROR_DB_ERROR;
423         }
424     } else {
425         retCode = CKM_API_ERROR_DB_LOCKED;
426     }
427
428     MessageBuffer response;
429     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
430     Serialization::Serialize(response, commandId);
431     Serialization::Serialize(response, retCode);
432     Serialization::Serialize(response, static_cast<int>(dataType));
433     Serialization::Serialize(response, aliasVector);
434     return response.Pop();
435 }
436
437 int CKMLogic::createKeyPairRSAHelper(
438     Credentials &cred,
439     int size,
440     const Alias &aliasPrivate,
441     const Alias &aliasPublic,
442     const PolicySerializable &policyPrivate,
443     const PolicySerializable &policyPublic)
444 {
445     if (0 >= m_userDataMap.count(cred.uid))
446         return CKM_API_ERROR_DB_LOCKED;
447
448     auto &handler = m_userDataMap[cred.uid];
449     KeyImpl prv, pub;
450     int retCode;
451
452     if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
453         (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
454     {
455         LogDebug("CryptoService error with code: " << retCode);
456         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
457     }
458
459     DBCrypto::Transaction transaction(&handler.database);
460     retCode = saveDataHelper(cred,
461                             toDBDataType(prv.getType()),
462                             aliasPrivate,
463                             prv.getDER(),
464                             policyPrivate);
465
466     if (CKM_API_SUCCESS != retCode)
467         return retCode;
468
469     retCode = saveDataHelper(cred,
470                             toDBDataType(pub.getType()),
471                             aliasPublic,
472                             pub.getDER(),
473                             policyPublic);
474
475     if (CKM_API_SUCCESS != retCode)
476         return retCode;
477
478     transaction.commit();
479
480     return retCode;
481 }
482
483 RawBuffer CKMLogic::createKeyPairRSA(
484     Credentials &cred,
485     int commandId,
486     int size,
487     const Alias &aliasPrivate,
488     const Alias &aliasPublic,
489     const PolicySerializable &policyPrivate,
490     const PolicySerializable &policyPublic)
491 {
492     int retCode = CKM_API_SUCCESS;
493
494     try {
495         retCode = createKeyPairRSAHelper(
496                         cred,
497                         size,
498                         aliasPrivate,
499                         aliasPublic,
500                         policyPrivate,
501                         policyPublic);
502
503     } catch (DBCrypto::Exception::AliasExists &e) {
504         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
505         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
506     } catch (DBCrypto::Exception::TransactionError &e) {
507         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
508         retCode = CKM_API_ERROR_DB_ERROR;
509     } catch (CKM::CryptoLogic::Exception::Base &e) {
510         LogDebug("CryptoLogic error: " << e.GetMessage());
511         retCode = CKM_API_ERROR_SERVER_ERROR;
512     } catch (DBCrypto::Exception::InternalError &e) {
513         LogDebug("DBCrypto internal error: " << e.GetMessage());
514         retCode = CKM_API_ERROR_DB_ERROR;
515     }
516
517     MessageBuffer response;
518     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
519     Serialization::Serialize(response, commandId);
520     Serialization::Serialize(response, retCode);
521
522     return response.Pop();
523 }
524
525 int CKMLogic::createKeyPairECDSAHelper(
526     Credentials &cred,
527     int type,
528     const Alias &aliasPrivate,
529     const Alias &aliasPublic,
530     const PolicySerializable &policyPrivate,
531     const PolicySerializable &policyPublic)
532 {
533     if (0 >= m_userDataMap.count(cred.uid))
534         return CKM_API_ERROR_DB_LOCKED;
535
536     auto &handler = m_userDataMap[cred.uid];
537     KeyImpl prv, pub;
538     int retCode;
539
540     if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
541         (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
542     {
543         LogError("CryptoService failed with code: " << retCode);
544         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
545     }
546
547     DBCrypto::Transaction transaction(&handler.database);
548
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::createKeyPairECDSA(
573     Credentials &cred,
574     int commandId,
575     int type,
576     const Alias &aliasPrivate,
577     const Alias &aliasPublic,
578     const PolicySerializable &policyPrivate,
579     const PolicySerializable &policyPublic)
580 {
581     int retCode = CKM_API_SUCCESS;
582
583     try {
584         retCode = createKeyPairECDSAHelper(
585                         cred,
586                         type,
587                         aliasPrivate,
588                         aliasPublic,
589                         policyPrivate,
590                         policyPublic);
591     } catch (const DBCrypto::Exception::AliasExists &e) {
592         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
593         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
594     } catch (const DBCrypto::Exception::TransactionError &e) {
595         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
596         retCode = CKM_API_ERROR_DB_ERROR;
597     } catch (const CKM::CryptoLogic::Exception::Base &e) {
598         LogDebug("CryptoLogic error: " << e.GetMessage());
599         retCode = CKM_API_ERROR_SERVER_ERROR;
600     } catch (const DBCrypto::Exception::InternalError &e) {
601         LogDebug("DBCrypto internal error: " << e.GetMessage());
602         retCode = CKM_API_ERROR_DB_ERROR;
603     }
604
605     MessageBuffer response;
606     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
607     Serialization::Serialize(response, commandId);
608     Serialization::Serialize(response, retCode);
609
610     return response.Pop();
611 }
612
613 RawBuffer CKMLogic::getCertificateChain(
614     Credentials &cred,
615     int commandId,
616     const RawBuffer &certificate,
617     const RawBufferVector &untrustedRawCertVector)
618 {
619     (void)cred;
620
621     CertificateImpl cert(certificate, DataFormat::FORM_DER);
622     CertificateImplVector untrustedCertVector;
623     CertificateImplVector chainVector;
624     RawBufferVector chainRawVector;
625
626     for (auto &e: untrustedRawCertVector)
627         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
628
629     LogDebug("Cert is empty: " << cert.empty());
630
631     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
632
633     if (retCode == CKM_API_SUCCESS) {
634         for (auto &e : chainVector)
635             chainRawVector.push_back(e.getDER());
636     }
637
638     MessageBuffer response;
639     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
640     Serialization::Serialize(response, commandId);
641     Serialization::Serialize(response, retCode);
642     Serialization::Serialize(response, chainRawVector);
643     return response.Pop();
644 }
645
646 RawBuffer CKMLogic::getCertificateChain(
647     Credentials &cred,
648     int commandId,
649     const RawBuffer &certificate,
650     const AliasVector &aliasVector)
651 {
652     int retCode = CKM_API_SUCCESS;
653     RawBufferVector chainRawVector;
654     try {
655         CertificateImpl cert(certificate, DataFormat::FORM_DER);
656         CertificateImplVector untrustedCertVector;
657         CertificateImplVector chainVector;
658         DBRow row;
659
660         if (cert.empty()) {
661             retCode = CKM_API_ERROR_SERVER_ERROR;
662             goto senderror;
663         }
664
665         for (auto &i: aliasVector) {
666             retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row);
667
668             if (retCode != CKM_API_SUCCESS)
669                 goto senderror;
670
671             untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
672         }
673
674         retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
675
676         if (retCode != CKM_API_SUCCESS)
677             goto senderror;
678
679         for (auto &i: chainVector)
680             chainRawVector.push_back(i.getDER());
681
682     } catch (const CryptoLogic::Exception::Base &e) {
683         LogError("DBCyptorModule failed with message: " << e.GetMessage());
684         retCode = CKM_API_ERROR_SERVER_ERROR;
685     } catch (const DBCrypto::Exception::Base &e) {
686         LogError("DBCrypto failed with message: " << e.GetMessage());
687         retCode = CKM_API_ERROR_DB_ERROR;
688     } catch (...) {
689         LogError("Unknown error.");
690     }
691
692 senderror:
693     MessageBuffer response;
694     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
695     Serialization::Serialize(response, commandId);
696     Serialization::Serialize(response, retCode);
697     Serialization::Serialize(response, chainRawVector);
698     return response.Pop();
699 }
700
701 RawBuffer CKMLogic::createSignature(
702         Credentials &cred,
703         int commandId,
704         const Alias &privateKeyAlias,
705         const Password &password,           // password for private_key
706         const RawBuffer &message,
707         const HashAlgorithm hash,
708         const RSAPaddingAlgorithm padding)
709 {
710     DBRow row;
711     CryptoService cs;
712     RawBuffer signature;
713
714     int retCode = CKM_API_SUCCESS;
715
716     try {
717         do {
718             retCode = getDataHelper(cred, DBDataType::KEY_RSA_PUBLIC, privateKeyAlias, password, row);
719             if (CKM_API_SUCCESS != retCode) {
720                 LogError("getDataHelper return error");
721                 break;
722             }
723
724             KeyImpl keyParsed(row.data, Password());
725             if (keyParsed.empty())
726                 retCode = CKM_API_ERROR_SERVER_ERROR;
727             else
728                 cs.createSignature(keyParsed, message, hash, padding, signature);
729         } while(0);
730     } catch (const KeyProvider::Exception::Base &e) {
731         LogError("KeyProvider failed with message: " << e.GetMessage());
732         retCode = CKM_API_ERROR_SERVER_ERROR;
733     } catch (const CryptoLogic::Exception::Base &e) {
734         LogError("CryptoLogic failed with message: " << e.GetMessage());
735         retCode = CKM_API_ERROR_SERVER_ERROR;
736     } catch (const DBCrypto::Exception::Base &e) {
737         LogError("DBCrypto failed with message: " << e.GetMessage());
738         retCode = CKM_API_ERROR_DB_ERROR;
739     } catch (const CKM::Exception &e) {
740         LogError("Unknown CKM::Exception: " << e.GetMessage());
741         retCode = CKM_API_ERROR_SERVER_ERROR;
742     }
743
744     MessageBuffer response;
745     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
746     Serialization::Serialize(response, commandId);
747     Serialization::Serialize(response, retCode);
748     Serialization::Serialize(response, signature);
749     return response.Pop();
750 }
751
752 RawBuffer CKMLogic::verifySignature(
753         Credentials &cred,
754         int commandId,
755         const Alias &publicKeyOrCertAlias,
756         const Password &password,           // password for public_key (optional)
757         const RawBuffer &message,
758         const RawBuffer &signature,
759         const HashAlgorithm hash,
760         const RSAPaddingAlgorithm padding)
761 {
762     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
763
764     try {
765         do {
766             CryptoService cs;
767             DBRow row;
768             KeyImpl key;
769
770             retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
771
772             if (retCode == CKM_API_SUCCESS) {
773                 key = KeyImpl(row.data);
774             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
775                 retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row);
776                 if (retCode != CKM_API_SUCCESS)
777                     break;
778                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
779                 key = cert.getKeyImpl();
780             } else {
781                 break;
782             }
783
784             if (key.empty()) {
785                 retCode = CKM_API_ERROR_SERVER_ERROR;
786                 break;
787             }
788
789             retCode = cs.verifySignature(key, message, signature, hash, padding);
790         } while(0);
791     } catch (const CryptoService::Exception::Crypto_internal &e) {
792         LogError("KeyProvider failed with message: " << e.GetMessage());
793         retCode = CKM_API_ERROR_SERVER_ERROR;
794     } catch (const CryptoService::Exception::opensslError &e) {
795         LogError("KeyProvider failed with message: " << e.GetMessage());
796         retCode = CKM_API_ERROR_SERVER_ERROR;
797     } catch (const KeyProvider::Exception::Base &e) {
798         LogError("KeyProvider failed with error: " << e.GetMessage());
799         retCode = CKM_API_ERROR_SERVER_ERROR;
800     } catch (const CryptoLogic::Exception::Base &e) {
801         LogError("CryptoLogic failed with message: " << e.GetMessage());
802         retCode = CKM_API_ERROR_SERVER_ERROR;
803     } catch (const DBCrypto::Exception::Base &e) {
804         LogError("DBCrypto failed with message: " << e.GetMessage());
805         retCode = CKM_API_ERROR_DB_ERROR;
806     } catch (const CKM::Exception &e) {
807         LogError("Unknown CKM::Exception: " << e.GetMessage());
808         retCode = CKM_API_ERROR_SERVER_ERROR;
809     }
810
811     MessageBuffer response;
812     Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
813     Serialization::Serialize(response, commandId);
814     Serialization::Serialize(response, retCode);
815
816     return response.Pop();
817 }
818 } // namespace CKM
819