c54f3a6b654997438d77d77aef9c6ebbaa4e2b2e
[platform/core/test/security-tests.git] / tests / ckm / cc-mode.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       cc-mode.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include <string>
29
30 #include <vconf/vconf.h>
31
32 #include <dpl/test/test_runner.h>
33 #include <tests_common.h>
34 #include <ckm-common.h>
35 #include <ckm/ckm-manager.h>
36 #include <ckm/ckm-control.h>
37
38 using namespace CKM;
39 using namespace std;
40
41 #ifndef VCONFKEY_SECURITY_MDPP_STATE
42 #define VCONFKEY_SECURITY_MDPP_STATE "file/security_mdpp/security_mdpp_state"
43 #endif
44
45 namespace {
46
47 const useconds_t SLEEP = 100*1000;
48
49 const size_t MAX_RETRIES = 50;
50
51 const char* const ENABLED = "Enabled";
52 const char* const ENFORCING = "Enforcing";
53 const char* const DISABLED = "Disabled";
54 const char* const READY = "Ready";
55 const char* const UNSET = "Unset"; // Meaningless value for unset.
56
57 const char* const CKM_LOCK = "/var/run/key-manager.pid";
58
59
60 // disable CC
61 /*
62  * k.tak: To unset vconf key on runtime is deprecated by vconf key policy.
63  *        To make new vconf key on runtime is deprecated by vconf key policy.
64  *        vconf key should be installed in package install time.
65  */
66 int _unset_mdpp_key = vconf_set_str(VCONFKEY_SECURITY_MDPP_STATE, UNSET);
67
68 // Wrapper for mdpp state that restores the original value upon destruction
69 class MdppState
70 {
71 public:
72     MdppState();
73     ~MdppState();
74
75     // pass NULL to unset
76     void set(const char* const value);
77
78 private:
79     char* m_original;
80 };
81
82 MdppState::MdppState()
83 {
84     m_original = vconf_get_str(VCONFKEY_SECURITY_MDPP_STATE);
85 }
86
87 MdppState::~MdppState()
88 {
89     if (!m_original)
90         vconf_set_str(VCONFKEY_SECURITY_MDPP_STATE, UNSET);
91     else {
92         vconf_set_str(VCONFKEY_SECURITY_MDPP_STATE, m_original);
93         free(m_original);
94     }
95 }
96
97 void MdppState::set(const char* const value)
98 {
99     if (value)
100         RUNNER_ASSERT_MSG(0 == vconf_set_str(VCONFKEY_SECURITY_MDPP_STATE, value),
101                              "vconf_set() failed");
102     else
103         vconf_set_str(VCONFKEY_SECURITY_MDPP_STATE, UNSET);
104 }
105
106 void remove_user_data()
107 {
108     auto control = Control::create();
109     int ret = control->removeUserData(0);
110     RUNNER_ASSERT_MSG(ret == CKM_API_SUCCESS,
111                          "Remove user data failed with error: " << ErrorToString(ret));
112 }
113
114 Alias rsa_pri_alias("rsa-private-T2002");
115 Alias rsa_pub_alias("rsa-public-T2002");
116 Alias ecdsa_pri_alias("ecdsa-private-T2002");
117 Alias ecdsa_pub_alias("ecdsa-public-T2002");
118
119 void save_keys()
120 {
121     int temp;
122     auto manager = Manager::create();
123
124     RUNNER_ASSERT_MSG(
125         CKM_API_SUCCESS == (temp = manager->createKeyPairRSA(
126                 1024,
127                 rsa_pri_alias,
128                 rsa_pub_alias,
129                 Policy(Password(), true),
130                 Policy(Password(), true))),
131             "Error=" << ErrorToString(temp));
132
133     RUNNER_ASSERT_MSG(
134         CKM_API_SUCCESS == (temp = manager->createKeyPairECDSA(
135                 ElipticCurve::prime192v1,
136                 ecdsa_pri_alias,
137                 ecdsa_pub_alias,
138                 Policy(Password(), true),
139                 Policy(Password(), true))),
140             "Error=" << ErrorToString(temp));
141 }
142
143 void read_key(ManagerShPtr& manager, const Alias& alias, int expected) {
144     KeyShPtr key;
145     int temp;
146     RUNNER_ASSERT_MSG(
147             expected == (temp = manager->getKey(alias, Password(), key)),
148             "Expected: " << expected << "/" << ErrorToString(expected) << " got: " << temp << "/" <<
149             ErrorToString(temp));
150 }
151
152 void read_keys(int expected)
153 {
154 // if mdpp is disabled at compilation time we expect that read_key always succeeds
155 #ifndef DSECURITY_MDFPP_STATE_ENABLE
156     expected = CKM_API_SUCCESS;
157 #endif
158     auto manager = Manager::create();
159
160     read_key(manager, rsa_pri_alias, expected);
161     read_key(manager, ecdsa_pri_alias, expected);
162 }
163
164 void update_cc_mode()
165 {
166     auto control = Control::create();
167     int ret;
168     RUNNER_ASSERT_MSG(CKM_API_SUCCESS == (ret = control->updateCCMode()),
169                          "Error=" << ErrorToString(ret));
170 }
171
172 void restart_ckm(const char* const mdpp_setting)
173 {
174     stop_service(MANAGER);
175     MdppState mdpp;
176     mdpp.set(mdpp_setting);
177     start_service(MANAGER);
178 }
179
180 } // namespace anonymous
181
182 RUNNER_TEST_GROUP_INIT(CKM_CC_MODE);
183
184 RUNNER_TEST(TCC_0000_init)
185 {
186     remove_user_data();
187
188     int tmp;
189     auto control = Control::create();
190     RUNNER_ASSERT_MSG(
191         CKM_API_SUCCESS == (tmp = control->unlockUserKey(0, "t200-special-password")),
192         "Error=" << ErrorToString(tmp));
193 }
194
195 // updatedCCMode should succeed regardless of mdpp setting
196 RUNNER_TEST(TCC_0010_updateCCMode)
197 {
198     MdppState mdpp;
199
200     mdpp.set(NULL);
201     update_cc_mode();
202
203     mdpp.set(ENABLED);
204     update_cc_mode();
205
206     mdpp.set(ENFORCING);
207     update_cc_mode();
208
209     mdpp.set(DISABLED);
210     update_cc_mode();
211
212     mdpp.set(READY);
213     update_cc_mode();
214
215     mdpp.set("whatever");
216     update_cc_mode();
217 }
218
219 // tests without listener (ckm only)
220 RUNNER_TEST(TCC_0020_noListener)
221 {
222     stop_service(LISTENER);
223     MdppState mdpp;
224
225     remove_user_data();
226     save_keys();
227
228     mdpp.set(NULL);
229     update_cc_mode();
230     read_keys(CKM_API_SUCCESS);
231
232     mdpp.set(DISABLED);
233     update_cc_mode();
234     // MJK, it's counter-intuitive: Disabled does not mean
235     // that CC mode is disabled, but that device
236     // self-test failed "device DISABLED"
237     read_keys(CKM_API_ERROR_BAD_REQUEST);
238
239     mdpp.set("whatever");
240     update_cc_mode();
241     read_keys(CKM_API_SUCCESS);
242
243     mdpp.set(ENABLED);
244     update_cc_mode();
245     read_keys(CKM_API_ERROR_BAD_REQUEST);
246
247     mdpp.set(ENFORCING);
248     update_cc_mode();
249     read_keys(CKM_API_ERROR_BAD_REQUEST);
250
251     mdpp.set(READY);
252     update_cc_mode();
253     read_keys(CKM_API_SUCCESS);
254
255     mdpp.set("whatever");
256     update_cc_mode();
257     read_keys(CKM_API_SUCCESS);
258
259     mdpp.set(DISABLED);
260     update_cc_mode();
261     read_keys(CKM_API_ERROR_BAD_REQUEST);
262 }
263
264 // when listener is started with mdpp key unset it should not update mdpp status in ckm
265 RUNNER_TEST(TCC_0030_noCallbackRegistered)
266 {
267     // restart listener without vconf callback
268     stop_service(LISTENER);
269     remove_user_data();
270     MdppState mdpp;
271     mdpp.set(NULL);
272     update_cc_mode();
273     start_service(LISTENER);
274
275     // save and read
276     save_keys();
277     read_keys(CKM_API_SUCCESS);
278
279     mdpp.set(ENABLED);
280     usleep(SLEEP); // give some time for notification to reach ckm
281
282     read_keys(CKM_API_SUCCESS);
283 }
284
285 // when listener is started with mdpp key set it should update mdpp status in ckm
286 RUNNER_TEST(TCC_0040_callbackRegistered)
287 {
288     // restart listener with vconf callback
289     stop_service(LISTENER);
290     MdppState mdpp;
291     mdpp.set(DISABLED);
292     update_cc_mode();
293     start_service(LISTENER);
294
295     remove_user_data();
296     save_keys();
297     read_keys(CKM_API_ERROR_BAD_REQUEST);
298
299     mdpp.set("whatever");
300     usleep(SLEEP); // give some time for notification to reach ckm
301     read_keys(CKM_API_SUCCESS);
302
303     mdpp.set(ENABLED);
304     usleep(SLEEP); // give some time for notification to reach ckm
305     read_keys(CKM_API_ERROR_BAD_REQUEST);
306
307     mdpp.set(DISABLED);
308     usleep(SLEEP); // give some time for notification to reach ckm
309     read_keys(CKM_API_ERROR_BAD_REQUEST);
310
311     mdpp.set(READY);
312     usleep(SLEEP); // give some time for notification to reach ckm
313     read_keys(CKM_API_SUCCESS);
314
315     mdpp.set(ENFORCING);
316     usleep(SLEEP); // give some time for notification to reach ckm
317     read_keys(CKM_API_ERROR_BAD_REQUEST);
318
319     mdpp.set(NULL);
320     usleep(SLEEP); // give some time for notification to reach ckm
321     read_keys(CKM_API_SUCCESS);
322 }
323
324 // run ckm manually and see if it properly loads mdpp setting
325 RUNNER_TEST(TCC_0050_manualCkmDisabled)
326 {
327     restart_ckm(DISABLED);
328
329     remove_user_data();
330     save_keys();
331     read_keys(CKM_API_ERROR_BAD_REQUEST);
332 }
333
334 // run ckm manually and see if it properly loads mdpp setting
335 RUNNER_TEST(TCC_0060_manualCkmEnabled)
336 {
337     restart_ckm(ENABLED);
338
339     remove_user_data();
340     save_keys();
341     read_keys(CKM_API_ERROR_BAD_REQUEST);
342 }
343
344 // run ckm manually and see if it properly loads mdpp setting
345 RUNNER_TEST(TCC_0070_manualCkmEnforcing)
346 {
347     restart_ckm(ENFORCING);
348
349     remove_user_data();
350     save_keys();
351     read_keys(CKM_API_ERROR_BAD_REQUEST);
352 }
353
354 // run ckm manually and see if it properly loads mdpp setting
355 RUNNER_TEST(TCC_0075_manualCkmReady)
356 {
357     restart_ckm(READY);
358
359     remove_user_data();
360     save_keys();
361     read_keys(CKM_API_SUCCESS);
362 }
363
364 // run ckm manually and see if it properly loads mdpp setting
365 RUNNER_TEST(TCC_0080_manualCkmWhatever)
366 {
367     restart_ckm("whatever");
368
369     remove_user_data();
370     save_keys();
371     read_keys(CKM_API_SUCCESS);
372 }
373
374 // run ckm manually and see if it properly loads mdpp setting
375 RUNNER_TEST(TCC_0090_manualCkmUnset)
376 {
377     restart_ckm(NULL);
378
379     remove_user_data();
380     save_keys();
381     read_keys(CKM_API_SUCCESS);
382 }
383
384 // make sure listener won't activate ckm to update mdpp
385 RUNNER_TEST(TCC_0100_listenerDoesntStartCkm)
386 {
387     stop_service(MANAGER);
388     stop_service(LISTENER);
389
390     MdppState mdpp;
391     mdpp.set(ENABLED);
392
393     start_service(LISTENER);
394
395     usleep(1000*1000); // by that time ckm would be already started
396
397     int lock = TEMP_FAILURE_RETRY(open(CKM_LOCK, O_RDWR));
398     RUNNER_ASSERT_MSG(-1 != lock, "Error in opening lock file. Errno: " << strerror(errno));
399
400     int ret = lockf(lock, F_TEST, 0);
401     close(lock);
402     RUNNER_ASSERT_MSG(ret == 0, "CKM lock is occupied. CKM seems to be running.");
403 }
404
405 RUNNER_TEST(TCC_9999_deinit)
406 {
407     remove_user_data();
408
409     int tmp;
410     auto control = Control::create();
411     RUNNER_ASSERT_MSG(
412         CKM_API_SUCCESS == (tmp = control->lockUserKey(0)),
413         "Error=" << ErrorToString(tmp));
414 }