Modify enum values for corrupted encryption
[platform/core/security/ode.git] / tools / cli / ode-admin-cli.cpp
1 /*
2  * Copyright (c) 2015 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
18 /**
19  * @file
20  * @brief   CLI tool to encrypt/decrypt storage and secure erase
21  */
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <termios.h>
25
26 #include <mutex>
27 #include <string>
28 #include <vector>
29 #include <iostream>
30 #include <condition_variable>
31 #include <stdexcept>
32
33 #include <ode/secure-erase.h>
34 #include <ode/internal-encryption.h>
35 #include <ode/external-encryption.h>
36 #include <ode/luks.h>
37 #include <ode/keys.h>
38
39 extern char** environ;
40
41 std::mutex mtx;
42 bool mountFlag = false;
43
44 static inline int usage(const std::string name)
45 {
46         std::cout << "Usage: " << name << " [Option]" << std::endl
47                           << std::endl
48                           << "Options :" << std::endl
49                           << "  -m, --mount=internal|external      mount" << std::endl
50                           << "  -u, --umount=internal|external     umount" << std::endl
51                           << "  -e, --encrypt=internal|external    encrypt" << std::endl
52                           << "  -d, --decrypt=internal|external    decrypt" << std::endl
53                           << "  -l  --luks=format|open|close|wait  perform LUKS operation using asynchronous" << std::endl
54                           << "                                     API or wait for completion. May also" << std::endl
55                           << "                                     require -D and/or -M option." << std::endl
56                           << "  -L  --luks_sync=format|open|close  perform LUKS operation using synchronous" << std::endl
57                           << "                                     API. May also require -D and/or -M option." << std::endl
58                           << "  -D  --device=<device>              device path" << std::endl
59                           << "  -M  --mapping=<mapping>            mapping name required for LUKS open and" << std::endl
60                           << "                                     LUKS close operations" << std::endl
61                           << "  -k, --keys=store|remove            Store/remove the master key of given device" << std::endl
62                           << "                                     for the purpose of system upgrade. Requires" << std::endl
63                           << "                                     -D option" << std::endl
64                           << "  -p, --changepw=internal|external   change password" << std::endl
65                           << "  -s, --state=internal|external      get state" << std::endl
66                           << "  -w, --waitmnt=internal|external    wait for mount"<< std::endl
67                           << "  -c, --clean=DIRECTORY              secure-clean" << std::endl
68                           << "  -r, --recovery=internal|external   recovery" << std::endl
69                           << "  -h, --help                         show this" << std::endl
70                           << std::endl;
71
72         return -1;
73 }
74
75 static inline std::string getPassword() {
76         std::string password;
77
78         std::cout << "Password: ";
79
80         struct termios oldt;
81         tcgetattr(STDIN_FILENO, &oldt);
82
83         termios newt = oldt;
84         newt.c_lflag &= ~ECHO;
85         tcsetattr(STDIN_FILENO, TCSANOW, &newt);
86
87         std::cin >> password;
88
89         tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
90         std::cout << std::endl;
91
92         return password;
93 }
94
95 static inline void printSelectableStorage(bool internal = true,
96                                           bool external = true)
97 {
98         bool firstDone = false;
99         std::cerr << "Just choose one among followings :" << std::endl;
100
101         if (internal) {
102                 std::cerr << "internal";
103                 firstDone = true;
104         }
105         if (external) {
106                 if (firstDone) {
107                         std::cerr << ", ";
108                 }
109                 std::cerr << "external";
110                 firstDone = true;
111         }
112
113         std::cerr << std::endl;
114 }
115
116 static inline int mount(const std::string name)
117 {
118         int ret;
119
120         if (name == "internal") {
121                 std::string password = getPassword();
122                 ret = ode_internal_encryption_set_mount_password(password.c_str());
123                 if (ret == 0) {
124                         ret = ode_internal_encryption_mount();
125                 } else {
126                         std::cerr << "Password setting failed" << std::endl;
127                 }
128         } else if (name == "external") {
129                 std::string password = getPassword();
130                 ret = ode_external_encryption_set_mount_password(password.c_str());
131                 if (ret == 0) {
132                         ret = ode_external_encryption_mount();
133                 } else {
134                         std::cerr << "Password setting failed" << std::endl;
135                 }
136         } else {
137                 printSelectableStorage();
138                 return -1;
139         }
140
141         if (ret != 0) {
142                 std::cerr << "Error : " << ret <<std::endl;
143         }
144
145         return ret;
146 }
147
148 static inline int umount(const std::string name)
149 {
150         int ret;
151
152         if (name == "internal") {
153                 ret = ode_internal_encryption_umount();
154         } else if (name == "external") {
155                 ret = ode_external_encryption_umount();
156         } else {
157                 printSelectableStorage();
158                 return -1;
159         }
160
161         if (ret != 0) {
162                 std::cerr << "Error : " << ret <<std::endl;
163         }
164
165         return ret;
166 }
167
168 static inline int encrypt_storage(const std::string name)
169 {
170         int ret;
171
172         if (name == "internal") {
173                 bool result = false;
174                 ode_internal_encryption_is_password_initialized(&result);
175
176                 if (!result) {
177                         std::cout << "New ";
178                         std::string password = getPassword();
179                         ode_internal_encryption_init_password(password.c_str());
180                 }
181
182                 result = false;
183                 std::cout << "Confirm ";
184                 std::string password = getPassword();
185                 ode_internal_encryption_verify_password(password.c_str(), &result);
186
187                 if (!result) {
188                         std::cerr << "Confirm password doesn't match" << std::endl;
189                         return -1;
190                 }
191
192                 unsigned int options = 0;
193                 ode_internal_encryption_get_supported_options(&options);
194
195                 char answer;
196                 if (options & ODE_OPTION_INTERNAL_INCLUDE_UNUSED_REGION) {
197                         std::cout << "Encrypt All (include unused region)? (y/n) ";
198                         std::cin >> answer;
199                         if (answer != 'Y' && answer != 'y') {
200                                 options &= ~ODE_OPTION_INTERNAL_INCLUDE_UNUSED_REGION;
201                         }
202                 }
203                 ret = ode_internal_encryption_encrypt(password.c_str(), options);
204         } else if (name == "external") {
205                 bool result = false;
206                 ode_external_encryption_is_password_initialized(&result);
207
208                 if (!result) {
209                         std::cout << "New ";
210                         std::string password = getPassword();
211                         ode_external_encryption_init_password(password.c_str());
212                 }
213
214                 result = false;
215                 std::cout << "Confirm ";
216                 std::string password = getPassword();
217                 ode_external_encryption_verify_password(password.c_str(), &result);
218
219                 if (!result) {
220                         std::cerr << "Confirm password doesn't match" << std::endl;
221                         return -1;
222                 }
223
224                 unsigned int options;
225                 ode_external_encryption_get_supported_options(&options);
226
227                 char answer;
228                 if (options & ODE_OPTION_EXTERNAL_ONLY_NEW_FILE) {
229                         std::cout << "Encrypt new files only? (y/n) ";
230                         std::cin >> answer;
231                         if (answer != 'Y' && answer != 'y') {
232                                 options &= ~ODE_OPTION_EXTERNAL_ONLY_NEW_FILE;
233                         }
234                 }
235                 if (options & ODE_OPTION_EXTERNAL_EXCEPT_FOR_MEDIA_FILE) {
236                         std::cout << "Encrypt non-media files only? (y/n) ";
237                         std::cin >> answer;
238                         if (answer != 'Y' && answer != 'y') {
239                                 options &= ~ODE_OPTION_EXTERNAL_EXCEPT_FOR_MEDIA_FILE;
240                         }
241                 }
242                 ret = ode_external_encryption_encrypt(password.c_str(), options);
243         } else {
244                 printSelectableStorage(true, true);
245                 return -1;
246         }
247
248         if (ret != 0) {
249                 std::cerr << "Error : " << ret <<std::endl;
250         }
251
252         return ret;
253 }
254
255 static inline int decrypt_storage(const std::string name)
256 {
257         int ret;
258
259         if (name == "internal") {
260                 std::string password = getPassword();
261                 ret = ode_internal_encryption_decrypt(password.c_str());
262                 if (ret == 0) {
263                         ode_internal_encryption_clean_password(password.c_str());
264                 }
265         } else if (name == "external") {
266                 std::string password = getPassword();
267                 ret = ode_external_encryption_decrypt(password.c_str());
268                 if (ret == 0) {
269                         ode_external_encryption_clean_password(password.c_str());
270                 }
271         } else {
272                 printSelectableStorage(true, true);
273                 return -1;
274         }
275
276         if (ret != 0) {
277                 std::cerr << "Error : " << ret <<std::endl;
278         }
279
280         return ret;
281 }
282
283 class LuksWrapper {
284 public:
285         explicit LuksWrapper(bool sync) : synchronous(sync) {
286                 if (synchronous)
287                         return;
288
289                 int ret = ode_luks_set_event_cb(&LuksWrapper::StaticCallback, this);
290                 if (ret != ODE_ERROR_NONE)
291                         throw std::runtime_error("Callback setting failed " + std::to_string(ret));
292         }
293
294         int format(const std::string& device)
295         {
296                 std::cout << "New ";
297                 std::string password = getPassword();
298
299                 std::cout << "Confirm ";
300                 std::string password2 = getPassword();
301                 if (password != password2) {
302                         std::cerr << "Confirm password doesn't match" << std::endl;
303                         return -1;
304                 }
305
306                 int ret;
307                 if (synchronous)
308                         ret = ode_luks_format_sync(device.c_str(), password.c_str());
309                 else
310                         ret = ode_luks_format(device.c_str(), password.c_str());
311
312                 if (ret != ODE_ERROR_NONE) {
313                         std::cerr << "ode_luks_format() failed " << ret << std::endl;
314                         return ret;
315                 }
316                 if (synchronous)
317                         return ret;
318
319                 return WaitForCallback(ODE_LUKS_FORMAT);
320         }
321
322         int open(const std::string& device, const std::string& mapping)
323         {
324                 std::string password = getPassword();
325                 int ret;
326                 if (synchronous)
327                         ret = ode_luks_open_sync(device.c_str(), password.c_str(), mapping.c_str());
328                 else
329                         ret = ode_luks_open(device.c_str(), password.c_str(), mapping.c_str());
330
331                 if (ret != ODE_ERROR_NONE) {
332                         std::cerr << "ode_luks_open() failed " << ret << std::endl;
333                         return ret;
334                 }
335                 if (synchronous)
336                         return ret;
337
338                 return WaitForCallback(ODE_LUKS_OPEN);
339         }
340
341         int close(const std::string& mapping)
342         {
343                 int ret;
344                 if (synchronous)
345                         ret = ode_luks_close_sync(mapping.c_str());
346                 else
347                         ret = ode_luks_close(mapping.c_str());
348
349                 if (ret != ODE_ERROR_NONE) {
350                         std::cerr << "ode_luks_close() failed " << ret << std::endl;
351                         return ret;
352                 }
353                 if (synchronous)
354                         return ret;
355
356                 return WaitForCallback(ODE_LUKS_CLOSE);
357         }
358
359         int wait()
360         {
361                 return WaitForCallbackInternal([](ode_luks_operation_e) { return true; });
362         }
363
364         ~LuksWrapper() {
365                 if (synchronous)
366                         ode_luks_unset_event_cb();
367         }
368
369 private:
370         static void StaticCallback(ode_luks_operation_e op, int ret, void* user_data)
371         {
372                 auto self = static_cast<LuksWrapper*>(user_data);
373                 self->Callback(op, ret);
374         }
375
376         void Callback(ode_luks_operation_e op, int ret)
377         {
378                 {
379                         std::lock_guard<std::mutex> guard(mutex);
380                         results.push_back({op, ret});
381                 }
382                 cond.notify_one();
383         }
384
385         int WaitForCallback(ode_luks_operation_e expected)
386         {
387                 return WaitForCallbackInternal([=](ode_luks_operation_e op) {
388                         return expected == op;
389                 });
390         }
391
392         int WaitForCallbackInternal(const std::function<bool(ode_luks_operation_e)>& opCheck)
393         {
394                 std::unique_lock<std::mutex> lock(mutex);
395                 cond.wait(lock, [this]{
396                         return !results.empty();
397                 });
398
399                 auto& res = results.front();
400                 int ret = res.ret;
401
402                 std::cout << "Luks callback received. Operation: " << static_cast<int>(res.op)
403                                   << " result: " << res.ret << std::endl;
404                 if (!opCheck(res.op)) {
405                         std::cerr << "Unexpected operation finished " << res.op << std::endl;
406                         ret = -1;
407                 }
408
409                 results.erase(results.begin());
410                 lock.unlock();
411
412                 return ret;
413         }
414
415         std::condition_variable cond;
416         std::mutex mutex;
417
418         struct result {
419                 ode_luks_operation_e op;
420                 int ret;
421         };
422
423         std::vector<result> results;
424         bool synchronous;
425 };
426
427 static inline int luks(bool sync,
428                                            const std::string& name,
429                                            const std::string& device,
430                                            const std::string& mapping)
431 {
432         try {
433                 if (name == "format") {
434                         if (device.empty())
435                                 return usage(name);
436
437                         LuksWrapper wrapper(sync);
438                         return wrapper.format(device);
439                 }
440
441                 if (name == "open") {
442                         if (device.empty() || mapping.empty())
443                                 return usage(name);
444
445                         LuksWrapper wrapper(sync);
446                         return wrapper.open(device, mapping);
447                 }
448
449                 if (name == "close") {
450                         if (mapping.empty())
451                                 return usage(name);
452
453                         LuksWrapper wrapper(sync);
454                         return wrapper.close(mapping);
455                 }
456
457                 if (name == "wait" && !sync) {
458                         LuksWrapper wrapper(sync);
459                         return wrapper.wait();
460                 }
461
462                 if (sync)
463                         std::cerr << "Wrong arguments (format|open|close)" << std::endl;
464                 else
465                         std::cerr << "Wrong arguments (format|open|close|wait)" << std::endl;
466                 return -1;
467         } catch (const std::runtime_error& e) {
468                 std::cerr << e.what() << std::endl;
469                 return -1;
470         }
471 }
472
473 static inline int keys(const std::string& name, const std::string& device)
474 {
475         if (name == "store") {
476                 if (device.empty())
477                         return usage(name);
478
479                 std::string password = getPassword();
480
481                 int ret = ode_key_store_master_key(device.c_str(), password.c_str());
482                 if (ret != ODE_ERROR_NONE)
483                         std::cerr << "Error : " << ret << std::endl;
484                 return -1;
485         }
486
487         if (name == "remove") {
488                 if (device.empty())
489                         return usage(name);
490
491                 int ret = ode_key_remove_master_key(device.c_str());
492                 if (ret != ODE_ERROR_NONE)
493                         std::cerr << "Error : " << ret << std::endl;
494                 return -1;
495         }
496
497         std::cerr << "Wrong arguments (store|remove)" << std::endl;
498         return -1;
499 }
500
501 static inline int change_password(const std::string name)
502 {
503         int ret;
504
505         std::cout << "Old ";
506         std::string oldPW = getPassword();
507
508         std::cout << "New ";
509         std::string newPW = getPassword();
510
511         if (name == "internal") {
512                 ret = ode_internal_encryption_change_password(oldPW.c_str(), newPW.c_str());
513         } else if (name == "external") {
514                 ret = ode_external_encryption_change_password(oldPW.c_str(), newPW.c_str());
515         } else {
516                 printSelectableStorage();
517                 return -1;
518         }
519
520         if (ret != 0) {
521                 std::cerr << "Error : " << ret <<std::endl;
522         }
523
524         return ret;
525 }
526
527 static inline int get_state(const std::string name)
528 {
529         int ret, state;
530
531         if (name == "internal") {
532                 ret = ode_internal_encryption_get_state(&state);
533         } else if (name == "external") {
534                 ret = ode_external_encryption_get_state(&state);
535         } else {
536                 printSelectableStorage();
537                 return -1;
538         }
539
540         if (ret != 0) {
541                 std::cerr << "Error : " << ret <<std::endl;
542                 return -1;
543         }
544
545         switch (state) {
546         case ODE_STATE_ENCRYPTED:
547                 std::cout << "Encrypted";
548                 break;
549         case ODE_STATE_UNENCRYPTED:
550                 std::cout << "Unencrypted";
551                 break;
552         case ODE_STATE_CORRUPTED:
553                 std::cout << "Corrupted";
554                 break;
555         default:
556                 std::cout << "Invalid";
557         }
558         std::cout << std::endl;
559
560         return ret;
561 }
562
563 static void mount_event_cb(void *user_data) {
564         std::unique_lock<std::mutex> lock(mtx);
565         std::condition_variable *pCond = (std::condition_variable*)user_data;
566         mountFlag = true;
567         pCond->notify_one();
568 }
569
570 static inline int wait_for_mount(const std::string name)
571 {
572         int ret;
573         std::unique_lock<std::mutex> lock(mtx);
574         std::condition_variable cond;
575
576         if (name == "internal") {
577                 std::cout << "Wait for internal storage mount..." << std::endl;
578                 ret = ode_internal_encryption_set_mount_event_cb(mount_event_cb, &cond);
579         } else if (name == "external") {
580                 std::cout << "Wait for external storage mount..." << std::endl;
581                 ret = ode_external_encryption_set_mount_event_cb(mount_event_cb, &cond);
582         } else {
583                 printSelectableStorage();
584                 return -1;
585         }
586
587         if (ret != 0) {
588                 std::cerr << "Error : " << ret <<std::endl;
589                 return -1;
590         }
591
592         cond.wait(lock, []{return mountFlag;});
593         std::cout << "Mount is completed"<< std::endl;
594         mountFlag = false;
595
596         return ret;
597 }
598
599 static inline int clean(const std::string name)
600 {
601         int ret;
602
603         ret = ode_secure_clean(name.c_str());
604         if (ret != 0) {
605                 std::cerr << "Error : " << ret <<std::endl;
606         }
607
608         return ret;
609 }
610
611 static inline int recovery(const std::string &name)
612 {
613         int ret = -1;
614
615         if (name == "internal")
616                 ret = ode_internal_encryption_recovery();
617         else if (name == "external")
618                 ret = ode_external_encryption_recovery();
619
620         if (ret != 0)
621                 std::cerr << "Error : " << ret << std::endl;
622
623         return ret;
624 }
625
626 int main(int argc, char* argv[])
627 {
628         int opt = 0, luks_opt = 0, index, ret = 0;
629
630         struct option options[] = {
631                 {"help", no_argument, 0, 'h'},
632                 {"mount", required_argument, 0, 'm'},
633                 {"umount", required_argument, 0, 'u'},
634                 {"encrypt", required_argument, 0, 'e'},
635                 {"decrypt", required_argument, 0, 'd'},
636                 {"luks" , required_argument, 0, 'l'},
637                 {"luks_sync" , required_argument, 0, 'L'},
638                 {"keys" , required_argument, 0, 'k'},
639                 {"state", required_argument, 0, 's'},
640                 {"waitmnt", required_argument, 0, 'w'},
641                 {"clean", required_argument, 0, 'c'},
642                 {"recovery", required_argument, 0, 'r'},
643                 {0, 0, 0, 0}
644         };
645
646         struct option luks_options[] = {
647                 {"device", required_argument, 0, 'D'},
648                 {"mapping", required_argument, 0, 'M'},
649                 {"synchronous", no_argument, 0, 'S'},
650                 {0, 0, 0, 0}
651         };
652
653         if (argc <= 1) {
654                 usage(argv[0]);
655                 return EXIT_SUCCESS;
656         }
657
658         std::string mapping, device, op;
659         bool sync = true;
660
661         while ((opt = getopt_long(argc, argv, "m:u:e:d:l:L:p:k:s:w:c:r:h", options, &index)) != -1) {
662                 switch (opt) {
663                 case 'm':
664                         ret = mount(optarg);
665                         break;
666                 case 'u':
667                         ret = umount(optarg);
668                         break;
669                 case 'e':
670                         ret = encrypt_storage(optarg);
671                         break;
672                 case 'd':
673                         ret = decrypt_storage(optarg);
674                         break;
675                 case 'l':
676                         sync = false;
677                         // No break on purpose. Logic is the same just the flag is different.
678                 case 'L':
679                         op = optarg;
680                         while ((luks_opt = getopt_long(argc, argv, "D:M:", luks_options, &index)) != -1) {
681                                 switch (luks_opt) {
682                                 case 'D':
683                                         device = optarg;
684                                         break;
685                                 case 'M':
686                                         mapping = optarg;
687                                         break;
688                                 default:
689                                         ret = usage(argv[0]);
690                                 }
691                         }
692                         if (ret == 0)
693                                 ret = luks(sync, op, device, mapping);
694                         break;
695                 case 'k':
696                         op = optarg;
697                         while ((luks_opt = getopt_long(argc, argv, "D:", luks_options, &index)) != -1) {
698                                 switch (luks_opt) {
699                                 case 'D':
700                                         device = optarg;
701                                         break;
702                                 default:
703                                         ret = usage(argv[0]);
704                                 }
705                         }
706                         if (ret == 0)
707                                 ret = keys(op, device);
708                         break;
709                 case 'p':
710                         ret = change_password(optarg);
711                         break;
712                 case 'w':
713                         ret = wait_for_mount(optarg);
714                         break;
715                 case 's':
716                         ret = get_state(optarg);
717                         break;
718                 case 'c':
719                         ret = clean(optarg);
720                         break;
721                 case 'r':
722                         ret = recovery(optarg);
723                         break;
724                 case 'D':
725                         device = optarg;
726                         break;
727                 case 'M':
728                         mapping = optarg;
729                         break;
730                 case 'h':
731                 default:
732                         ret = usage(argv[0]);
733                 }
734         }
735
736         return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
737 }