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