• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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