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