Integration with CryptoService class.
[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 <key-rsa.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     return KEY_MANAGER_API_SUCCESS;
268 }
269
270 RawBuffer CKMLogic::getData(
271     Credentials &cred,
272     int commandId,
273     DBDataType dataType,
274     const Alias &alias,
275     const std::string &password)
276 {
277     int retCode = KEY_MANAGER_API_SUCCESS;
278     DBRow row;
279
280     try {
281         retCode = getDataHelper(cred, dataType, alias, password, row);
282     } catch (const KeyProvider::Exception::Base &e) {
283         LogError("KeyProvider failed with error: " << e.GetMessage());
284         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
285     } catch (const DBCryptoModule::Exception::Base &e) {
286         LogError("DBCryptoModule failed with message: " << e.GetMessage());
287         retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
288     }
289
290     if (KEY_MANAGER_API_SUCCESS != retCode) {
291         row.data.clear();
292         row.dataType = dataType;
293     }
294
295     MessageBuffer response;
296     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
297     Serialization::Serialize(response, commandId);
298     Serialization::Serialize(response, retCode);
299     Serialization::Serialize(response, static_cast<int>(row.dataType));
300     Serialization::Serialize(response, row.data);
301     return response.Pop();
302 }
303
304 RawBuffer CKMLogic::getDataList(
305     Credentials &cred,
306     int commandId,
307     DBDataType dataType)
308 {
309     int retCode = KEY_MANAGER_API_SUCCESS;
310     AliasVector aliasVector;
311
312     if (0 < m_userDataMap.count(cred.uid)) {
313         auto &handler = m_userDataMap[cred.uid];
314         if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
315             retCode = handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
316         } else {
317             retCode = handler.database.getKeyAliases(cred.smackLabel, aliasVector);
318         }
319     } else {
320         retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
321     }
322
323     MessageBuffer response;
324     Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
325     Serialization::Serialize(response, commandId);
326     Serialization::Serialize(response, retCode);
327     Serialization::Serialize(response, static_cast<int>(dataType));
328     Serialization::Serialize(response, aliasVector);
329     return response.Pop();
330 }
331
332 int CKMLogic::createKeyPairRSAHelper(
333     Credentials &cred,
334     int size,
335     const Alias &aliasPrivate,
336     const Alias &aliasPublic,
337     const PolicySerializable &policyPrivate,
338     const PolicySerializable &policyPublic)
339 {
340     if (0 >= m_userDataMap.count(cred.uid))
341         return KEY_MANAGER_API_ERROR_DB_LOCKED;
342
343     auto &handler = m_userDataMap[cred.uid];
344     KeyRSAPrivate prv;
345     KeyRSAPublic pub;
346     CryptoService cr;
347     int retCode;
348
349     if (CKM_CRYPTO_CREATEKEY_SUCCESS != (retCode = cr.createKeyPairRSA(size, prv, pub))) {
350         LogError("CryptoService failed with code: " << retCode);
351         return KEY_MANAGER_API_ERROR_SERVER_ERROR; // TODO error code
352     }
353
354     retCode = saveDataHelper(cred,
355                             toDBDataType(prv.getType()),
356                             aliasPrivate,
357                             prv.getDER(),
358                             policyPrivate);
359
360     if (KEY_MANAGER_API_SUCCESS != retCode)
361         return retCode;
362
363     retCode = saveDataHelper(cred,
364                             toDBDataType(pub.getType()),
365                             aliasPublic,
366                             pub.getDER(),
367                             policyPublic);
368
369     if (KEY_MANAGER_API_SUCCESS != retCode) {
370         handler.database.deleteDBRow(aliasPrivate, cred.smackLabel);
371     }
372
373     return retCode;
374 }
375
376 RawBuffer CKMLogic::createKeyPairRSA(
377     Credentials &cred,
378     int commandId,
379     int size,
380     const Alias &aliasPrivate,
381     const Alias &aliasPublic,
382     const PolicySerializable &policyPrivate,
383     const PolicySerializable &policyPublic)
384 {
385     int retCode = createKeyPairRSAHelper(
386                         cred,
387                         size,
388                         aliasPrivate,
389                         aliasPublic,
390                         policyPrivate,
391                         policyPublic);
392
393     MessageBuffer response;
394     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
395     Serialization::Serialize(response, commandId);
396     Serialization::Serialize(response, retCode);
397  
398     return response.Pop();
399 }
400
401 RawBuffer CKMLogic::createKeyPairECDSA(
402     Credentials &cred,
403     int commandId,
404     int type,
405     const Alias &aliasPrivate,
406     const Alias &aliasPublic,
407     const PolicySerializable &policyPrivate,
408     const PolicySerializable &policyPublic)
409 {
410     (void)cred;
411     (void)type;
412     (void)aliasPrivate;
413     (void)aliasPublic;
414     (void)policyPrivate;
415     (void)policyPublic;
416
417     MessageBuffer response;
418     Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
419     Serialization::Serialize(response, commandId);
420     Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
421  
422     return response.Pop();
423 }
424
425 } // namespace CKM
426