Change some error messages to debug.
[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
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 <generic-key.h>
32
33 namespace {
34 const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
35 } // anonymous namespace
36
37 namespace CKM {
38
39 CKMLogic::CKMLogic()
40 {
41     int retCode = FileSystem::init();
42     // TODO what can I do when init went wrong? exit(-1) ??
43     if (retCode) {
44         LogError("Fatal error in FileSystem::init()");
45     }
46
47     if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
48         LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
49     }
50 }
51
52 CKMLogic::~CKMLogic(){}
53
54 RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
55     // TODO try catch for all errors that should be supported by error code
56     int retCode = CKM_API_SUCCESS;
57
58     try {
59         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
60             auto &handle = m_userDataMap[user];
61             FileSystem fs(user);
62             auto wrappedDomainKEK = fs.getDomainKEK();
63
64             if (wrappedDomainKEK.empty()) {
65                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
66                 fs.saveDomainKEK(wrappedDomainKEK);
67             }
68
69             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
70
71             RawBuffer key = handle.keyProvider.getPureDomainKEK();
72             handle.database = DBCrypto(fs.getDBPath(), key);
73             handle.crypto = DBCryptoModule(key);
74             // TODO wipe key
75         }
76     } catch (const KeyProvider::Exception::Base &e) {
77         LogError("Error in KeyProvider " << e.GetMessage());
78         retCode = CKM_API_ERROR_SERVER_ERROR;
79     }
80
81     MessageBuffer response;
82     Serialization::Serialize(response, retCode);
83     return response.Pop();
84 }
85
86 RawBuffer CKMLogic::lockUserKey(uid_t user) {
87     int retCode = CKM_API_SUCCESS;
88     // TODO try catch for all errors that should be supported by error code
89     m_userDataMap.erase(user);
90
91     MessageBuffer response;
92     Serialization::Serialize(response, retCode);
93     return response.Pop();
94 }
95
96 RawBuffer CKMLogic::removeUserData(uid_t user) {
97     int retCode = CKM_API_SUCCESS;
98     // TODO try catch for all errors that should be supported by error code
99     m_userDataMap.erase(user);
100
101     FileSystem fs(user);
102     fs.removeUserData();
103
104     MessageBuffer response;
105     Serialization::Serialize(response, retCode);
106     return response.Pop();
107 }
108
109 RawBuffer CKMLogic::changeUserPassword(
110     uid_t user,
111     const std::string &oldPassword,
112     const std::string &newPassword)
113 {
114     int retCode = CKM_API_SUCCESS;
115     // TODO try-catch
116     FileSystem fs(user);
117     auto wrappedDomainKEK = fs.getDomainKEK();
118     if (wrappedDomainKEK.empty()) {
119         retCode = CKM_API_ERROR_BAD_REQUEST;
120     } else {
121         wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
122         fs.saveDomainKEK(wrappedDomainKEK);
123     }
124     MessageBuffer response;
125     Serialization::Serialize(response, retCode);
126     return response.Pop();
127 }
128
129 RawBuffer CKMLogic::resetUserPassword(
130     uid_t user,
131     const std::string &newPassword)
132 {
133     int retCode = CKM_API_SUCCESS;
134     // TODO try-catch
135     if (0 == m_userDataMap.count(user)) {
136         retCode = CKM_API_ERROR_BAD_REQUEST;
137     } else {
138         auto &handler = m_userDataMap[user];
139         FileSystem fs(user);
140         fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
141     }
142
143     MessageBuffer response;
144     Serialization::Serialize(response, retCode);
145     return response.Pop();
146 }
147
148 int CKMLogic::saveDataHelper(
149     Credentials &cred,
150     DBDataType dataType,
151     const Alias &alias,
152     const RawBuffer &key,
153     const PolicySerializable &policy)
154 {
155     if (0 == m_userDataMap.count(cred.uid))
156         return CKM_API_ERROR_DB_LOCKED;
157
158     DBRow row = { alias, cred.smackLabel, policy.restricted,
159          policy.extractable, dataType, DBCMAlgType::NONE,
160          0, RawBuffer(10, 'c'), key.size(), key };
161
162     auto &handler = m_userDataMap[cred.uid];
163     DBCrypto::Transaction transaction(&handler.database);
164     if (!handler.crypto.haveKey(cred.smackLabel)) {
165         RawBuffer key;
166         auto key_optional = handler.database.getKey(cred.smackLabel);
167         if(!key_optional) {
168             LogDebug("No Key in database found. Generating new one for label: "
169                     << cred.smackLabel);
170             key = handler.keyProvider.generateDEK(cred.smackLabel);
171         } else {
172             key = *key_optional;
173         }
174
175         key = handler.keyProvider.getPureDEK(key);
176         handler.crypto.pushKey(cred.smackLabel, key);
177         handler.database.saveKey(cred.smackLabel, key);
178     }
179     handler.crypto.encryptRow(policy.password, row);
180     handler.database.saveDBRow(row);
181     transaction.commit();
182     return CKM_API_SUCCESS;
183 }
184
185 RawBuffer CKMLogic::saveData(
186     Credentials &cred,
187     int commandId,
188     DBDataType dataType,
189     const Alias &alias,
190     const RawBuffer &key,
191     const PolicySerializable &policy)
192 {
193     int retCode = CKM_API_SUCCESS;
194     try {
195         retCode = saveDataHelper(cred, dataType, alias, key, policy);
196         LogDebug("SaveDataHelper returned: " << retCode);
197     } catch (const KeyProvider::Exception::Base &e) {
198         LogError("KeyProvider failed with message: " << e.GetMessage());
199         retCode = CKM_API_ERROR_SERVER_ERROR;
200     } catch (const DBCryptoModule::Exception::Base &e) {
201         LogError("DBCryptoModule failed with message: " << e.GetMessage());
202         retCode = CKM_API_ERROR_SERVER_ERROR;
203     } catch (const DBCrypto::Exception::InternalError &e) {
204         LogError("DBCrypto failed with message: " << e.GetMessage());
205         retCode = CKM_API_ERROR_DB_ERROR;
206     } catch (const DBCrypto::Exception::AliasExists &e) {
207         LogError("DBCrypto couldn't save duplicate alias");
208         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
209     } catch (const DBCrypto::Exception::TransactionError &e) {
210         LogError("DBCrypto transaction failed with message " << e.GetMessage());
211         retCode = CKM_API_ERROR_DB_ERROR;
212     }
213
214     MessageBuffer response;
215     Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
216     Serialization::Serialize(response, commandId);
217     Serialization::Serialize(response, retCode);
218     Serialization::Serialize(response, static_cast<int>(dataType));
219
220     return response.Pop();
221 }
222
223 RawBuffer CKMLogic::removeData(
224     Credentials &cred,
225     int commandId,
226     DBDataType dataType,
227     const Alias &alias)
228 {
229     int retCode = CKM_API_SUCCESS;
230
231     if (0 < m_userDataMap.count(cred.uid)) {
232         Try {
233             m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
234         } Catch (CKM::Exception) {
235             LogError("Error in deleting row!");
236             retCode = CKM_API_ERROR_DB_ERROR;
237         }
238     } else {
239         retCode = CKM_API_ERROR_DB_LOCKED;
240     }
241
242     MessageBuffer response;
243     Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
244     Serialization::Serialize(response, commandId);
245     Serialization::Serialize(response, retCode);
246     Serialization::Serialize(response, static_cast<int>(dataType));
247
248     return response.Pop();
249 }
250
251 int CKMLogic::getDataHelper(
252     Credentials &cred,
253     DBDataType dataType,
254     const Alias &alias,
255     const std::string &password,
256     DBRow &row)
257 {
258
259     if (0 == m_userDataMap.count(cred.uid))
260         return CKM_API_ERROR_DB_LOCKED;
261
262     auto &handler = m_userDataMap[cred.uid];
263
264     DBCrypto::DBRowOptional row_optional;
265     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
266         row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
267     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
268             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
269     {
270         row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
271     } else {
272         LogError("Unknown type of requested data" << (int)dataType);
273         return CKM_API_ERROR_BAD_REQUEST;
274     }
275     if(!row_optional) {
276         LogError("No row for given alias, label and type");
277         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
278     } else {
279         row = *row_optional;
280     }
281
282     if (!handler.crypto.haveKey(row.smackLabel)) {
283         RawBuffer key;
284         auto key_optional = handler.database.getKey(row.smackLabel);
285         if(!key_optional) {
286             LogError("No key for given label in database");
287             return CKM_API_ERROR_DB_ERROR;
288         }
289         key = *key_optional;
290         key = handler.keyProvider.getPureDEK(key);
291         handler.crypto.pushKey(cred.smackLabel, key);
292     }
293     handler.crypto.decryptRow(password, row);
294
295     return CKM_API_SUCCESS;
296 }
297
298 RawBuffer CKMLogic::getData(
299     Credentials &cred,
300     int commandId,
301     DBDataType dataType,
302     const Alias &alias,
303     const std::string &password)
304 {
305     int retCode = CKM_API_SUCCESS;
306     DBRow row;
307
308     try {
309         retCode = getDataHelper(cred, dataType, alias, password, row);
310     } catch (const KeyProvider::Exception::Base &e) {
311         LogError("KeyProvider failed with error: " << e.GetMessage());
312         retCode = CKM_API_ERROR_SERVER_ERROR;
313     } catch (const DBCryptoModule::Exception::Base &e) {
314         LogError("DBCryptoModule failed with message: " << e.GetMessage());
315         retCode = CKM_API_ERROR_SERVER_ERROR;
316     } catch (const DBCrypto::Exception::Base &e) {
317         LogError("DBCrypto failed with message: " << e.GetMessage());
318         retCode = CKM_API_ERROR_DB_ERROR;
319     }
320
321     if (CKM_API_SUCCESS != retCode) {
322         row.data.clear();
323         row.dataType = dataType;
324     }
325
326     MessageBuffer response;
327     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
328     Serialization::Serialize(response, commandId);
329     Serialization::Serialize(response, retCode);
330     Serialization::Serialize(response, static_cast<int>(row.dataType));
331     Serialization::Serialize(response, row.data);
332     return response.Pop();
333 }
334
335 RawBuffer CKMLogic::getDataList(
336     Credentials &cred,
337     int commandId,
338     DBDataType dataType)
339 {
340     int retCode = CKM_API_SUCCESS;
341     AliasVector aliasVector;
342
343     if (0 < m_userDataMap.count(cred.uid)) {
344         auto &handler = m_userDataMap[cred.uid];
345         Try {
346             if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
347                 handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
348             } else {
349                 handler.database.getKeyAliases(cred.smackLabel, aliasVector);
350             }
351         } Catch (CKM::Exception) {
352             LogError("Failed to get aliases");
353             retCode = CKM_API_ERROR_DB_ERROR;
354         }
355     } else {
356         retCode = CKM_API_ERROR_DB_LOCKED;
357     }
358
359     MessageBuffer response;
360     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
361     Serialization::Serialize(response, commandId);
362     Serialization::Serialize(response, retCode);
363     Serialization::Serialize(response, static_cast<int>(dataType));
364     Serialization::Serialize(response, aliasVector);
365     return response.Pop();
366 }
367
368 int CKMLogic::createKeyPairRSAHelper(
369     Credentials &cred,
370     int size,
371     const Alias &aliasPrivate,
372     const Alias &aliasPublic,
373     const PolicySerializable &policyPrivate,
374     const PolicySerializable &policyPublic)
375 {
376     if (0 >= m_userDataMap.count(cred.uid))
377         return CKM_API_ERROR_DB_LOCKED;
378
379     auto &handler = m_userDataMap[cred.uid];
380     GenericKey prv, pub;
381     int retCode;
382
383     if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
384         (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
385     {
386         LogDebug("CryptoService error with code: " << retCode);
387         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
388     }
389
390     DBCrypto::Transaction transaction(&handler.database);
391     retCode = saveDataHelper(cred,
392                             toDBDataType(prv.getType()),
393                             aliasPrivate,
394                             prv.getDER(),
395                             policyPrivate);
396
397     if (CKM_API_SUCCESS != retCode)
398         return retCode;
399
400     retCode = saveDataHelper(cred,
401                             toDBDataType(pub.getType()),
402                             aliasPublic,
403                             pub.getDER(),
404                             policyPublic);
405
406     if (CKM_API_SUCCESS != retCode)
407         return retCode;
408
409     transaction.commit();
410
411     return retCode;
412 }
413
414 RawBuffer CKMLogic::createKeyPairRSA(
415     Credentials &cred,
416     int commandId,
417     int size,
418     const Alias &aliasPrivate,
419     const Alias &aliasPublic,
420     const PolicySerializable &policyPrivate,
421     const PolicySerializable &policyPublic)
422 {
423     int retCode = CKM_API_SUCCESS;
424
425     try {
426         retCode = createKeyPairRSAHelper(
427                         cred,
428                         size,
429                         aliasPrivate,
430                         aliasPublic,
431                         policyPrivate,
432                         policyPublic);
433
434     } catch (DBCrypto::Exception::AliasExists &e) {
435         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
436         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
437     } catch (DBCrypto::Exception::TransactionError &e) {
438         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
439         retCode = CKM_API_ERROR_DB_ERROR;
440     } catch (DBCrypto::Exception::InternalError &e) {
441         LogDebug("DBCrypto internal error: " << e.GetMessage());
442         retCode = CKM_API_ERROR_DB_ERROR;
443     }
444
445     MessageBuffer response;
446     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
447     Serialization::Serialize(response, commandId);
448     Serialization::Serialize(response, retCode);
449  
450     return response.Pop();
451 }
452
453 int CKMLogic::createKeyPairECDSAHelper(
454     Credentials &cred,
455     int type,
456     const Alias &aliasPrivate,
457     const Alias &aliasPublic,
458     const PolicySerializable &policyPrivate,
459     const PolicySerializable &policyPublic)
460 {
461     if (0 >= m_userDataMap.count(cred.uid))
462         return CKM_API_ERROR_DB_LOCKED;
463
464     auto &handler = m_userDataMap[cred.uid];
465     GenericKey prv, pub;
466     int retCode;
467
468     if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
469         (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
470     {
471         LogError("CryptoService failed with code: " << retCode);
472         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
473     }
474
475     DBCrypto::Transaction transaction(&handler.database);
476
477     retCode = saveDataHelper(cred,
478                             toDBDataType(prv.getType()),
479                             aliasPrivate,
480                             prv.getDER(),
481                             policyPrivate);
482
483     if (CKM_API_SUCCESS != retCode)
484         return retCode;
485
486     retCode = saveDataHelper(cred,
487                             toDBDataType(pub.getType()),
488                             aliasPublic,
489                             pub.getDER(),
490                             policyPublic);
491
492     if (CKM_API_SUCCESS != retCode)
493         return retCode;
494
495     transaction.commit();
496
497     return retCode;
498 }
499
500 RawBuffer CKMLogic::createKeyPairECDSA(
501     Credentials &cred,
502     int commandId,
503     int type,
504     const Alias &aliasPrivate,
505     const Alias &aliasPublic,
506     const PolicySerializable &policyPrivate,
507     const PolicySerializable &policyPublic)
508 {
509     int retCode = CKM_API_SUCCESS;
510     
511     try {
512         retCode = createKeyPairECDSAHelper(
513                         cred,
514                         type,
515                         aliasPrivate,
516                         aliasPublic,
517                         policyPrivate,
518                         policyPublic);
519     } catch (const DBCrypto::Exception::AliasExists &e) {
520         LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
521         retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
522     } catch (const DBCrypto::Exception::TransactionError &e) {
523         LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
524         retCode = CKM_API_ERROR_DB_ERROR;
525     } catch (const DBCrypto::Exception::InternalError &e) {
526         LogDebug("DBCrypto internal error: " << e.GetMessage());
527         retCode = CKM_API_ERROR_DB_ERROR;
528     }
529
530     MessageBuffer response;
531     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
532     Serialization::Serialize(response, commandId);
533     Serialization::Serialize(response, retCode);
534  
535     return response.Pop();
536 }
537
538 RawBuffer CKMLogic::getCertificateChain(
539     Credentials &cred,
540     int commandId,
541     const RawBuffer &certificate,
542     const RawBufferVector &untrustedRawCertVector)
543 {
544     (void)cred;
545
546     CertificateImpl cert(certificate, DataFormat::FORM_DER);
547     CertificateImplVector untrustedCertVector;
548     CertificateImplVector chainVector;
549     RawBufferVector chainRawVector;
550
551     for (auto &e: untrustedRawCertVector)
552         untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
553
554     LogDebug("Cert is empty: " << cert.empty());
555
556     int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
557
558     if (retCode == CKM_API_SUCCESS) {
559         for (auto &e : chainVector)
560             chainRawVector.push_back(e.getDER());
561     }
562
563     MessageBuffer response;
564     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
565     Serialization::Serialize(response, commandId);
566     Serialization::Serialize(response, retCode);
567     Serialization::Serialize(response, chainRawVector);
568     return response.Pop();
569 }
570
571 RawBuffer CKMLogic::getCertificateChain(
572     Credentials &cred,
573     int commandId,
574     const RawBuffer &certificate,
575     const AliasVector &aliasVector)
576 {
577     (void) cred;
578     (void) commandId;
579     (void) certificate;
580     (void) aliasVector;
581
582     MessageBuffer response;
583     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
584     Serialization::Serialize(response, commandId);
585     Serialization::Serialize(response, static_cast<int>(CKM_API_SUCCESS));
586     Serialization::Serialize(response, RawBufferVector());
587     return response.Pop();
588 }
589
590 } // namespace CKM
591