Refactor ecryptfs structures to C++ style
[platform/core/security/krate.git] / volume / main.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 #include <fcntl.h>
18 #include <unistd.h>
19 #include <getopt.h>
20 #include <sys/stat.h>
21 #include <sys/mount.h>
22 #include <sys/types.h>
23
24 #include <cstring>
25 #include <string>
26 #include <vector>
27 #include <iostream>
28
29 #include <klay/error.h>
30 #include <klay/exception.h>
31 #include <klay/audit/logger.h>
32
33 #include "ecryptfs.h"
34 #include "kernel-keyring.h"
35 #include "key-manager.h"
36 #include "key-generator.h"
37
38 int generateKey(const std::string& keyName)
39 {
40         if (KeyManager::isKeyExist(keyName)) {
41                 ERROR("Key already registered");
42                 return -1;
43         }
44
45         try {
46                 std::string pass = KeyGenerator::generateKey(ECRYPTFS_MAX_KEY_SIZE);
47                 std::string salt = KeyGenerator::generateKey(ECRYPTFS_SALT_SIZE);
48                 std::string wrappedKey = KeyGenerator::wrapKey(pass, salt, ECRYPTFS_MAX_KEY_SIZE);
49
50                 KeyManager::addKey(keyName, wrappedKey);
51         } catch (runtime::Exception& e) {
52                 ERROR(e.what());
53                 return -1;
54         }
55
56         return 0;
57 }
58
59 EcryptfsPayload* generateToken(char* key)
60 {
61         auto *payload = new EcryptfsPayload(EcryptfsPayload::Type::PasswordToken);
62         payload->token.password.flags = EcryptfsPassword::Flag::
63                                                                         SessionKeyEncryptionKeySet;
64         payload->token.password.sessionKeyEncryptionKeySize = ECRYPTFS_MAX_KEY_SIZE;
65         ::memcpy(payload->token.password.sessionKeyEncryptionKey, key,
66                                 payload->token.password.sessionKeyEncryptionKeySize);
67
68         ::memcpy((char *)payload->token.password.signature,
69                                 key, ECRYPTFS_SIGNATURE_SIZE);
70
71         return payload;
72 }
73
74 int mountEcryptfs(const std::string& src, const std::string& keyName)
75 {
76         int rc;
77         char ecryptfsOpts[1024];
78         EcryptfsPayload* payload = NULL;
79
80         std::string key;
81         try {
82                 key = KeyManager::getKey(keyName);
83         } catch (runtime::Exception& e) {
84                 ERROR(e.what());
85                 return -1;
86         }
87
88         if (KernelKeyRing::link(KEY_SPEC_USER_KEYRING, KEY_SPEC_SESSION_KEYRING) != 0) {
89                 ERROR("Failed to link key");
90                 return -1;
91         }
92
93         if ((payload = generateToken((char*)key.c_str())) == NULL) {
94                 ERROR("Failed to generate Token");
95                 return -1;
96         }
97
98         const char* signature = (const char*)payload->token.password.signature;
99         rc = KernelKeyRing::search(KEY_SPEC_USER_KEYRING,
100                                                            "user",
101                                                            signature,
102                                                            0);
103
104         if (rc == -1) {
105                 if (errno != ENOKEY) {
106                         ERROR("Failed to find key");
107                         delete payload;
108                         return -1;
109                 }
110
111                 rc = KernelKeyRing::add("user",
112                                                                 signature,
113                                                                 (void*)payload,
114                                                                 sizeof(*payload),
115                                                                 KEY_SPEC_USER_KEYRING);
116
117                 if (rc == -1) {
118                         ERROR("Failed to add key");
119                         delete payload;
120                         return -1;
121                 }
122         }
123
124         ::snprintf(ecryptfsOpts, 1024,
125                            "ecryptfs_passthrough,"
126                            "ecryptfs_cipher=aes,"
127                            "ecryptfs_key_bytes=%d,"
128                            "ecryptfs_sig=%s,"
129                            "smackfsroot=*,smackfsdef=*",
130                            ECRYPTFS_MAX_KEY_SIZE, signature);
131
132         delete payload;
133
134         rc = ::mount(src.c_str(), src.c_str(), "ecryptfs", MS_NODEV, ecryptfsOpts);
135         if (rc != 0) {
136                 ERROR(runtime::GetSystemErrorMessage());
137                 return -1;
138         }
139
140         return 0;
141 }
142
143 int mountEcryptfsToAll()
144 {
145         return 0;
146 }
147
148 void usage(const std::string& prog)
149 {
150         std::cout << "Usage: " << prog << std::endl
151                           << "-a            : Automount" << std::endl
152                           << "-g name       : Generate key for krate" << std::endl
153                           << "-m name       : Apply filesystem encrytion to krate" << std::endl;
154 }
155
156 int main(int argc, char* argv[])
157 {
158         int opt, index, ret = -1;
159         struct option options[] = {
160                 {"automount", no_argument, 0, 'a'},
161                 {"generate", required_argument, 0, 'g'},
162                 {"mount", required_argument, 0, 'm'},
163                 {0, 0, 0, 0}
164         };
165
166         while ((opt = getopt_long(argc, argv, "ag:m:", options, &index)) != -1) {
167                 switch (opt) {
168                 case 'a':
169                         ret = mountEcryptfsToAll();
170                         break;
171                 case 'g':
172                         ret = generateKey(optarg);
173                         break;
174                 case 'm':
175                         ret = mountEcryptfs("/home/" + std::string(optarg), optarg);
176                         break;
177                 default:
178                         std::cerr << "unknown" << std::endl;
179                         usage(argv[0]);
180                         break;
181                 }
182         }
183
184         if (ret != 0) {
185                 return EXIT_FAILURE;
186         }
187
188         return EXIT_SUCCESS;
189 }