New DB layout: CKM_TABLE split into NAME_TABLE and OBJECT_TABLE.
[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 <vconf/vconf.h>
23 #include <dpl/serialization.h>
24 #include <dpl/log/log.h>
25 #include <ckm/ckm-error.h>
26 #include <ckm/ckm-type.h>
27 #include <key-provider.h>
28 #include <file-system.h>
29 #include <CryptoService.h>
30 #include <ckm-logic.h>
31 #include <key-impl.h>
32
33 namespace {
34 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
35
36 bool isLabelValid(const CKM::Label &label) {
37     // TODO: copy code from libprivilege control (for check smack label)
38     if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos)
39         return false;
40     return true;
41 }
42
43 bool isNameValid(const CKM::Name &name) {
44     if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos)
45         return false;
46     return true;
47 }
48
49 } // anonymous namespace
50
51 namespace CKM {
52
53 CKMLogic::CKMLogic()
54 {
55     if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
56         LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
57     }
58
59     m_accessControl.updateCCMode();
60 }
61
62 CKMLogic::~CKMLogic(){}
63
64 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) {
65     // TODO try catch for all errors that should be supported by error code
66     int retCode = CKM_API_SUCCESS;
67
68     try {
69         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
70             auto &handle = m_userDataMap[user];
71             FileSystem fs(user);
72             auto wrappedDomainKEK = fs.getDKEK();
73
74             if (wrappedDomainKEK.empty()) {
75                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
76                 fs.saveDKEK(wrappedDomainKEK);
77             }
78
79             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
80
81             auto wrappedDatabaseDEK = fs.getDBDEK();
82
83             if (wrappedDatabaseDEK.empty()) {
84                 wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
85                 fs.saveDBDEK(wrappedDatabaseDEK);
86             }
87
88             RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
89             handle.database = DBCrypto(fs.getDBPath(), key);
90             handle.crypto = CryptoLogic();
91
92             // remove data of removed apps during locked state
93             AppLabelVector removedApps = fs.clearRemovedsApps();
94             for(auto& appSmackLabel : removedApps) {
95                 handle.database.deleteKey(appSmackLabel);
96             }
97         }
98     } catch (const KeyProvider::Exception::PassWordError &e) {
99         LogError("Incorrect Password " << e.GetMessage());
100         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
101     } catch (const KeyProvider::Exception::Base &e) {
102         LogError("Error in KeyProvider " << e.GetMessage());
103         retCode = CKM_API_ERROR_SERVER_ERROR;
104     } catch (const CryptoLogic::Exception::Base &e) {
105         LogError("CryptoLogic error: " << e.GetMessage());
106         retCode = CKM_API_ERROR_SERVER_ERROR;
107     } catch (const CKM::Exception &e) {
108         LogError("CKM::Exception: " << e.GetMessage());
109         retCode = CKM_API_ERROR_SERVER_ERROR;
110     }
111
112     if(retCode != CKM_API_SUCCESS) {
113         // When not successful, UserData in m_userDataMap should be erased.
114         // Because other operations make decision based on the existence of UserData in m_userDataMap.
115         m_userDataMap.erase(user);
116     }
117
118     return MessageBuffer::Serialize(retCode).Pop();
119 }
120
121 RawBuffer CKMLogic::updateCCMode() {
122     m_accessControl.updateCCMode();
123     return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
124 }
125
126 RawBuffer CKMLogic::lockUserKey(uid_t user) {
127     int retCode = CKM_API_SUCCESS;
128     // TODO try catch for all errors that should be supported by error code
129     m_userDataMap.erase(user);
130
131     return MessageBuffer::Serialize(retCode).Pop();
132
133 }
134
135 RawBuffer CKMLogic::removeUserData(uid_t user) {
136     int retCode = CKM_API_SUCCESS;
137     // TODO try catch for all errors that should be supported by error code
138     m_userDataMap.erase(user);
139
140     FileSystem fs(user);
141     fs.removeUserData();
142
143     return MessageBuffer::Serialize(retCode).Pop();
144 }
145
146 RawBuffer CKMLogic::changeUserPassword(
147     uid_t user,
148     const Password &oldPassword,
149     const Password &newPassword)
150 {
151     int retCode = CKM_API_SUCCESS;
152     try {
153         FileSystem fs(user);
154         auto wrappedDomainKEK = fs.getDKEK();
155         if (wrappedDomainKEK.empty()) {
156             retCode = CKM_API_ERROR_BAD_REQUEST;
157         } else {
158             wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
159             fs.saveDKEK(wrappedDomainKEK);
160         }
161     } catch (const KeyProvider::Exception::PassWordError &e) {
162         LogError("Incorrect Password " << e.GetMessage());
163         retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
164     } catch (const KeyProvider::Exception::Base &e) {
165         LogError("Error in KeyProvider " << e.GetMessage());
166         retCode = CKM_API_ERROR_SERVER_ERROR;
167     } catch (const CKM::Exception &e) {
168         LogError("CKM::Exception: " << e.GetMessage());
169         retCode = CKM_API_ERROR_SERVER_ERROR;
170     }
171
172     return MessageBuffer::Serialize(retCode).Pop();
173 }
174
175 RawBuffer CKMLogic::resetUserPassword(
176     uid_t user,
177     const Password &newPassword)
178 {
179     int retCode = CKM_API_SUCCESS;
180     // TODO try-catch
181     if (0 == m_userDataMap.count(user)) {
182         retCode = CKM_API_ERROR_BAD_REQUEST;
183     } else {
184         auto &handler = m_userDataMap[user];
185         FileSystem fs(user);
186         fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
187     }
188
189     return MessageBuffer::Serialize(retCode).Pop();
190 }
191
192 RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
193     int retCode = CKM_API_SUCCESS;
194
195     try {
196
197         if (smackLabel.empty()) {
198             retCode = CKM_API_ERROR_INPUT_PARAM;
199         } else {
200             UidVector uids = FileSystem::getUIDsFromDBFile();
201             for (auto userId : uids) {
202                 if (0 == m_userDataMap.count(userId)) {
203                     FileSystem fs(userId);
204                     fs.addRemovedApp(smackLabel);
205                 } else {
206                     auto &handle = m_userDataMap[userId];
207                     handle.database.deleteKey(smackLabel);
208                 }
209             }
210         }
211
212     } catch (const DBCrypto::Exception::InternalError &e) {
213         LogError("DBCrypto couldn't remove data: " << e.GetMessage());
214         retCode = CKM_API_ERROR_DB_ERROR;
215     } catch (const DBCrypto::Exception::TransactionError &e) {
216         LogError("DBCrypto transaction failed with message " << e.GetMessage());
217         retCode = CKM_API_ERROR_DB_ERROR;
218     }
219
220     return MessageBuffer::Serialize(retCode).Pop();
221 }
222
223 int CKMLogic::saveDataHelper(
224     const Credentials &cred,
225     DBDataType dataType,
226     const Name &name,
227     const Label &label,
228     const RawBuffer &key,
229     const PolicySerializable &policy)
230 {
231     // use client label if not explicitly provided
232     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
233
234     // verify name and label are correct
235     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
236         LogWarning("Invalid parameter passed to key-manager");
237         return CKM_API_ERROR_INPUT_PARAM;
238     }
239
240     // check if allowed to save using ownerLabel
241     int access_ec = m_accessControl.canSave(ownerLabel, cred.smackLabel);
242     if(access_ec != CKM_API_SUCCESS)
243     {
244         LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
245         return access_ec;
246     }
247
248     // proceed to data save
249     DBRow row = { name, cred.smackLabel,
250          policy.extractable, dataType, DBCMAlgType::NONE,
251          0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
252
253     if (0 == m_userDataMap.count(cred.uid))
254         return CKM_API_ERROR_DB_LOCKED;
255
256     auto &handler = m_userDataMap[cred.uid];
257     DBCrypto::Transaction transaction(&handler.database);
258
259     // check if not a duplicate
260     if( handler.database.isNameLabelPresent(name, cred.smackLabel) )
261         return CKM_API_ERROR_DB_ALIAS_EXISTS;
262
263     // encryption section
264     if (!handler.crypto.haveKey(cred.smackLabel)) {
265         RawBuffer got_key;
266         auto key_optional = handler.database.getKey(cred.smackLabel);
267         if(!key_optional) {
268             LogDebug("No Key in database found. Generating new one for label: "
269                     << cred.smackLabel);
270             got_key = handler.keyProvider.generateDEK(cred.smackLabel);
271             handler.database.saveKey(cred.smackLabel, got_key);
272         } else {
273             LogDebug("Key from DB");
274             got_key = *key_optional;
275         }
276
277         got_key = handler.keyProvider.getPureDEK(got_key);
278         handler.crypto.pushKey(cred.smackLabel, got_key);
279     }
280
281     // do not encrypt data with password during cc_mode on
282     if(m_accessControl.isCCMode()) {
283         handler.crypto.encryptRow("", row);
284     } else {
285         handler.crypto.encryptRow(policy.password, row);
286     }
287
288     handler.database.saveDBRow(row);
289     transaction.commit();
290     return CKM_API_SUCCESS;
291 }
292
293 void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const
294 {
295     // verify the data integrity
296     switch(dataType)
297     {
298         case DBDataType::KEY_RSA_PUBLIC:
299         case DBDataType::KEY_RSA_PRIVATE:
300         case DBDataType::KEY_ECDSA_PUBLIC:
301         case DBDataType::KEY_ECDSA_PRIVATE:
302         case DBDataType::KEY_DSA_PUBLIC:
303         case DBDataType::KEY_DSA_PRIVATE:
304         case DBDataType::KEY_AES:
305         {
306             KeyShPtr output_key = CKM::Key::create(input_data);
307             if(output_key.get() == NULL)
308                 ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data");
309             break;
310         }
311
312         case DBDataType::CERTIFICATE:
313         {
314             CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
315             if(cert.get() == NULL)
316                 ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data");
317             break;
318         }
319
320         // TODO: add here BINARY_DATA verification, i.e: max size etc.
321
322         default: break;
323     }
324 }
325
326 RawBuffer CKMLogic::saveData(
327     const Credentials &cred,
328     int commandId,
329     DBDataType dataType,
330     const Name &name,
331     const Label &label,
332     const RawBuffer &key,
333     const PolicySerializable &policy)
334 {
335     int retCode = CKM_API_SUCCESS;
336     try {
337         verifyBinaryData(dataType, key);
338
339         retCode = saveDataHelper(cred, dataType, name, label, key, policy);
340         LogDebug("SaveDataHelper returned: " << retCode);
341     } catch (const CKMLogic::Exception::InputDataInvalid &e) {
342         LogError("Provided data invalid: " << e.GetMessage());
343         retCode = CKM_API_ERROR_INPUT_PARAM;
344     } catch (const KeyProvider::Exception::Base &e) {
345         LogError("KeyProvider failed with message: " << e.GetMessage());
346         retCode = CKM_API_ERROR_SERVER_ERROR;
347     } catch (const CryptoLogic::Exception::Base &e) {
348         LogError("CryptoLogic failed with message: " << e.GetMessage());
349         retCode = CKM_API_ERROR_SERVER_ERROR;
350     } catch (const DBCrypto::Exception::InternalError &e) {
351         LogError("DBCrypto failed with message: " << e.GetMessage());
352         retCode = CKM_API_ERROR_DB_ERROR;
353     } catch (const DBCrypto::Exception::TransactionError &e) {
354         LogError("DBCrypto transaction failed with message " << e.GetMessage());
355         retCode = CKM_API_ERROR_DB_ERROR;
356     }
357
358     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
359                                              commandId,
360                                              retCode,
361                                              static_cast<int>(dataType));
362     return response.Pop();
363 }
364
365 int CKMLogic::removeDataHelper(
366         const Credentials &cred,
367         const Name &name,
368         const Label &ownerLabel)
369 {
370     if (0 == m_userDataMap.count(cred.uid))
371         return CKM_API_ERROR_DB_LOCKED;
372
373     if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
374         LogError("Invalid label or name format");
375         return CKM_API_ERROR_INPUT_PARAM;
376     }
377
378     auto &database = m_userDataMap[cred.uid].database;
379     DBCrypto::Transaction transaction(&database);
380
381     // read and check permissions
382     PermissionOptional permissionRowOpt =
383             database.getPermissionRow(name, ownerLabel, cred.smackLabel);
384     int access_ec = m_accessControl.canDelete(ownerLabel, PermissionForLabel(cred.smackLabel, permissionRowOpt));
385     if(access_ec != CKM_API_SUCCESS)
386     {
387         LogWarning("access control check result: " << access_ec);
388         return access_ec;
389     }
390
391     auto erased = database.deleteDBRow(name, ownerLabel);
392     // check if the data existed or not
393     if(erased)
394         transaction.commit();
395     else {
396         LogError("No row for given name and label");
397         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
398     }
399
400     return CKM_API_SUCCESS;
401 }
402
403 RawBuffer CKMLogic::removeData(
404     const Credentials &cred,
405     int commandId,
406     DBDataType dataType,
407     const Name &name,
408     const Label &label)
409 {
410     int retCode;
411     Try {
412         // use client label if not explicitly provided
413         const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
414
415         retCode = removeDataHelper(cred, name, ownerLabel);
416     } Catch (CKM::Exception) {
417         LogError("Error in deleting row!");
418         retCode = CKM_API_ERROR_DB_ERROR;
419     }
420
421     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
422                                              commandId,
423                                              retCode,
424                                              static_cast<int>(dataType));
425     return response.Pop();
426 }
427
428 int CKMLogic::readDataRowHelper(const Name &name,
429                                 const Label &ownerLabel,
430                                 DBDataType dataType,
431                                 DBCrypto & database,
432                                 DBRow &row)
433 {
434     // read row
435     DBCrypto::DBRowOptional row_optional;
436     // TODO: move this check into request deserialization
437     if((static_cast<int>(dataType)<static_cast<int>(DBDataType::DB_DATA_TYPE_FIRST)) ||
438        (static_cast<int>(dataType)>static_cast<int>(DBDataType::DB_DATA_TYPE_LAST)))
439     {
440         LogError("Unknown type of requested data: " << (int)dataType);
441         return CKM_API_ERROR_BAD_REQUEST;
442     }
443     // TODO: provide internal type rather than using DB types in socket comms
444     else if ((dataType >= DBDataType::DB_KEY_FIRST) &&
445              (dataType <= DBDataType::DB_KEY_LAST))
446     {
447         // read all key types
448         row_optional = database.getDBRow(name,
449                                          ownerLabel,
450                                          DBDataType::DB_KEY_FIRST,
451                                          DBDataType::DB_KEY_LAST);
452     }
453     else {
454         // read anything else
455         row_optional = database.getDBRow(name,
456                                          ownerLabel,
457                                          dataType);
458     }
459
460     if(!row_optional) {
461         LogError("No row for given name, label and type");
462         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
463     } else {
464         row = *row_optional;
465     }
466
467     return CKM_API_SUCCESS;
468 }
469
470 int CKMLogic::checkDataPermissionsHelper(const Name &name,
471                                          const Label &ownerLabel,
472                                          const Label &accessorLabel,
473                                          const DBRow &row,
474                                          bool exportFlag,
475                                          DBCrypto & database)
476 {
477     PermissionOptional permissionRowOpt =
478             database.getPermissionRow(name, ownerLabel, accessorLabel);
479
480     if(exportFlag)
481         return m_accessControl.canExport(row, PermissionForLabel(accessorLabel, permissionRowOpt));
482     return m_accessControl.canRead(row, PermissionForLabel(accessorLabel, permissionRowOpt));
483 }
484
485 int CKMLogic::readDataHelper(
486     bool exportFlag,
487     const Credentials &cred,
488     DBDataType dataType,
489     const Name &name,
490     const Label &label,
491     const Password &password,
492     DBRow &row)
493 {
494     if (0 == m_userDataMap.count(cred.uid))
495         return CKM_API_ERROR_DB_LOCKED;
496
497     // use client label if not explicitly provided
498     const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
499
500     if (!isNameValid(name) || !isLabelValid(ownerLabel))
501         return CKM_API_ERROR_INPUT_PARAM;
502
503     auto &handler = m_userDataMap[cred.uid];
504
505     // read row
506     DBCrypto::Transaction transaction(&handler.database);
507     int ec = readDataRowHelper(name, ownerLabel, dataType, handler.database, row);
508     if(CKM_API_SUCCESS != ec)
509         return ec;
510
511
512     // check access rights
513     ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
514     if(CKM_API_SUCCESS != ec)
515         return ec;
516
517     // decrypt row
518     if (!handler.crypto.haveKey(row.ownerLabel)) {
519         RawBuffer key;
520         auto key_optional = handler.database.getKey(row.ownerLabel);
521         if(!key_optional) {
522             LogError("No key for given label in database");
523             return CKM_API_ERROR_DB_ERROR;
524         }
525         key = *key_optional;
526         key = handler.keyProvider.getPureDEK(key);
527         handler.crypto.pushKey(row.ownerLabel, key);
528     }
529     handler.crypto.decryptRow(password, row);
530
531     return CKM_API_SUCCESS;
532 }
533
534 RawBuffer CKMLogic::getData(
535     const Credentials &cred,
536     int commandId,
537     DBDataType dataType,
538     const Name &name,
539     const Label &label,
540     const Password &password)
541 {
542     int retCode = CKM_API_SUCCESS;
543     DBRow row;
544
545     try {
546         retCode = readDataHelper(true, cred, dataType, name, label, password, row);
547     } catch (const KeyProvider::Exception::Base &e) {
548         LogError("KeyProvider failed with error: " << e.GetMessage());
549         retCode = CKM_API_ERROR_SERVER_ERROR;
550     } catch (const CryptoLogic::Exception::Base &e) {
551         LogError("CryptoLogic failed with message: " << e.GetMessage());
552         retCode = CKM_API_ERROR_SERVER_ERROR;
553     } catch (const DBCrypto::Exception::Base &e) {
554         LogError("DBCrypto failed with message: " << e.GetMessage());
555         retCode = CKM_API_ERROR_DB_ERROR;
556     }
557
558     if (CKM_API_SUCCESS != retCode) {
559         row.data.clear();
560         row.dataType = dataType;
561     }
562
563     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
564                                              commandId,
565                                              retCode,
566                                              static_cast<int>(row.dataType),
567                                              row.data);
568     return response.Pop();
569 }
570
571 RawBuffer CKMLogic::getDataList(
572     const Credentials &cred,
573     int commandId,
574     DBDataType dataType)
575 {
576     int retCode = CKM_API_SUCCESS;
577     LabelNameVector labelNameVector;
578
579     if (0 < m_userDataMap.count(cred.uid)) {
580         auto &database = m_userDataMap[cred.uid].database;
581
582         Try {
583             // list names
584             // TODO: move this check into request deserialization
585             if((static_cast<int>(dataType)<static_cast<int>(DBDataType::DB_DATA_TYPE_FIRST)) ||
586                (static_cast<int>(dataType)>static_cast<int>(DBDataType::DB_DATA_TYPE_LAST)))
587             {
588                 LogError("Unknown type of requested data: " << (int)dataType);
589                 retCode = CKM_API_ERROR_BAD_REQUEST;
590             }
591             // TODO: provide internal type rather than using DB types in socket comms
592             else if ((dataType >= DBDataType::DB_KEY_FIRST) && (dataType <= DBDataType::DB_KEY_LAST))
593             {
594                 // list all key types
595                 database.listNames(cred.smackLabel,
596                                    labelNameVector,
597                                    DBDataType::DB_KEY_FIRST,
598                                    DBDataType::DB_KEY_LAST);
599             }
600             else {
601                 // list anything else
602                 database.listNames(cred.smackLabel,
603                                    labelNameVector,
604                                    dataType);
605             }
606         }
607         Catch (CKM::Exception) {
608             LogError("Failed to get names");
609             retCode = CKM_API_ERROR_DB_ERROR;
610         }
611     } else {
612         retCode = CKM_API_ERROR_DB_LOCKED;
613     }
614
615     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
616                                              commandId,
617                                              retCode,
618                                              static_cast<int>(dataType),
619                                              labelNameVector);
620     return response.Pop();
621 }
622
623
624 int CKMLogic::createKeyPairHelper(
625     const Credentials &cred,
626     const KeyType key_type,
627     const int additional_param,
628     const Name &namePrivate,
629     const Label &labelPrivate,
630     const Name &namePublic,
631     const Label &labelPublic,
632     const PolicySerializable &policyPrivate,
633     const PolicySerializable &policyPublic)
634 {
635     if (0 == m_userDataMap.count(cred.uid))
636         return CKM_API_ERROR_DB_LOCKED;
637
638     KeyImpl prv, pub;
639     int retCode;
640     switch(key_type)
641     {
642         case KeyType::KEY_RSA_PUBLIC:
643         case KeyType::KEY_RSA_PRIVATE:
644             retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub);
645             break;
646
647         case KeyType::KEY_DSA_PUBLIC:
648         case KeyType::KEY_DSA_PRIVATE:
649             retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub);
650             break;
651
652         case KeyType::KEY_ECDSA_PUBLIC:
653         case KeyType::KEY_ECDSA_PRIVATE:
654             retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
655             break;
656
657         default:
658             return CKM_API_ERROR_INPUT_PARAM;
659     }
660
661     if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
662     {
663         LogDebug("CryptoService error with code: " << retCode);
664         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
665     }
666
667     auto &database = m_userDataMap[cred.uid].database;
668     DBCrypto::Transaction transaction(&database);
669     retCode = saveDataHelper(cred,
670                             toDBDataType(prv.getType()),
671                             namePrivate,
672                             labelPrivate,
673                             prv.getDER(),
674                             policyPrivate);
675
676     if (CKM_API_SUCCESS != retCode)
677         return retCode;
678
679     retCode = saveDataHelper(cred,
680                             toDBDataType(pub.getType()),
681                             namePublic,
682                             labelPublic,
683                             pub.getDER(),
684                             policyPublic);
685
686     if (CKM_API_SUCCESS != retCode)
687         return retCode;
688
689     transaction.commit();
690
691     return retCode;
692 }
693
694 RawBuffer CKMLogic::createKeyPair(
695     const Credentials &cred,
696     LogicCommand protocol_cmd,
697     int commandId,
698     const int additional_param,
699     const Name &namePrivate,
700     const Label &labelPrivate,
701     const Name &namePublic,
702     const Label &labelPublic,
703     const PolicySerializable &policyPrivate,
704     const PolicySerializable &policyPublic)
705 {
706     int retCode = CKM_API_SUCCESS;
707
708     KeyType key_type = KeyType::KEY_NONE;
709     switch(protocol_cmd)
710     {
711         case LogicCommand::CREATE_KEY_PAIR_RSA:
712             key_type = KeyType::KEY_RSA_PUBLIC;
713             break;
714         case LogicCommand::CREATE_KEY_PAIR_DSA:
715             key_type = KeyType::KEY_DSA_PUBLIC;
716             break;
717         case LogicCommand::CREATE_KEY_PAIR_ECDSA:
718             key_type = KeyType::KEY_ECDSA_PUBLIC;
719             break;
720         default:
721             break;
722     }
723
724     try {
725         retCode = createKeyPairHelper(
726                         cred,
727                         key_type,
728                         additional_param,
729                         namePrivate,
730                         labelPrivate,
731                         namePublic,
732                         labelPublic,
733                         policyPrivate,
734                         policyPublic);
735     } catch (DBCrypto::Exception::TransactionError &e) {
736         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
737         retCode = CKM_API_ERROR_DB_ERROR;
738     } catch (CKM::CryptoLogic::Exception::Base &e) {
739         LogDebug("CryptoLogic error: " << e.GetMessage());
740         retCode = CKM_API_ERROR_SERVER_ERROR;
741     } catch (DBCrypto::Exception::InternalError &e) {
742         LogDebug("DBCrypto internal error: " << e.GetMessage());
743         retCode = CKM_API_ERROR_DB_ERROR;
744     }
745
746     return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
747 }
748
749 RawBuffer CKMLogic::getCertificateChain(
750     const Credentials &cred,
751     int commandId,
752     const RawBuffer &certificate,
753     const RawBufferVector &untrustedRawCertVector)
754 {
755     (void)cred;
756
757     CertificateImpl cert(certificate, DataFormat::FORM_DER);
758     CertificateImplVector untrustedCertVector;
759     CertificateImplVector chainVector;
760     RawBufferVector chainRawVector;
761
762     for (auto &e: untrustedRawCertVector)
763         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
764
765     LogDebug("Cert is empty: " << cert.empty());
766
767     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
768
769     if (retCode == CKM_API_SUCCESS) {
770         for (auto &e : chainVector)
771             chainRawVector.push_back(e.getDER());
772     }
773
774     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
775                                              commandId,
776                                              retCode,
777                                              chainRawVector);
778     return response.Pop();
779 }
780
781 int CKMLogic::getCertificateChainHelper(
782         const Credentials &cred,
783         const RawBuffer &certificate,
784         const LabelNameVector &labelNameVector,
785         RawBufferVector & chainRawVector)
786 {
787     CertificateImpl cert(certificate, DataFormat::FORM_DER);
788     CertificateImplVector untrustedCertVector;
789     CertificateImplVector chainVector;
790     DBRow row;
791
792     if (cert.empty())
793         return CKM_API_ERROR_SERVER_ERROR;
794
795     for (auto &i: labelNameVector) {
796         int ec = readDataHelper(false, cred, DBDataType::CERTIFICATE, i.second, i.first, Password(), row);
797         if (ec != CKM_API_SUCCESS)
798             return ec;
799
800         untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
801     }
802
803     int ec = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
804     if (ec != CKM_API_SUCCESS)
805         return ec;
806
807     for (auto &i: chainVector)
808         chainRawVector.push_back(i.getDER());
809
810     return CKM_API_SUCCESS;
811 }
812
813 RawBuffer CKMLogic::getCertificateChain(
814     const Credentials &cred,
815     int commandId,
816     const RawBuffer &certificate,
817     const LabelNameVector &labelNameVector)
818 {
819     int retCode = CKM_API_SUCCESS;
820     RawBufferVector chainRawVector;
821     try {
822
823         retCode = getCertificateChainHelper(cred, certificate, labelNameVector, chainRawVector);
824     } catch (const CryptoLogic::Exception::Base &e) {
825         LogError("CryptoLogic failed with message: " << e.GetMessage());
826         retCode = CKM_API_ERROR_SERVER_ERROR;
827     } catch (const DBCrypto::Exception::Base &e) {
828         LogError("DBCrypto failed with message: " << e.GetMessage());
829         retCode = CKM_API_ERROR_DB_ERROR;
830     } catch (...) {
831         LogError("Unknown error.");
832     }
833
834     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
835                                              commandId,
836                                              retCode,
837                                              chainRawVector);
838     return response.Pop();
839 }
840
841 RawBuffer CKMLogic::createSignature(
842         const Credentials &cred,
843         int commandId,
844         const Name &privateKeyName,
845         const Label & ownerLabel,
846         const Password &password,           // password for private_key
847         const RawBuffer &message,
848         const HashAlgorithm hash,
849         const RSAPaddingAlgorithm padding)
850 {
851     DBRow row;
852     CryptoService cs;
853     RawBuffer signature;
854
855     int retCode = CKM_API_SUCCESS;
856
857     try {
858         retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
859         if(retCode == CKM_API_SUCCESS)
860         {
861             KeyImpl keyParsed(row.data, Password());
862             if (keyParsed.empty())
863                 retCode = CKM_API_ERROR_SERVER_ERROR;
864             else
865                 retCode = cs.createSignature(keyParsed, message, hash, padding, signature);
866         }
867     } catch (const KeyProvider::Exception::Base &e) {
868         LogError("KeyProvider failed with message: " << e.GetMessage());
869         retCode = CKM_API_ERROR_SERVER_ERROR;
870     } catch (const CryptoLogic::Exception::Base &e) {
871         LogError("CryptoLogic failed with message: " << e.GetMessage());
872         retCode = CKM_API_ERROR_SERVER_ERROR;
873     } catch (const DBCrypto::Exception::Base &e) {
874         LogError("DBCrypto failed with message: " << e.GetMessage());
875         retCode = CKM_API_ERROR_DB_ERROR;
876     } catch (const CKM::Exception &e) {
877         LogError("Unknown CKM::Exception: " << e.GetMessage());
878         retCode = CKM_API_ERROR_SERVER_ERROR;
879     }
880
881     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
882                                              commandId,
883                                              retCode,
884                                              signature);
885     return response.Pop();
886 }
887
888 RawBuffer CKMLogic::verifySignature(
889         const Credentials &cred,
890         int commandId,
891         const Name &publicKeyOrCertName,
892         const Label & ownerLabel,
893         const Password &password,           // password for public_key (optional)
894         const RawBuffer &message,
895         const RawBuffer &signature,
896         const HashAlgorithm hash,
897         const RSAPaddingAlgorithm padding)
898 {
899     int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
900
901     try {
902         do {
903             CryptoService cs;
904             DBRow row;
905             KeyImpl key;
906
907             retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
908
909             if (retCode == CKM_API_SUCCESS) {
910                 key = KeyImpl(row.data);
911             } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
912                 retCode = readDataHelper(false, cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
913                 if (retCode != CKM_API_SUCCESS)
914                     break;
915                 CertificateImpl cert(row.data, DataFormat::FORM_DER);
916                 key = cert.getKeyImpl();
917             } else {
918                 break;
919             }
920
921             if (key.empty()) {
922                 retCode = CKM_API_ERROR_SERVER_ERROR;
923                 break;
924             }
925
926             retCode = cs.verifySignature(key, message, signature, hash, padding);
927         } while(0);
928     } catch (const CryptoService::Exception::Crypto_internal &e) {
929         LogError("KeyProvider failed with message: " << e.GetMessage());
930         retCode = CKM_API_ERROR_SERVER_ERROR;
931     } catch (const CryptoService::Exception::opensslError &e) {
932         LogError("KeyProvider failed with message: " << e.GetMessage());
933         retCode = CKM_API_ERROR_SERVER_ERROR;
934     } catch (const KeyProvider::Exception::Base &e) {
935         LogError("KeyProvider failed with error: " << e.GetMessage());
936         retCode = CKM_API_ERROR_SERVER_ERROR;
937     } catch (const CryptoLogic::Exception::Base &e) {
938         LogError("CryptoLogic failed with message: " << e.GetMessage());
939         retCode = CKM_API_ERROR_SERVER_ERROR;
940     } catch (const DBCrypto::Exception::Base &e) {
941         LogError("DBCrypto failed with message: " << e.GetMessage());
942         retCode = CKM_API_ERROR_DB_ERROR;
943     } catch (const CKM::Exception &e) {
944         LogError("Unknown CKM::Exception: " << e.GetMessage());
945         retCode = CKM_API_ERROR_SERVER_ERROR;
946     }
947
948     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
949                                              commandId,
950                                              retCode);
951     return response.Pop();
952 }
953
954 int CKMLogic::setPermissionHelper(
955         const Credentials &cred,
956         const Name &name,
957         const Label &label,
958         const Label &accessorLabel,
959         const Permission newPermission)
960 {
961     if(cred.smackLabel.empty() || cred.smackLabel==accessorLabel)
962         return CKM_API_ERROR_INPUT_PARAM;
963
964     // use client label if not explicitly provided
965     const Label& ownerLabel = label.empty() ? cred.smackLabel : label;
966
967     // verify name and label are correct
968     if (!isNameValid(name) || !isLabelValid(ownerLabel))
969         return CKM_API_ERROR_INPUT_PARAM;
970
971     int access_ec = m_accessControl.canModify(ownerLabel, cred.smackLabel);
972     if(access_ec != CKM_API_SUCCESS)
973         return access_ec;
974
975     if (0 == m_userDataMap.count(cred.uid))
976         return CKM_API_ERROR_DB_LOCKED;
977
978     auto &database = m_userDataMap[cred.uid].database;
979     DBCrypto::Transaction transaction(&database);
980
981     if( ! database.isNameLabelPresent(name, ownerLabel) )
982         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
983
984     // removing non-existing permissions: fail
985     if(newPermission == Permission::NONE)
986     {
987         if( !database.getPermissionRow(name, ownerLabel, accessorLabel) )
988             return CKM_API_ERROR_INPUT_PARAM;
989     }
990
991     database.setPermission(name, cred.smackLabel, accessorLabel, newPermission);
992     transaction.commit();
993
994     return CKM_API_SUCCESS;
995 }
996
997 RawBuffer CKMLogic::setPermission(
998         const Credentials &cred,
999         int command,
1000         int msgID,
1001         const Name &name,
1002         const Label &label,
1003         const Label &accessorLabel,
1004         const Permission newPermission)
1005 {
1006     int retCode;
1007     Try {
1008         retCode = setPermissionHelper(cred, name, label, accessorLabel, newPermission);
1009     } Catch (CKM::Exception) {
1010         LogError("Error in set row!");
1011         retCode = CKM_API_ERROR_DB_ERROR;
1012     }
1013
1014     return MessageBuffer::Serialize(command, msgID, retCode).Pop();
1015 }
1016
1017 } // namespace CKM
1018