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