1 /*
2 * Copyright (C) 2021 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 "init/hap_crl_manager.h"
17
18 #include <fstream>
19 #include <string>
20
21 #include "common/hap_verify_log.h"
22 #include "common/random_access_file.h"
23 #include "openssl/asn1.h"
24 #include "openssl/x509.h"
25 #include "unordered_map"
26 #include "util/hap_cert_verify_openssl_utils.h"
27 #include "utility"
28
29 namespace OHOS {
30 namespace Security {
31 namespace Verify {
32 #ifndef STANDARD_SYSTEM
33 const std::string HapCrlManager::HAP_CRL_FILE_PATH = "/data/sadata/hap_crl";
34 #else
35 const std::string HapCrlManager::HAP_CRL_FILE_PATH = "/data/hap_crl";
36 #endif
37
GetInstance()38 HapCrlManager& HapCrlManager::GetInstance()
39 {
40 static HapCrlManager hapCrlManager;
41 return hapCrlManager;
42 }
43
HapCrlManager()44 HapCrlManager::HapCrlManager() : crlMtx(), crlsMap(), isInit(false)
45 {
46 }
47
~HapCrlManager()48 HapCrlManager::~HapCrlManager()
49 {
50 for (auto crlPair : crlsMap) {
51 X509_CRL_free(crlPair.second);
52 }
53 crlsMap.clear();
54 }
55
Init()56 void HapCrlManager::Init()
57 {
58 if (isInit) {
59 return;
60 }
61
62 crlMtx.lock();
63 HapByteBuffer crlsBuffer;
64 bool ret = ReadCrls(crlsBuffer);
65 if (ret && crlsBuffer.HasRemaining()) {
66 ParseCrls(crlsBuffer);
67 isInit = true;
68 }
69 crlMtx.unlock();
70 }
71
ParseCrls(HapByteBuffer & crlsBuffer)72 bool HapCrlManager::ParseCrls(HapByteBuffer& crlsBuffer)
73 {
74 uint32_t numOfCrl;
75 if (!crlsBuffer.GetUInt32(0, numOfCrl)) {
76 HAPVERIFY_LOG_ERROR(LABEL, "get numOfCrl failed");
77 return false;
78 }
79
80 int32_t hasUsed = static_cast<int>(sizeof(numOfCrl));
81 crlsBuffer.SetPosition(hasUsed);
82 HAPVERIFY_LOG_DEBUG(LABEL, "total crl num: %{public}u", numOfCrl);
83 while (numOfCrl && hasUsed <= crlsBuffer.GetCapacity()) {
84 int32_t crlLen;
85 if (!crlsBuffer.GetInt32(crlLen)) {
86 HAPVERIFY_LOG_ERROR(LABEL, "get crlLen failed");
87 return false;
88 }
89 hasUsed += static_cast<int>(sizeof(crlLen));
90 X509_CRL* crl = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlsBuffer, hasUsed, crlLen);
91 if (crl == nullptr) {
92 HAPVERIFY_LOG_WARN(LABEL, "crl file is destroyed");
93 return false;
94 }
95
96 std::string crlIssuer;
97 if (!HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(crl, crlIssuer)) {
98 X509_CRL_free(crl);
99 HAPVERIFY_LOG_WARN(LABEL, "GetIssuerFromX509Crl failed");
100 return false;
101 }
102
103 if (crlsMap.find(crlIssuer) != crlsMap.end()) {
104 X509_CRL_free(crlsMap[crlIssuer]);
105 }
106 crlsMap[crlIssuer] = crl;
107
108 hasUsed += crlLen;
109 crlsBuffer.SetPosition(hasUsed);
110 HAPVERIFY_LOG_INFO(LABEL, "get %{public}ust crl's Issuer: %{public}s", numOfCrl, crlIssuer.c_str());
111 numOfCrl--;
112 }
113 return true;
114 }
115
ReadCrls(HapByteBuffer & crlsBuffer)116 bool HapCrlManager::ReadCrls(HapByteBuffer& crlsBuffer)
117 {
118 RandomAccessFile crlRandomAccess;
119 crlRandomAccess.Init(HAP_CRL_FILE_PATH);
120 long long fileLen = crlRandomAccess.GetLength();
121 if (fileLen <= 0) {
122 HAPVERIFY_LOG_WARN(LABEL, "crl fileLen: %{public}lld", fileLen);
123 return true;
124 }
125 crlsBuffer.SetCapacity(fileLen);
126 long long readLen = crlRandomAccess.ReadFileFullyFromOffset(crlsBuffer, 0);
127 if (readLen != fileLen) {
128 HAPVERIFY_LOG_ERROR(LABEL, "read file len: %{public}lld is not same as %{public}lld", readLen, fileLen);
129 return false;
130 }
131 return true;
132 }
133
WriteCrlsToFile()134 void HapCrlManager::WriteCrlsToFile()
135 {
136 crlMtx.lock();
137 std::ofstream crlFile(HAP_CRL_FILE_PATH, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
138 if (!crlFile.is_open()) {
139 HAPVERIFY_LOG_ERROR(LABEL, "open %{public}s failed", HAP_CRL_FILE_PATH.c_str());
140 crlMtx.unlock();
141 return;
142 }
143 uint32_t numOfCrl = crlsMap.size();
144 crlFile.write(reinterpret_cast<char*>(&numOfCrl), sizeof(numOfCrl));
145 for (auto crlPair : crlsMap) {
146 HapCertVerifyOpensslUtils::WriteX509CrlToStream(crlFile, crlPair.second);
147 }
148 HAPVERIFY_LOG_INFO(LABEL, "Write %{public}u crls to file done", numOfCrl);
149 crlFile.close();
150 crlMtx.unlock();
151 }
152
GetCrlByIssuer(const std::string & issuer)153 X509_CRL* HapCrlManager::GetCrlByIssuer(const std::string& issuer)
154 {
155 if (crlsMap.find(issuer) == crlsMap.end()) {
156 return nullptr;
157 }
158 return crlsMap[issuer];
159 }
160
UpdateCrlByIssuer(const std::string & issuer,X509_CRL * crl)161 void HapCrlManager::UpdateCrlByIssuer(const std::string& issuer, X509_CRL* crl)
162 {
163 if (crl == nullptr) {
164 return;
165 }
166
167 if (crlsMap.find(issuer) != crlsMap.end()) {
168 X509_CRL_free(crlsMap[issuer]);
169 }
170 crlsMap[issuer] = X509_CRL_dup(crl);
171 }
172
CrlCheck(X509 * cert,X509_CRL * targetCrl,Pkcs7Context & pkcs7Context)173 bool HapCrlManager::CrlCheck(X509* cert, X509_CRL* targetCrl, Pkcs7Context& pkcs7Context)
174 {
175 if (cert == nullptr) {
176 HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
177 return false;
178 }
179
180 crlMtx.lock();
181 /* crl in package compare with local crl, and decide which one to use */
182 targetCrl = GetFinalCrl(targetCrl, pkcs7Context);
183 if (targetCrl == nullptr) {
184 HAPVERIFY_LOG_INFO(LABEL, "no crl");
185 crlMtx.unlock();
186 return true;
187 }
188 X509_REVOKED* revoked = nullptr;
189 if (X509_CRL_get0_by_cert(targetCrl, &revoked, cert) != 0) {
190 long long certNumber;
191 std::string certSuject;
192 HapCertVerifyOpensslUtils::GetSerialNumberFromX509(cert, certNumber);
193 HapCertVerifyOpensslUtils::GetSubjectFromX509(cert, certSuject);
194 HAPVERIFY_LOG_ERROR(LABEL, "cert(issuer: %{public}s, subject: %{public}s, number:%{public}lld) is revoked",
195 pkcs7Context.certIssuer.c_str(), certSuject.c_str(), certNumber);
196 crlMtx.unlock();
197 return false;
198 }
199 crlMtx.unlock();
200 return true;
201 }
202
GetFinalCrl(X509_CRL * crlInPackage,Pkcs7Context & pkcs7Context)203 X509_CRL* HapCrlManager::GetFinalCrl(X509_CRL* crlInPackage, Pkcs7Context& pkcs7Context)
204 {
205 X509_CRL* localCrl = GetCrlByIssuer(pkcs7Context.certIssuer);
206 /* if no crl in package, use local crl */
207 if (crlInPackage == nullptr) {
208 return localCrl;
209 }
210
211 /* if no local crl, use crl in package */
212 if (localCrl == nullptr) {
213 /* no local crl, update crl in package to local */
214 UpdateCrlByIssuer(pkcs7Context.certIssuer, crlInPackage);
215 pkcs7Context.needWriteCrl = true;
216 return crlInPackage;
217 }
218
219 /* if both are present, use which one recently updated */
220 const ASN1_TIME* localCrlUpdateTime = X509_CRL_get0_lastUpdate(localCrl);
221 const ASN1_TIME* packageCrlUpdateTime = X509_CRL_get0_lastUpdate(crlInPackage);
222 if (localCrlUpdateTime == nullptr || packageCrlUpdateTime == nullptr) {
223 HAPVERIFY_LOG_INFO(LABEL, "crl no update time");
224 return nullptr;
225 }
226 if (ASN1_TIME_compare(localCrlUpdateTime, packageCrlUpdateTime) >= 0) {
227 return localCrl;
228 }
229 /* if crl in package is newer version, use it to update local crl */
230 UpdateCrlByIssuer(pkcs7Context.certIssuer, crlInPackage);
231 pkcs7Context.needWriteCrl = true;
232 return crlInPackage;
233 }
234 } // namespace Verify
235 } // namespace Security
236 } // namespace OHOS
237