Change internal implementation from RSA* to EVP_PKEY.
[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 CKM {
34
35 CKMLogic::CKMLogic(){
36     int retCode = FileSystem::init();
37     // TODO what can I do when init went wrong? exit(-1) ??
38     if (retCode) {
39         LogError("Fatal error in FileSystem::init()");
40     }
41 }
42
43 CKMLogic::~CKMLogic(){}
44
45 RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
46     // TODO try catch for all errors that should be supported by error code
47     int retCode = KEY_MANAGER_API_SUCCESS;
48
49     try {
50         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
51             auto &handle = m_userDataMap[user];
52             FileSystem fs(user);
53             auto wrappedDomainKEK = fs.getDomainKEK();
54
55             if (wrappedDomainKEK.empty()) {
56                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
57                 fs.saveDomainKEK(wrappedDomainKEK);
58             }
59
60             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
61
62             RawBuffer key = handle.keyProvider.getPureDomainKEK();
63             handle.database = DBCrypto(fs.getDBPath(), key);
64             handle.crypto = DBCryptoModule(key);
65             // TODO wipe key
66         }
67     } catch (const KeyProvider::Exception::Base &e) {
68         LogError("Error in KeyProvider " << e.GetMessage());
69         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
70     }
71
72     MessageBuffer response;
73     Serialization::Serialize(response, retCode);
74     return response.Pop();
75 }
76
77 RawBuffer CKMLogic::lockUserKey(uid_t user) {
78     int retCode = KEY_MANAGER_API_SUCCESS;
79     // TODO try catch for all errors that should be supported by error code
80     m_userDataMap.erase(user);
81
82     MessageBuffer response;
83     Serialization::Serialize(response, retCode);
84     return response.Pop();
85 }
86
87 RawBuffer CKMLogic::removeUserData(uid_t user) {
88     int retCode = KEY_MANAGER_API_SUCCESS;
89     // TODO try catch for all errors that should be supported by error code
90     m_userDataMap.erase(user);
91
92     FileSystem fs(user);
93     fs.removeUserData();
94
95     MessageBuffer response;
96     Serialization::Serialize(response, retCode);
97     return response.Pop();
98 }
99
100 RawBuffer CKMLogic::changeUserPassword(
101     uid_t user,
102     const std::string &oldPassword,
103     const std::string &newPassword)
104 {
105     int retCode = KEY_MANAGER_API_SUCCESS;
106     // TODO try-catch
107     FileSystem fs(user);
108     auto wrappedDomainKEK = fs.getDomainKEK();
109     if (wrappedDomainKEK.empty()) {
110         retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
111     } else {
112         wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
113         fs.saveDomainKEK(wrappedDomainKEK);
114     }
115     MessageBuffer response;
116     Serialization::Serialize(response, retCode);
117     return response.Pop();
118 }
119
120 RawBuffer CKMLogic::resetUserPassword(
121     uid_t user,
122     const std::string &newPassword)
123 {
124     int retCode = KEY_MANAGER_API_SUCCESS;
125     // TODO try-catch
126     if (0 == m_userDataMap.count(user)) {
127         retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
128     } else {
129         auto &handler = m_userDataMap[user];
130         FileSystem fs(user);
131         fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
132     }
133
134     MessageBuffer response;
135     Serialization::Serialize(response, retCode);
136     return response.Pop();
137 }
138
139 int CKMLogic::saveDataHelper(
140     Credentials &cred,
141     DBDataType dataType,
142     const Alias &alias,
143     const RawBuffer &key,
144     const PolicySerializable &policy)
145 {
146     if (0 == m_userDataMap.count(cred.uid))
147         return KEY_MANAGER_API_ERROR_DB_LOCKED;
148
149     DBRow row = {   alias,  cred.smackLabel, policy.restricted,
150          policy.extractable, dataType, DBCMAlgType::NONE,
151          0, RawBuffer(10, 'c'), key.size(), key };
152
153     auto &handler = m_userDataMap[cred.uid];
154     if (!handler.crypto.haveKey(cred.smackLabel)) {
155         RawBuffer key;
156         int status = handler.database.getKey(cred.smackLabel, key);
157         if (KEY_MANAGER_API_ERROR_DB_BAD_REQUEST == status) {
158             LogDebug("No Key in database found. Generating new one for label: " << cred.smackLabel);
159             key = handler.keyProvider.generateDEK(cred.smackLabel);
160             if (KEY_MANAGER_API_SUCCESS != handler.database.saveKey(cred.smackLabel, key)) {
161                 LogError("Failed to save key for smack label: " << cred.smackLabel);
162                 return KEY_MANAGER_API_ERROR_DB_ERROR;
163             }
164         }
165         key = handler.keyProvider.getPureDEK(key);
166         handler.crypto.pushKey(cred.smackLabel, key);
167     }
168     handler.crypto.encryptRow(policy.password, row);
169     return handler.database.saveDBRow(row);
170 }
171
172 RawBuffer CKMLogic::saveData(
173     Credentials &cred,
174     int commandId,
175     DBDataType dataType,
176     const Alias &alias,
177     const RawBuffer &key,
178     const PolicySerializable &policy)
179 {
180     int retCode = KEY_MANAGER_API_SUCCESS;
181
182     try {
183         retCode = saveDataHelper(cred, dataType, alias, key, policy);
184         LogDebug("SaveDataHelper returned: " << retCode);
185     } catch (const KeyProvider::Exception::Base &e) {
186         LogError("KeyProvider failed with message: " << e.GetMessage());
187         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
188     } catch (const DBCryptoModule::Exception::Base &e) {
189         LogError("DBCryptoModule failed with message: " << e.GetMessage());
190         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
191     }
192
193     MessageBuffer response;
194     Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
195     Serialization::Serialize(response, commandId);
196     Serialization::Serialize(response, retCode);
197     Serialization::Serialize(response, static_cast<int>(dataType));
198
199     return response.Pop();
200 }
201
202 RawBuffer CKMLogic::removeData(
203     Credentials &cred,
204     int commandId,
205     DBDataType dataType,
206     const Alias &alias)
207 {
208     int retCode = KEY_MANAGER_API_SUCCESS;
209
210     if (0 < m_userDataMap.count(cred.uid)) {
211         retCode = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
212     } else {
213         retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
214     }
215
216     MessageBuffer response;
217     Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
218     Serialization::Serialize(response, commandId);
219     Serialization::Serialize(response, retCode);
220     Serialization::Serialize(response, static_cast<int>(dataType));
221
222     return response.Pop();
223 }
224
225 int CKMLogic::getDataHelper(
226     Credentials &cred,
227     DBDataType dataType,
228     const Alias &alias,
229     const std::string &password,
230     DBRow &row)
231 {
232     int retCode = KEY_MANAGER_API_SUCCESS;
233
234     if (0 == m_userDataMap.count(cred.uid))
235         return KEY_MANAGER_API_ERROR_DB_LOCKED;
236
237     auto &handler = m_userDataMap[cred.uid];
238
239     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
240         retCode = handler.database.getDBRow(alias, cred.smackLabel, dataType, row);
241     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
242             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
243     {
244         retCode = handler.database.getKeyDBRow(alias, cred.smackLabel, row);
245     } else {
246         LogError("Unknown type of requested data" << (int)dataType);
247         return KEY_MANAGER_API_ERROR_BAD_REQUEST;
248     }
249
250     if (KEY_MANAGER_API_SUCCESS != retCode){
251         LogDebug("DBCrypto::getDBRow failed with code: " << retCode);
252         return retCode;
253     }
254
255     if (!handler.crypto.haveKey(row.smackLabel)) {
256         RawBuffer key;
257         retCode = handler.database.getKey(row.smackLabel, key);
258         if (KEY_MANAGER_API_SUCCESS != retCode) {
259             LogDebug("DBCrypto::getKey failed with: " << retCode);
260             return retCode;
261         }
262         key = handler.keyProvider.getPureDEK(key);
263         handler.crypto.pushKey(cred.smackLabel, key);
264     }
265     handler.crypto.decryptRow(password, row);
266
267     LogError("Datatype: " << (int) row.dataType);
268
269     return KEY_MANAGER_API_SUCCESS;
270 }
271
272 RawBuffer CKMLogic::getData(
273     Credentials &cred,
274     int commandId,
275     DBDataType dataType,
276     const Alias &alias,
277     const std::string &password)
278 {
279     int retCode = KEY_MANAGER_API_SUCCESS;
280     DBRow row;
281
282     try {
283         retCode = getDataHelper(cred, dataType, alias, password, row);
284     } catch (const KeyProvider::Exception::Base &e) {
285         LogError("KeyProvider failed with error: " << e.GetMessage());
286         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
287     } catch (const DBCryptoModule::Exception::Base &e) {
288         LogError("DBCryptoModule failed with message: " << e.GetMessage());
289         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
290     }
291
292     if (KEY_MANAGER_API_SUCCESS != retCode) {
293         row.data.clear();
294         row.dataType = dataType;
295     }
296
297     LogError("Sending dataType: " << (int)row.dataType);
298
299     MessageBuffer response;
300     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
301     Serialization::Serialize(response, commandId);
302     Serialization::Serialize(response, retCode);
303     Serialization::Serialize(response, static_cast<int>(row.dataType));
304     Serialization::Serialize(response, row.data);
305     return response.Pop();
306 }
307
308 RawBuffer CKMLogic::getDataList(
309     Credentials &cred,
310     int commandId,
311     DBDataType dataType)
312 {
313     int retCode = KEY_MANAGER_API_SUCCESS;
314     AliasVector aliasVector;
315
316     if (0 < m_userDataMap.count(cred.uid)) {
317         auto &handler = m_userDataMap[cred.uid];
318         if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
319             retCode = handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
320         } else {
321             retCode = handler.database.getKeyAliases(cred.smackLabel, aliasVector);
322         }
323     } else {
324         retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
325     }
326
327     MessageBuffer response;
328     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
329     Serialization::Serialize(response, commandId);
330     Serialization::Serialize(response, retCode);
331     Serialization::Serialize(response, static_cast<int>(dataType));
332     Serialization::Serialize(response, aliasVector);
333     return response.Pop();
334 }
335
336 int CKMLogic::createKeyPairRSAHelper(
337     Credentials &cred,
338     int size,
339     const Alias &aliasPrivate,
340     const Alias &aliasPublic,
341     const PolicySerializable &policyPrivate,
342     const PolicySerializable &policyPublic)
343 {
344     if (0 >= m_userDataMap.count(cred.uid))
345         return KEY_MANAGER_API_ERROR_DB_LOCKED;
346
347     auto &handler = m_userDataMap[cred.uid];
348     GenericKey prv, pub;
349     CryptoService cr;
350     int retCode;
351
352     if (CKM_CRYPTO_CREATEKEY_SUCCESS != (retCode = cr.createKeyPairRSA(size, prv, pub))) {
353         LogError("CryptoService failed with code: " << retCode);
354         return KEY_MANAGER_API_ERROR_SERVER_ERROR; // TODO error code
355     }
356
357     retCode = saveDataHelper(cred,
358                             toDBDataType(prv.getType()),
359                             aliasPrivate,
360                             prv.getDER(),
361                             policyPrivate);
362
363     if (KEY_MANAGER_API_SUCCESS != retCode)
364         return retCode;
365
366     retCode = saveDataHelper(cred,
367                             toDBDataType(pub.getType()),
368                             aliasPublic,
369                             pub.getDER(),
370                             policyPublic);
371
372     if (KEY_MANAGER_API_SUCCESS != retCode) {
373         handler.database.deleteDBRow(aliasPrivate, cred.smackLabel);
374     }
375
376     return retCode;
377 }
378
379 RawBuffer CKMLogic::createKeyPairRSA(
380     Credentials &cred,
381     int commandId,
382     int size,
383     const Alias &aliasPrivate,
384     const Alias &aliasPublic,
385     const PolicySerializable &policyPrivate,
386     const PolicySerializable &policyPublic)
387 {
388     int retCode = createKeyPairRSAHelper(
389                         cred,
390                         size,
391                         aliasPrivate,
392                         aliasPublic,
393                         policyPrivate,
394                         policyPublic);
395
396     MessageBuffer response;
397     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
398     Serialization::Serialize(response, commandId);
399     Serialization::Serialize(response, retCode);
400  
401     return response.Pop();
402 }
403
404 int CKMLogic::createKeyPairECDSAHelper(
405     Credentials &cred,
406     int type,
407     const Alias &aliasPrivate,
408     const Alias &aliasPublic,
409     const PolicySerializable &policyPrivate,
410     const PolicySerializable &policyPublic)
411 {
412     if (0 >= m_userDataMap.count(cred.uid))
413         return KEY_MANAGER_API_ERROR_DB_LOCKED;
414
415     auto &handler = m_userDataMap[cred.uid];
416     GenericKey prv, pub;
417     CryptoService cr;
418     int retCode;
419
420     if (CKM_CRYPTO_CREATEKEY_SUCCESS != (retCode = cr.createKeyPairECDSA(
421               static_cast<ElipticCurve>(type), prv, pub)))
422     {
423         LogError("CryptoService failed with code: " << retCode);
424         return KEY_MANAGER_API_ERROR_SERVER_ERROR; // TODO error code
425     }
426
427     retCode = saveDataHelper(cred,
428                             toDBDataType(prv.getType()),
429                             aliasPrivate,
430                             prv.getDER(),
431                             policyPrivate);
432
433     if (KEY_MANAGER_API_SUCCESS != retCode)
434         return retCode;
435
436     retCode = saveDataHelper(cred,
437                             toDBDataType(pub.getType()),
438                             aliasPublic,
439                             pub.getDER(),
440                             policyPublic);
441
442     if (KEY_MANAGER_API_SUCCESS != retCode) {
443         handler.database.deleteDBRow(aliasPrivate, cred.smackLabel);
444     }
445
446     return retCode;
447 }
448
449 RawBuffer CKMLogic::createKeyPairECDSA(
450     Credentials &cred,
451     int commandId,
452     int type,
453     const Alias &aliasPrivate,
454     const Alias &aliasPublic,
455     const PolicySerializable &policyPrivate,
456     const PolicySerializable &policyPublic)
457 {
458     int retCode = createKeyPairECDSAHelper(
459                         cred,
460                         type,
461                         aliasPrivate,
462                         aliasPublic,
463                         policyPrivate,
464                         policyPublic);
465
466     MessageBuffer response;
467     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
468     Serialization::Serialize(response, commandId);
469     Serialization::Serialize(response, retCode);
470  
471     return response.Pop();
472 }
473
474 } // namespace CKM
475