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