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