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