• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "fscrypt_key_v1.h"
17 
18 #include <openssl/sha.h>
19 
20 #include "libfscrypt/key_control.h"
21 #include "storage_service_log.h"
22 
23 namespace OHOS {
24 namespace StorageDaemon {
25 static const std::string CRYPTO_NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt"};
26 
ActiveKey(uint32_t flag,const std::string & mnt)27 bool FscryptKeyV1::ActiveKey(uint32_t flag, const std::string &mnt)
28 {
29     (void)mnt;
30     LOGD("enter");
31     if (!GenerateKeyDesc()) {
32         LOGE("GenerateKeyDesc failed");
33         return false;
34     }
35 
36     if (!fscryptV1Ext.ActiveKeyExt(flag, keyInfo_.key.data.get(), keyInfo_.key.size)) {
37         LOGE("fscryptV1Ext ActiveKeyExtfailed");
38         return false;
39     }
40     if (!InstallKeyToKeyring()) {
41         LOGE("InstallKeyToKeyring failed");
42         return false;
43     }
44     LOGD("success");
45     return true;
46 }
47 
InstallKeyToKeyring()48 bool FscryptKeyV1::InstallKeyToKeyring()
49 {
50     fscrypt_key fskey;
51     fskey.mode = FS_ENCRYPTION_MODE_AES_256_XTS;
52     fskey.size = keyInfo_.key.size;
53     auto err = memcpy_s(fskey.raw, FS_MAX_KEY_SIZE, keyInfo_.key.data.get(), keyInfo_.key.size);
54     if (err != EOK) {
55         LOGE("memcpy failed ret %{public}d", err);
56         return false;
57     }
58 
59     key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
60     if (krid == -1) {
61         LOGI("no session keyring for fscrypt");
62         krid = KeyCtrlAddKey("keyring", "fscrypt", KEY_SPEC_SESSION_KEYRING);
63         if (krid == -1) {
64             LOGE("failed to add session keyring");
65             return false;
66         }
67     }
68     for (auto prefix : CRYPTO_NAME_PREFIXES) {
69         std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
70         key_serial_t ks =
71             KeyCtrlAddKeyEx("logon", keyref.c_str(), &fskey, krid);
72         if (ks == -1) {
73             // Addkey failed, need to process the error
74             LOGE("Failed to AddKey %{public}s into keyring %{public}d, errno %{public}d", keyref.c_str(), krid,
75                 errno);
76         }
77     }
78     if (!SaveKeyBlob(keyInfo_.keyDesc, dir_ + PATH_KEYDESC)) {
79         return false;
80     }
81     keyInfo_.key.Clear();
82     LOGD("success");
83     return true;
84 }
85 
InactiveKey(uint32_t flag,const std::string & mnt)86 bool FscryptKeyV1::InactiveKey(uint32_t flag, const std::string &mnt)
87 {
88     (void)mnt;
89     LOGD("enter");
90     bool ret = true;
91 
92     if (!UninstallKeyToKeyring()) {
93         LOGE("UninstallKeyToKeyring failed");
94         ret = false;
95     }
96     if (!fscryptV1Ext.InactiveKeyExt(flag)) {
97         LOGE("fscryptV1Ext InactiveKeyExt failed");
98         ret = false;
99     }
100     LOGD("finish");
101     return ret;
102 }
103 
UninstallKeyToKeyring()104 bool FscryptKeyV1::UninstallKeyToKeyring()
105 {
106     if (keyInfo_.keyDesc.IsEmpty()) {
107         LOGE("keyDesc is null, key not installed?");
108         return false;
109     }
110 
111     key_serial_t krid = KeyCtrlSearch(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
112     if (krid == -1) {
113         LOGE("Error searching session keyring for fscrypt-provisioning key for fscrypt");
114         return false;
115     }
116     for (auto prefix : CRYPTO_NAME_PREFIXES) {
117         std::string keyref = prefix + ":" + keyInfo_.keyDesc.ToString();
118         key_serial_t ks = KeyCtrlSearch(krid, "logon", keyref.c_str(), 0);
119         if (KeyCtrlUnlink(ks, krid) != 0) {
120             LOGE("Failed to unlink key with serial %{public}d ref %{public}s", krid, keyref.c_str());
121         }
122     }
123 
124     LOGD("success");
125     return true;
126 }
127 
GenerateKeyDesc()128 bool FscryptKeyV1::GenerateKeyDesc()
129 {
130     if (keyInfo_.key.IsEmpty()) {
131         LOGE("key is empty");
132         return false;
133     }
134     SHA512_CTX c;
135 
136     SHA512_Init(&c);
137     SHA512_Update(&c, keyInfo_.key.data.get(), keyInfo_.key.size);
138     uint8_t keyRef1[SHA512_DIGEST_LENGTH] = { 0 };
139     SHA512_Final(keyRef1, &c);
140 
141     SHA512_Init(&c);
142     SHA512_Update(&c, keyRef1, SHA512_DIGEST_LENGTH);
143     uint8_t keyRef2[SHA512_DIGEST_LENGTH] = { 0 };
144     SHA512_Final(keyRef2, &c);
145 
146     static_assert(SHA512_DIGEST_LENGTH >= CRYPTO_KEY_DESC_SIZE, "Hash too short for descriptor");
147     keyInfo_.keyDesc.Alloc(CRYPTO_KEY_DESC_SIZE);
148     auto err = memcpy_s(keyInfo_.keyDesc.data.get(), keyInfo_.keyDesc.size, keyRef2, CRYPTO_KEY_DESC_SIZE);
149     if (err != EOK) {
150         LOGE("memcpy failed ret %{public}d", err);
151         return false;
152     }
153     return true;
154 }
155 } // namespace StorageDaemon
156 } // namespace OHOS
157