mirror of
https://gitee.com/openharmony/security_appverify
synced 2024-11-23 06:29:44 +00:00
update OpenHarmony 2.0 Canary
This commit is contained in:
parent
671920d75a
commit
7549bc0c4b
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.trp filter=lfs diff=lfs merge=lfs -text
|
||||
*.apk filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.asm filter=lfs diff=lfs merge=lfs -text
|
||||
*.8svn filter=lfs diff=lfs merge=lfs -text
|
||||
*.9svn filter=lfs diff=lfs merge=lfs -text
|
||||
*.dylib filter=lfs diff=lfs merge=lfs -text
|
||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||
*.a filter=lfs diff=lfs merge=lfs -text
|
||||
*.so filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
@ -1,11 +0,0 @@
|
||||
### 该问题是怎么引起的?
|
||||
|
||||
|
||||
|
||||
### 重现步骤
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
### 相关的Issue
|
||||
|
||||
|
||||
### 原因(目的、解决的问题等)
|
||||
|
||||
|
||||
### 描述(做了什么,变更了什么)
|
||||
|
||||
|
||||
### 测试用例(新增、改动、可能影响的功能)
|
||||
|
||||
|
19
BUILD.gn
Normal file
19
BUILD.gn
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
group("testcase_packages") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"//base/security/appverify/interfaces/innerkits/appverify/test:unittest",
|
||||
]
|
||||
}
|
84
README.md
84
README.md
@ -1,8 +1,86 @@
|
||||
# Application Signature Verification<a name="EN-US_TOPIC_0000001121676905"></a>
|
||||
# appverify<a name="EN-US_TOPIC_0000001096592945"></a>
|
||||
|
||||
- [Introduction](#section11660541593)
|
||||
- [Architecture](#section9498162413412)
|
||||
- [Directory Structure](#section161941989596)
|
||||
- [Constraints](#section119744591305)
|
||||
- [Usage](#section1312121216216)
|
||||
- [Available APIs](#section1551164914237)
|
||||
- [Usage Guidelines](#section129654513264)
|
||||
|
||||
- [Repositories Involved](#section1371113476307)
|
||||
|
||||
## Introduction<a name="section11660541593"></a>
|
||||
|
||||
To ensure the integrity and trustworthiness of the applications to be installed in OpenHarmony, the applications must be signed and their signatures must be verified.
|
||||
|
||||
In application development: After developing an application, you need to sign its installation package to ensure that the installation package is not tampered with when it is released on devices. To sign the application package, you can use the signature tools and the public key certificates and follow the signing certificate generation specifications provided by the application integrity verification module. For your convenience, a public key certificate and a corresponding private key are preset in OpenHarmony. You need to replace the public key certificate and private key in your commercial version of OpenHarmony.
|
||||
- **In application development**: After developing an application, you need to sign its installation package to ensure that the installation package is not tampered with when it is released on devices. To sign the application package, you can use the signature tools and the public key certificates and follow the signing certificate generation specifications provided by the application integrity verification module. For your convenience, a public key certificate and a corresponding private key are preset in OpenHarmony. You need to replace the public key certificate and private key in your commercial version of OpenHarmony.
|
||||
|
||||
In application installation: the application framework subsystem of OpenHarmony installs applications. Upon receiving the application installation package, the application framework subsystem parses the signature of the installation package, and verifies the signature using the APIs provided by the application integrity verification module. The application can be installed only after the verification succeeds. The application integrity verification module uses the preset public key certificate to verify the signature.
|
||||
- **In application installation**: The Application Framework subsystem of OpenHarmony installs applications. Upon receiving an application installation package, the Application Framework subsystem parses the signature of the installation package, and verifies the signature using the application integrity verification APIs. The application can be installed only after the verification succeeds. During the verification, the application integrity verification module uses the preset public key certificate to verify the signature.
|
||||
|
||||
## Architecture<a name="section9498162413412"></a>
|
||||
|
||||
**Figure 1** Application integrity verification architecture<a name="fig78941174427"></a>
|
||||
![](figures/image_appverify.png "application-integrity-verification-architecture")
|
||||
|
||||
- **APIs between subsystems**: APIs provided by the application integrity verification module for other modules
|
||||
|
||||
- **Integrity verification**: ensures the integrity of application bundles and prevents tampering through signature verification.
|
||||
|
||||
- **Application source identification**: identifies the application source by matching the signature certificate chain with the trusted source list.
|
||||
|
||||
## Directory Structure<a name="section161941989596"></a>
|
||||
|
||||
```
|
||||
/base/security/appverify
|
||||
├── interfaces/innerkits/appverify # Application integrity verification module
|
||||
│ ├── config # Application signature root certificates and configuration files for the trusted source list
|
||||
│ ├── include # Header files
|
||||
│ ├── src # Source code
|
||||
│ ├── test # Automated test cases
|
||||
├── test/resource # Test resources
|
||||
```
|
||||
|
||||
## Constraints<a name="section119744591305"></a>
|
||||
|
||||
The certificates used for application integrity verification are specific to OpenHarmony. The corresponding public key certificates and private keys are preset in the open-source code repositories of OpenHarmony to provide offline signing and verification capabilities for the open-source community. The public key certificates and the corresponding private keys need to be replaced in commercial versions that are based on OpenHarmony.
|
||||
|
||||
## Usage<a name="section1312121216216"></a>
|
||||
|
||||
The application integrity verification module provides an inter-subsystem API, which is called by the Bundle Manager Service \(BMS\) during application installation.
|
||||
|
||||
### Available APIs<a name="section1551164914237"></a>
|
||||
|
||||
<a name="table775715438253"></a>
|
||||
<table><thead align="left"><tr id="row12757154342519"><th class="cellrowborder" valign="top" width="50.22%" id="mcps1.1.3.1.1"><p id="p1075794372512"><a name="p1075794372512"></a><a name="p1075794372512"></a>API</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="49.78%" id="mcps1.1.3.1.2"><p id="p375844342518"><a name="p375844342518"></a><a name="p375844342518"></a>Description</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row1348165765318"><td class="cellrowborder" valign="top" width="50.22%" headers="mcps1.1.3.1.1 "><p id="p154855755315"><a name="p154855755315"></a><a name="p154855755315"></a>int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="49.78%" headers="mcps1.1.3.1.2 "><p id="p64845775315"><a name="p64845775315"></a><a name="p64845775315"></a>Verifies application integrity and identifies the application source.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Usage Guidelines<a name="section129654513264"></a>
|
||||
|
||||
The **HapVerify\(\)** API provided by the application integrity verification module is an inter-subsystem API. This API can be called with the HAP file path passed to verify the integrity of an application, and the verification result can be obtained from the return value. The signature of the application can be obtained from the input parameter **hapVerifyResult**.
|
||||
|
||||
```
|
||||
Security::Verify::HapVerifyResult verifyResult;
|
||||
int32_t res = Security::Verify::HapVerify(hapPath, verifyResult);
|
||||
if (res != Security::Verify::HapVerifyResultCode::VERIFY_SUCCESS) {
|
||||
// processing error
|
||||
}
|
||||
```
|
||||
|
||||
## Repositories Involved<a name="section1371113476307"></a>
|
||||
|
||||
Security subsystem
|
||||
|
||||
hmf/security/appverify
|
||||
|
||||
|
86
README_zh.md
86
README_zh.md
@ -1,8 +1,86 @@
|
||||
# 应用签名验签子系统<a name="ZH-CN_TOPIC_0000001121676905"></a>
|
||||
# 应用完整性校验<a name="ZH-CN_TOPIC_0000001096592945"></a>
|
||||
|
||||
OpenHarmony允许应用安装。为了确保应用的完整性和来源可靠,需要对安装的应用进行签名和验签。
|
||||
- [简介](#section11660541593)
|
||||
- [系统架构图](#section9498162413412)
|
||||
- [目录](#section161941989596)
|
||||
- [约束](#section119744591305)
|
||||
- [说明](#section1312121216216)
|
||||
- [接口说明](#section1551164914237)
|
||||
- [使用说明](#section129654513264)
|
||||
|
||||
应用开发阶段:开发者完成开发并生成安装包后,需要开发者对安装包进行签名,以证明安装包发布到设备的过程中没有被篡改。OpenHarmony的应用完整性校验模块提供了签名工具、签名证书生成规范,以及签名所需的公钥证书等完整的机制,支撑开发者对应用安装包签名。为了方便开源社区开发者,版本中预置了公钥证书和对应的私钥,为开源社区提供离线签名和校验能力;在商用版本中应替换此公钥证书和对应的私钥。
|
||||
- [相关仓](#section1371113476307)
|
||||
|
||||
应用安装阶段:OpenHarmony程序框架子系统负责应用的安装。在接收到应用安装包之后,应用程序框架子系统需要解析安装包的签名数据,然后使用应用完整性校验模块的API对签名进行验证,只有校验成功之后才允许安装此应用. 应用完整性校验模块在校验安装包签名数据时,会使用系统预置的公钥证书进行验签。
|
||||
## 简介<a name="section11660541593"></a>
|
||||
|
||||
为了确保应用的完整性和来源可靠,OpenHarmony需要对应用进行签名和验签。
|
||||
|
||||
- **应用开发阶段:**开发者完成开发并生成安装包后,需要开发者对安装包进行签名,以证明安装包发布到设备的过程中没有被篡改。OpenHarmony的应用完整性校验模块提供了签名工具、签名证书生成规范,以及签名所需的公钥证书等完整的机制,支撑开发者对应用安装包签名。为了方便开源社区开发者,版本中预置了公钥证书和对应的私钥,为开源社区提供离线签名和校验能力;在OpenHarmony商用版本中应替换此公钥证书和对应的私钥。
|
||||
|
||||
- **应用安装阶段:**OpenHarmony用户程序框架子系统负责应用的安装。在接收到应用安装包之后,应用程序框架子系统需要解析安装包的签名数据,然后使用应用完整性校验模块的API对签名进行验证,只有校验成功之后才允许安装此应用. 应用完整性校验模块在校验安装包签名数据时,会使用系统预置的公钥证书进行验签。
|
||||
|
||||
## 系统架构图<a name="section9498162413412"></a>
|
||||
|
||||
**图 1** 应用完整性校验架构图<a name="fig78941174427"></a>
|
||||
![](figures/zh-cn_image_appverify.png "应用完整性校验架构图")
|
||||
|
||||
- **子系统间接口:**应用完整性校验模块给其他模块提供的接口;
|
||||
|
||||
- **完整性校验:**通过验签,保障应用包完整性,防篡改;
|
||||
|
||||
- **应用来源识别:**通过匹配签名证书链与可信源列表,识别应用来源。
|
||||
|
||||
## 目录<a name="section161941989596"></a>
|
||||
|
||||
```
|
||||
/base/security/appverify
|
||||
├── interfaces/innerkits/appverify # 应用完整性校验模块代码
|
||||
│ ├── config # 应用签名根证书和可信源列表配置文件存放目录
|
||||
│ ├── include # 头文件存放目录
|
||||
│ ├── src # 源代码存放目录
|
||||
│ ├── test # 模块自动化测试用例存放目录
|
||||
├── test/resource # 测试资源存放目录
|
||||
```
|
||||
|
||||
## 约束<a name="section119744591305"></a>
|
||||
|
||||
应用完整性校验在OpenHarmony中使用的证书,是专为OpenHarmony生成的,涉及的公钥证书和对应的私钥均预置在OpenHarmony开源代码仓中,为开源社区提供离线签名和校验能力;在商用版本中应替换此公钥证书和对应的私钥。
|
||||
|
||||
## 说明<a name="section1312121216216"></a>
|
||||
|
||||
应用完整性校验模块提供一个子系统间接口,由包管理服务在安装应用时调用。
|
||||
|
||||
### 接口说明<a name="section1551164914237"></a>
|
||||
|
||||
<a name="table775715438253"></a>
|
||||
<table><thead align="left"><tr id="row12757154342519"><th class="cellrowborder" valign="top" width="50.22%" id="mcps1.1.3.1.1"><p id="p1075794372512"><a name="p1075794372512"></a><a name="p1075794372512"></a>接口名</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="49.78%" id="mcps1.1.3.1.2"><p id="p375844342518"><a name="p375844342518"></a><a name="p375844342518"></a>说明</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row1348165765318"><td class="cellrowborder" valign="top" width="50.22%" headers="mcps1.1.3.1.1 "><p id="p154855755315"><a name="p154855755315"></a><a name="p154855755315"></a>int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="49.78%" headers="mcps1.1.3.1.2 "><p id="p64845775315"><a name="p64845775315"></a><a name="p64845775315"></a>校验应用完整性,识别应用来源</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### 使用说明<a name="section129654513264"></a>
|
||||
|
||||
应用完整性校验提供的是子系统间接口,仅提供底层能力,不对开发者开放。以应用文件路径作为输入,调用HapVerify接口即可校验应用完整性,通过接口返回值可以获取校验结果,通过引用传参hapVerifyResult获取签名相关信息。
|
||||
|
||||
```
|
||||
Security::Verify::HapVerifyResult verifyResult;
|
||||
int32_t res = Security::Verify::HapVerify(hapPath, verifyResult);
|
||||
if (res != Security::Verify::HapVerifyResultCode::VERIFY_SUCCESS) {
|
||||
// processing error
|
||||
}
|
||||
```
|
||||
|
||||
## 相关仓<a name="section1371113476307"></a>
|
||||
|
||||
安全子系统
|
||||
|
||||
hmf/security/appverify
|
||||
|
||||
|
BIN
figures/image_appverify.png
Normal file
BIN
figures/image_appverify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
figures/zh-cn_image_appverify.png
Normal file
BIN
figures/zh-cn_image_appverify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
70
interfaces/innerkits/appverify/BUILD.gn
Normal file
70
interfaces/innerkits/appverify/BUILD.gn
Normal file
@ -0,0 +1,70 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
|
||||
config("libhapverify_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"//base/security/appverify/interfaces/innerkits/appverify/include",
|
||||
"//third_party/openssl/include",
|
||||
"//third_party/json/include",
|
||||
"//third_party/json/single_include",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
}
|
||||
|
||||
ohos_shared_library("libhapverify") {
|
||||
sources = [
|
||||
"src/common/hap_byte_buffer.cpp",
|
||||
"src/common/hap_byte_buffer_data_source.cpp",
|
||||
"src/common/hap_file_data_source.cpp",
|
||||
"src/common/random_access_file.cpp",
|
||||
"src/init/hap_crl_manager.cpp",
|
||||
"src/init/json_parser_utils.cpp",
|
||||
"src/init/trusted_root_ca.cpp",
|
||||
"src/init/trusted_source_manager.cpp",
|
||||
"src/interfaces/hap_verify.cpp",
|
||||
"src/interfaces/hap_verify_result.cpp",
|
||||
"src/provision/provision_verify.cpp",
|
||||
"src/util/digest_parameter.cpp",
|
||||
"src/util/hap_cert_verify_openssl_utils.cpp",
|
||||
"src/util/hap_profile_verify_utils.cpp",
|
||||
"src/util/hap_signing_block_utils.cpp",
|
||||
"src/util/hap_verify_openssl_utils.cpp",
|
||||
"src/verify/hap_verify_v2.cpp",
|
||||
]
|
||||
|
||||
public_configs = [ ":libhapverify_config" ]
|
||||
|
||||
cflags_cc = [
|
||||
"-DHILOG_ENABLE",
|
||||
"-fvisibility=hidden",
|
||||
]
|
||||
|
||||
ldflags = [ "-Wl,--exclude-libs,ALL" ]
|
||||
|
||||
deps = [
|
||||
"//third_party/openssl:libcrypto_static",
|
||||
"//utils/native/base:utils",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"ipc:ipc_core",
|
||||
]
|
||||
|
||||
part_name = "appverify"
|
||||
|
||||
subsystem_name = "security"
|
||||
}
|
50
interfaces/innerkits/appverify/config/BUILD.gn
Normal file
50
interfaces/innerkits/appverify/config/BUILD.gn
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
|
||||
ohos_prebuilt_etc("trusted_apps_sources") {
|
||||
if (build_public_version) {
|
||||
source = "OpenHarmony/trusted_apps_sources.json"
|
||||
} else {
|
||||
source = "trusted_apps_sources.json"
|
||||
}
|
||||
part_name = "appverify"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "security"
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("trusted_apps_sources_test") {
|
||||
source = "trusted_apps_sources_test.json"
|
||||
part_name = "appverify"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "security"
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("trusted_root_ca") {
|
||||
if (build_public_version) {
|
||||
source = "OpenHarmony/trusted_root_ca.json"
|
||||
} else {
|
||||
source = "trusted_root_ca.json"
|
||||
}
|
||||
part_name = "appverify"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "security"
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("trusted_root_ca_test") {
|
||||
source = "trusted_root_ca_test.json"
|
||||
part_name = "appverify"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "security"
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
{
|
||||
"version": "1.0.1",
|
||||
"release-time":"2020-12-28 11:33:00",
|
||||
"trust-app-source":[
|
||||
{
|
||||
"name":"huawei app gallery",
|
||||
"app-signing-cert":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS AppGallery Application Release",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
},
|
||||
{
|
||||
"name":"huawei system apps",
|
||||
"app-signing-cert":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Release",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Release",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Release_Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
},
|
||||
{
|
||||
"name":"OpenHarmony apps",
|
||||
"app-signing-cert":"C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Release",
|
||||
"profile-signing-certificate":"C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Profile Release",
|
||||
"profile-debug-signing-certificate":"C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Profile Debug",
|
||||
"issuer-ca":"C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application CA",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2":"-----BEGIN CERTIFICATE-----\nMIICGjCCAaGgAwIBAgIIShhpn519jNAwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\nQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\nAwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjAzMDQzOVoXDTQ5MDMx\nNjAzMDQzOVowUzELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\nCwwKSHVhd2VpIENCRzEeMBwGA1UEAwwVSHVhd2VpIENCRyBSb290IENBIEcyMHYw\nEAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrs\nGUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpHMB\nwcz4DA0kgHCMm/wDec6kOHx1xvCRo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\nAQH/BAUwAwEB/zAdBgNVHQ4EFgQUo45a9Vq8cYwqaiVyfkiS4pLcIAAwCgYIKoZI\nzj0EAwMDZwAwZAIwMypeB7P0IbY7c6gpWcClhRznOJFj8uavrNu2PIoz9KIqr3jn\nBlBHJs0myI7ntYpEAjBbm8eDMZY5zq5iMZUC6H7UzYSix4Uy1YlsLVV738PtKP9h\nFTjgDHctXJlC5L7+ZDY=\n-----END CERTIFICATE-----\n",
|
||||
"C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Root CA":"-----BEGIN CERTIFICATE-----\nMIICRDCCAcmgAwIBAgIED+E4izAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\nMTAyMDIxMjE0MThaFw00OTEyMzExMjE0MThaMGgxCzAJBgNVBAYTAkNOMRQwEgYD\nVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEoMCYG\nA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTB2MBAGByqGSM49\nAgEGBSuBBAAiA2IABE023XmRaw2DnO8NSsb+KG/uY0FtS3u5LQucdr3qWVnRW5ui\nQIL6ttNZBEeLTUeYcJZCpayg9Llf+1SmDA7dY4iP2EcRo4UN3rilovtfFfsmH4ty\n3SApHVFzWUl+NwdH8KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFBc6EKGrGXzlAE+s0Zgnsphadw7NMAwGCCqGSM49BAMDBQAD\nZwAwZAIwd1p3JzHN93eoPped1li0j64npgqNzwy4OrkehYAqNXpcpaEcLZ7UxW8E\nI2lZJ3SbAjAkqySHb12sIwdSFKSN9KCMMEo/eUT5dUXlcKR2nZz0MJdxT5F51qcX\n1CumzkcYhgU=\n-----END CERTIFICATE-----\n"
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "1.0.1",
|
||||
"release-time":"2020-07-09 21:20:00",
|
||||
"trust-app-source":[
|
||||
{
|
||||
"name":"huawei app gallery",
|
||||
"app-signing-cert":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS AppGallery Application Release",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
},
|
||||
{
|
||||
"name":"huawei system apps",
|
||||
"app-signing-cert":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Release",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Release",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Release_Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "1.0.1",
|
||||
"release-time":"2020-7-10 9:49:00",
|
||||
"trust-app-source":[
|
||||
{
|
||||
"name":"huawei app gallery",
|
||||
"app-signing-cert":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS AppGallery Application Release",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei, OU=HOS AppGallery, CN=HOS Profile Management Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA Test",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
},
|
||||
{
|
||||
"name":"huawei system apps",
|
||||
"app-signing-cert":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Dev",
|
||||
"profile-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Dev",
|
||||
"profile-debug-signing-certificate":"C=CN, O=Huawei CBG, OU=HOS Development Team, CN=HOS Application Provision Profile Dev_Debug",
|
||||
"issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA Test",
|
||||
"max-certs-path":3,
|
||||
"critialcal-cert-extension":["keyusage","huawei-signing-capability"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2":"-----BEGIN CERTIFICATE-----\nMIICGjCCAaGgAwIBAgIIShhpn519jNAwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\nQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\nAwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjAzMDQzOVoXDTQ5MDMx\nNjAzMDQzOVowUzELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\nCwwKSHVhd2VpIENCRzEeMBwGA1UEAwwVSHVhd2VpIENCRyBSb290IENBIEcyMHYw\nEAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrs\nGUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpHMB\nwcz4DA0kgHCMm/wDec6kOHx1xvCRo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\nAQH/BAUwAwEB/zAdBgNVHQ4EFgQUo45a9Vq8cYwqaiVyfkiS4pLcIAAwCgYIKoZI\nzj0EAwMDZwAwZAIwMypeB7P0IbY7c6gpWcClhRznOJFj8uavrNu2PIoz9KIqr3jn\nBlBHJs0myI7ntYpEAjBbm8eDMZY5zq5iMZUC6H7UzYSix4Uy1YlsLVV738PtKP9h\nFTjgDHctXJlC5L7+ZDY=\n-----END CERTIFICATE-----\n"
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2 Test":"-----BEGIN CERTIFICATE-----\nMIICJTCCAaugAwIBAgIIb/9KnVieVTgwCgYIKoZIzj0EAwMwWDELMAkGA1UEBhMC\nQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEjMCEGA1UE\nAwwaSHVhd2VpIENCRyBSb290IENBIEcyIFRlc3QwHhcNMjAwMzEyMTI0NDAwWhcN\nNDkwMzEyMTI0NDAwWjBYMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMw\nEQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkgQ0JHIFJvb3QgQ0Eg\nRzIgVGVzdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABLS4fgvaYKKfyMZW/4nNTsSv\nxqVxqOEDfLySZK/fSEN0IDQj0sK/qK5hvnf0OxWhwI49P3dKGmQ+cSujXvy0me2D\nJTjY127XYZJrvJwwMkrT/vMrZC5kSOEJbt1qAgSmiaNCMEAwDgYDVR0PAQH/BAQD\nAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFGldwFjx9Tzm/QpA8R1gc9wc\neMbFMAoGCCqGSM49BAMDA2gAMGUCMQCCUDRaglmycUGrHmF+L8owKJhbqOUqbwuX\n7XL/vJcp3HeHjiXu7XZmYQ+QAvHPhU0CMCiwWFbDl8ETw4VK25QbwhL/QiUfiRfC\nJ6LzteOvjLTEV5iebQMz/nS1j7/oj3Rsqg==\n-----END CERTIFICATE-----\n"
|
||||
}
|
35
interfaces/innerkits/appverify/include/common/data_source.h
Normal file
35
interfaces/innerkits/appverify/include/common/data_source.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_DATASOURCE_H
|
||||
#define HAP_DATASOURCE_H
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
class DataSource {
|
||||
public:
|
||||
virtual ~DataSource() {};
|
||||
virtual bool HasRemaining() const = 0;
|
||||
virtual long long Remaining() const = 0;
|
||||
virtual void Reset() = 0;
|
||||
virtual bool ReadDataAndDigestUpdate(const DigestParameter& digestParam, int chunkSize) = 0;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_DATASOURCE_H
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_EXPORT_DEFINE_H
|
||||
#define HAP_EXPORT_DEFINE_H
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#define DLL_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#define DLL_LOCAL
|
||||
#endif
|
||||
#endif // HAP_EXPORT_DEFINE_H
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_BYTEBUFFER_H
|
||||
#define HAP_BYTEBUFFER_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "common/export_define.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum ReadFileErrorCode {
|
||||
DEST_BUFFER_IS_NULL = -1,
|
||||
FILE_IS_CLOSE = -2,
|
||||
MMAP_COPY_FAILED = -3,
|
||||
READ_OFFSET_OUT_OF_RANGE = -4,
|
||||
MMAP_FAILED = -5,
|
||||
MMAP_PARAM_INVALID = -6,
|
||||
};
|
||||
|
||||
class HapByteBuffer {
|
||||
public:
|
||||
DLL_EXPORT HapByteBuffer();
|
||||
DLL_EXPORT explicit HapByteBuffer(int bufferCapacity);
|
||||
DLL_EXPORT HapByteBuffer(const HapByteBuffer& other);
|
||||
DLL_EXPORT ~HapByteBuffer();
|
||||
DLL_EXPORT HapByteBuffer& operator=(const HapByteBuffer& other);
|
||||
DLL_EXPORT bool GetInt64(long long& value);
|
||||
DLL_EXPORT bool GetInt64(int index, long long& value);
|
||||
DLL_EXPORT bool GetUInt32(int index, unsigned int& value);
|
||||
DLL_EXPORT bool GetInt32(int& value);
|
||||
DLL_EXPORT bool GetInt32(int index, int& value);
|
||||
DLL_EXPORT bool GetUInt16(int index, unsigned short& value);
|
||||
DLL_EXPORT void PutInt32(int offset, int value);
|
||||
DLL_EXPORT void PutByte(int offset, char value);
|
||||
DLL_EXPORT void PutData(int offset, const char data[], int len);
|
||||
DLL_EXPORT int GetCapacity() const;
|
||||
DLL_EXPORT int GetPosition() const;
|
||||
DLL_EXPORT int GetLimit() const;
|
||||
DLL_EXPORT const char* GetBufferPtr() const;
|
||||
DLL_EXPORT void SetPosition(int pos);
|
||||
DLL_EXPORT void SetLimit(int lim);
|
||||
DLL_EXPORT void SetCapacity(int cap);
|
||||
DLL_EXPORT void Slice();
|
||||
DLL_EXPORT int Remaining() const;
|
||||
DLL_EXPORT bool HasRemaining() const;
|
||||
DLL_EXPORT bool CopyPartialBuffer(const HapByteBuffer& other, int len);
|
||||
DLL_EXPORT void Clear();
|
||||
DLL_EXPORT bool IsEqual(const HapByteBuffer& other);
|
||||
DLL_EXPORT bool IsEqual(const std::string& other);
|
||||
|
||||
private:
|
||||
void Init(int bufferCapacity);
|
||||
bool CheckInputForGettingData(int index, int dataLen);
|
||||
|
||||
private:
|
||||
static const int MAX_PRINT_LENGTH;
|
||||
static const int HEX_PRINT_LENGTH;
|
||||
std::unique_ptr<char[]> buffer;
|
||||
int position;
|
||||
int limit;
|
||||
int capacity;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_BYTEBUFFER_H
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_BYTEBUFFER_DATASOURCE_H
|
||||
#define HAP_BYTEBUFFER_DATASOURCE_H
|
||||
|
||||
#include "common/data_source.h"
|
||||
#include "common/export_define.h"
|
||||
#include "common/random_access_file.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
class HapByteBufferDataSource : public DataSource {
|
||||
public:
|
||||
DLL_EXPORT HapByteBufferDataSource(HapByteBuffer& hapBuffer);
|
||||
DLL_EXPORT ~HapByteBufferDataSource();
|
||||
bool HasRemaining() const override;
|
||||
long long Remaining() const override;
|
||||
void Reset() override;
|
||||
bool ReadDataAndDigestUpdate(const DigestParameter& digestParam, int chunkSize) override;
|
||||
|
||||
private:
|
||||
HapByteBuffer& hapByteBuffer;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_BYTEBUFFER_DATASOURCE_H
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_FILEDATASOURCE_H
|
||||
#define HAP_FILEDATASOURCE_H
|
||||
|
||||
#include "common/data_source.h"
|
||||
#include "common/random_access_file.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
class HapFileDataSource : public DataSource {
|
||||
public:
|
||||
HapFileDataSource(RandomAccessFile& hapFile, long long offset, long long size, long long position);
|
||||
~HapFileDataSource();
|
||||
bool HasRemaining() const override;
|
||||
long long Remaining() const override;
|
||||
void Reset() override;
|
||||
bool ReadDataAndDigestUpdate(const DigestParameter& digestParam, int chunkSize) override;
|
||||
|
||||
private:
|
||||
RandomAccessFile& hapFileRandomAccess;
|
||||
long long fileOffset;
|
||||
long long sourceSize;
|
||||
long long sourcePosition;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_FILEDATASOURCE_H
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HAPVERIFY_LOG_H
|
||||
#define HAPVERIFY_LOG_H
|
||||
|
||||
#include "hilog/log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
static constexpr unsigned int SECURITY_DOMAIN = 0xD002F00;
|
||||
static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN, "HapVerify"};
|
||||
|
||||
#define HAPVERIFY_LOG_DEBUG(label, fmt, ...) \
|
||||
OHOS::HiviewDFX::HiLog::Debug(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#define HAPVERIFY_LOG_INFO(label, fmt, ...) \
|
||||
OHOS::HiviewDFX::HiLog::Info(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#define HAPVERIFY_LOG_WARN(label, fmt, ...) \
|
||||
OHOS::HiviewDFX::HiLog::Warn(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#define HAPVERIFY_LOG_ERROR(label, fmt, ...) \
|
||||
OHOS::HiviewDFX::HiLog::Error(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#define HAPVERIFY_LOG_FATAL(label, fmt, ...) \
|
||||
OHOS::HiviewDFX::HiLog::Fatal(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAPVERIFY_LOG_H
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_RANDOM_ACCESS_FILE_H
|
||||
#define HAP_RANDOM_ACCESS_FILE_H
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
struct MmapInfo {
|
||||
long long mmapPosition;
|
||||
int readMoreLen;
|
||||
int mmapSize;
|
||||
char* mapAddr;
|
||||
};
|
||||
|
||||
class RandomAccessFile {
|
||||
public:
|
||||
DLL_EXPORT RandomAccessFile();
|
||||
DLL_EXPORT ~RandomAccessFile();
|
||||
DLL_EXPORT bool Init(const std::string& filePath);
|
||||
DLL_EXPORT long long GetLength() const;
|
||||
DLL_EXPORT long long ReadFileFullyFromOffset(HapByteBuffer& buffer, long long offset);
|
||||
DLL_EXPORT long long ReadFileFullyFromOffset(char buf[], long long offset, int bufCapacity);
|
||||
bool ReadFileFromOffsetAndDigestUpdate(const DigestParameter& digestParam, int chunkSize, long long offset);
|
||||
|
||||
private:
|
||||
long long DoMMap(int bufCapacity, long long offset, MmapInfo& mmapInfo);
|
||||
|
||||
static const int FILE_OPEN_FAIL_ERROR_NUM;
|
||||
static int memoryPageSize;
|
||||
int fd;
|
||||
long long fileLength;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_RANDOM_ACCESS_FILE_H
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_CRL_MANAGER_H
|
||||
#define HAP_CRL_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "openssl/x509.h"
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "util/pkcs7_context.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using IssuerCrlMap = std::unordered_map<std::string, X509_CRL*>;
|
||||
|
||||
class HapCrlManager {
|
||||
public:
|
||||
DLL_EXPORT static HapCrlManager& GetInstance();
|
||||
DLL_EXPORT void Init();
|
||||
DLL_EXPORT bool CrlCheck(X509* cert, X509_CRL* targetCrl, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT void WriteCrlsToFile();
|
||||
|
||||
private:
|
||||
HapCrlManager();
|
||||
~HapCrlManager();
|
||||
|
||||
/* Forbid external replication constructs and external replication */
|
||||
HapCrlManager(const HapCrlManager& hapCrlManager);
|
||||
const HapCrlManager& operator=(const HapCrlManager& hapCrlManager);
|
||||
|
||||
DLL_EXPORT X509_CRL* GetFinalCrl(X509_CRL* crlInPackage, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT X509_CRL* GetCrlByIssuer(const std::string& issuer);
|
||||
DLL_EXPORT void UpdateCrlByIssuer(const std::string& issuer, X509_CRL* crl);
|
||||
DLL_EXPORT bool ReadCrls(HapByteBuffer& crlsBuffer);
|
||||
DLL_EXPORT bool ParseCrls(HapByteBuffer& crlsBuffer);
|
||||
|
||||
private:
|
||||
DLL_EXPORT static const std::string HAP_CRL_FILE_PATH;
|
||||
std::mutex crlMtx;
|
||||
IssuerCrlMap crlsMap;
|
||||
bool isInit;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_CRL_MANAGER_H
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_JSON_PARSER_UTILS_H
|
||||
#define HAP_JSON_PARSER_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using JsonMap = std::unordered_map<std::string, std::string>;
|
||||
using JsonObjVec = std::vector<nlohmann::json>;
|
||||
using StringVec = std::vector<std::string>;
|
||||
|
||||
class JsonParserUtils {
|
||||
public:
|
||||
static bool ReadTrustedRootCAFromJson(nlohmann::json& jsonObj, const std::string& jsonPath, std::string& error);
|
||||
static bool GetJsonString(const nlohmann::json& json, const std::string& key, std::string& value);
|
||||
static bool ParseJsonToObjVec(const nlohmann::json& json, const std::string& key, JsonObjVec& jsonObjVec);
|
||||
static bool GetJsonInt(const nlohmann::json& json, const std::string& key, int& value);
|
||||
static bool GetJsonStringVec(const nlohmann::json& json, const std::string& key, StringVec& value);
|
||||
static void ParseJsonToMap(const nlohmann::json& json, JsonMap& JsonMap);
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_JSON_PARSER_UTILS_H
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_MATCHING_RESULT_H
|
||||
#define HAP_MATCHING_RESULT_H
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum TrustedSources {
|
||||
NOT_TRUSTED_SOURCE = 0,
|
||||
APP_GALLARY,
|
||||
APP_SYSTEM,
|
||||
};
|
||||
|
||||
enum MatchingStates {
|
||||
DO_NOT_MATCH = 0,
|
||||
MATCH_WITH_SIGN,
|
||||
MATCH_WITH_PROFILE,
|
||||
MATCH_WITH_PROFILE_DEBUG,
|
||||
};
|
||||
|
||||
struct MatchingResult {
|
||||
MatchingStates matchState;
|
||||
TrustedSources source;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_MATCHING_RESULT_H
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_TRUSTED_ROOT_CA_H
|
||||
#define HAP_TRUSTED_ROOT_CA_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "openssl/x509.h"
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "init/json_parser_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using StringCertMap = std::unordered_map<std::string, X509*>;
|
||||
|
||||
class TrustedRootCa {
|
||||
public:
|
||||
DLL_EXPORT static TrustedRootCa& GetInstance();
|
||||
DLL_EXPORT bool Init();
|
||||
DLL_EXPORT void Recovery();
|
||||
DLL_EXPORT bool EnableDebug();
|
||||
DLL_EXPORT void DisableDebug();
|
||||
DLL_EXPORT X509* FindMatchedRoot(X509* caCert);
|
||||
|
||||
private:
|
||||
TrustedRootCa();
|
||||
~TrustedRootCa();
|
||||
|
||||
/* Forbid external replication constructs and external replication */
|
||||
TrustedRootCa(const TrustedRootCa& trustedRoot);
|
||||
const TrustedRootCa& operator=(const TrustedRootCa& trustedRoot);
|
||||
|
||||
DLL_EXPORT bool GetTrustedRootCAFromJson(StringCertMap& rootCertMap, const std::string& filePath);
|
||||
X509* FindMatchedRoot(const StringCertMap& rootCertMap, X509* caCert);
|
||||
|
||||
private:
|
||||
static const std::string TRUSTED_ROOT_CA_FILE_PATH;
|
||||
static const std::string TRUSTED_ROOT_CA_TEST_FILE_PATH;
|
||||
StringCertMap rootCerts;
|
||||
StringCertMap rootCertsForTest;
|
||||
bool isInit;
|
||||
bool isDebug;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_TRUSTED_ROOT_CA_H
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_TRUSTED_SOURCE_MANAGER_H
|
||||
#define HAP_TRUSTED_SOURCE_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "init/json_parser_utils.h"
|
||||
#include "init/matching_result.h"
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
struct HapAppSourceInfo {
|
||||
TrustedSources source;
|
||||
std::string sourceName;
|
||||
std::string appSigningCert;
|
||||
std::string profileSigningCertificate;
|
||||
std::string profileDebugSigningCertificate;
|
||||
std::string issuer;
|
||||
int maxCertsPath;
|
||||
StringVec critialcalCertExtension;
|
||||
};
|
||||
|
||||
using SourceInfoVec = std::vector<HapAppSourceInfo>;
|
||||
|
||||
class TrustedSourceManager {
|
||||
public:
|
||||
DLL_EXPORT static TrustedSourceManager& GetInstance();
|
||||
DLL_EXPORT bool Init();
|
||||
DLL_EXPORT void Recovery();
|
||||
DLL_EXPORT bool EnableDebug();
|
||||
DLL_EXPORT void DisableDebug();
|
||||
DLL_EXPORT MatchingResult IsTrustedSource(const std::string& certSubject, const std::string& certIssuer,
|
||||
HapBlobType blobType, int certListPath) const;
|
||||
|
||||
private:
|
||||
TrustedSourceManager();
|
||||
~TrustedSourceManager();
|
||||
|
||||
/* Forbid external replication constructs and external replication */
|
||||
TrustedSourceManager(const TrustedSourceManager& trustedSource) = delete;
|
||||
const TrustedSourceManager& operator=(const TrustedSourceManager& trustedSource) = delete;
|
||||
|
||||
bool GetAppTrustedSources(SourceInfoVec& trustedAppSources, std::string& souucesVersion,
|
||||
std::string& souucesReleaseTime, const std::string& filePath);
|
||||
bool ParseTrustedAppSourceJson(SourceInfoVec& trustedAppSources, const JsonObjVec& trustedAppSourceJson);
|
||||
std::string EncapTrustedAppSourceString(const HapAppSourceInfo& appSourceInfo);
|
||||
MatchingResult MatchTrustedSource(const SourceInfoVec& trustedAppSources, const std::string& certSubject,
|
||||
const std::string& certIssuer, HapBlobType blobType, int certListPath) const;
|
||||
MatchingStates TrustedSourceListCompare(const std::string& certSubject, const std::string& certIssuer,
|
||||
const HapAppSourceInfo& appSource, HapBlobType blobType) const;
|
||||
TrustedSources GetTrustedSource(std::string& sourceName);
|
||||
|
||||
private:
|
||||
static const std::string APP_TRUSTED_SOURCE_FILE_PATH;
|
||||
static const std::string APP_TRUSTED_SOURCE_TEST_FILE_PATH;
|
||||
static const std::string KEY_OF_APP_TRUSTED_SOURCE;
|
||||
static const std::string KEY_OF_APP_TRUSTED_SOURCE_VERSION;
|
||||
static const std::string KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME;
|
||||
static const std::string KEY_OF_SOURCE_NAME;
|
||||
static const std::string KEY_OF_APP_SIGNING_CERT;
|
||||
static const std::string KEY_OF_PROFILE_SIGNING_CERTIFICATE;
|
||||
static const std::string KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE;
|
||||
static const std::string KEY_OF_ISSUER;
|
||||
static const std::string KEY_OF_MAX_CERTS_PATH;
|
||||
static const std::string KEY_OF_CRITIALCAL_CERT_EXTENSION;
|
||||
static const std::string APP_GALLARY_SOURCE_NAME;
|
||||
static const std::string APP_SYSTEM_SOURCE_NAME;
|
||||
SourceInfoVec appTrustedSources;
|
||||
SourceInfoVec appTrustedSourcesForTest;
|
||||
std::string version;
|
||||
std::string versionForTest;
|
||||
std::string releaseTime;
|
||||
std::string releaseTimeForTest;
|
||||
bool isInit;
|
||||
bool isDebug;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_TRUSTED_SOURCE_MANAGER_H
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_H
|
||||
#define HAP_VERIFY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
DLL_EXPORT bool EnableDebugMode();
|
||||
DLL_EXPORT int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult);
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_VERIFY_H
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_RESULT_H
|
||||
#define HAP_VERIFY_RESULT_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "provision/provision_info.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum HapVerifyResultCode {
|
||||
VERIFY_SUCCESS = 0,
|
||||
FILE_PATH_INVALID = -1,
|
||||
OPEN_FILE_ERROR = -2,
|
||||
SIGNATURE_NOT_FOUND = -3,
|
||||
VERIFY_APP_PKCS7_FAIL = -4,
|
||||
PROFILE_PARSE_FAIL = -5,
|
||||
APP_SOURCE_NOT_TRUSTED = -6,
|
||||
GET_DIGEST_FAIL = -7,
|
||||
VERIFY_INTEGRITY_FAIL = -8,
|
||||
FILE_SIZE_TOO_LARGE = -9,
|
||||
GET_PUBLICKEY_FAIL = -10,
|
||||
GET_SIGNATURE_FAIL = -11,
|
||||
NO_PROFILE_BLOCK_FAIL = -12,
|
||||
VERIFY_SIGNATURE_FAIL = -13,
|
||||
VERIFY_SOURCE_INIT_FAIL = -14,
|
||||
};
|
||||
|
||||
enum GetOptionalBlockResultCode {
|
||||
GET_SUCCESS = 0,
|
||||
NO_THIS_BLOCK_IN_PACKAGE = 1,
|
||||
};
|
||||
|
||||
struct OptionalBlock {
|
||||
int optionalType;
|
||||
HapByteBuffer optionalBlockValue;
|
||||
};
|
||||
|
||||
class HapVerifyResult {
|
||||
public:
|
||||
DLL_EXPORT HapVerifyResult();
|
||||
DLL_EXPORT ~HapVerifyResult();
|
||||
DLL_EXPORT int GetVersion() const;
|
||||
DLL_EXPORT void SetVersion(int signatureVersion);
|
||||
DLL_EXPORT void SetPkcs7SignBlock(const HapByteBuffer& pkcs7);
|
||||
DLL_EXPORT void SetPkcs7ProfileBlock(const HapByteBuffer& pkcs7);
|
||||
DLL_EXPORT void SetOptionalBlocks(const std::vector<OptionalBlock>& option);
|
||||
DLL_EXPORT void SetProvisionInfo(const ProvisionInfo& info);
|
||||
DLL_EXPORT int GetProperty(std::string& property);
|
||||
DLL_EXPORT ProvisionInfo GetProvisionInfo();
|
||||
DLL_EXPORT std::vector<std::string> GetPublicKey();
|
||||
DLL_EXPORT std::vector<std::string> GetSignature();
|
||||
void SetPublicKey(const std::vector<std::string>& inputPubkeys);
|
||||
void SetSignature(const std::vector<std::string>& inputSignatures);
|
||||
|
||||
private:
|
||||
DLL_EXPORT int GetBlockFromOptionalBlocks(int blockType, std::string& block);
|
||||
|
||||
private:
|
||||
int version;
|
||||
std::vector<std::string> publicKeys;
|
||||
std::vector<std::string> signatures;
|
||||
HapByteBuffer pkcs7SignBlock;
|
||||
HapByteBuffer pkcs7ProfileBlock;
|
||||
std::vector<OptionalBlock> optionalBlocks;
|
||||
ProvisionInfo provisionInfo;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_VERIFY_RESULT_H
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef PROVISION_INFO_H
|
||||
#define PROVISION_INFO_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum ProvisionType {
|
||||
DEBUG = 0,
|
||||
RELEASE = 1,
|
||||
};
|
||||
|
||||
enum AppDistType {
|
||||
NONE_TYPE = 0,
|
||||
APP_GALLERY = 1,
|
||||
ENTERPRISE = 2,
|
||||
OS_INTEGRATION = 3,
|
||||
};
|
||||
|
||||
struct BundleInfo {
|
||||
std::string developerId;
|
||||
std::string developmentCertificate;
|
||||
std::string distributionCertificate;
|
||||
std::string bundleName;
|
||||
std::string appFeature;
|
||||
};
|
||||
|
||||
struct Permissions {
|
||||
std::vector<std::string> restrictedPermissions;
|
||||
std::vector<std::string> restrictedCapabilities;
|
||||
};
|
||||
|
||||
struct DebugInfo {
|
||||
std::string deviceIdType;
|
||||
std::vector<std::string> deviceIds;
|
||||
};
|
||||
|
||||
struct ProvisionInfo {
|
||||
int32_t versionCode = 0;
|
||||
std::string versionName;
|
||||
std::string uuid;
|
||||
ProvisionType type = DEBUG;
|
||||
AppDistType distributionType = NONE_TYPE;
|
||||
BundleInfo bundleInfo;
|
||||
Permissions permissions;
|
||||
DebugInfo debugInfo;
|
||||
std::string issuer;
|
||||
std::string appId;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // PROVISION_INFO_H
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef PROVISION_VERIFY_H
|
||||
#define PROVISION_VERIFY_H
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "provision/provision_info.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum AppProvisionVerifyResult {
|
||||
PROVISION_INVALID, // Invalid json string
|
||||
PROVISION_OK, // Passed
|
||||
PROVISION_UNSUPPORTED_DEVICE_TYPE, // Failed to get device id
|
||||
PROVISION_NUM_DEVICE_EXCEEDED, // No. of device exceeds maximum number
|
||||
PROVISION_DEVICE_UNAUTHORIZED // Device id not included
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parse and verify the app provision
|
||||
* @param appProvision The app provision json string.
|
||||
* @param info Out param, the parsed app provision structure.
|
||||
* @return AppProvisionVerifyResult Verification result.
|
||||
*/
|
||||
DLL_EXPORT AppProvisionVerifyResult ParseAndVerify(const std::string& appProvision, ProvisionInfo& info);
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // PROVISION_VERIFY_H
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HOSP_DIGESTPARAMETER_H
|
||||
#define HOSP_DIGESTPARAMETER_H
|
||||
|
||||
#include "openssl/evp.h"
|
||||
|
||||
#include "common/export_define.h"
|
||||
|
||||
namespace OHOS::Security::Verify {
|
||||
class DigestParameter {
|
||||
public:
|
||||
DLL_EXPORT DigestParameter();
|
||||
DLL_EXPORT ~DigestParameter();
|
||||
|
||||
DLL_EXPORT DigestParameter(const DigestParameter& other);
|
||||
DLL_EXPORT DigestParameter& operator = (const DigestParameter& other);
|
||||
|
||||
public:
|
||||
int digestOutputSizeBytes;
|
||||
const EVP_MD* md;
|
||||
EVP_MD_CTX* ptrCtx;
|
||||
};
|
||||
}
|
||||
#endif // HOSP_DIGESTPARAMETER_H
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_CERT_VERIFY_OPENSSL_UTILS_H
|
||||
#define HAP_CERT_VERIFY_OPENSSL_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "util/pkcs7_context.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using CertSign = std::unordered_map<X509*, bool>;
|
||||
|
||||
class HapCertVerifyOpensslUtils {
|
||||
public:
|
||||
DLL_EXPORT static X509* GetX509CertFromPemString(const std::string& pemString);
|
||||
DLL_EXPORT static X509* GetX509CertFromBase64String(const std::string& base64String);
|
||||
DLL_EXPORT static X509_CRL* GetX509CrlFromDerBuffer(const HapByteBuffer& crlBuffer, int offset, int len);
|
||||
DLL_EXPORT static void GenerateCertSignFromCertStack(STACK_OF(X509)* certs, CertSign& certVisitSign);
|
||||
DLL_EXPORT static void ClearCertVisitSign(CertSign& certVisitSign);
|
||||
DLL_EXPORT static bool GetCertsChain(CertChain& certsChain, CertSign& certVisitSign);
|
||||
DLL_EXPORT static bool CertVerify(X509* cert, const X509* issuerCert);
|
||||
DLL_EXPORT static bool GetSubjectFromX509(const X509* cert, std::string& subject);
|
||||
DLL_EXPORT static bool GetIssuerFromX509(const X509* cert, std::string& issuer);
|
||||
DLL_EXPORT static bool GetSerialNumberFromX509(const X509* cert, long long& certNumber);
|
||||
DLL_EXPORT static bool GetIssuerFromX509Crl(const X509_CRL* crl, std::string& issuer);
|
||||
DLL_EXPORT static bool VerifyCertChainPeriodOfValidity(CertChain& certsChain, const ASN1_TYPE* signTime);
|
||||
DLL_EXPORT static bool VerifyCrl(CertChain& certsChain, STACK_OF(X509_CRL)* crls, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool CompareX509Cert(const X509* certA, const std::string& base64Cert);
|
||||
DLL_EXPORT static void WriteX509CrlToStream(std::ofstream& crlFile, X509_CRL* crl);
|
||||
DLL_EXPORT static bool GetPublickeyBase64FromPemCert(const std::string& certStr, std::string& publicKey);
|
||||
DLL_EXPORT static bool X509NameCompare(const X509_NAME* a, const X509_NAME* b);
|
||||
DLL_EXPORT static bool GetPublickeyBase64(const X509* cert, std::string& publicKey);
|
||||
DLL_EXPORT static int CalculateLenAfterBase64Encode(int len);
|
||||
|
||||
private:
|
||||
DLL_EXPORT static X509* FindCertOfIssuer(X509* cert, CertSign& certVisitSign);
|
||||
DLL_EXPORT static std::string GetDnToString(X509_NAME* name);
|
||||
DLL_EXPORT static void GetTextFromX509Name(X509_NAME* name, int nId, std::string& text);
|
||||
DLL_EXPORT static X509_CRL* GetCrlBySignedCertIssuer(STACK_OF(X509_CRL)* crls, const X509* cert);
|
||||
DLL_EXPORT static bool CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
|
||||
const ASN1_TIME* notBefore, const ASN1_TIME* notAfter);
|
||||
DLL_EXPORT static bool CheckAsn1TimeIsValid(const ASN1_TIME* asn1Time);
|
||||
DLL_EXPORT static bool CheckAsn1TypeIsValid(const ASN1_TYPE* asn1Type);
|
||||
|
||||
private:
|
||||
static const unsigned int MIN_CERT_CHAIN_LEN_NEED_VERIFY_CRL;
|
||||
static const int OPENSSL_READ_CRL_MAX_TIME;
|
||||
static const int OPENSSL_READ_CRL_LEN_EACH_TIME;
|
||||
static const int BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA;
|
||||
static const int BASE64_ENCODE_PACKET_LEN;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_CERT_VERIFY_OPENSSL_UTILS_H
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_PROFILE_VERIFY_UTILS_H
|
||||
#define HAP_PROFILE_VERIFY_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
class HapProfileVerifyUtils {
|
||||
public:
|
||||
DLL_EXPORT static bool ParseProfile(Pkcs7Context& profilePkcs7Context, const Pkcs7Context& hapPkcs7Context,
|
||||
const HapByteBuffer& pkcs7ProfileBlock, std::string& profile);
|
||||
DLL_EXPORT static bool VerifyProfile(Pkcs7Context& pkcs7Context);
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_PROFILE_VERIFY_UTILS_H
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_SIGNING_BLOCK_UTILS_H
|
||||
#define HAP_SIGNING_BLOCK_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "openssl/evp.h"
|
||||
|
||||
#include "common/data_source.h"
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "common/random_access_file.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
#include "util/signature_info.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
constexpr int ZIP_CHUNK_DIGEST_PRIFIX_LEN = 5;
|
||||
|
||||
enum HapBlobType {
|
||||
HAP_SIGN_BLOB = 0x20000000,
|
||||
PROOF_ROTATION_BLOB = 0x20000001,
|
||||
PROFILE_BLOB = 0x20000002,
|
||||
PROPERTY_BLOB = 0x20000003,
|
||||
};
|
||||
|
||||
struct HapSignBlockHead {
|
||||
int version;
|
||||
int blockCount;
|
||||
long long hapSignBlockSize;
|
||||
long long hapSignBlockMagicLo;
|
||||
long long hapSignBlockMagicHi;
|
||||
};
|
||||
|
||||
struct HapSubSignBlockHead {
|
||||
unsigned int type;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
class HapSigningBlockUtils {
|
||||
public:
|
||||
DLL_EXPORT static bool FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo);
|
||||
DLL_EXPORT static bool GetOptionalBlockIndex(std::vector<OptionalBlock>& optionBlocks, int type, int& index);
|
||||
DLL_EXPORT static bool VerifyHapIntegrity(Pkcs7Context& digestInfo, RandomAccessFile& hapFile,
|
||||
SignatureInfo& signInfo);
|
||||
|
||||
private:
|
||||
DLL_EXPORT static const long long HAP_SIG_BLOCK_MAGIC_HIGH;
|
||||
DLL_EXPORT static const long long HAP_SIG_BLOCK_MAGIC_LOW;
|
||||
DLL_EXPORT static const int ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
|
||||
DLL_EXPORT static const int ZIP_EOCD_SEGMENT_FLAG;
|
||||
static const long long CHUNK_SIZE;
|
||||
static const int HAP_SIG_BLOCK_MIN_SIZE;
|
||||
static const int ZIP_EOCD_SEG_MIN_SIZE;
|
||||
static const int ZIP_EOCD_COMMENT_LENGTH_OFFSET;
|
||||
static const int ZIP_CD_OFFSET_IN_EOCD;
|
||||
static const int ZIP_CD_SIZE_OFFSET_IN_EOCD;
|
||||
static const int ZIP_BLOCKS_NUM_NEED_DIGEST;
|
||||
static const char ZIP_FIRST_LEVEL_CHUNK_PREFIX;
|
||||
static const char ZIP_SECOND_LEVEL_CHUNK_PREFIX;
|
||||
/* the specifications of hap sign block */
|
||||
static constexpr long long MAX_HAP_SIGN_BLOCK_SIZE = 1024 * 1024 * 10LL; // 10MB
|
||||
static constexpr int MAX_BLOCK_COUNT = 10;
|
||||
|
||||
private:
|
||||
DLL_EXPORT static bool FindEocdInHap(RandomAccessFile& hapFile, std::pair<HapByteBuffer, long long>& eocd);
|
||||
DLL_EXPORT static bool FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize,
|
||||
std::pair<HapByteBuffer, long long>& eocd);
|
||||
DLL_EXPORT static bool FindEocdInSearchBuffer(HapByteBuffer& zipContents, int& offset);
|
||||
DLL_EXPORT static bool GetCentralDirectoryOffset(HapByteBuffer& eocd, long long eocdOffset,
|
||||
long long& centralDirectoryOffset);
|
||||
static bool FindHapSigningBlock(RandomAccessFile& hapFile, long long centralDirOffset,
|
||||
SignatureInfo& signInfo);
|
||||
static bool FindHapSubSigningBlock(RandomAccessFile& hapFile, int blockCount,
|
||||
long long blockArrayLen, long long hapSignBlockOffset, SignatureInfo& signInfo);
|
||||
DLL_EXPORT static bool ClassifyHapSubSigningBlock(SignatureInfo& signInfo,
|
||||
const HapByteBuffer& subBlock, unsigned int type);
|
||||
DLL_EXPORT static bool SetUnsignedInt32(HapByteBuffer& buffer, int offset, long long value);
|
||||
DLL_EXPORT static bool ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam,
|
||||
const std::vector<OptionalBlock>& optionalBlocks, const HapByteBuffer& chunkDigest,
|
||||
HapByteBuffer& finalDigest);
|
||||
static bool ComputeDigestsForEachChunk(const DigestParameter& digestParam, DataSource* contents[],
|
||||
int len, HapByteBuffer& result);
|
||||
static int GetChunkCount(long long inputSize, long long chunkSize);
|
||||
static bool InitDigestPrefix(const DigestParameter& digestParam,
|
||||
unsigned char (&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN], int chunkLen);
|
||||
DLL_EXPORT static DigestParameter GetDigestParameter(int nId);
|
||||
DLL_EXPORT static bool GetSumOfChunkDigestLen(DataSource* contents[], int len, int chunkDigestLen,
|
||||
int& chunkCount, int& sumOfChunkDigestLen);
|
||||
static bool ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, HapByteBuffer& hapBlockHead);
|
||||
static inline bool CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead);
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_SIGNING_BLOCK_UTILS_H
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_OPENSSL_UTILS_H
|
||||
#define HAP_VERIFY_OPENSSL_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "openssl/evp.h"
|
||||
|
||||
#include "common/export_define.h"
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
#include "util/digest_parameter.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
enum SignatureAlgorithm {
|
||||
ALGORITHM_SHA256_WITH_RSA_PSS = 0x00000101,
|
||||
ALGORITHM_SHA384_WITH_RSA_PSS,
|
||||
ALGORITHM_SHA512_WITH_RSA_PSS,
|
||||
ALGORITHM_SHA256_WITH_RSA_PKCS1_V1_5,
|
||||
ALGORITHM_SHA384_WITH_RSA_PKCS1_V1_5,
|
||||
ALGORITHM_SHA512_WITH_RSA_PKCS1_V1_5,
|
||||
ALGORITHM_SHA256_WITH_ECDSA = 0x00000201,
|
||||
ALGORITHM_SHA384_WITH_ECDSA,
|
||||
ALGORITHM_SHA512_WITH_ECDSA,
|
||||
ALGORITHM_SHA256_WITH_DSA = 0x00000301,
|
||||
ALGORITHM_SHA384_WITH_DSA,
|
||||
ALGORITHM_SHA512_WITH_DSA,
|
||||
};
|
||||
|
||||
class HapVerifyOpensslUtils {
|
||||
public:
|
||||
DLL_EXPORT static bool ParsePkcs7Package(const unsigned char packageData[],
|
||||
unsigned int packageLen, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool VerifyPkcs7(Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool GetPublickeys(const CertChain& signCertChain, std::vector<std::string>& SignatureVec);
|
||||
DLL_EXPORT static bool GetSignatures(const CertChain& signCertChain, std::vector<std::string>& SignatureVec);
|
||||
static int GetDigest(const HapByteBuffer& chunk, const std::vector<OptionalBlock>& optionalBlocks,
|
||||
const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE]);
|
||||
static bool DigestInit(const DigestParameter& digestParameter);
|
||||
static bool DigestUpdate(const DigestParameter& digestParameter, const unsigned char content[], int len);
|
||||
static int GetDigest(const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE]);
|
||||
static int GetDigestAlgorithmOutputSizeBytes(int nId);
|
||||
DLL_EXPORT static int GetDigestAlgorithmId(int signAlgorithm);
|
||||
static void GetOpensslErrorMessage();
|
||||
|
||||
private:
|
||||
DLL_EXPORT static bool VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool VerifySignInfo(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack,
|
||||
BIO* p7Bio, int signInfoNum, Pkcs7Context& pkcs7Context);
|
||||
DLL_EXPORT static bool GetPublickeyFromCertificate(const X509* ptrX509, std::vector<std::string>& publicKeyVec);
|
||||
DLL_EXPORT static bool GetDerCert(X509* ptrX509, std::vector<std::string>& SignatureVec);
|
||||
static bool VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo, BIO* p7Bio, EVP_PKEY* pkey, bool isPss);
|
||||
DLL_EXPORT static bool VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo, EVP_PKEY* pkey, bool isPss,
|
||||
const unsigned char digest[], unsigned int digestLen);
|
||||
static bool VerifyCertChain(CertChain& certsChain, PKCS7* p7, PKCS7_SIGNER_INFO* signInfo,
|
||||
Pkcs7Context& pkcs7Context, CertSign& certVisitSign);
|
||||
static bool IsEnablePss(const PKCS7_SIGNER_INFO* signInfo);
|
||||
static bool GetContentInfo(const PKCS7* p7ContentInfo, HapByteBuffer& content);
|
||||
static bool CheckPkcs7SignedDataIsValid(const PKCS7* p7);
|
||||
DLL_EXPORT static bool AsnStringCmp(const ASN1_OCTET_STRING* asnStr, const unsigned char data[], int len);
|
||||
static bool VerifyPkcs7AuthAttributes(const PKCS7_SIGNER_INFO* signInfo, EVP_MD_CTX* mdCtx, int mdType);
|
||||
static const EVP_MD_CTX* FindMdCtxInBio(BIO* p7Bio, int mdType);
|
||||
static bool CheckDigestParameter(const DigestParameter& digestParameter);
|
||||
|
||||
private:
|
||||
static const int OPENSSL_PKCS7_VERIFY_SUCCESS;
|
||||
static const int OPENSSL_ERR_MESSAGE_MAX_LEN;
|
||||
static const int OPENSSL_READ_DATA_MAX_TIME;
|
||||
static const int OPENSSL_READ_DATA_LEN_EACH_TIME;
|
||||
static const int MAX_OID_LENGTH;
|
||||
static const std::string PKCS7_EXT_SHAWITHRSA_PSS;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_VERIFY_OPENSSL_UTILS_H
|
65
interfaces/innerkits/appverify/include/util/pkcs7_context.h
Normal file
65
interfaces/innerkits/appverify/include/util/pkcs7_context.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_PKCS7_CONTEXT_H
|
||||
#define HAP_PKCS7_CONTEXT_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "openssl/pkcs7.h"
|
||||
#include "openssl/x509.h"
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "init/matching_result.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using CertChain = std::vector<X509*>;
|
||||
using Pkcs7CertChains = std::vector<CertChain>;
|
||||
|
||||
struct Pkcs7Context {
|
||||
bool needWriteCrl;
|
||||
int digestAlgorithm;
|
||||
MatchingResult matchResult;
|
||||
std::string certIssuer;
|
||||
PKCS7* p7;
|
||||
Pkcs7CertChains certChains;
|
||||
HapByteBuffer content;
|
||||
|
||||
Pkcs7Context()
|
||||
: needWriteCrl(false), digestAlgorithm(0), matchResult(), certIssuer(),
|
||||
p7(nullptr), certChains(), content()
|
||||
{
|
||||
}
|
||||
|
||||
~Pkcs7Context()
|
||||
{
|
||||
if (p7 != nullptr) {
|
||||
PKCS7_free(p7);
|
||||
p7 = nullptr;
|
||||
}
|
||||
for (auto certChain : certChains) {
|
||||
for (auto cert : certChain) {
|
||||
X509_free(cert);
|
||||
}
|
||||
}
|
||||
certChains.clear();
|
||||
}
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_PKCS7_CONTEXT_H
|
38
interfaces/innerkits/appverify/include/util/signature_info.h
Normal file
38
interfaces/innerkits/appverify/include/util/signature_info.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_SIGNATURE_INFO_H
|
||||
#define HAP_SIGNATURE_INFO_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
struct SignatureInfo {
|
||||
HapByteBuffer hapSignatureBlock;
|
||||
long long hapSigningBlockOffset;
|
||||
long long hapCentralDirOffset;
|
||||
long long hapEocdOffset;
|
||||
HapByteBuffer hapEocd;
|
||||
std::vector<OptionalBlock> optionBlocks;
|
||||
int version;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_SIGNATURE_INFO_H
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_HAP_V2_H
|
||||
#define HAP_VERIFY_HAP_V2_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "common/random_access_file.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
#include "provision/provision_verify.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
class HapVerifyV2 {
|
||||
public:
|
||||
int Verify(const std::string& filePath, HapVerifyResult& hapVerifyV1Result);
|
||||
|
||||
private:
|
||||
int Verify(RandomAccessFile& hapFile, HapVerifyResult& hapVerifyV1Result);
|
||||
bool VerifyAppPkc7AndParseProfile(Pkcs7Context& pkcs7Context, HapByteBuffer& hapProfileBlock,
|
||||
HapVerifyResult& hapVerifyV1Result);
|
||||
bool VerifyAppSourceAndParseProfile(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapProfileBlock,
|
||||
HapVerifyResult& hapVerifyV1Result, bool& profileNeadWriteCrl);
|
||||
bool VerifyAppPkcs7(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapSignatureBlock);
|
||||
bool VerifyAppSource(Pkcs7Context& pkcs7Context, Pkcs7Context& profileContext);
|
||||
DLL_EXPORT bool GetDigestAndAlgorithm(Pkcs7Context& digest);
|
||||
DLL_EXPORT bool CheckFilePath(const std::string& filePath, std::string& standardFilePath);
|
||||
void WriteCrlIfNeed(const Pkcs7Context& pkcs7Context, const bool& profileNeedWriteCrl);
|
||||
DLL_EXPORT bool ParseAndVerifyProfileIfNeed(const std::string& profile, ProvisionInfo& provisionInfo,
|
||||
bool isCallParseAndVerify);
|
||||
bool IsAppDistributedTypeAllowInstall(const AppDistType& type) const;
|
||||
DLL_EXPORT bool VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs7Context& profileContext,
|
||||
ProvisionInfo& provisionInfo);
|
||||
bool CheckProfileSignatureIsRight(const MatchingStates& matchState, const ProvisionType& type);
|
||||
DLL_EXPORT bool GenerateAppId(ProvisionInfo& provisionInfo);
|
||||
|
||||
private:
|
||||
static const int HEX_PRINT_LENGTH;
|
||||
static const int DIGEST_BLOCK_LEN_OFFSET;
|
||||
static const int DIGEST_ALGORITHM_OFFSET;
|
||||
static const int DIGEST_LEN_OFFSET;
|
||||
static const int DIGEST_OFFSET_IN_CONTENT;
|
||||
static const std::string HAP_APP_PATTERN;
|
||||
};
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
#endif // HAP_VERIFY_HAP_V2_H
|
353
interfaces/innerkits/appverify/src/common/hap_byte_buffer.cpp
Normal file
353
interfaces/innerkits/appverify/src/common/hap_byte_buffer.cpp
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
|
||||
#include "securec.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const int HapByteBuffer::MAX_PRINT_LENGTH = 200;
|
||||
const int HapByteBuffer::HEX_PRINT_LENGTH = 3;
|
||||
|
||||
HapByteBuffer::HapByteBuffer() : buffer(nullptr), position(0), limit(0), capacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
HapByteBuffer::HapByteBuffer(int bufferCapacity) : buffer(nullptr), position(0), limit(0), capacity(0)
|
||||
{
|
||||
Init(bufferCapacity);
|
||||
}
|
||||
|
||||
HapByteBuffer::HapByteBuffer(const HapByteBuffer& other) : buffer(nullptr), position(0), limit(0), capacity(0)
|
||||
{
|
||||
Init(other.GetCapacity());
|
||||
if (buffer != nullptr && capacity > 0) {
|
||||
if (memcpy_s(buffer.get(), capacity, other.GetBufferPtr(), other.GetCapacity()) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return;
|
||||
}
|
||||
position = other.GetPosition();
|
||||
limit = other.GetLimit();
|
||||
}
|
||||
}
|
||||
|
||||
HapByteBuffer::~HapByteBuffer()
|
||||
{
|
||||
buffer.reset(nullptr);
|
||||
}
|
||||
|
||||
void HapByteBuffer::Init(int bufferCapacity)
|
||||
{
|
||||
if (bufferCapacity > 0) {
|
||||
buffer = std::make_unique<char[]>(bufferCapacity);
|
||||
if (buffer != nullptr) {
|
||||
limit = bufferCapacity;
|
||||
capacity = bufferCapacity;
|
||||
}
|
||||
} else {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "bufferCapacity %{public}d is too small", bufferCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
HapByteBuffer& HapByteBuffer::operator=(const HapByteBuffer& other)
|
||||
{
|
||||
if (&other == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
buffer.reset(nullptr);
|
||||
Init(other.GetCapacity());
|
||||
if (buffer != nullptr && other.GetBufferPtr() != nullptr && capacity > 0) {
|
||||
if (memcpy_s(buffer.get(), capacity, other.GetBufferPtr(), other.GetCapacity()) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return *this;
|
||||
}
|
||||
position = other.GetPosition();
|
||||
limit = other.GetLimit();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::CheckInputForGettingData(int index, int dataLen)
|
||||
{
|
||||
if (buffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "buffer is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (index < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid index %{public}d", index);
|
||||
return false;
|
||||
}
|
||||
long long getDataLast = static_cast<long long>(position) + static_cast<long long>(index) +
|
||||
static_cast<long long>(dataLen);
|
||||
if (getDataLast > static_cast<long long>(limit)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "position %{public}d, index %{public}d, limit %{public}d",
|
||||
position, index, limit);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetInt64(long long& value)
|
||||
{
|
||||
if (!GetInt64(0, value)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetInt64 failed");
|
||||
return false;
|
||||
}
|
||||
position += sizeof(long long);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetInt64(int index, long long& value)
|
||||
{
|
||||
if (!CheckInputForGettingData(index, sizeof(long long))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Failed to get Int64");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(long long)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int HapByteBuffer::GetCapacity() const
|
||||
{
|
||||
return capacity;
|
||||
}
|
||||
|
||||
const char* HapByteBuffer::GetBufferPtr() const
|
||||
{
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetInt32(int& value)
|
||||
{
|
||||
if (!GetInt32(0, value)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetInt32 failed");
|
||||
return false;
|
||||
}
|
||||
position += sizeof(int);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetInt32(int index, int& value)
|
||||
{
|
||||
if (!CheckInputForGettingData(index, sizeof(int))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Failed to get Int32");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(int)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetUInt32(int index, unsigned int& value)
|
||||
{
|
||||
if (!CheckInputForGettingData(index, sizeof(unsigned int))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Failed to get UInt32");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(unsigned int)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::GetUInt16(int index, unsigned short& value)
|
||||
{
|
||||
if (!CheckInputForGettingData(index, sizeof(unsigned short))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Failed to get UInt16");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(unsigned short)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HapByteBuffer::PutInt32(int offset, int value)
|
||||
{
|
||||
if (buffer != nullptr && offset >= 0 && limit - offset >= static_cast<int>(sizeof(value))) {
|
||||
if (memcpy_s((buffer.get() + offset), (limit - offset), &value, sizeof(value)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HapByteBuffer::PutByte(int offset, char value)
|
||||
{
|
||||
if (buffer != nullptr && offset >= 0 && limit - offset >= static_cast<int>(sizeof(value))) {
|
||||
if (memcpy_s((buffer.get() + offset), (limit - offset), (&value), sizeof(value)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HapByteBuffer::PutData(int offset, const char data[], int len)
|
||||
{
|
||||
if (buffer != nullptr && data != nullptr && offset >= 0 && len > 0 && (limit - offset) >= len) {
|
||||
if (memcpy_s((buffer.get() + offset), (limit - offset), data, len) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HapByteBuffer::SetPosition(int pos)
|
||||
{
|
||||
if (pos >= 0 && pos <= limit) {
|
||||
position = pos;
|
||||
}
|
||||
}
|
||||
|
||||
void HapByteBuffer::Slice()
|
||||
{
|
||||
if (position >= capacity || limit > capacity || position >= limit || buffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "position %{public}d capacity %{public}d limit %{public}d error",
|
||||
position, capacity, limit);
|
||||
return;
|
||||
}
|
||||
int newCapacity = limit - position;
|
||||
std::unique_ptr<char[]> newBuffer = std::make_unique<char[]>(newCapacity);
|
||||
if (newBuffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "make_unique failed");
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(newBuffer.get(), newCapacity, (buffer.get() + position), (limit - position)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return;
|
||||
}
|
||||
buffer.reset(newBuffer.release());
|
||||
position = 0;
|
||||
capacity = newCapacity;
|
||||
limit = capacity;
|
||||
}
|
||||
|
||||
int HapByteBuffer::GetPosition() const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
int HapByteBuffer::GetLimit() const
|
||||
{
|
||||
return limit;
|
||||
}
|
||||
|
||||
void HapByteBuffer::SetLimit(int lim)
|
||||
{
|
||||
if (lim <= capacity && lim >= position) {
|
||||
limit = lim;
|
||||
}
|
||||
}
|
||||
|
||||
int HapByteBuffer::Remaining() const
|
||||
{
|
||||
return limit - position;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::HasRemaining() const
|
||||
{
|
||||
return position < limit;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::CopyPartialBuffer(const HapByteBuffer& other, int len)
|
||||
{
|
||||
int readableDataLen = other.Remaining();
|
||||
if (readableDataLen < len) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "readableDataLen %{public}d less than len %{public}d", readableDataLen, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer.reset(nullptr);
|
||||
buffer = std::make_unique<char[]>(len);
|
||||
if (buffer != nullptr && other.GetBufferPtr() != nullptr) {
|
||||
capacity = len;
|
||||
limit = capacity;
|
||||
if (memcpy_s(buffer.get(), capacity, (other.GetBufferPtr() + other.GetPosition()), len) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
position = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HapByteBuffer::Clear()
|
||||
{
|
||||
position = 0;
|
||||
limit = capacity;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::IsEqual(const HapByteBuffer& other)
|
||||
{
|
||||
if (&other == this) {
|
||||
return true;
|
||||
}
|
||||
if (capacity != other.GetCapacity() || other.GetBufferPtr() == nullptr || buffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
|
||||
return false;
|
||||
}
|
||||
const char* otherBuffer = other.GetBufferPtr();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
if (buffer[i] != otherBuffer[i]) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "diff value[%{public}d]: %{public}x %{public}x",
|
||||
i, buffer[i], otherBuffer[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapByteBuffer::IsEqual(const std::string& other)
|
||||
{
|
||||
if (capacity != static_cast<int>(other.size()) || buffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
if (buffer[i] != other[i]) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "diff value[%{public}d]: %{public}x %{public}x",
|
||||
i, buffer[i], other[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HapByteBuffer::SetCapacity(int cap)
|
||||
{
|
||||
if (buffer != nullptr) {
|
||||
buffer.reset(nullptr);
|
||||
position = 0;
|
||||
limit = 0;
|
||||
capacity = 0;
|
||||
}
|
||||
Init(cap);
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common/hap_byte_buffer_data_source.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
HapByteBufferDataSource::HapByteBufferDataSource(HapByteBuffer& hapBuffer)
|
||||
: DataSource(), hapByteBuffer(hapBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
HapByteBufferDataSource::~HapByteBufferDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
bool HapByteBufferDataSource::HasRemaining() const
|
||||
{
|
||||
return hapByteBuffer.HasRemaining();
|
||||
}
|
||||
|
||||
long long HapByteBufferDataSource::Remaining() const
|
||||
{
|
||||
return static_cast<long long>(hapByteBuffer.Remaining());
|
||||
}
|
||||
|
||||
void HapByteBufferDataSource::Reset()
|
||||
{
|
||||
hapByteBuffer.Clear();
|
||||
}
|
||||
|
||||
bool HapByteBufferDataSource::ReadDataAndDigestUpdate(const DigestParameter& digestParam, int chunkSize)
|
||||
{
|
||||
const unsigned char* chunk = reinterpret_cast<const unsigned char*>(hapByteBuffer.GetBufferPtr() +
|
||||
hapByteBuffer.GetPosition());
|
||||
bool res = HapVerifyOpensslUtils::DigestUpdate(digestParam, chunk, chunkSize);
|
||||
if (res) {
|
||||
hapByteBuffer.SetPosition(hapByteBuffer.GetPosition() + chunkSize);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common/hap_file_data_source.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
HapFileDataSource::HapFileDataSource(RandomAccessFile& hapFile,
|
||||
long long offset, long long size, long long position)
|
||||
: DataSource(), hapFileRandomAccess(hapFile), fileOffset(offset), sourceSize(size), sourcePosition(position)
|
||||
{
|
||||
}
|
||||
|
||||
HapFileDataSource::~HapFileDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
bool HapFileDataSource::HasRemaining() const
|
||||
{
|
||||
return sourcePosition < sourceSize;
|
||||
}
|
||||
|
||||
long long HapFileDataSource::Remaining() const
|
||||
{
|
||||
return sourceSize - sourcePosition;
|
||||
}
|
||||
|
||||
void HapFileDataSource::Reset()
|
||||
{
|
||||
sourcePosition = 0;
|
||||
}
|
||||
|
||||
bool HapFileDataSource::ReadDataAndDigestUpdate(const DigestParameter& digestParam, int chunkSize)
|
||||
{
|
||||
if (!hapFileRandomAccess.ReadFileFromOffsetAndDigestUpdate(digestParam, chunkSize, fileOffset + sourcePosition)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ReadFileFromOffsetAndDigestUpdate failed");
|
||||
return false;
|
||||
}
|
||||
sourcePosition += chunkSize;
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
147
interfaces/innerkits/appverify/src/common/random_access_file.cpp
Normal file
147
interfaces/innerkits/appverify/src/common/random_access_file.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common/random_access_file.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "securec.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const int RandomAccessFile::FILE_OPEN_FAIL_ERROR_NUM = -1;
|
||||
int RandomAccessFile::memoryPageSize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
RandomAccessFile::RandomAccessFile()
|
||||
: fd(FILE_OPEN_FAIL_ERROR_NUM), fileLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
RandomAccessFile::~RandomAccessFile()
|
||||
{
|
||||
if (fd != FILE_OPEN_FAIL_ERROR_NUM) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
bool RandomAccessFile::Init(const std::string& filePath)
|
||||
{
|
||||
fd = open(filePath.c_str(), O_RDONLY);
|
||||
if (fd == FILE_OPEN_FAIL_ERROR_NUM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memoryPageSize <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "getting pagesize failed: %{public}d", memoryPageSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
fileLength = lseek(fd, 0, SEEK_END);
|
||||
if (fileLength < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "getting fileLength failed: %{public}lld", fileLength);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
long long RandomAccessFile::GetLength() const
|
||||
{
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
long long RandomAccessFile::DoMMap(int bufCapacity, long long offset, MmapInfo& mmapInfo)
|
||||
{
|
||||
mmapInfo.mapAddr = reinterpret_cast<char*>(MAP_FAILED);
|
||||
if (fd == FILE_OPEN_FAIL_ERROR_NUM) {
|
||||
return FILE_IS_CLOSE;
|
||||
}
|
||||
if (offset < 0 || offset > fileLength - bufCapacity) {
|
||||
return READ_OFFSET_OUT_OF_RANGE;
|
||||
}
|
||||
mmapInfo.mmapPosition = (offset / memoryPageSize) * memoryPageSize;
|
||||
mmapInfo.readMoreLen = static_cast<int>(offset - mmapInfo.mmapPosition);
|
||||
mmapInfo.mmapSize = bufCapacity + mmapInfo.readMoreLen;
|
||||
mmapInfo.mapAddr = reinterpret_cast<char*>(mmap(nullptr, mmapInfo.mmapSize, PROT_READ,
|
||||
MAP_SHARED | MAP_POPULATE, fd, mmapInfo.mmapPosition));
|
||||
if (mmapInfo.mapAddr == MAP_FAILED) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "MAP_FAILED: %{public}d", errno);
|
||||
return MMAP_FAILED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long RandomAccessFile::ReadFileFullyFromOffset(char buf[], long long offset, int bufCapacity)
|
||||
{
|
||||
if (buf == nullptr) {
|
||||
return DEST_BUFFER_IS_NULL;
|
||||
}
|
||||
|
||||
MmapInfo mmapInfo;
|
||||
long long ret = DoMMap(bufCapacity, offset, mmapInfo);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (memcpy_s(buf, bufCapacity, mmapInfo.mapAddr + mmapInfo.readMoreLen,
|
||||
mmapInfo.mmapSize - mmapInfo.readMoreLen) != EOK) {
|
||||
munmap(mmapInfo.mapAddr, mmapInfo.mmapSize);
|
||||
return MMAP_COPY_FAILED;
|
||||
}
|
||||
munmap(mmapInfo.mapAddr, mmapInfo.mmapSize);
|
||||
return bufCapacity;
|
||||
}
|
||||
|
||||
long long RandomAccessFile::ReadFileFullyFromOffset(HapByteBuffer& buffer, long long offset)
|
||||
{
|
||||
if (!buffer.HasRemaining()) {
|
||||
return DEST_BUFFER_IS_NULL;
|
||||
}
|
||||
|
||||
MmapInfo mmapInfo;
|
||||
int bufCapacity = buffer.GetCapacity();
|
||||
long long ret = DoMMap(bufCapacity, offset, mmapInfo);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
buffer.PutData(0, mmapInfo.mapAddr + mmapInfo.readMoreLen, bufCapacity);
|
||||
munmap(mmapInfo.mapAddr, mmapInfo.mmapSize);
|
||||
return bufCapacity;
|
||||
}
|
||||
|
||||
bool RandomAccessFile::ReadFileFromOffsetAndDigestUpdate(const DigestParameter& digestParam,
|
||||
int chunkSize, long long offset)
|
||||
{
|
||||
MmapInfo mmapInfo;
|
||||
long long ret = DoMMap(chunkSize, offset, mmapInfo);
|
||||
if (ret < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "DoMMap failed: %{public}lld", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char* content = reinterpret_cast<unsigned char*>(mmapInfo.mapAddr + mmapInfo.readMoreLen);
|
||||
bool res = HapVerifyOpensslUtils::DigestUpdate(digestParam, content, chunkSize);
|
||||
munmap(mmapInfo.mapAddr, mmapInfo.mmapSize);
|
||||
return res;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
227
interfaces/innerkits/appverify/src/init/hap_crl_manager.cpp
Normal file
227
interfaces/innerkits/appverify/src/init/hap_crl_manager.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init/hap_crl_manager.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
#include "common/random_access_file.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const std::string HapCrlManager::HAP_CRL_FILE_PATH = "/data/hap_crl";
|
||||
|
||||
HapCrlManager& HapCrlManager::GetInstance()
|
||||
{
|
||||
static HapCrlManager hapCrlManager;
|
||||
return hapCrlManager;
|
||||
}
|
||||
|
||||
HapCrlManager::HapCrlManager() : crlMtx(), crlsMap(), isInit(false)
|
||||
{
|
||||
}
|
||||
|
||||
HapCrlManager::~HapCrlManager()
|
||||
{
|
||||
for (auto crlPair : crlsMap) {
|
||||
X509_CRL_free(crlPair.second);
|
||||
}
|
||||
crlsMap.clear();
|
||||
}
|
||||
|
||||
void HapCrlManager::Init()
|
||||
{
|
||||
if (isInit) {
|
||||
return;
|
||||
}
|
||||
|
||||
crlMtx.lock();
|
||||
HapByteBuffer crlsBuffer;
|
||||
bool ret = ReadCrls(crlsBuffer);
|
||||
if (ret && crlsBuffer.HasRemaining()) {
|
||||
ParseCrls(crlsBuffer);
|
||||
isInit = true;
|
||||
}
|
||||
crlMtx.unlock();
|
||||
}
|
||||
|
||||
bool HapCrlManager::ParseCrls(HapByteBuffer& crlsBuffer)
|
||||
{
|
||||
unsigned int numOfCrl;
|
||||
if (!crlsBuffer.GetUInt32(0, numOfCrl)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get numOfCrl failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int hasUsed = static_cast<int>(sizeof(numOfCrl));
|
||||
crlsBuffer.SetPosition(hasUsed);
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "total crl num: %{public}u", numOfCrl);
|
||||
while (numOfCrl && hasUsed <= crlsBuffer.GetCapacity()) {
|
||||
int crlLen;
|
||||
if (!crlsBuffer.GetInt32(crlLen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get crlLen failed");
|
||||
return false;
|
||||
}
|
||||
hasUsed += static_cast<int>(sizeof(crlLen));
|
||||
X509_CRL* crl = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlsBuffer, hasUsed, crlLen);
|
||||
if (crl == nullptr) {
|
||||
HAPVERIFY_LOG_WARN(LABEL, "crl file is destroyed");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string crlIssuer;
|
||||
if (!HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(crl, crlIssuer)) {
|
||||
X509_CRL_free(crl);
|
||||
HAPVERIFY_LOG_WARN(LABEL, "GetIssuerFromX509Crl failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crlsMap.find(crlIssuer) != crlsMap.end()) {
|
||||
X509_CRL_free(crlsMap[crlIssuer]);
|
||||
}
|
||||
crlsMap[crlIssuer] = crl;
|
||||
|
||||
hasUsed += crlLen;
|
||||
crlsBuffer.SetPosition(hasUsed);
|
||||
HAPVERIFY_LOG_INFO(LABEL, "get %{public}ust crl's Issuer: %{public}s", numOfCrl, crlIssuer.c_str());
|
||||
numOfCrl--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCrlManager::ReadCrls(HapByteBuffer& crlsBuffer)
|
||||
{
|
||||
RandomAccessFile crlRandomAccess;
|
||||
crlRandomAccess.Init(HAP_CRL_FILE_PATH);
|
||||
long long fileLen = crlRandomAccess.GetLength();
|
||||
if (fileLen <= 0) {
|
||||
HAPVERIFY_LOG_WARN(LABEL, "crl fileLen: %{public}lld", fileLen);
|
||||
return true;
|
||||
}
|
||||
crlsBuffer.SetCapacity(fileLen);
|
||||
long long readLen = crlRandomAccess.ReadFileFullyFromOffset(crlsBuffer, 0);
|
||||
if (readLen != fileLen) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "read file len: %{public}lld is not same as %{public}lld", readLen, fileLen);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HapCrlManager::WriteCrlsToFile()
|
||||
{
|
||||
crlMtx.lock();
|
||||
std::ofstream crlFile(HAP_CRL_FILE_PATH, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
|
||||
if (!crlFile.is_open()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "open %{public}s failed", HAP_CRL_FILE_PATH.c_str());
|
||||
crlMtx.unlock();
|
||||
return;
|
||||
}
|
||||
unsigned int numOfCrl = crlsMap.size();
|
||||
crlFile.write(reinterpret_cast<char*>(&numOfCrl), sizeof(numOfCrl));
|
||||
for (auto crlPair : crlsMap) {
|
||||
HapCertVerifyOpensslUtils::WriteX509CrlToStream(crlFile, crlPair.second);
|
||||
}
|
||||
HAPVERIFY_LOG_INFO(LABEL, "Write %{public}u crls to file done", numOfCrl);
|
||||
crlFile.close();
|
||||
crlMtx.unlock();
|
||||
}
|
||||
|
||||
X509_CRL* HapCrlManager::GetCrlByIssuer(const std::string& issuer)
|
||||
{
|
||||
if (crlsMap.find(issuer) == crlsMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return crlsMap[issuer];
|
||||
}
|
||||
|
||||
void HapCrlManager::UpdateCrlByIssuer(const std::string& issuer, X509_CRL* crl)
|
||||
{
|
||||
if (crl == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (crlsMap.find(issuer) != crlsMap.end()) {
|
||||
X509_CRL_free(crlsMap[issuer]);
|
||||
}
|
||||
crlsMap[issuer] = X509_CRL_dup(crl);
|
||||
}
|
||||
|
||||
bool HapCrlManager::CrlCheck(X509* cert, X509_CRL* targetCrl, Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
|
||||
return false;
|
||||
}
|
||||
|
||||
crlMtx.lock();
|
||||
/* crl in package compare with local crl, and decide which one to use */
|
||||
targetCrl = GetFinalCrl(targetCrl, pkcs7Context);
|
||||
if (targetCrl == nullptr) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "no crl");
|
||||
crlMtx.unlock();
|
||||
return true;
|
||||
}
|
||||
X509_REVOKED* revoked = nullptr;
|
||||
if (X509_CRL_get0_by_cert(targetCrl, &revoked, cert) != 0) {
|
||||
long long certNumber;
|
||||
std::string certSuject;
|
||||
HapCertVerifyOpensslUtils::GetSerialNumberFromX509(cert, certNumber);
|
||||
HapCertVerifyOpensslUtils::GetSubjectFromX509(cert, certSuject);
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "cert(issuer: %{public}s, subject: %{public}s, number:%{public}lld) is revoked",
|
||||
pkcs7Context.certIssuer.c_str(), certSuject.c_str(), certNumber);
|
||||
crlMtx.unlock();
|
||||
return false;
|
||||
}
|
||||
crlMtx.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
X509_CRL* HapCrlManager::GetFinalCrl(X509_CRL* crlInPackage, Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
X509_CRL* localCrl = GetCrlByIssuer(pkcs7Context.certIssuer);
|
||||
/* if no crl in package, use local crl */
|
||||
if (crlInPackage == nullptr) {
|
||||
return localCrl;
|
||||
}
|
||||
|
||||
/* if no local crl, use crl in package */
|
||||
if (localCrl == nullptr) {
|
||||
/* no local crl, update crl in package to local */
|
||||
UpdateCrlByIssuer(pkcs7Context.certIssuer, crlInPackage);
|
||||
pkcs7Context.needWriteCrl = true;
|
||||
return crlInPackage;
|
||||
}
|
||||
|
||||
/* if both are present, use which one recently updated */
|
||||
const ASN1_TIME* localCrlUpdateTime = X509_CRL_get0_lastUpdate(localCrl);
|
||||
const ASN1_TIME* packageCrlUpdateTime = X509_CRL_get0_lastUpdate(crlInPackage);
|
||||
if (localCrlUpdateTime == nullptr || packageCrlUpdateTime == nullptr) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "crl no update time");
|
||||
return nullptr;
|
||||
}
|
||||
if (ASN1_TIME_compare(localCrlUpdateTime, packageCrlUpdateTime) >= 0) {
|
||||
return localCrl;
|
||||
}
|
||||
/* if crl in package is newer version, use it to update local crl */
|
||||
UpdateCrlByIssuer(pkcs7Context.certIssuer, crlInPackage);
|
||||
pkcs7Context.needWriteCrl = true;
|
||||
return crlInPackage;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
103
interfaces/innerkits/appverify/src/init/json_parser_utils.cpp
Normal file
103
interfaces/innerkits/appverify/src/init/json_parser_utils.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init/json_parser_utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
bool JsonParserUtils::ReadTrustedRootCAFromJson(nlohmann::json& jsonObj,
|
||||
const std::string& jsonPath, std::string& error)
|
||||
{
|
||||
std::ifstream jsonFileStream;
|
||||
jsonFileStream.open(jsonPath.c_str(), std::ios::in);
|
||||
if (!jsonFileStream.is_open()) {
|
||||
error += "open file failed";
|
||||
return false;
|
||||
}
|
||||
std::ostringstream buf;
|
||||
char ch;
|
||||
while (buf && jsonFileStream.get(ch)) {
|
||||
buf.put(ch);
|
||||
}
|
||||
jsonFileStream.close();
|
||||
|
||||
std::string jsonStr = buf.str();
|
||||
jsonObj = nlohmann::json::parse(jsonStr, nullptr, false);
|
||||
if (!jsonObj.is_structured()) {
|
||||
error += "parse jsonStr failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParserUtils::GetJsonString(const nlohmann::json& json, const std::string& key, std::string& value)
|
||||
{
|
||||
if (!json.is_object()) {
|
||||
return false;
|
||||
}
|
||||
if (json.find(key) != json.end() && json.at(key).is_string()) {
|
||||
value = json.at(key).get<std::string>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParserUtils::GetJsonInt(const nlohmann::json& json, const std::string& key, int& value)
|
||||
{
|
||||
if (!json.is_object()) {
|
||||
return false;
|
||||
}
|
||||
if (json.find(key) != json.end() && json.at(key).is_number()) {
|
||||
value = json.at(key).get<int>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParserUtils::GetJsonStringVec(const nlohmann::json& json, const std::string& key, StringVec& value)
|
||||
{
|
||||
if (!json.is_object()) {
|
||||
return false;
|
||||
}
|
||||
if (json.find(key) != json.end() && json.at(key).is_array()) {
|
||||
value = json.at(key).get<StringVec>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParserUtils::ParseJsonToObjVec(const nlohmann::json& json, const std::string& key, JsonObjVec& jsonObjVec)
|
||||
{
|
||||
if (!json.is_object()) {
|
||||
return false;
|
||||
}
|
||||
if (json.find(key) != json.end() && json.at(key).is_array()) {
|
||||
jsonObjVec = json.at(key).get<JsonObjVec>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonParserUtils::ParseJsonToMap(const nlohmann::json& json, JsonMap& jsonMap)
|
||||
{
|
||||
for (auto it = json.begin(); it != json.end(); it++) {
|
||||
jsonMap[it.key()] = it.value().get<std::string>();
|
||||
}
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
154
interfaces/innerkits/appverify/src/init/trusted_root_ca.cpp
Normal file
154
interfaces/innerkits/appverify/src/init/trusted_root_ca.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init/trusted_root_ca.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const std::string TrustedRootCa::TRUSTED_ROOT_CA_FILE_PATH = "/system/etc/security/trusted_root_ca.json";
|
||||
const std::string TrustedRootCa::TRUSTED_ROOT_CA_TEST_FILE_PATH = "/system/etc/security/trusted_root_ca_test.json";
|
||||
|
||||
TrustedRootCa& TrustedRootCa::GetInstance()
|
||||
{
|
||||
static TrustedRootCa singleTrustedRoot;
|
||||
return singleTrustedRoot;
|
||||
}
|
||||
|
||||
TrustedRootCa::TrustedRootCa() : rootCerts(), rootCertsForTest(), isInit(false), isDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
TrustedRootCa::~TrustedRootCa()
|
||||
{
|
||||
for (auto rootCert : rootCerts) {
|
||||
X509_free(rootCert.second);
|
||||
}
|
||||
for (auto rootCert : rootCertsForTest) {
|
||||
X509_free(rootCert.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool TrustedRootCa::EnableDebug()
|
||||
{
|
||||
if (isDebug) {
|
||||
return true;
|
||||
}
|
||||
|
||||
isDebug = GetTrustedRootCAFromJson(rootCertsForTest, TRUSTED_ROOT_CA_TEST_FILE_PATH);
|
||||
if (isDebug) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "parse root certs test success, certs num: %{public}zu", rootCertsForTest.size());
|
||||
}
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
void TrustedRootCa::DisableDebug()
|
||||
{
|
||||
for (auto& rootCert : rootCertsForTest) {
|
||||
X509_free(rootCert.second);
|
||||
}
|
||||
rootCertsForTest.clear();
|
||||
isDebug = false;
|
||||
}
|
||||
|
||||
bool TrustedRootCa::Init()
|
||||
{
|
||||
if (isInit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
isInit = GetTrustedRootCAFromJson(rootCerts, TRUSTED_ROOT_CA_FILE_PATH);
|
||||
if (isInit) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "parse root certs success, certs num: %{public}zu", rootCerts.size());
|
||||
}
|
||||
return isInit;
|
||||
}
|
||||
|
||||
void TrustedRootCa::Recovery()
|
||||
{
|
||||
for (auto& rootCert : rootCerts) {
|
||||
X509_free(rootCert.second);
|
||||
}
|
||||
rootCerts.clear();
|
||||
isInit = false;
|
||||
}
|
||||
|
||||
bool TrustedRootCa::GetTrustedRootCAFromJson(StringCertMap& rootCertMap, const std::string& filePath)
|
||||
{
|
||||
nlohmann::json trustedRootCAJson;
|
||||
std::string errorInfo;
|
||||
if (!JsonParserUtils::ReadTrustedRootCAFromJson(trustedRootCAJson, filePath, errorInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get jsonObj from %{public}s failed, because %{public}s",
|
||||
filePath.c_str(), errorInfo.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonMap trustedRootCAJsonMap;
|
||||
JsonParserUtils::ParseJsonToMap(trustedRootCAJson, trustedRootCAJsonMap);
|
||||
for (auto jsonPair : trustedRootCAJsonMap) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "parse cert: %{public}s", jsonPair.second.c_str());
|
||||
X509* cert = HapCertVerifyOpensslUtils::GetX509CertFromPemString(jsonPair.second);
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetX509CertFromPemString failed, key: %{public}s value: %{public}s",
|
||||
jsonPair.first.c_str(), jsonPair.second.c_str());
|
||||
return false;
|
||||
}
|
||||
rootCertMap[jsonPair.first] = cert;
|
||||
}
|
||||
|
||||
if (rootCertMap.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no root cert");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
X509* TrustedRootCa::FindMatchedRoot(X509* caCert)
|
||||
{
|
||||
if (caCert == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
X509* root = FindMatchedRoot(rootCerts, caCert);
|
||||
if (root != nullptr) {
|
||||
return root;
|
||||
}
|
||||
|
||||
if (isDebug) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "try to match with test root");
|
||||
root = FindMatchedRoot(rootCertsForTest, caCert);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
X509* TrustedRootCa::FindMatchedRoot(const StringCertMap& rootCertMap, X509* caCert)
|
||||
{
|
||||
for (auto root : rootCertMap) {
|
||||
if (HapCertVerifyOpensslUtils::X509NameCompare(X509_get_subject_name(root.second),
|
||||
X509_get_issuer_name(caCert)) &&
|
||||
HapCertVerifyOpensslUtils::CertVerify(caCert, root.second)) {
|
||||
return X509_dup(root.second);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init/trusted_source_manager.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_FILE_PATH =
|
||||
"/system/etc/security/trusted_apps_sources.json";
|
||||
const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_TEST_FILE_PATH =
|
||||
"/system/etc/security/trusted_apps_sources_test.json";
|
||||
const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE = "trust-app-source";
|
||||
const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_VERSION = "version";
|
||||
const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME = "release-time";
|
||||
const std::string TrustedSourceManager::KEY_OF_SOURCE_NAME = "name";
|
||||
const std::string TrustedSourceManager::KEY_OF_APP_SIGNING_CERT = "app-signing-cert";
|
||||
const std::string TrustedSourceManager::KEY_OF_PROFILE_SIGNING_CERTIFICATE = "profile-signing-certificate";
|
||||
const std::string TrustedSourceManager::KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE = "profile-debug-signing-certificate";
|
||||
const std::string TrustedSourceManager::KEY_OF_ISSUER = "issuer-ca";
|
||||
const std::string TrustedSourceManager::KEY_OF_MAX_CERTS_PATH = "max-certs-path";
|
||||
const std::string TrustedSourceManager::KEY_OF_CRITIALCAL_CERT_EXTENSION = "critialcal-cert-extension";
|
||||
const std::string TrustedSourceManager::APP_GALLARY_SOURCE_NAME = "huawei app gallery";
|
||||
const std::string TrustedSourceManager::APP_SYSTEM_SOURCE_NAME = "huawei system apps";
|
||||
|
||||
TrustedSourceManager& TrustedSourceManager::GetInstance()
|
||||
{
|
||||
static TrustedSourceManager singleTrustedSourceManager;
|
||||
return singleTrustedSourceManager;
|
||||
}
|
||||
|
||||
TrustedSourceManager::TrustedSourceManager()
|
||||
: appTrustedSources(), appTrustedSourcesForTest(), version(), versionForTest(), releaseTime(),
|
||||
releaseTimeForTest(), isInit(false), isDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
TrustedSourceManager::~TrustedSourceManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool TrustedSourceManager::EnableDebug()
|
||||
{
|
||||
if (isDebug) {
|
||||
return true;
|
||||
}
|
||||
|
||||
isDebug = GetAppTrustedSources(appTrustedSourcesForTest, versionForTest,
|
||||
releaseTimeForTest, APP_TRUSTED_SOURCE_TEST_FILE_PATH);
|
||||
if (isDebug) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "trusted app source test version: %{public}s, releaseTime: %{public}s, Size:"
|
||||
" %{public}zu", versionForTest.c_str(), releaseTimeForTest.c_str(), appTrustedSourcesForTest.size());
|
||||
}
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
void TrustedSourceManager::DisableDebug()
|
||||
{
|
||||
appTrustedSourcesForTest.clear();
|
||||
isDebug = false;
|
||||
}
|
||||
|
||||
bool TrustedSourceManager::Init()
|
||||
{
|
||||
if (isInit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
isInit = GetAppTrustedSources(appTrustedSources, version, releaseTime, APP_TRUSTED_SOURCE_FILE_PATH);
|
||||
if (isInit) {
|
||||
HAPVERIFY_LOG_INFO(LABEL, "trusted app source version: %{public}s, releaseTime: %{public}s, Size:"
|
||||
" %{public}zu", version.c_str(), releaseTime.c_str(), appTrustedSources.size());
|
||||
}
|
||||
return isInit;
|
||||
}
|
||||
|
||||
void TrustedSourceManager::Recovery()
|
||||
{
|
||||
appTrustedSources.clear();
|
||||
isInit = false;
|
||||
}
|
||||
|
||||
bool TrustedSourceManager::GetAppTrustedSources(SourceInfoVec& trustedAppSources, std::string& souucesVersion,
|
||||
std::string& souucesReleaseTime, const std::string& filePath)
|
||||
{
|
||||
nlohmann::json trustedSourceJson;
|
||||
std::string errorInfo;
|
||||
if (!JsonParserUtils::ReadTrustedRootCAFromJson(trustedSourceJson, filePath, errorInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get jsonObj from %{public}s failed, because %{public}s",
|
||||
filePath.c_str(), errorInfo.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonString(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE_VERSION, souucesVersion)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get version failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonString(trustedSourceJson,
|
||||
KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME, souucesReleaseTime)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get releaseTime failed");
|
||||
return false;
|
||||
}
|
||||
JsonObjVec trustedAppSourceJson;
|
||||
if (!JsonParserUtils::ParseJsonToObjVec(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE, trustedAppSourceJson)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get JsonObjVec failed");
|
||||
return false;
|
||||
}
|
||||
if (!ParseTrustedAppSourceJson(trustedAppSources, trustedAppSourceJson)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "parse JsonObjVec failed");
|
||||
return false;
|
||||
}
|
||||
if (trustedAppSources.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no app trusted source");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TrustedSourceManager::ParseTrustedAppSourceJson(SourceInfoVec& trustedAppSources,
|
||||
const JsonObjVec& trustedAppSourceJson)
|
||||
{
|
||||
for (auto appSource : trustedAppSourceJson) {
|
||||
HapAppSourceInfo hapAppSource;
|
||||
if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_SOURCE_NAME, hapAppSource.sourceName)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get sourceName Failed");
|
||||
return false;
|
||||
}
|
||||
hapAppSource.source = GetTrustedSource(hapAppSource.sourceName);
|
||||
if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_APP_SIGNING_CERT, hapAppSource.appSigningCert)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get appSigningCert Failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_SIGNING_CERTIFICATE,
|
||||
hapAppSource.profileSigningCertificate)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get profileSigningCertificate Failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE,
|
||||
hapAppSource.profileDebugSigningCertificate)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get profileDebugSigningCertificate Failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_ISSUER, hapAppSource.issuer)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get issuer Failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonInt(appSource, KEY_OF_MAX_CERTS_PATH, hapAppSource.maxCertsPath)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get maxCertsPath Failed");
|
||||
return false;
|
||||
}
|
||||
if (!JsonParserUtils::GetJsonStringVec(appSource, KEY_OF_CRITIALCAL_CERT_EXTENSION,
|
||||
hapAppSource.critialcalCertExtension)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get critialcalCertExtension Failed");
|
||||
return false;
|
||||
}
|
||||
HAPVERIFY_LOG_INFO(LABEL, "trusted app source: %{public}s", EncapTrustedAppSourceString(hapAppSource).c_str());
|
||||
trustedAppSources.push_back(hapAppSource);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string TrustedSourceManager::EncapTrustedAppSourceString(const HapAppSourceInfo& appSourceInfo)
|
||||
{
|
||||
std::string info = "sourceName: " + appSourceInfo.sourceName + "\n" +
|
||||
"sourceNumber: " + std::to_string(static_cast<int>(appSourceInfo.source)) + "\n" +
|
||||
"appSigningCert: " + appSourceInfo.appSigningCert + "\n" +
|
||||
"profileSigningCertificate: " + appSourceInfo.profileSigningCertificate + "\n" +
|
||||
"profileDebugSigningCertificate: " + appSourceInfo.profileDebugSigningCertificate + "\n" +
|
||||
"issuer: " + appSourceInfo.issuer + "\n" +
|
||||
"maxCertsPath: " + std::to_string(appSourceInfo.maxCertsPath) + "\n" +
|
||||
"critialcalCertExtension: ";
|
||||
for (auto extension : appSourceInfo.critialcalCertExtension) {
|
||||
info += extension + ", ";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
MatchingResult TrustedSourceManager::IsTrustedSource(const std::string& certSubject,
|
||||
const std::string& certIssuer, HapBlobType blobType, int certListPath) const
|
||||
{
|
||||
MatchingResult ret = MatchTrustedSource(appTrustedSources, certSubject, certIssuer, blobType, certListPath);
|
||||
if (ret.matchState != DO_NOT_MATCH) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (isDebug) {
|
||||
return MatchTrustedSource(appTrustedSourcesForTest, certSubject, certIssuer, blobType, certListPath);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MatchingResult TrustedSourceManager::MatchTrustedSource(const SourceInfoVec& trustedAppSources,
|
||||
const std::string& certSubject, const std::string& certIssuer, HapBlobType blobType, int certListPath) const
|
||||
{
|
||||
MatchingResult ret;
|
||||
ret.matchState = DO_NOT_MATCH;
|
||||
for (auto appSource : trustedAppSources) {
|
||||
if (certListPath == appSource.maxCertsPath) {
|
||||
ret.matchState = TrustedSourceListCompare(certSubject, certIssuer, appSource, blobType);
|
||||
if (ret.matchState != DO_NOT_MATCH) {
|
||||
ret.source = appSource.source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MatchingStates TrustedSourceManager::TrustedSourceListCompare(const std::string& certSubject,
|
||||
const std::string& certIssuer, const HapAppSourceInfo& appSource, HapBlobType blobType) const
|
||||
{
|
||||
MatchingStates ret = DO_NOT_MATCH;
|
||||
switch (blobType) {
|
||||
case HAP_SIGN_BLOB: {
|
||||
if (appSource.appSigningCert.compare(certSubject) == 0 && appSource.issuer.compare(certIssuer) == 0) {
|
||||
ret = MATCH_WITH_SIGN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROFILE_BLOB: {
|
||||
if (appSource.issuer.compare(certIssuer) == 0) {
|
||||
if (appSource.profileSigningCertificate.compare(certSubject) == 0) {
|
||||
ret = MATCH_WITH_PROFILE;
|
||||
} else if (appSource.profileDebugSigningCertificate.compare(certSubject) == 0) {
|
||||
ret = MATCH_WITH_PROFILE_DEBUG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TrustedSources TrustedSourceManager::GetTrustedSource(std::string& sourceName)
|
||||
{
|
||||
if (APP_GALLARY_SOURCE_NAME.compare(sourceName) == 0) {
|
||||
return APP_GALLARY;
|
||||
}
|
||||
if (APP_SYSTEM_SOURCE_NAME.compare(sourceName) == 0) {
|
||||
return APP_SYSTEM;
|
||||
}
|
||||
return NOT_TRUSTED_SOURCE;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
71
interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp
Normal file
71
interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "interfaces/hap_verify.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "init/hap_crl_manager.h"
|
||||
#include "init/trusted_root_ca.h"
|
||||
#include "init/trusted_source_manager.h"
|
||||
#include "verify/hap_verify_v2.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
static std::mutex g_mtx;
|
||||
static bool g_isInit = false;
|
||||
|
||||
bool HapVerifyInit()
|
||||
{
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
TrustedSourceManager& trustedAppSourceManager = TrustedSourceManager::GetInstance();
|
||||
HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
|
||||
g_mtx.lock();
|
||||
g_isInit = rootCertsObj.Init() && trustedAppSourceManager.Init();
|
||||
if (!g_isInit) {
|
||||
rootCertsObj.Recovery();
|
||||
trustedAppSourceManager.Recovery();
|
||||
}
|
||||
hapCrlManager.Init();
|
||||
g_mtx.unlock();
|
||||
return g_isInit;
|
||||
}
|
||||
|
||||
bool EnableDebugMode()
|
||||
{
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
TrustedSourceManager& trustedAppSourceManager = TrustedSourceManager::GetInstance();
|
||||
g_mtx.lock();
|
||||
bool ret = rootCertsObj.EnableDebug() && trustedAppSourceManager.EnableDebug();
|
||||
if (!ret) {
|
||||
rootCertsObj.DisableDebug();
|
||||
trustedAppSourceManager.DisableDebug();
|
||||
}
|
||||
g_mtx.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)
|
||||
{
|
||||
if (!g_isInit && !HapVerifyInit()) {
|
||||
return VERIFY_SOURCE_INIT_FAIL;
|
||||
}
|
||||
HapVerifyV2 hapVerifyV2;
|
||||
return hapVerifyV2.Verify(filePath, hapVerifyResult);
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
HapVerifyResult::HapVerifyResult()
|
||||
: version(0), publicKeys(), signatures(), pkcs7SignBlock(),
|
||||
pkcs7ProfileBlock(), optionalBlocks(), provisionInfo()
|
||||
{
|
||||
}
|
||||
|
||||
HapVerifyResult::~HapVerifyResult()
|
||||
{
|
||||
}
|
||||
|
||||
int HapVerifyResult::GetVersion() const
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetVersion(int signatureVersion)
|
||||
{
|
||||
version = signatureVersion;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetPkcs7SignBlock(const HapByteBuffer& pkcs7)
|
||||
{
|
||||
pkcs7SignBlock = pkcs7;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetPkcs7ProfileBlock(const HapByteBuffer& pkcs7)
|
||||
{
|
||||
pkcs7ProfileBlock = pkcs7;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetOptionalBlocks(const std::vector<OptionalBlock>& option)
|
||||
{
|
||||
optionalBlocks = option;
|
||||
}
|
||||
|
||||
std::vector<std::string> HapVerifyResult::GetPublicKey()
|
||||
{
|
||||
return publicKeys;
|
||||
}
|
||||
|
||||
std::vector<std::string> HapVerifyResult::GetSignature()
|
||||
{
|
||||
return signatures;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetPublicKey(const std::vector<std::string>& inputPubkeys)
|
||||
{
|
||||
publicKeys = inputPubkeys;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetSignature(const std::vector<std::string>& inputSignatures)
|
||||
{
|
||||
signatures = inputSignatures;
|
||||
}
|
||||
|
||||
int HapVerifyResult::GetProperty(std::string& property)
|
||||
{
|
||||
return GetBlockFromOptionalBlocks(PROPERTY_BLOB, property);
|
||||
}
|
||||
|
||||
int HapVerifyResult::GetBlockFromOptionalBlocks(int blockType, std::string& block)
|
||||
{
|
||||
for (unsigned long i = 0; i < optionalBlocks.size(); i++) {
|
||||
if (optionalBlocks[i].optionalType == blockType) {
|
||||
HapByteBuffer& option = optionalBlocks[i].optionalBlockValue;
|
||||
block += std::string(option.GetBufferPtr(), option.GetCapacity());
|
||||
return GET_SUCCESS;
|
||||
}
|
||||
}
|
||||
return NO_THIS_BLOCK_IN_PACKAGE;
|
||||
}
|
||||
|
||||
void HapVerifyResult::SetProvisionInfo(const ProvisionInfo &info)
|
||||
{
|
||||
provisionInfo = info;
|
||||
}
|
||||
|
||||
ProvisionInfo HapVerifyResult::GetProvisionInfo()
|
||||
{
|
||||
return provisionInfo;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "provision/provision_verify.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nlohmann;
|
||||
|
||||
namespace {
|
||||
const string KEY_VERSION_CODE = "version-code";
|
||||
const string KEY_VERSION_NAME = "version-name";
|
||||
const string KEY_UUID = "uuid";
|
||||
const string KEY_TYPE = "type";
|
||||
const string KEY_APP_DIST_TYPE = "app-distribution-type";
|
||||
const string KEY_BUNDLE_INFO = "bundle-info";
|
||||
const string KEY_DEVELOPER_ID = "developer-id";
|
||||
const string KEY_DEVELOPMENT_CERTIFICATE = "development-certificate";
|
||||
const string KEY_DISTRIBUTION_CERTIFICATE = "distribution-certificate";
|
||||
const string KEY_BUNDLE_NAME = "bundle-name";
|
||||
const string KEY_APP_FEATURE = "app-feature";
|
||||
const string KEY_PERMISSIONS = "permissions";
|
||||
const string KEY_RESTRICTED_PERMISSIONS = "restricted-permissions";
|
||||
const string KEY_RESTRICTED_CAPABILITIES = "restricted-capabilities";
|
||||
const string KEY_DEBUG_INFO = "debug-info";
|
||||
const string KEY_DEVICE_ID_TYPE = "device-id-type";
|
||||
const string KEY_DEVICE_IDS = "device-ids";
|
||||
const string KEY_ISSUER = "issuer";
|
||||
const string VALUE_TYPE_RELEASE = "release";
|
||||
const string VALUE_DIST_TYPE_APP_GALLERY = "app_gallery";
|
||||
const string VALUE_DIST_TYPE_ENTERPRISE = "enterprise";
|
||||
const string VALUE_DIST_TYPE_OS_INTEGRATION = "os_integration";
|
||||
const string VALUE_DEVICE_ID_TYPE_UDID = "udid";
|
||||
|
||||
const string GENERIC_BUNDLE_NAME = ".*";
|
||||
|
||||
const int MAXIMUM_NUM_DEVICES = 100;
|
||||
|
||||
inline void GetStringIfExist(const json& obj, const string& key, string& out)
|
||||
{
|
||||
if (obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_string()) {
|
||||
obj[key.c_str()].get_to(out);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GetInt32IfExist(const json& obj, const string& key, int32_t& out)
|
||||
{
|
||||
if (obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_number_integer()) {
|
||||
obj[key.c_str()].get_to(out);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GetStringArrayIfExist(const json& obj, const string& key, vector<string>& out)
|
||||
{
|
||||
if (obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_array()) {
|
||||
for (auto& item : obj[key.c_str()]) {
|
||||
if (item.is_string()) {
|
||||
out.push_back(item.get<string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsObjectExist(const json& obj, const string& key)
|
||||
{
|
||||
return obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_object();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
void ParseType(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
string type;
|
||||
GetStringIfExist(obj, KEY_TYPE, type);
|
||||
/* If not release, then it's debug */
|
||||
out.type = (type == VALUE_TYPE_RELEASE) ? ProvisionType::RELEASE : ProvisionType::DEBUG;
|
||||
}
|
||||
|
||||
void ParseAppDistType(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
string distType;
|
||||
GetStringIfExist(obj, KEY_APP_DIST_TYPE, distType);
|
||||
if (distType == VALUE_DIST_TYPE_APP_GALLERY) {
|
||||
out.distributionType = AppDistType::APP_GALLERY;
|
||||
} else if (distType == VALUE_DIST_TYPE_ENTERPRISE) {
|
||||
out.distributionType = AppDistType::ENTERPRISE;
|
||||
} else if (distType == VALUE_DIST_TYPE_OS_INTEGRATION) {
|
||||
out.distributionType = AppDistType::OS_INTEGRATION;
|
||||
} else {
|
||||
out.distributionType = AppDistType::NONE_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
void ParseBundleInfo(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
if (IsObjectExist(obj, KEY_BUNDLE_INFO)) {
|
||||
auto& bundleInfo = obj[KEY_BUNDLE_INFO];
|
||||
GetStringIfExist(bundleInfo, KEY_DEVELOPER_ID, out.bundleInfo.developerId);
|
||||
GetStringIfExist(bundleInfo, KEY_DEVELOPMENT_CERTIFICATE, out.bundleInfo.developmentCertificate);
|
||||
GetStringIfExist(bundleInfo, KEY_DISTRIBUTION_CERTIFICATE, out.bundleInfo.distributionCertificate);
|
||||
GetStringIfExist(bundleInfo, KEY_BUNDLE_NAME, out.bundleInfo.bundleName);
|
||||
GetStringIfExist(bundleInfo, KEY_APP_FEATURE, out.bundleInfo.appFeature);
|
||||
}
|
||||
}
|
||||
|
||||
void ParsePermissions(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
if (IsObjectExist(obj, KEY_PERMISSIONS)) {
|
||||
auto& permissions = obj[KEY_PERMISSIONS];
|
||||
GetStringArrayIfExist(permissions, KEY_RESTRICTED_PERMISSIONS, out.permissions.restrictedPermissions);
|
||||
GetStringArrayIfExist(permissions, KEY_RESTRICTED_CAPABILITIES, out.permissions.restrictedCapabilities);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseDebugInfo(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
if (IsObjectExist(obj, KEY_DEBUG_INFO)) {
|
||||
GetStringIfExist(obj[KEY_DEBUG_INFO], KEY_DEVICE_ID_TYPE, out.debugInfo.deviceIdType);
|
||||
GetStringArrayIfExist(obj[KEY_DEBUG_INFO], KEY_DEVICE_IDS, out.debugInfo.deviceIds);
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const json& obj, ProvisionInfo& out)
|
||||
{
|
||||
if (!obj.is_object()) {
|
||||
return;
|
||||
}
|
||||
GetInt32IfExist(obj, KEY_VERSION_CODE, out.versionCode);
|
||||
GetStringIfExist(obj, KEY_VERSION_NAME, out.versionName);
|
||||
GetStringIfExist(obj, KEY_UUID, out.uuid);
|
||||
ParseType(obj, out);
|
||||
ParseAppDistType(obj, out);
|
||||
ParseBundleInfo(obj, out);
|
||||
ParsePermissions(obj, out);
|
||||
ParseDebugInfo(obj, out);
|
||||
GetStringIfExist(obj, KEY_ISSUER, out.issuer);
|
||||
}
|
||||
|
||||
#define RETURN_IF_STRING_IS_EMPTY(str, msg) \
|
||||
if (str.empty()) { \
|
||||
HAPVERIFY_LOG_ERROR(LABEL, msg); \
|
||||
return PROVISION_INVALID; \
|
||||
}
|
||||
|
||||
#define RETURN_IF_INT_IS_NON_POSITIVE(num, msg) \
|
||||
if (num <= 0) { \
|
||||
HAPVERIFY_LOG_ERROR(LABEL, msg); \
|
||||
return PROVISION_INVALID; \
|
||||
}
|
||||
|
||||
AppProvisionVerifyResult ParseProvision(const string& appProvision, ProvisionInfo& info)
|
||||
{
|
||||
json obj = json::parse(appProvision, nullptr, false);
|
||||
if (!obj.is_structured()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Parsing appProvision failed. json: %{public}s", appProvision.c_str());
|
||||
return PROVISION_INVALID;
|
||||
}
|
||||
obj.get_to(info);
|
||||
|
||||
RETURN_IF_INT_IS_NON_POSITIVE(info.versionCode, "Tag version code is empty.")
|
||||
RETURN_IF_STRING_IS_EMPTY(info.versionName, "Tag version name is empty.")
|
||||
RETURN_IF_STRING_IS_EMPTY(info.uuid, "Tag uuid is empty.")
|
||||
RETURN_IF_STRING_IS_EMPTY(info.bundleInfo.developerId, "Tag developer-id is empty.")
|
||||
if (info.type == ProvisionType::DEBUG) {
|
||||
RETURN_IF_STRING_IS_EMPTY(info.bundleInfo.developmentCertificate, "Tag development-certificate is empty.")
|
||||
} else if (info.type == ProvisionType::RELEASE) {
|
||||
RETURN_IF_INT_IS_NON_POSITIVE(info.distributionType, "Tag app-distribution-type is empty.")
|
||||
RETURN_IF_STRING_IS_EMPTY(info.bundleInfo.distributionCertificate, "Tag distribution-certificate is empty.")
|
||||
}
|
||||
RETURN_IF_STRING_IS_EMPTY(info.bundleInfo.bundleName, "Tag bundle-name is empty.")
|
||||
if (info.bundleInfo.bundleName == GENERIC_BUNDLE_NAME) {
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "generic package name: %{public}s, is used.", GENERIC_BUNDLE_NAME.c_str());
|
||||
}
|
||||
RETURN_IF_STRING_IS_EMPTY(info.bundleInfo.appFeature, "Tag app-feature is empty.")
|
||||
|
||||
return PROVISION_OK;
|
||||
}
|
||||
|
||||
AppProvisionVerifyResult CheckDeviceID(ProvisionInfo& info)
|
||||
{
|
||||
// Checking device ids
|
||||
if (info.debugInfo.deviceIds.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "device-id list is empty.");
|
||||
return PROVISION_DEVICE_UNAUTHORIZED;
|
||||
}
|
||||
if (info.debugInfo.deviceIds.size() > MAXIMUM_NUM_DEVICES) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "No. of device IDs in list exceed maximum number %{public}d", MAXIMUM_NUM_DEVICES);
|
||||
return PROVISION_NUM_DEVICE_EXCEEDED;
|
||||
}
|
||||
string deviceId;
|
||||
if (info.debugInfo.deviceIdType != VALUE_DEVICE_ID_TYPE_UDID) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "type of device ID is not supported.");
|
||||
return PROVISION_UNSUPPORTED_DEVICE_TYPE;
|
||||
}
|
||||
if (deviceId.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "device-id of current device is empty.");
|
||||
return PROVISION_DEVICE_UNAUTHORIZED;
|
||||
}
|
||||
auto iter = find(info.debugInfo.deviceIds.begin(), info.debugInfo.deviceIds.end(), deviceId);
|
||||
if (iter == info.debugInfo.deviceIds.end()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "current device is not authorized.");
|
||||
return PROVISION_DEVICE_UNAUTHORIZED;
|
||||
}
|
||||
return PROVISION_OK;
|
||||
}
|
||||
|
||||
AppProvisionVerifyResult ParseAndVerify(const string& appProvision, ProvisionInfo& info)
|
||||
{
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "Enter HarmonyAppProvision Verify");
|
||||
AppProvisionVerifyResult ret = ParseProvision(appProvision, info);
|
||||
if (ret != PROVISION_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (info.type == ProvisionType::DEBUG) {
|
||||
ret = CheckDeviceID(info);
|
||||
if (ret != PROVISION_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "Leave HarmonyAppProvision Verify");
|
||||
return PROVISION_OK;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
54
interfaces/innerkits/appverify/src/util/digest_parameter.cpp
Normal file
54
interfaces/innerkits/appverify/src/util/digest_parameter.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "util/digest_parameter.h"
|
||||
|
||||
namespace OHOS::Security::Verify {
|
||||
DigestParameter::DigestParameter() : digestOutputSizeBytes(0), md(nullptr), ptrCtx(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DigestParameter::~DigestParameter()
|
||||
{
|
||||
if (ptrCtx != nullptr) {
|
||||
EVP_MD_CTX_destroy(ptrCtx);
|
||||
ptrCtx = nullptr;
|
||||
}
|
||||
/* md points to the OpenSSL global static struct constant, no need to free. */
|
||||
md = nullptr;
|
||||
}
|
||||
|
||||
DigestParameter::DigestParameter(const DigestParameter& other)
|
||||
{
|
||||
digestOutputSizeBytes = other.digestOutputSizeBytes;
|
||||
md = other.md;
|
||||
ptrCtx = EVP_MD_CTX_create();
|
||||
EVP_MD_CTX_copy(ptrCtx, other.ptrCtx);
|
||||
}
|
||||
|
||||
DigestParameter& DigestParameter::operator = (const DigestParameter& other)
|
||||
{
|
||||
if (ptrCtx != nullptr) {
|
||||
EVP_MD_CTX_destroy(ptrCtx);
|
||||
ptrCtx = nullptr;
|
||||
}
|
||||
|
||||
digestOutputSizeBytes = other.digestOutputSizeBytes;
|
||||
md = other.md;
|
||||
ptrCtx = EVP_MD_CTX_create();
|
||||
EVP_MD_CTX_copy(ptrCtx, other.ptrCtx);
|
||||
return *this;
|
||||
}
|
||||
}
|
@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
#include "openssl/pem.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
#include "init/hap_crl_manager.h"
|
||||
#include "init/trusted_root_ca.h"
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const unsigned int HapCertVerifyOpensslUtils::MIN_CERT_CHAIN_LEN_NEED_VERIFY_CRL = 2;
|
||||
const int HapCertVerifyOpensslUtils::OPENSSL_READ_CRL_MAX_TIME = 1048576; // 1024 * 1024
|
||||
const int HapCertVerifyOpensslUtils::OPENSSL_READ_CRL_LEN_EACH_TIME = 1024;
|
||||
const int HapCertVerifyOpensslUtils::BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA = 4;
|
||||
const int HapCertVerifyOpensslUtils::BASE64_ENCODE_PACKET_LEN = 3;
|
||||
|
||||
X509* HapCertVerifyOpensslUtils::GetX509CertFromPemString(const std::string& pemString)
|
||||
{
|
||||
BIO* pemBio = BIO_new(BIO_s_mem());
|
||||
if (pemBio == nullptr) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "BIO_new failed");
|
||||
return nullptr;
|
||||
}
|
||||
int strLen = static_cast<int>(pemString.size());
|
||||
if (BIO_write(pemBio, pemString.c_str(), strLen) != strLen) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "BIO_write failed");
|
||||
BIO_free_all(pemBio);
|
||||
return nullptr;
|
||||
}
|
||||
X509* cert = PEM_read_bio_X509(pemBio, nullptr, nullptr, nullptr);
|
||||
BIO_free_all(pemBio);
|
||||
return cert;
|
||||
}
|
||||
|
||||
X509* HapCertVerifyOpensslUtils::GetX509CertFromBase64String(const std::string& base64String)
|
||||
{
|
||||
std::unique_ptr<unsigned char[]> decodeBuffer = std::make_unique<unsigned char[]>(base64String.size());
|
||||
if (decodeBuffer == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "make_unique failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const unsigned char* input = reinterpret_cast<const unsigned char *>(base64String.c_str());
|
||||
int len = EVP_DecodeBlock(decodeBuffer.get(), input, base64String.size());
|
||||
if (len <= 0) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "base64Decode failed, len: %{public}d", len);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const unsigned char* derBits = decodeBuffer.get();
|
||||
X509* cert = d2i_X509(nullptr, &derBits, len);
|
||||
return cert;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetPublickeyBase64FromPemCert(const std::string& certStr, std::string& publicKey)
|
||||
{
|
||||
X509* cert = GetX509CertFromPemString(certStr);
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetX509CertFromPemString failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetPublickeyBase64(cert, publicKey)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "X509_get_pubkey failed");
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
X509_free(cert);
|
||||
return false;
|
||||
}
|
||||
X509_free(cert);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetPublickeyBase64(const X509* cert, std::string& publicKey)
|
||||
{
|
||||
EVP_PKEY *pkey = X509_get0_pubkey(cert);
|
||||
if (pkey == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "X509_get0_pubkey failed");
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyLen = i2d_PublicKey(pkey, nullptr);
|
||||
if (keyLen <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "keyLen %{public}d, i2d_PublicKey failed", keyLen);
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<unsigned char[]> derPublicKey = std::make_unique<unsigned char[]>(keyLen);
|
||||
int base64KeyLen = CalculateLenAfterBase64Encode(keyLen);
|
||||
std::unique_ptr<unsigned char[]> base64PublicKey = std::make_unique<unsigned char[]>(base64KeyLen);
|
||||
if (derPublicKey == nullptr || base64PublicKey == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "make_unique failed");
|
||||
return false;
|
||||
}
|
||||
unsigned char* derCertificateBackup = derPublicKey.get();
|
||||
if (i2d_PublicKey(pkey, &derCertificateBackup) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "i2d_PublicKey failed");
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
int outLen = EVP_EncodeBlock(base64PublicKey.get(), derPublicKey.get(), keyLen);
|
||||
publicKey = std::string(reinterpret_cast<char*>(base64PublicKey.get()), outLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The length after Base64 encoding is 4/3 of the length before encoding,
|
||||
* and openssl function will add '\0' to the encoded string.
|
||||
* So len_after_encode = len_before_encode * 4/3 + 1
|
||||
*/
|
||||
int HapCertVerifyOpensslUtils::CalculateLenAfterBase64Encode(int len)
|
||||
{
|
||||
return static_cast<int>(ceil(static_cast<long double>(len) / BASE64_ENCODE_PACKET_LEN) *
|
||||
BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA + 1);
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::CompareX509Cert(const X509* certA, const std::string& base64Cert)
|
||||
{
|
||||
if (certA == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "certA is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509* certB = GetX509CertFromPemString(base64Cert);
|
||||
if (certB == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "generate certB failed");
|
||||
return false;
|
||||
}
|
||||
bool ret = (X509_cmp(certA, certB) == 0);
|
||||
X509_free(certB);
|
||||
return ret;
|
||||
}
|
||||
|
||||
X509_CRL* HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(const HapByteBuffer& crlBuffer, int offset, int len)
|
||||
{
|
||||
if (crlBuffer.GetBufferPtr() == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input, crlbuffer is null");
|
||||
return nullptr;
|
||||
}
|
||||
if ((len <= 0) || (offset < 0) || (crlBuffer.GetCapacity() - len < offset)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input, offset: %{public}d, len: %{public}d", offset, len);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BIO* derBio = BIO_new(BIO_s_mem());
|
||||
if (derBio == nullptr) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "BIO_new failed");
|
||||
return nullptr;
|
||||
}
|
||||
if (BIO_write(derBio, crlBuffer.GetBufferPtr() + offset, len) != len) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "BIO_write failed");
|
||||
BIO_free_all(derBio);
|
||||
return nullptr;
|
||||
}
|
||||
X509_CRL* crl = d2i_X509_CRL_bio(derBio, nullptr);
|
||||
BIO_free_all(derBio);
|
||||
return crl;
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtils::WriteX509CrlToStream(std::ofstream& crlFile, X509_CRL* crl)
|
||||
{
|
||||
if (!crlFile.is_open()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "fill is not open");
|
||||
return;
|
||||
}
|
||||
|
||||
BIO* derBio = BIO_new(BIO_s_mem());
|
||||
if (derBio == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "BIO_new failed");
|
||||
return;
|
||||
}
|
||||
if (crl == nullptr || i2d_X509_CRL_bio(derBio, crl) == 0) {
|
||||
BIO_free_all(derBio);
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "i2d_X509_CRL_bio failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int totalLen = 0;
|
||||
long long posStart = crlFile.tellp();
|
||||
crlFile.seekp(posStart + sizeof(totalLen));
|
||||
char buf[OPENSSL_READ_CRL_LEN_EACH_TIME];
|
||||
int readLen = BIO_read(derBio, buf, sizeof(buf));
|
||||
int readTime = 0;
|
||||
while (readLen > 0 && (++readTime < OPENSSL_READ_CRL_MAX_TIME)) {
|
||||
crlFile.write(buf, readLen);
|
||||
totalLen += readLen;
|
||||
readLen = BIO_read(derBio, buf, sizeof(buf));
|
||||
}
|
||||
BIO_free_all(derBio);
|
||||
long long posEnd = crlFile.tellp();
|
||||
crlFile.seekp(posStart);
|
||||
/* write crl data len */
|
||||
crlFile.write(reinterpret_cast<char*>(&totalLen), sizeof(totalLen));
|
||||
crlFile.seekp(posEnd);
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtils::GenerateCertSignFromCertStack(STACK_OF(X509)* certs, CertSign& certVisitSign)
|
||||
{
|
||||
if (certs == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sk_X509_num(certs); i++) {
|
||||
X509* cert = sk_X509_value(certs, i);
|
||||
if (cert == nullptr) {
|
||||
continue;
|
||||
}
|
||||
certVisitSign[cert] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtils::ClearCertVisitSign(CertSign& certVisitSign)
|
||||
{
|
||||
for (auto& certPair : certVisitSign) {
|
||||
certPair.second = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetCertsChain(CertChain& certsChain, CertSign& certVisitSign)
|
||||
{
|
||||
if (certsChain.empty() || certVisitSign.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "input is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509* issuerCert;
|
||||
X509* cert = certsChain[0];
|
||||
while ((issuerCert = FindCertOfIssuer(cert, certVisitSign)) != nullptr) {
|
||||
certsChain.push_back(X509_dup(issuerCert));
|
||||
certVisitSign[issuerCert] = true;
|
||||
cert = issuerCert;
|
||||
}
|
||||
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
issuerCert = rootCertsObj.FindMatchedRoot(certsChain[certsChain.size() - 1]);
|
||||
if (issuerCert == nullptr) {
|
||||
std::string caIssuer;
|
||||
GetIssuerFromX509(certsChain[certsChain.size() - 1], caIssuer);
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "it do not come from trusted root, issuer: %{public}s", caIssuer.c_str());
|
||||
return false;
|
||||
}
|
||||
if (X509_cmp(issuerCert, certsChain[certsChain.size() - 1]) == 0) {
|
||||
X509_free(issuerCert);
|
||||
} else {
|
||||
certsChain.push_back(issuerCert);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
X509* HapCertVerifyOpensslUtils::FindCertOfIssuer(X509* cert, CertSign& certVisitSign)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "input is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
X509_NAME* signCertIssuer = X509_get_issuer_name(cert);
|
||||
for (auto certPair : certVisitSign) {
|
||||
if (certPair.second) {
|
||||
continue;
|
||||
}
|
||||
|
||||
X509* issuerCert = certPair.first;
|
||||
X509_NAME* issuerCertSubject = X509_get_subject_name(issuerCert);
|
||||
/* verify sign and issuer */
|
||||
if (X509NameCompare(issuerCertSubject, signCertIssuer) &&
|
||||
CertVerify(cert, issuerCert)) {
|
||||
return issuerCert;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::CertVerify(X509* cert, const X509* issuerCert)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "input is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
EVP_PKEY* caPublicKey = X509_get0_pubkey(issuerCert);
|
||||
if (caPublicKey == nullptr) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get pubkey from caCert failed");
|
||||
return false;
|
||||
}
|
||||
return X509_verify(cert, caPublicKey) > 0;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(CertChain& certsChain, const ASN1_TYPE* signTime)
|
||||
{
|
||||
if (certsChain.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < certsChain.size() - 1; i++) {
|
||||
if (certsChain[i] == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "%{public}dst cert is nullptr", i);
|
||||
return false;
|
||||
}
|
||||
const ASN1_TIME* notBefore = X509_get0_notBefore(certsChain[i]);
|
||||
const ASN1_TIME* notAfter = X509_get0_notAfter(certsChain[i]);
|
||||
if (!CheckSignTimeInValidPeriod(signTime, notBefore, notAfter)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "%{public}dst cert is not in period of validity", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::CheckAsn1TimeIsValid(const ASN1_TIME* asn1Time)
|
||||
{
|
||||
if (asn1Time == nullptr || asn1Time->data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::CheckAsn1TypeIsValid(const ASN1_TYPE* asn1Type)
|
||||
{
|
||||
if (asn1Type == nullptr || asn1Type->value.asn1_string == nullptr ||
|
||||
asn1Type->value.asn1_string->data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
|
||||
const ASN1_TIME* notBefore, const ASN1_TIME* notAfter)
|
||||
{
|
||||
if (!CheckAsn1TimeIsValid(notBefore) || !CheckAsn1TimeIsValid(notAfter)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no valid period");
|
||||
return false;
|
||||
}
|
||||
if (!CheckAsn1TypeIsValid(signTime)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signTime is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0 ||
|
||||
ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Out of valid period, signTime: %{public}s, notBefore: %{public}s, "
|
||||
"notAfter: %{public}s", signTime->value.asn1_string->data, notBefore->data, notAfter->data);
|
||||
return false;
|
||||
}
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "signTime type: %{public}d, data: %{public}s, notBefore: %{public}s, "
|
||||
"notAfter: %{public}s", signTime->type, signTime->value.asn1_string->data, notBefore->data, notAfter->data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::VerifyCrl(CertChain& certsChain, STACK_OF(X509_CRL)* crls, Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (certsChain.empty()) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "cert chain is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get signed cert's issuer and then it will be used to find local crl */
|
||||
if (!GetIssuerFromX509(certsChain[0], pkcs7Context.certIssuer)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get issuer of signed cert failed");
|
||||
return false;
|
||||
}
|
||||
X509_CRL* targetCrl = GetCrlBySignedCertIssuer(crls, certsChain[0]);
|
||||
/* crl is optional */
|
||||
if (targetCrl != nullptr && certsChain.size() >= MIN_CERT_CHAIN_LEN_NEED_VERIFY_CRL) {
|
||||
/* if it include crl, it must be verified by ca cert */
|
||||
if (X509_CRL_verify(targetCrl, X509_get0_pubkey(certsChain[1])) <= 0) {
|
||||
HapVerifyOpensslUtils::GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "verify crlInPackage failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
|
||||
return hapCrlManager.CrlCheck(certsChain[0], targetCrl, pkcs7Context);
|
||||
}
|
||||
|
||||
X509_CRL* HapCertVerifyOpensslUtils::GetCrlBySignedCertIssuer(STACK_OF(X509_CRL)* crls, const X509* cert)
|
||||
{
|
||||
if (crls == nullptr || cert == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
X509_NAME* certIssuer = X509_get_issuer_name(cert);
|
||||
for (int i = 0; i < sk_X509_CRL_num(crls); i++) {
|
||||
X509_CRL* crl = sk_X509_CRL_value(crls, i);
|
||||
if (crl == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
X509_NAME* crlIssuer = X509_CRL_get_issuer(crl);
|
||||
if (X509NameCompare(crlIssuer, certIssuer)) {
|
||||
return crl;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::X509NameCompare(const X509_NAME* a, const X509_NAME* b)
|
||||
{
|
||||
if (a == nullptr || b == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return X509_NAME_cmp(a, b) == 0;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetSubjectFromX509(const X509* cert, std::string& subject)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "cert is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509_NAME* name = X509_get_subject_name(cert);
|
||||
subject = GetDnToString(name);
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "subject = %{public}s", subject.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetIssuerFromX509(const X509* cert, std::string& issuer)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "cert is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509_NAME* name = X509_get_issuer_name(cert);
|
||||
issuer = GetDnToString(name);
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "cert issuer = %{public}s", issuer.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetSerialNumberFromX509(const X509* cert, long long& certNumber)
|
||||
{
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "cert is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
const ASN1_INTEGER* certSN = X509_get0_serialNumber(cert);
|
||||
certNumber = ASN1_INTEGER_get(certSN);
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "cert number = %{public}lld", certNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(const X509_CRL* crl, std::string& issuer)
|
||||
{
|
||||
if (crl == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "clr is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509_NAME* name = X509_CRL_get_issuer(crl);
|
||||
if (name == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "crl issuer nullptr");
|
||||
return false;
|
||||
}
|
||||
issuer = GetDnToString(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string HapCertVerifyOpensslUtils::GetDnToString(X509_NAME* name)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string countryName;
|
||||
GetTextFromX509Name(name, NID_countryName, countryName);
|
||||
std::string organizationName;
|
||||
GetTextFromX509Name(name, NID_organizationName, organizationName);
|
||||
std::string organizationalUnitName;
|
||||
GetTextFromX509Name(name, NID_organizationalUnitName, organizationalUnitName);
|
||||
std::string commonName;
|
||||
GetTextFromX509Name(name, NID_commonName, commonName);
|
||||
return "C=" + countryName + ", O=" + organizationName + ", OU=" + organizationalUnitName +
|
||||
", CN=" + commonName;
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtils::GetTextFromX509Name(X509_NAME* name, int nId, std::string& text)
|
||||
{
|
||||
int textLen = X509_NAME_get_text_by_NID(name, nId, nullptr, 0);
|
||||
if (textLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(textLen + 1);
|
||||
if (buffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (X509_NAME_get_text_by_NID(name, nId, buffer.get(), textLen + 1) != textLen) {
|
||||
return;
|
||||
}
|
||||
text = std::string(buffer.get());
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "util/hap_profile_verify_utils.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
#include "init/trusted_source_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
bool HapProfileVerifyUtils::ParseProfile(Pkcs7Context& profilePkcs7Context, const Pkcs7Context& hapPkcs7Context,
|
||||
const HapByteBuffer& pkcs7ProfileBlock, std::string& profile)
|
||||
{
|
||||
if (hapPkcs7Context.matchResult.matchState == MATCH_WITH_SIGN &&
|
||||
hapPkcs7Context.matchResult.source == APP_GALLARY) {
|
||||
profile = std::string(pkcs7ProfileBlock.GetBufferPtr(), pkcs7ProfileBlock.GetCapacity());
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "hap include unsigned provision");
|
||||
return true;
|
||||
}
|
||||
const unsigned char* pkcs7Block = reinterpret_cast<const unsigned char*>(pkcs7ProfileBlock.GetBufferPtr());
|
||||
unsigned int pkcs7Len = pkcs7ProfileBlock.GetCapacity();
|
||||
if (!HapVerifyOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, profilePkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "parse pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
profile = std::string(profilePkcs7Context.content.GetBufferPtr(), profilePkcs7Context.content.GetCapacity());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapProfileVerifyUtils::VerifyProfile(Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (!HapVerifyOpensslUtils::GetCertChains(pkcs7Context.p7, pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetCertChains from pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HapVerifyOpensslUtils::VerifyPkcs7(pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "verify profile signature failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string certSubject;
|
||||
std::string certIssuer;
|
||||
if (!HapCertVerifyOpensslUtils::GetSubjectFromX509(pkcs7Context.certChains[0][0], certSubject) ||
|
||||
!HapCertVerifyOpensslUtils::GetIssuerFromX509(pkcs7Context.certChains[0][0], certIssuer)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get info of sign cert failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
TrustedSourceManager& trustedSourceManager = TrustedSourceManager::GetInstance();
|
||||
pkcs7Context.matchResult = trustedSourceManager.IsTrustedSource(certSubject, certIssuer, PROFILE_BLOB,
|
||||
pkcs7Context.certChains[0].size());
|
||||
if (pkcs7Context.matchResult.matchState == DO_NOT_MATCH) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "profile signature is not trusted source, subject: %{public}s, issuer: %{public}s",
|
||||
certSubject.c_str(), certIssuer.c_str());
|
||||
return false;
|
||||
}
|
||||
HAPVERIFY_LOG_INFO(LABEL, "profile subject: %{public}s, issuer: %{public}s",
|
||||
certSubject.c_str(), certIssuer.c_str());
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
|
||||
#include <climits>
|
||||
#include <map>
|
||||
|
||||
#include "securec.h"
|
||||
|
||||
#include "common/hap_byte_buffer_data_source.h"
|
||||
#include "common/hap_file_data_source.h"
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW = 2334950737560224072LL;
|
||||
const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 3617552046287187010LL;
|
||||
|
||||
/* 1MB = 1024 * 1024 Bytes */
|
||||
const long long HapSigningBlockUtils::CHUNK_SIZE = 1048576LL;
|
||||
|
||||
const int HapSigningBlockUtils::HAP_SIG_BLOCK_MIN_SIZE = 32;
|
||||
const int HapSigningBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH = 32;
|
||||
|
||||
const int HapSigningBlockUtils::ZIP_EOCD_SEG_MIN_SIZE = 22;
|
||||
const int HapSigningBlockUtils::ZIP_EOCD_SEGMENT_FLAG = 0x06054b50;
|
||||
const int HapSigningBlockUtils::ZIP_EOCD_COMMENT_LENGTH_OFFSET = 20;
|
||||
const int HapSigningBlockUtils::ZIP_CD_OFFSET_IN_EOCD = 16;
|
||||
const int HapSigningBlockUtils::ZIP_CD_SIZE_OFFSET_IN_EOCD = 12;
|
||||
const int HapSigningBlockUtils::ZIP_BLOCKS_NUM_NEED_DIGEST = 3;
|
||||
|
||||
const char HapSigningBlockUtils::ZIP_FIRST_LEVEL_CHUNK_PREFIX = 0x5a;
|
||||
const char HapSigningBlockUtils::ZIP_SECOND_LEVEL_CHUNK_PREFIX = 0xa5;
|
||||
|
||||
/*
|
||||
* The package of hap is ZIP format, and contains four segments: contents of Zip entry,
|
||||
* hap signatures block, central directory and end of central directory.
|
||||
* The function will find the data segment of hap signature block from hap file.
|
||||
*/
|
||||
bool HapSigningBlockUtils::FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo)
|
||||
{
|
||||
std::pair<HapByteBuffer, long long> eocdAndOffsetInFile;
|
||||
if (!FindEocdInHap(hapFile, eocdAndOffsetInFile)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "find EoCD failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
signInfo.hapEocd = eocdAndOffsetInFile.first;
|
||||
signInfo.hapEocdOffset = eocdAndOffsetInFile.second;
|
||||
if (!GetCentralDirectoryOffset(signInfo.hapEocd, signInfo.hapEocdOffset, signInfo.hapCentralDirOffset)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get CD offset failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FindHapSigningBlock(hapFile, signInfo.hapCentralDirOffset, signInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "find signing block failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, std::pair<HapByteBuffer, long long>& eocd)
|
||||
{
|
||||
/*
|
||||
* EoCD has an optional comment block. Most hap packages do not contain this block.
|
||||
* For hap packages without comment block, EoCD is the last 22 bytes of hap file.
|
||||
* Try as a hap without comment block first to avoid unnecessarily reading more data.
|
||||
*/
|
||||
if (FindEocdInHap(hapFile, 0, eocd)) {
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "Find EoCD of Zip file");
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* If EoCD contain the comment block, we should find it from the offset of (fileLen - maxCommentSize - 22).
|
||||
* The max size of comment block is 65535, because the comment length is an unsigned 16-bit number.
|
||||
*/
|
||||
return FindEocdInHap(hapFile, USHRT_MAX, eocd);
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize,
|
||||
std::pair<HapByteBuffer, long long>& eocd)
|
||||
{
|
||||
long long fileLength = hapFile.GetLength();
|
||||
/* check whether has enough space for EoCD in the file. */
|
||||
if (fileLength < ZIP_EOCD_SEG_MIN_SIZE) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "file length %{public}lld is too smaller", fileLength);
|
||||
return false;
|
||||
}
|
||||
|
||||
int searchRange = maxCommentSize + ZIP_EOCD_SEG_MIN_SIZE;
|
||||
if (fileLength < static_cast<long long>(searchRange)) {
|
||||
searchRange = static_cast<int>(fileLength);
|
||||
}
|
||||
|
||||
HapByteBuffer searchEocdBuffer(searchRange);
|
||||
long long searchRangeOffset = fileLength - searchEocdBuffer.GetCapacity();
|
||||
long long ret = hapFile.ReadFileFullyFromOffset(searchEocdBuffer, searchRangeOffset);
|
||||
if (ret < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "read data from hap file error: %{public}lld", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
int eocdOffsetInSearchBuffer = 0;
|
||||
if (!FindEocdInSearchBuffer(searchEocdBuffer, eocdOffsetInSearchBuffer)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "No Eocd is found");
|
||||
return false;
|
||||
}
|
||||
|
||||
searchEocdBuffer.SetPosition(eocdOffsetInSearchBuffer);
|
||||
searchEocdBuffer.Slice();
|
||||
eocd.first = searchEocdBuffer;
|
||||
eocd.second = searchRangeOffset + eocdOffsetInSearchBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Eocd format:
|
||||
* 4-bytes: End of central directory flag
|
||||
* 2-bytes: Number of this disk
|
||||
* 2-bytes: Number of the disk with the start of central directory
|
||||
* 2-bytes: Total number of entries in the central directory on this disk
|
||||
* 2-bytes: Total number of entries in the central directory
|
||||
* 4-bytes: Size of central directory
|
||||
* 4-bytes: offset of central directory in zip file
|
||||
* 2-bytes: ZIP file comment length, the value n is in the range of [0, 65535]
|
||||
* n-bytes: ZIP Comment block data
|
||||
*
|
||||
* This function find Eocd by searching Eocd flag from input buffer(searchBuffer) and
|
||||
* making sure the comment length is equal to the expected value.
|
||||
*/
|
||||
bool HapSigningBlockUtils::FindEocdInSearchBuffer(HapByteBuffer& searchBuffer, int& offset)
|
||||
{
|
||||
int searchBufferSize = searchBuffer.GetCapacity();
|
||||
if (searchBufferSize < ZIP_EOCD_SEG_MIN_SIZE) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "The size of searchBuffer %{public}d is smaller than min size of Eocd",
|
||||
searchBufferSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
int currentOffset = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE;
|
||||
while (currentOffset >= 0) {
|
||||
int hapEocdSegmentFlag;
|
||||
if (searchBuffer.GetInt32(currentOffset, hapEocdSegmentFlag) &&
|
||||
(hapEocdSegmentFlag == ZIP_EOCD_SEGMENT_FLAG)) {
|
||||
unsigned short commentLength;
|
||||
int expectedCommentLength = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE - currentOffset;
|
||||
if (searchBuffer.GetUInt16(currentOffset + ZIP_EOCD_COMMENT_LENGTH_OFFSET, commentLength) &&
|
||||
static_cast<int>(commentLength) == expectedCommentLength) {
|
||||
offset = currentOffset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
currentOffset--;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::GetCentralDirectoryOffset(HapByteBuffer& eocd, long long eocdOffset,
|
||||
long long& centralDirectoryOffset)
|
||||
{
|
||||
unsigned int offsetValue;
|
||||
unsigned int sizeValue;
|
||||
if (!eocd.GetUInt32(ZIP_CD_OFFSET_IN_EOCD, offsetValue) ||
|
||||
!eocd.GetUInt32(ZIP_CD_SIZE_OFFSET_IN_EOCD, sizeValue)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetUInt32 failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
centralDirectoryOffset = offsetValue;
|
||||
if (centralDirectoryOffset > eocdOffset) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "centralDirOffset %{public}lld is larger than eocdOffset %{public}lld",
|
||||
centralDirectoryOffset, eocdOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
long long centralDirectorySize = sizeValue;
|
||||
if (centralDirectoryOffset + centralDirectorySize != eocdOffset) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "centralDirOffset %{public}lld add centralDirSize %{public}lld is not equal\
|
||||
to eocdOffset %{public}lld", centralDirectoryOffset, centralDirectorySize, eocdOffset);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::SetUnsignedInt32(HapByteBuffer& buffer, int offset, long long value)
|
||||
{
|
||||
if ((value < 0) || (value > static_cast<long long>(UINT_MAX))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "uint32 value of out range: %{public}lld", value);
|
||||
return false;
|
||||
}
|
||||
buffer.PutInt32(offset, static_cast<int>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, long long centralDirOffset,
|
||||
SignatureInfo& signInfo)
|
||||
{
|
||||
if (centralDirOffset < HAP_SIG_BLOCK_MIN_SIZE) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "HAP too small for HAP Signing Block: %{public}lld", centralDirOffset);
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* read hap signing block head, it's format:
|
||||
* int32: blockCount
|
||||
* int64: size
|
||||
* 16 bytes: magic
|
||||
* int32: version
|
||||
*/
|
||||
HapByteBuffer hapBlockHead(ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH);
|
||||
long long ret = hapFile.ReadFileFullyFromOffset(hapBlockHead, centralDirOffset - hapBlockHead.GetCapacity());
|
||||
if (ret < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "read hapBlockHead error: %{public}lld", ret);
|
||||
return false;
|
||||
}
|
||||
HapSignBlockHead hapSignBlockHead;
|
||||
if (!ParseSignBlockHead(hapSignBlockHead, hapBlockHead)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ParseSignBlockHead failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSignBlockHead(hapSignBlockHead)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "hapSignBlockHead is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
signInfo.version = hapSignBlockHead.version;
|
||||
long long blockArrayLen = hapSignBlockHead.hapSignBlockSize - ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
|
||||
long long hapSignBlockOffset = centralDirOffset - hapSignBlockHead.hapSignBlockSize;
|
||||
if (hapSignBlockOffset < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "HAP Signing Block offset out of range %{public}lld", hapSignBlockOffset);
|
||||
return false;
|
||||
}
|
||||
signInfo.hapSigningBlockOffset = hapSignBlockOffset;
|
||||
return FindHapSubSigningBlock(hapFile, hapSignBlockHead.blockCount, blockArrayLen, hapSignBlockOffset, signInfo);
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead)
|
||||
{
|
||||
if ((hapSignBlockHead.hapSignBlockMagicLo != HAP_SIG_BLOCK_MAGIC_LOW) ||
|
||||
(hapSignBlockHead.hapSignBlockMagicHi != HAP_SIG_BLOCK_MAGIC_HIGH)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "No HAP Signing Block before ZIP Central Directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((hapSignBlockHead.hapSignBlockSize < ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH) ||
|
||||
(hapSignBlockHead.hapSignBlockSize > MAX_HAP_SIGN_BLOCK_SIZE)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "HAP Signing Block size out of range %{public}lld",
|
||||
hapSignBlockHead.hapSignBlockSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hapSignBlockHead.blockCount > MAX_BLOCK_COUNT) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "HAP Signing Block count out of range %{public}d", hapSignBlockHead.blockCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, HapByteBuffer& hapBlockHead)
|
||||
{
|
||||
return hapBlockHead.GetInt32(hapSignBlockHead.blockCount) &&
|
||||
hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockSize) &&
|
||||
hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicLo) &&
|
||||
hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicHi) &&
|
||||
hapBlockHead.GetInt32(hapSignBlockHead.version);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hap Sign Block Format:
|
||||
* HapSubSignBlock1_Head
|
||||
* HapSubSignBlock2_Head
|
||||
* ...
|
||||
* HapSubSignBlockn_Head
|
||||
* HapSubSignBlock1_data
|
||||
* HapSubSignBlock2_data
|
||||
* ...
|
||||
* HapSubSignBlockn_data
|
||||
* hap signing block head
|
||||
*
|
||||
* This function reads the head of the HapSubSignBlocks,
|
||||
* and then reads the corresponding data of each block according to the offset provided by the head
|
||||
*/
|
||||
bool HapSigningBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile, int blockCount,
|
||||
long long blockArrayLen, long long hapSignBlockOffset, SignatureInfo& signInfo)
|
||||
{
|
||||
long long offsetMax = hapSignBlockOffset + blockArrayLen;
|
||||
long long readLen = 0;
|
||||
long long readHeadOffset = hapSignBlockOffset;
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "hapSignBlockOffset %{public}lld blockArrayLen: %{public}lld blockCount: %{public}d",
|
||||
hapSignBlockOffset, blockArrayLen, blockCount);
|
||||
for (int i = 0; i < blockCount; i++) {
|
||||
HapSubSignBlockHead subSignBlockHead;
|
||||
long long ret = hapFile.ReadFileFullyFromOffset(reinterpret_cast<char*>(&subSignBlockHead),
|
||||
readHeadOffset, sizeof(HapSubSignBlockHead));
|
||||
if (ret < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "read %{public}dst subblock head error: %{public}lld", i, ret);
|
||||
return false;
|
||||
}
|
||||
readLen += sizeof(HapSubSignBlockHead);
|
||||
|
||||
readHeadOffset += sizeof(HapSubSignBlockHead);
|
||||
if (readHeadOffset > offsetMax) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "find %{public}dst next head offset error", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check subSignBlockHead */
|
||||
if ((offsetMax - subSignBlockHead.offset) < hapSignBlockOffset) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Find %{public}dst subblock data offset error", i);
|
||||
return false;
|
||||
}
|
||||
if ((blockArrayLen - subSignBlockHead.length) < readLen) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no enough data to be read for %{public}dst subblock", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
long long dataOffset = hapSignBlockOffset + subSignBlockHead.offset;
|
||||
HapByteBuffer signBuffer(subSignBlockHead.length);
|
||||
ret = hapFile.ReadFileFullyFromOffset(signBuffer, dataOffset);
|
||||
if (ret < 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "read %{public}dst subblock error: %{public}lld", i, ret);
|
||||
return false;
|
||||
}
|
||||
readLen += subSignBlockHead.length;
|
||||
|
||||
if (!ClassifyHapSubSigningBlock(signInfo, signBuffer, subSignBlockHead.type)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ClassifyHapSubSigningBlock error, type is %{public}d",
|
||||
subSignBlockHead.type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* size of block must be equal to the sum of all subblocks length */
|
||||
if (readLen != blockArrayLen) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "readLen: %{public}lld is not same as blockArrayLen: %{public}lld",
|
||||
readLen, blockArrayLen);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::ClassifyHapSubSigningBlock(SignatureInfo& signInfo,
|
||||
const HapByteBuffer& subBlock, unsigned int type)
|
||||
{
|
||||
bool ret = false;
|
||||
switch (type) {
|
||||
case HAP_SIGN_BLOB: {
|
||||
if (signInfo.hapSignatureBlock.GetCapacity() != 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "find more than one hap sign block");
|
||||
break;
|
||||
}
|
||||
signInfo.hapSignatureBlock = subBlock;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
case PROFILE_BLOB:
|
||||
case PROOF_ROTATION_BLOB:
|
||||
case PROPERTY_BLOB: {
|
||||
OptionalBlock optionalBlock;
|
||||
optionalBlock.optionalType = type;
|
||||
optionalBlock.optionalBlockValue = subBlock;
|
||||
signInfo.optionBlocks.push_back(optionalBlock);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::GetOptionalBlockIndex(std::vector<OptionalBlock>& optionBlocks, int type, int& index)
|
||||
{
|
||||
int len = static_cast<int>(optionBlocks.size());
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (optionBlocks[i].optionalType == type) {
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::VerifyHapIntegrity(
|
||||
Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo)
|
||||
{
|
||||
if (!SetUnsignedInt32(signInfo.hapEocd, ZIP_CD_OFFSET_IN_EOCD, signInfo.hapSigningBlockOffset)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Set central dir offset failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
long long centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset;
|
||||
HapFileDataSource contentsZip(hapFile, 0, signInfo.hapSigningBlockOffset, 0);
|
||||
HapFileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0);
|
||||
HapByteBufferDataSource eocd(signInfo.hapEocd);
|
||||
DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = { &contentsZip, ¢ralDir, &eocd };
|
||||
int nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(digestInfo.digestAlgorithm);
|
||||
DigestParameter digestParam = GetDigestParameter(nId);
|
||||
HapByteBuffer chunkDigest;
|
||||
if (!ComputeDigestsForEachChunk(digestParam, content, ZIP_BLOCKS_NUM_NEED_DIGEST, chunkDigest)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Compute Content Digests failed, alg: %{public}d", nId);
|
||||
return false;
|
||||
}
|
||||
|
||||
HapByteBuffer actualDigest;
|
||||
if (!ComputeDigestsWithOptionalBlock(digestParam, signInfo.optionBlocks, chunkDigest, actualDigest)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Compute Final Digests failed, alg: %{public}d", nId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!digestInfo.content.IsEqual(actualDigest)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "digest of contents verify failed, alg %{public}d", nId);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam,
|
||||
const std::vector<OptionalBlock>& optionalBlocks, const HapByteBuffer& chunkDigest, HapByteBuffer& finalDigest)
|
||||
{
|
||||
unsigned char out[EVP_MAX_MD_SIZE];
|
||||
int digestLen = HapVerifyOpensslUtils::GetDigest(chunkDigest, optionalBlocks, digestParam, out);
|
||||
if (digestLen != digestParam.digestOutputSizeBytes) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetDigest failed, outLen is not right, %{public}u, %{public}d",
|
||||
digestLen, digestParam.digestOutputSizeBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
finalDigest.SetCapacity(digestParam.digestOutputSizeBytes);
|
||||
finalDigest.PutData(0, reinterpret_cast<char*>(out), digestParam.digestOutputSizeBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int len,
|
||||
int chunkDigestLen, int& chunkCount, int& sumOfChunkDigestLen)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (contents[i] == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "contents[%{public}d] is nullptr", i);
|
||||
return false;
|
||||
}
|
||||
contents[i]->Reset();
|
||||
chunkCount += GetChunkCount(contents[i]->Remaining(), CHUNK_SIZE);
|
||||
}
|
||||
|
||||
if (chunkCount <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no content for digest");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chunkDigestLen < 0 || ((INT_MAX - ZIP_CHUNK_DIGEST_PRIFIX_LEN) / chunkCount) < chunkDigestLen) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "overflow chunkCount: %{public}d, chunkDigestLen: %{public}d",
|
||||
chunkCount, chunkDigestLen);
|
||||
return false;
|
||||
}
|
||||
|
||||
sumOfChunkDigestLen = ZIP_CHUNK_DIGEST_PRIFIX_LEN + chunkCount * chunkDigestLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam,
|
||||
DataSource* contents[], int len, HapByteBuffer& result)
|
||||
{
|
||||
int chunkCount = 0;
|
||||
int sumOfChunksLen = 0;
|
||||
if (!GetSumOfChunkDigestLen(contents, len, digestParam.digestOutputSizeBytes, chunkCount, sumOfChunksLen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetSumOfChunkDigestLen failed");
|
||||
return false;
|
||||
}
|
||||
result.SetCapacity(sumOfChunksLen);
|
||||
result.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX);
|
||||
result.PutInt32(1, chunkCount);
|
||||
|
||||
int chunkIndex = 0;
|
||||
unsigned char out[EVP_MAX_MD_SIZE];
|
||||
unsigned char chunkContentPrefix[ZIP_CHUNK_DIGEST_PRIFIX_LEN] = {ZIP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
|
||||
int offset = ZIP_CHUNK_DIGEST_PRIFIX_LEN;
|
||||
for (int i = 0; i < len; i++) {
|
||||
while (contents[i]->HasRemaining()) {
|
||||
int chunkSize = std::min(contents[i]->Remaining(), CHUNK_SIZE);
|
||||
if (!InitDigestPrefix(digestParam, chunkContentPrefix, chunkSize)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "InitDigestPrefix failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!contents[i]->ReadDataAndDigestUpdate(digestParam, chunkSize)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Copy Partial Buffer failed, count: %{public}d", chunkIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
int digestLen = HapVerifyOpensslUtils::GetDigest(digestParam, out);
|
||||
if (digestLen != digestParam.digestOutputSizeBytes) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetDigest failed len: %{public}d digestSizeBytes: %{public}d",
|
||||
digestLen, digestParam.digestOutputSizeBytes);
|
||||
return false;
|
||||
}
|
||||
result.PutData(offset, reinterpret_cast<char*>(out), digestParam.digestOutputSizeBytes);
|
||||
offset += digestLen;
|
||||
chunkIndex++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DigestParameter HapSigningBlockUtils::GetDigestParameter(int nId)
|
||||
{
|
||||
DigestParameter digestParam;
|
||||
digestParam.digestOutputSizeBytes = HapVerifyOpensslUtils::GetDigestAlgorithmOutputSizeBytes(nId);
|
||||
digestParam.md = EVP_get_digestbynid(nId);
|
||||
digestParam.ptrCtx = EVP_MD_CTX_create();
|
||||
EVP_MD_CTX_init(digestParam.ptrCtx);
|
||||
return digestParam;
|
||||
}
|
||||
|
||||
int HapSigningBlockUtils::GetChunkCount(long long inputSize, long long chunkSize)
|
||||
{
|
||||
if (chunkSize <= 0 || inputSize > LLONG_MAX - chunkSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long res = (inputSize + chunkSize - 1) / chunkSize;
|
||||
if (res > INT_MAX || res < 0) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int>(res);
|
||||
}
|
||||
|
||||
bool HapSigningBlockUtils::InitDigestPrefix(const DigestParameter& digestParam,
|
||||
unsigned char (&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN], int chunkLen)
|
||||
{
|
||||
if (memcpy_s((chunkContentPrefix + 1), ZIP_CHUNK_DIGEST_PRIFIX_LEN - 1, (&chunkLen), sizeof(chunkLen)) != EOK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "memcpy_s failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HapVerifyOpensslUtils::DigestInit(digestParam)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "DigestInit failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HapVerifyOpensslUtils::DigestUpdate(digestParam, chunkContentPrefix, ZIP_CHUNK_DIGEST_PRIFIX_LEN)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "DigestUpdate failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
@ -0,0 +1,651 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/pem.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
using Pkcs7SignerInfoStack = STACK_OF(PKCS7_SIGNER_INFO);
|
||||
using X509AttributeStack = STACK_OF(X509_ATTRIBUTE);
|
||||
|
||||
const int HapVerifyOpensslUtils::OPENSSL_PKCS7_VERIFY_SUCCESS = 1;
|
||||
const int HapVerifyOpensslUtils::OPENSSL_ERR_MESSAGE_MAX_LEN = 1024;
|
||||
|
||||
/*
|
||||
* OPENSSL_READ_DATA_MAX_TIME * OPENSSL_READ_DATA_LEN_EACH_TIME < 2GBytes.
|
||||
* make the maximum size of data that can be read each time be 1 KBytes,
|
||||
* so the maximum times of read data is 1024 * 1024 * 2 = 2097152;
|
||||
*/
|
||||
const int HapVerifyOpensslUtils::OPENSSL_READ_DATA_MAX_TIME = 2097152;
|
||||
const int HapVerifyOpensslUtils::OPENSSL_READ_DATA_LEN_EACH_TIME = 1024;
|
||||
|
||||
/* Signature algorithm OID for extended PKCS7 */
|
||||
const std::string HapVerifyOpensslUtils::PKCS7_EXT_SHAWITHRSA_PSS = "1.2.840.113549.1.1.10";
|
||||
const int HapVerifyOpensslUtils::MAX_OID_LENGTH = 128;
|
||||
|
||||
bool HapVerifyOpensslUtils::ParsePkcs7Package(const unsigned char packageData[],
|
||||
unsigned int packageLen, Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (packageData == nullptr || packageLen == 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
|
||||
return false;
|
||||
}
|
||||
|
||||
pkcs7Context.p7 = d2i_PKCS7(nullptr, &packageData, packageLen);
|
||||
if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "p7 is invalid");
|
||||
return false;
|
||||
}
|
||||
if (!GetContentInfo(pkcs7Context.p7->d.sign->contents, pkcs7Context.content)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get content from pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (!CheckPkcs7SignedDataIsValid(p7)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "p7 is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
CertSign certVisitSign;
|
||||
HapCertVerifyOpensslUtils::GenerateCertSignFromCertStack(p7->d.sign->cert, certVisitSign);
|
||||
|
||||
Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(p7);
|
||||
if (signerInfoStack == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get signerInfoStack error");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
int signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
|
||||
if (signCount <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "can not find signinfo");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < signCount; i++) {
|
||||
/* get ith signInfo */
|
||||
PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, i);
|
||||
if (signInfo == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signInfo %{public}dst is nullptr", i);
|
||||
return false;
|
||||
}
|
||||
/* GET X509 certificate */
|
||||
X509* cert = PKCS7_cert_from_signer_info(p7, signInfo);
|
||||
if (cert == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get cert for %{public}dst signInfo failed", i);
|
||||
return false;
|
||||
}
|
||||
CertChain certChain;
|
||||
pkcs7Context.certChains.push_back(certChain);
|
||||
pkcs7Context.certChains[i].push_back(X509_dup(cert));
|
||||
HapCertVerifyOpensslUtils::ClearCertVisitSign(certVisitSign);
|
||||
certVisitSign[cert] = true;
|
||||
if (!VerifyCertChain(pkcs7Context.certChains[i], p7, signInfo, pkcs7Context, certVisitSign)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "verify %{public}dst certchain failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyCertChain(CertChain& certsChain, PKCS7* p7,
|
||||
PKCS7_SIGNER_INFO* signInfo, Pkcs7Context& pkcs7Context, CertSign& certVisitSign)
|
||||
{
|
||||
if (!HapCertVerifyOpensslUtils::GetCertsChain(certsChain, certVisitSign)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get cert chain for signInfo failed");
|
||||
return false;
|
||||
}
|
||||
ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signInfo, NID_pkcs9_signingTime);
|
||||
if (!HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, signTime)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyCertChainPeriodOfValidity for signInfo failed");
|
||||
return false;
|
||||
}
|
||||
if (!HapCertVerifyOpensslUtils::VerifyCrl(certsChain, p7->d.sign->crl, pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyCrl for signInfo failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::CheckPkcs7SignedDataIsValid(const PKCS7* p7)
|
||||
{
|
||||
if (p7 == nullptr || !PKCS7_type_is_signed(p7) || p7->d.sign == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyPkcs7(Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "p7 type is invalid signed_data_pkcs7");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VerifyPkcs7SignedData(pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "verify p7 error");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context)
|
||||
{
|
||||
/* get signed data which was used to be signed */
|
||||
BIO* p7Bio = PKCS7_dataDecode(pkcs7Context.p7, nullptr, nullptr, nullptr);
|
||||
if (p7Bio == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get p7bio error");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
char buf[OPENSSL_READ_DATA_LEN_EACH_TIME];
|
||||
int readLen = BIO_read(p7Bio, buf, sizeof(buf));
|
||||
int readTime = 0;
|
||||
while ((readLen > 0) && (++readTime < OPENSSL_READ_DATA_MAX_TIME)) {
|
||||
readLen = BIO_read(p7Bio, buf, sizeof(buf));
|
||||
}
|
||||
Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(pkcs7Context.p7);
|
||||
if (signerInfoStack == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get signerInfoStack error");
|
||||
BIO_free_all(p7Bio);
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
/* get the num of signInfo */
|
||||
int signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
|
||||
if (signCount <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "can not find signinfo");
|
||||
BIO_free_all(p7Bio);
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < signCount; i++) {
|
||||
if (!VerifySignInfo(signerInfoStack, p7Bio, i, pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Verify %{public}dst signInfo failed", i);
|
||||
BIO_free_all(p7Bio);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BIO_free_all(p7Bio);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifySignInfo(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack,
|
||||
BIO* p7Bio, int signInfoNum, Pkcs7Context& pkcs7Context) {
|
||||
if (signerInfoStack == nullptr || p7Bio == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "invalid input");
|
||||
return false;
|
||||
}
|
||||
/* get signInfo */
|
||||
PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, signInfoNum);
|
||||
if (signInfo == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signInfo %{public}dst is nullptr", signInfoNum);
|
||||
return false;
|
||||
}
|
||||
/* GET X509 certificate */
|
||||
X509* cert = pkcs7Context.certChains[signInfoNum][0];
|
||||
bool isShaWithRsaPss = IsEnablePss(signInfo);
|
||||
if (isShaWithRsaPss) {
|
||||
EVP_PKEY* pkey = X509_get0_pubkey(cert);
|
||||
if (pkey == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signInfo %{public}dst X509_get_pubkey failed", signInfoNum);
|
||||
return false;
|
||||
}
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "use RSA/pss");
|
||||
if (!VerifyShaWithRsaPss(signInfo, p7Bio, pkey, isShaWithRsaPss)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyShaWithRsaPss %{public}dst signInfo failed", signInfoNum);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (PKCS7_signatureVerify(p7Bio, pkcs7Context.p7, signInfo, cert) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "PKCS7_signatureVerify %{public}dst signInfo failed", signInfoNum);
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::IsEnablePss(const PKCS7_SIGNER_INFO* signInfo)
|
||||
{
|
||||
char oId[MAX_OID_LENGTH];
|
||||
if (signInfo->digest_enc_alg == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signInfo->digest_enc_alg is nullptr");
|
||||
return false;
|
||||
}
|
||||
int len = OBJ_obj2txt(oId, sizeof(oId), signInfo->digest_enc_alg->algorithm, 1);
|
||||
if (len < 0 || len > MAX_OID_LENGTH) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get length of oId failed");
|
||||
return false;
|
||||
}
|
||||
return PKCS7_EXT_SHAWITHRSA_PSS.compare(0, PKCS7_EXT_SHAWITHRSA_PSS.size(), oId, len) == 0;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo,
|
||||
BIO* p7Bio, EVP_PKEY* pkey, bool isPss)
|
||||
{
|
||||
if (signInfo->digest_alg == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signInfo->digest_alg is nullptr");
|
||||
return false;
|
||||
}
|
||||
int mdType = OBJ_obj2nid(signInfo->digest_alg->algorithm);
|
||||
const EVP_MD_CTX* mdCtx = FindMdCtxInBio(p7Bio, mdType);
|
||||
EVP_MD_CTX* mdCtxTmp = EVP_MD_CTX_new();
|
||||
if (mdCtxTmp == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_MD_CTX_new failed");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_MD_CTX_copy_ex(mdCtxTmp, mdCtx)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_MD_CTX_copy_ex failed");
|
||||
EVP_MD_CTX_free(mdCtxTmp);
|
||||
return false;
|
||||
}
|
||||
if (!VerifyPkcs7AuthAttributes(signInfo, mdCtxTmp, mdType)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyPkcs7AuthAttributes failed");
|
||||
EVP_MD_CTX_free(mdCtxTmp);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int digestLen;
|
||||
if (EVP_DigestFinal_ex(mdCtxTmp, digest, &digestLen) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Digest content failed");
|
||||
GetOpensslErrorMessage();
|
||||
EVP_MD_CTX_free(mdCtxTmp);
|
||||
return false;
|
||||
}
|
||||
EVP_MD_CTX_free(mdCtxTmp);
|
||||
|
||||
if (!VerifyShaWithRsaPss(signInfo, pkey, isPss, digest, digestLen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyShaWithRsaPss failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const EVP_MD_CTX* HapVerifyOpensslUtils::FindMdCtxInBio(BIO* p7Bio, int mdType)
|
||||
{
|
||||
EVP_MD_CTX* mdCtx = nullptr;
|
||||
while (p7Bio) {
|
||||
BIO_get_md_ctx(p7Bio, &mdCtx);
|
||||
if (mdCtx == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get null from bio");
|
||||
return nullptr;
|
||||
}
|
||||
if ((EVP_MD_CTX_type(mdCtx) == mdType) || (EVP_MD_pkey_type(EVP_MD_CTX_md(mdCtx)) == mdType)) {
|
||||
break;
|
||||
}
|
||||
p7Bio = BIO_next(p7Bio);
|
||||
}
|
||||
return mdCtx;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyPkcs7AuthAttributes(const PKCS7_SIGNER_INFO* signInfo, EVP_MD_CTX* mdCtx, int mdType)
|
||||
{
|
||||
X509AttributeStack* authAttributes = signInfo->auth_attr;
|
||||
if ((authAttributes != nullptr) && (sk_X509_ATTRIBUTE_num(authAttributes) != 0)) {
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int digestLen;
|
||||
if (EVP_DigestFinal_ex(mdCtx, digest, &digestLen) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Digest content failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
ASN1_OCTET_STRING* digestInAttribute = PKCS7_digest_from_attributes(authAttributes);
|
||||
if (!AsnStringCmp(digestInAttribute, digest, static_cast<int>(digestLen))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "AsnStringCmp failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EVP_VerifyInit_ex(mdCtx, EVP_get_digestbynid(mdType), nullptr)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_VerifyInit_ex failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char* attributesData = nullptr;
|
||||
int attributesLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE*>(authAttributes), &attributesData,
|
||||
ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
|
||||
if (attributesLen <= 0 || attributesData == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ASN1_item_i2d failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
if (!EVP_VerifyUpdate(mdCtx, attributesData, attributesLen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_VerifyUpdate failed");
|
||||
GetOpensslErrorMessage();
|
||||
OPENSSL_free(attributesData);
|
||||
return false;
|
||||
}
|
||||
OPENSSL_free(attributesData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::AsnStringCmp(const ASN1_OCTET_STRING* asnStr, const unsigned char data[], int len)
|
||||
{
|
||||
if (asnStr == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "asnStr is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (asnStr->data == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "asnStr->data is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "data is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (asnStr->length != len) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "asnStr->length: %{public}d is not equal to len: %{public}d", asnStr->length, len);
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (asnStr->data[i] != data[i]) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "%{public}dst data is not equal", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo, EVP_PKEY* pkey, bool isPss,
|
||||
const unsigned char digest[], unsigned int digestLen)
|
||||
{
|
||||
EVP_PKEY_CTX* pkeyCtx = EVP_PKEY_CTX_new(pkey, nullptr);
|
||||
if (pkeyCtx == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_PKEY_CTX_new failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_PKEY_verify_init failed");
|
||||
GetOpensslErrorMessage();
|
||||
EVP_PKEY_CTX_free(pkeyCtx);
|
||||
return false;
|
||||
}
|
||||
if (signInfo->digest_alg == nullptr || signInfo->enc_digest == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "no digest_alg or enc_digest in signInfo");
|
||||
EVP_PKEY_CTX_free(pkeyCtx);
|
||||
return false;
|
||||
}
|
||||
int mdType = OBJ_obj2nid(signInfo->digest_alg->algorithm);
|
||||
if ((isPss && EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, RSA_PKCS1_PSS_PADDING) <= 0) ||
|
||||
(EVP_PKEY_CTX_set_signature_md(pkeyCtx, EVP_get_digestbynid(mdType)) <= 0)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "set rsa_padding or signature_md failed");
|
||||
GetOpensslErrorMessage();
|
||||
EVP_PKEY_CTX_free(pkeyCtx);
|
||||
return false;
|
||||
}
|
||||
if (EVP_PKEY_verify(pkeyCtx, signInfo->enc_digest->data, signInfo->enc_digest->length, digest, digestLen) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_PKEY_verify failed");
|
||||
GetOpensslErrorMessage();
|
||||
EVP_PKEY_CTX_free(pkeyCtx);
|
||||
return false;
|
||||
}
|
||||
EVP_PKEY_CTX_free(pkeyCtx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetPublickeys(const CertChain& signCertChain,
|
||||
std::vector<std::string>& SignatureVec)
|
||||
{
|
||||
for (unsigned int i = 0; i < signCertChain.size(); i++) {
|
||||
if (!GetPublickeyFromCertificate(signCertChain[i], SignatureVec)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "%{public}ust Get Publickey failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !SignatureVec.empty();
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetSignatures(const CertChain& signCertChain,
|
||||
std::vector<std::string>& SignatureVec)
|
||||
{
|
||||
for (unsigned int i = 0; i < signCertChain.size(); i++) {
|
||||
if (!GetDerCert(signCertChain[i], SignatureVec)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "%{public}ust GetDerCert failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !SignatureVec.empty();
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetDerCert(X509* ptrX509, std::vector<std::string>& SignatureVec)
|
||||
{
|
||||
if (ptrX509 == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int certLen = i2d_X509(ptrX509, nullptr);
|
||||
if (certLen <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "certLen %{public}d, i2d_X509 failed", certLen);
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<unsigned char[]> derCertificate = std::make_unique<unsigned char[]>(certLen);
|
||||
int base64CertLen = HapCertVerifyOpensslUtils::CalculateLenAfterBase64Encode(certLen);
|
||||
std::unique_ptr<unsigned char[]> base64Certificate = std::make_unique<unsigned char[]>(base64CertLen);
|
||||
if (derCertificate == nullptr || base64Certificate == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "make_unique failed");
|
||||
return false;
|
||||
}
|
||||
unsigned char* derCertificateBackup = derCertificate.get();
|
||||
if (i2d_X509(ptrX509, &derCertificateBackup) <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "i2d_X509 failed");
|
||||
GetOpensslErrorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* base64 encode */
|
||||
int len = EVP_EncodeBlock(base64Certificate.get(), derCertificate.get(), certLen);
|
||||
SignatureVec.emplace_back(std::string(reinterpret_cast<char*>(base64Certificate.get()), len));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetPublickeyFromCertificate(const X509* ptrX509, std::vector<std::string>& publicKeyVec)
|
||||
{
|
||||
if (ptrX509 == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string publicKey;
|
||||
if (!HapCertVerifyOpensslUtils::GetPublickeyBase64(ptrX509, publicKey)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetPublickeyBase64 Failed");
|
||||
return false;
|
||||
}
|
||||
publicKeyVec.emplace_back(publicKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::GetContentInfo(const PKCS7* p7ContentInfo, HapByteBuffer& content)
|
||||
{
|
||||
if ((p7ContentInfo == nullptr) || !PKCS7_type_is_data(p7ContentInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "p7ContentInfo is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1_OCTET_STRING* strContentInfo = p7ContentInfo->d.data;
|
||||
if (strContentInfo == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "strContentInfo is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
int strContentInfoLen = strContentInfo->length;
|
||||
unsigned char* strContentInfoData = strContentInfo->data;
|
||||
if (strContentInfoData == nullptr || strContentInfoLen <= 0) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ASN1_OCTET_STRING is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
content.SetCapacity(strContentInfoLen);
|
||||
content.PutData(0, reinterpret_cast<char*>(strContentInfoData), strContentInfoLen);
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "strContentInfoLen: %{public}d", strContentInfoLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
int HapVerifyOpensslUtils::GetDigestAlgorithmOutputSizeBytes(int nId)
|
||||
{
|
||||
return EVP_MD_size(EVP_get_digestbynid(nId));
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::CheckDigestParameter(const DigestParameter& digestParameter)
|
||||
{
|
||||
if (digestParameter.md == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "md is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (digestParameter.ptrCtx == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ptrCtx is nullptr");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyOpensslUtils::DigestInit(const DigestParameter& digestParameter)
|
||||
{
|
||||
if (!CheckDigestParameter(digestParameter)) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_DigestInit(digestParameter.ptrCtx, digestParameter.md) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestInit failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* the caller must ensure that EVP_DigestInit was called before calling this function */
|
||||
bool HapVerifyOpensslUtils::DigestUpdate(const DigestParameter& digestParameter,
|
||||
const unsigned char content[], int len)
|
||||
{
|
||||
if (content == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "content is nullptr");
|
||||
return false;
|
||||
}
|
||||
if (!CheckDigestParameter(digestParameter)) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_DigestUpdate(digestParameter.ptrCtx, content, len) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestUpdate chunk failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int HapVerifyOpensslUtils::GetDigest(const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE])
|
||||
{
|
||||
unsigned int outLen = 0;
|
||||
if (!CheckDigestParameter(digestParameter)) {
|
||||
return outLen;
|
||||
}
|
||||
if (EVP_DigestFinal(digestParameter.ptrCtx, out, &outLen) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestFinal failed");
|
||||
outLen = 0;
|
||||
}
|
||||
return outLen;
|
||||
}
|
||||
|
||||
int HapVerifyOpensslUtils::GetDigest(const HapByteBuffer& chunk, const std::vector<OptionalBlock>& optionalBlocks,
|
||||
const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE])
|
||||
{
|
||||
int chunkLen = chunk.Remaining();
|
||||
unsigned int outLen = 0;
|
||||
if (digestParameter.md == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "md is nullprt");
|
||||
return outLen;
|
||||
}
|
||||
if (digestParameter.ptrCtx == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "ptrCtx is nullprt");
|
||||
return outLen;
|
||||
}
|
||||
|
||||
if (EVP_DigestInit(digestParameter.ptrCtx, digestParameter.md) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestInit failed");
|
||||
return outLen;
|
||||
}
|
||||
|
||||
if (EVP_DigestUpdate(digestParameter.ptrCtx, chunk.GetBufferPtr(), chunkLen) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestUpdate chunk failed");
|
||||
return outLen;
|
||||
}
|
||||
for (int i = 0; i < static_cast<int>(optionalBlocks.size()); i++) {
|
||||
chunkLen = optionalBlocks[i].optionalBlockValue.GetCapacity();
|
||||
if (EVP_DigestUpdate(digestParameter.ptrCtx, optionalBlocks[i].optionalBlockValue.GetBufferPtr(),
|
||||
chunkLen) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestUpdate %{public}dst optional block failed", i);
|
||||
return outLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_DigestFinal(digestParameter.ptrCtx, out, &outLen) <= 0) {
|
||||
GetOpensslErrorMessage();
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "EVP_DigestFinal failed");
|
||||
outLen = 0;
|
||||
}
|
||||
return outLen;
|
||||
}
|
||||
|
||||
void HapVerifyOpensslUtils::GetOpensslErrorMessage()
|
||||
{
|
||||
unsigned long retOpenssl;
|
||||
char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
|
||||
while ((retOpenssl = ERR_get_error()) != 0) {
|
||||
ERR_error_string(retOpenssl, errOpenssl);
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "openssl err: %{public}lu, message: %{public}s", retOpenssl, errOpenssl);
|
||||
}
|
||||
}
|
||||
|
||||
int HapVerifyOpensslUtils::GetDigestAlgorithmId(int signAlgorithm)
|
||||
{
|
||||
switch (signAlgorithm) {
|
||||
case ALGORITHM_SHA256_WITH_RSA_PSS:
|
||||
case ALGORITHM_SHA256_WITH_RSA_PKCS1_V1_5:
|
||||
case ALGORITHM_SHA256_WITH_ECDSA:
|
||||
case ALGORITHM_SHA256_WITH_DSA:
|
||||
return NID_sha256;
|
||||
case ALGORITHM_SHA384_WITH_RSA_PSS:
|
||||
case ALGORITHM_SHA384_WITH_RSA_PKCS1_V1_5:
|
||||
case ALGORITHM_SHA384_WITH_ECDSA:
|
||||
case ALGORITHM_SHA384_WITH_DSA:
|
||||
return NID_sha384;
|
||||
case ALGORITHM_SHA512_WITH_RSA_PSS:
|
||||
case ALGORITHM_SHA512_WITH_RSA_PKCS1_V1_5:
|
||||
case ALGORITHM_SHA512_WITH_ECDSA:
|
||||
case ALGORITHM_SHA512_WITH_DSA:
|
||||
return NID_sha512;
|
||||
default:
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "signAlgorithm: %{public}d error", signAlgorithm);
|
||||
return NID_undef;
|
||||
}
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
337
interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp
Normal file
337
interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "verify/hap_verify_v2.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <regex>
|
||||
|
||||
#include "securec.h"
|
||||
|
||||
#include "common/hap_verify_log.h"
|
||||
#include "init/hap_crl_manager.h"
|
||||
#include "init/trusted_source_manager.h"
|
||||
#include "util/hap_profile_verify_utils.h"
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
#include "util/signature_info.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const int HapVerifyV2::HEX_PRINT_LENGTH = 3;
|
||||
const int HapVerifyV2::DIGEST_BLOCK_LEN_OFFSET = 8;
|
||||
const int HapVerifyV2::DIGEST_ALGORITHM_OFFSET = 12;
|
||||
const int HapVerifyV2::DIGEST_LEN_OFFSET = 16;
|
||||
const int HapVerifyV2::DIGEST_OFFSET_IN_CONTENT = 20;
|
||||
const std::string HapVerifyV2::HAP_APP_PATTERN = "[^]*.hap$";
|
||||
|
||||
int HapVerifyV2::Verify(const std::string& filePath, HapVerifyResult& hapVerifyV1Result)
|
||||
{
|
||||
std::string standardFilePath;
|
||||
if (!CheckFilePath(filePath, standardFilePath)) {
|
||||
return FILE_PATH_INVALID;
|
||||
}
|
||||
|
||||
RandomAccessFile hapFile;
|
||||
if (!hapFile.Init(standardFilePath)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "open %{public}s failed", standardFilePath.c_str());
|
||||
return OPEN_FILE_ERROR;
|
||||
}
|
||||
|
||||
int resultCode = Verify(hapFile, hapVerifyV1Result);
|
||||
HAPVERIFY_LOG_INFO(LABEL, "Hap verify %{public}s, result: %{public}d", standardFilePath.c_str(), resultCode);
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::CheckFilePath(const std::string& filePath, std::string& standardFilePath)
|
||||
{
|
||||
char path[PATH_MAX + 1] = { 0x00 };
|
||||
if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "It is not a standard path, %{public}s", filePath.c_str());
|
||||
return false;
|
||||
}
|
||||
standardFilePath = std::string(path);
|
||||
if (!std::regex_match(standardFilePath, std::regex(HAP_APP_PATTERN))) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "file is not hap package, %{public}s", standardFilePath.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int HapVerifyV2::Verify(RandomAccessFile& hapFile, HapVerifyResult& hapVerifyV1Result)
|
||||
{
|
||||
SignatureInfo hapSignInfo;
|
||||
if (!HapSigningBlockUtils::FindHapSignature(hapFile, hapSignInfo)) {
|
||||
return SIGNATURE_NOT_FOUND;
|
||||
}
|
||||
hapVerifyV1Result.SetVersion(hapSignInfo.version);
|
||||
hapVerifyV1Result.SetPkcs7SignBlock(hapSignInfo.hapSignatureBlock);
|
||||
hapVerifyV1Result.SetPkcs7ProfileBlock(hapSignInfo.hapSignatureBlock);
|
||||
hapVerifyV1Result.SetOptionalBlocks(hapSignInfo.optionBlocks);
|
||||
Pkcs7Context pkcs7Context;
|
||||
if (!VerifyAppPkcs7(pkcs7Context, hapSignInfo.hapSignatureBlock)) {
|
||||
return VERIFY_APP_PKCS7_FAIL;
|
||||
}
|
||||
int profileIndex = 0;
|
||||
if (!HapSigningBlockUtils::GetOptionalBlockIndex(hapSignInfo.optionBlocks, PROFILE_BLOB, profileIndex)) {
|
||||
return NO_PROFILE_BLOCK_FAIL;
|
||||
}
|
||||
bool profileNeedWriteCrl = false;
|
||||
if (!VerifyAppSourceAndParseProfile(pkcs7Context, hapSignInfo.optionBlocks[profileIndex].optionalBlockValue,
|
||||
hapVerifyV1Result, profileNeedWriteCrl)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "APP source is not trusted");
|
||||
return APP_SOURCE_NOT_TRUSTED;
|
||||
}
|
||||
if (!GetDigestAndAlgorithm(pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get digest failed");
|
||||
return GET_DIGEST_FAIL;
|
||||
}
|
||||
std::vector<std::string> publicKeys;
|
||||
if (!HapVerifyOpensslUtils::GetPublickeys(pkcs7Context.certChains[0], publicKeys)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get publicKeys failed");
|
||||
return GET_PUBLICKEY_FAIL;
|
||||
}
|
||||
hapVerifyV1Result.SetPublicKey(publicKeys);
|
||||
std::vector<std::string> certSignatures;
|
||||
if (!HapVerifyOpensslUtils::GetSignatures(pkcs7Context.certChains[0], certSignatures)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get sianatures failed");
|
||||
return GET_SIGNATURE_FAIL;
|
||||
}
|
||||
hapVerifyV1Result.SetSignature(certSignatures);
|
||||
if (!HapSigningBlockUtils::VerifyHapIntegrity(pkcs7Context, hapFile, hapSignInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Verify Integrity failed");
|
||||
return VERIFY_INTEGRITY_FAIL;
|
||||
}
|
||||
WriteCrlIfNeed(pkcs7Context, profileNeedWriteCrl);
|
||||
return VERIFY_SUCCESS;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::VerifyAppPkcs7(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapSignatureBlock)
|
||||
{
|
||||
const unsigned char* pkcs7Block = reinterpret_cast<const unsigned char*>(hapSignatureBlock.GetBufferPtr());
|
||||
unsigned int pkcs7Len = hapSignatureBlock.GetCapacity();
|
||||
if (!HapVerifyOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "parse pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
if (!HapVerifyOpensslUtils::GetCertChains(pkcs7Context.p7, pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GetCertChains from pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
if (!HapVerifyOpensslUtils::VerifyPkcs7(pkcs7Context)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "verify signature failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::VerifyAppSourceAndParseProfile(Pkcs7Context& pkcs7Context,
|
||||
const HapByteBuffer& hapProfileBlock, HapVerifyResult& hapVerifyV1Result, bool& profileNeadWriteCrl)
|
||||
{
|
||||
std::string certSubject;
|
||||
if (!HapCertVerifyOpensslUtils::GetSubjectFromX509(pkcs7Context.certChains[0][0], certSubject)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Get info of sign cert failed");
|
||||
return false;
|
||||
}
|
||||
HAPVERIFY_LOG_INFO(LABEL, "App signature subject: %{public}s, issuer: %{public}s",
|
||||
certSubject.c_str(), pkcs7Context.certIssuer.c_str());
|
||||
|
||||
TrustedSourceManager& trustedSourceManager = TrustedSourceManager::GetInstance();
|
||||
pkcs7Context.matchResult = trustedSourceManager.IsTrustedSource(certSubject, pkcs7Context.certIssuer,
|
||||
HAP_SIGN_BLOB, pkcs7Context.certChains[0].size());
|
||||
|
||||
Pkcs7Context profileContext;
|
||||
std::string profile;
|
||||
if (!HapProfileVerifyUtils::ParseProfile(profileContext, pkcs7Context, hapProfileBlock, profile)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "Parse profile pkcs7 failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If app source is not trusted, verify profile.
|
||||
* If profile is debug, check whether app signed cert is same as the debug cert in profile.
|
||||
* If profile is release, do not allow installation of this app.
|
||||
*/
|
||||
bool isCallParseAndVerify = false;
|
||||
ProvisionInfo provisionInfo;
|
||||
if (pkcs7Context.matchResult.matchState == DO_NOT_MATCH) {
|
||||
if (!HapProfileVerifyUtils::VerifyProfile(profileContext)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "profile verify failed");
|
||||
return false;
|
||||
}
|
||||
AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo);
|
||||
if (profileRet != PROVISION_OK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "profile parsing failed, error: %{public}d", static_cast<int>(profileRet));
|
||||
return false;
|
||||
}
|
||||
if (!VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "VerifyProfileInfo failed");
|
||||
return false;
|
||||
}
|
||||
isCallParseAndVerify = true;
|
||||
}
|
||||
|
||||
if (!ParseAndVerifyProfileIfNeed(profile, provisionInfo, isCallParseAndVerify)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GenerateAppId(provisionInfo)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "GenerateAppId failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
hapVerifyV1Result.SetProvisionInfo(provisionInfo);
|
||||
profileNeadWriteCrl = profileContext.needWriteCrl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::GenerateAppId(ProvisionInfo& provisionInfo)
|
||||
{
|
||||
std::string& certInProfile = provisionInfo.bundleInfo.distributionCertificate;
|
||||
if (provisionInfo.bundleInfo.distributionCertificate.empty()) {
|
||||
certInProfile = provisionInfo.bundleInfo.developmentCertificate;
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "use development Certificate");
|
||||
}
|
||||
std::string publicKey;
|
||||
if (!HapCertVerifyOpensslUtils::GetPublickeyBase64FromPemCert(certInProfile, publicKey)) {
|
||||
return false;
|
||||
}
|
||||
provisionInfo.appId = publicKey;
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "provisionInfo.appId: %{public}s", provisionInfo.appId.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs7Context& profileContext,
|
||||
ProvisionInfo& provisionInfo)
|
||||
{
|
||||
if (!CheckProfileSignatureIsRight(profileContext.matchResult.matchState, provisionInfo.type)) {
|
||||
return false;
|
||||
}
|
||||
std::string& certInProfile = provisionInfo.bundleInfo.developmentCertificate;
|
||||
if (provisionInfo.type == ProvisionType::RELEASE) {
|
||||
if (!IsAppDistributedTypeAllowInstall(provisionInfo.distributionType)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "untrusted source app with release profile distributionType: %{public}d",
|
||||
static_cast<int>(provisionInfo.distributionType));
|
||||
return false;
|
||||
}
|
||||
certInProfile = provisionInfo.bundleInfo.distributionCertificate;
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "allow install app with release profile distributionType: %{public}d",
|
||||
static_cast<int>(provisionInfo.distributionType));
|
||||
}
|
||||
HAPVERIFY_LOG_DEBUG(LABEL, "provisionInfo.type: %{public}d", static_cast<int>(provisionInfo.type));
|
||||
if (!HapCertVerifyOpensslUtils::CompareX509Cert(pkcs7Context.certChains[0][0], certInProfile)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "developed cert is not same as signed cert");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::IsAppDistributedTypeAllowInstall(const AppDistType& type) const
|
||||
{
|
||||
switch (type) {
|
||||
case AppDistType::NONE_TYPE:
|
||||
case AppDistType::APP_GALLERY:
|
||||
return false;
|
||||
case AppDistType::ENTERPRISE:
|
||||
case AppDistType::OS_INTEGRATION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool HapVerifyV2::CheckProfileSignatureIsRight(const MatchingStates& matchState, const ProvisionType& type)
|
||||
{
|
||||
if (matchState == MATCH_WITH_PROFILE && type == ProvisionType::RELEASE) {
|
||||
return true;
|
||||
} else if (matchState == MATCH_WITH_PROFILE_DEBUG && type == ProvisionType::DEBUG) {
|
||||
return true;
|
||||
}
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "isTrustedSource: %{public}d is not match with profile type: %{public}d",
|
||||
static_cast<int>(matchState), static_cast<int>(type));
|
||||
return false;
|
||||
}
|
||||
|
||||
void HapVerifyV2::WriteCrlIfNeed(const Pkcs7Context& pkcs7Context, const bool& profileNeedWriteCrl)
|
||||
{
|
||||
if (!pkcs7Context.needWriteCrl && !profileNeedWriteCrl) {
|
||||
return;
|
||||
}
|
||||
HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
|
||||
hapCrlManager.WriteCrlsToFile();
|
||||
}
|
||||
|
||||
bool HapVerifyV2::ParseAndVerifyProfileIfNeed(const std::string& profile,
|
||||
ProvisionInfo& provisionInfo, bool isCallParseAndVerify)
|
||||
{
|
||||
if (isCallParseAndVerify) {
|
||||
return isCallParseAndVerify;
|
||||
}
|
||||
AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo);
|
||||
if (profileRet != PROVISION_OK) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "profile parse failed, error: %{public}d", static_cast<int>(profileRet));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HapVerifyV2::GetDigestAndAlgorithm(Pkcs7Context& digest)
|
||||
{
|
||||
/*
|
||||
* contentinfo format:
|
||||
* int: version
|
||||
* int: block number
|
||||
* digest blocks:
|
||||
* each digest block format:
|
||||
* int: length of sizeof(digestblock) - 4
|
||||
* int: Algorithm ID
|
||||
* int: length of digest
|
||||
* byte[]: digest
|
||||
*/
|
||||
/* length of sizeof(digestblock - 4) */
|
||||
int digestBlockLen;
|
||||
if (!digest.content.GetInt32(DIGEST_BLOCK_LEN_OFFSET, digestBlockLen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get digestBlockLen failed");
|
||||
return false;
|
||||
}
|
||||
/* Algorithm ID */
|
||||
if (!digest.content.GetInt32(DIGEST_ALGORITHM_OFFSET, digest.digestAlgorithm)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get digestAlgorithm failed");
|
||||
return false;
|
||||
}
|
||||
/* length of digest */
|
||||
int digestlen;
|
||||
if (!digest.content.GetInt32(DIGEST_LEN_OFFSET, digestlen)) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "get digestlen failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int sum = sizeof(digestlen) + sizeof(digest.digestAlgorithm) + digestlen;
|
||||
if (sum != digestBlockLen) {
|
||||
HAPVERIFY_LOG_ERROR(LABEL, "digestBlockLen: %{public}d is not equal to sum: %{public}d",
|
||||
digestBlockLen, sum);
|
||||
return false;
|
||||
}
|
||||
/* set position to the digest start point */
|
||||
digest.content.SetPosition(DIGEST_OFFSET_IN_CONTENT);
|
||||
/* set limit to the digest end point */
|
||||
digest.content.SetLimit(DIGEST_OFFSET_IN_CONTENT + digestlen);
|
||||
digest.content.Slice();
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
68
interfaces/innerkits/appverify/test/BUILD.gn
Normal file
68
interfaces/innerkits/appverify/test/BUILD.gn
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/test.gni")
|
||||
|
||||
module_output_path = "appverify/verify"
|
||||
|
||||
config("verify_test_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"//base/security/appverify/interfaces/innerkits/appverify/test/unittest/include",
|
||||
"//base/security/appverify/interfaces/innerkits/appverify/include",
|
||||
"//third_party/openssl/include",
|
||||
"//third_party/json/single_include",
|
||||
"//utils/native/base/include",
|
||||
]
|
||||
cflags = [ "-fvisibility=hidden" ]
|
||||
ldflags = [ "-Wl,--exclude-libs,ALL" ]
|
||||
}
|
||||
|
||||
ohos_unittest("verify_test") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
"unittest/src/hap_byte_buffer_test.cpp",
|
||||
"unittest/src/hap_cert_verify_openssl_utils_test.cpp",
|
||||
"unittest/src/hap_crl_manager_test.cpp",
|
||||
"unittest/src/hap_signing_block_utils_test.cpp",
|
||||
"unittest/src/hap_verify_openssl_utils_test.cpp",
|
||||
"unittest/src/hap_verify_result_test.cpp",
|
||||
"unittest/src/hap_verify_test.cpp",
|
||||
"unittest/src/hap_verify_v2_test.cpp",
|
||||
"unittest/src/provision_verify_test.cpp",
|
||||
"unittest/src/random_access_file_test.cpp",
|
||||
"unittest/src/trusted_root_ca_test.cpp",
|
||||
]
|
||||
|
||||
configs = [ ":verify_test_config" ]
|
||||
deps = [
|
||||
"//base/security/appverify/interfaces/innerkits/appverify:libhapverify",
|
||||
"//third_party/googletest:gtest_main",
|
||||
"//third_party/openssl:libcrypto_static",
|
||||
"//utils/native/base:utils",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"ipc:ipc_core",
|
||||
]
|
||||
|
||||
resource_config_file =
|
||||
"//base/security/appverify/test/resource/appverify/ohos_test.xml"
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [ ":verify_test" ]
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HAP_BYTE_BUFFER_TEST_H
|
||||
#define HAP_BYTE_BUFFER_TEST_H
|
||||
int HapByteBuffer001(void);
|
||||
int GetIntAndPutOperation001(void);
|
||||
int Slice001(void);
|
||||
int CopyPartialBuffer001(void);
|
||||
int IsEqual001(void);
|
||||
int IsEqual002(void);
|
||||
#endif // HAP_BYTE_BUFFER_TEST_H
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H
|
||||
#define HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
bool Base64StringDecode(const std::string& base64String, HapByteBuffer& output);
|
||||
}
|
||||
}
|
||||
}
|
||||
int GetCertInfo001(void);
|
||||
int CertVerify001(void);
|
||||
int Base64NotUrlSafeCertTest001(void);
|
||||
int GetX509CrlFromDerBufferTest001(void);
|
||||
int GetCertsChainTest001(void);
|
||||
int GetIssuerAndSubjectTest001(void);
|
||||
int GetSerialNumberFromX509Test001(void);
|
||||
int VerifyCertChainPeriodOfValidityTest001(void);
|
||||
int VerifyCrlTest001(void);
|
||||
int CompareX509CertTest001(void);
|
||||
int WriteX509CrlToStreamTest001(void);
|
||||
int PrivateFuncInvalidInputTest001(void);
|
||||
#endif // HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_CRL_MANAGER_TEST_H
|
||||
#define HAP_CRL_MANAGER_TEST_H
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
int WriteAndReadCrlsFileTest001(void);
|
||||
#endif // HAP_CRL_MANAGER_TEST_H
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HAP_SIGNING_BLOCK_UTILS_TEST_H
|
||||
#define HAP_SIGNING_BLOCK_UTILS_TEST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "util/signature_info.h"
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
int FindHapSignatureTest001(void);
|
||||
int VerifyHapIntegrityTest001(void);
|
||||
int FindEocdInHapTest001(void);
|
||||
int GetCentralDirectoryOffsetTest001(void);
|
||||
int ClassifyHapSubSigningBlock001(void);
|
||||
int ComputeDigestsWithOptionalBlock001(void);
|
||||
int GetSumOfChunkDigestLenTest001(void);
|
||||
#endif // HAP_SIGNING_BLOCK_UTILS_TEST_H
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_OPENSSL_UTILS_TEST_H
|
||||
#define HAP_VERIFY_OPENSSL_UTILS_TEST_H
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
int VerifyPkcs7001(void);
|
||||
int GetDigestAlgorithmId001(void);
|
||||
#endif // HAP_VERIFY_OPENSSL_UTILS_TEST_H
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_RESULT_TEST_H
|
||||
#define HAP_VERIFY_RESULT_TEST_H
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
int GetPublicKeyAndSignature001(void);
|
||||
int GetProfileAndProperty001(void);
|
||||
int SetVersionAndGetVersion001(void);
|
||||
#endif // HAP_VERIFY_RESULT_TEST_H
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_TEST_H
|
||||
#define HAP_VERIFY_TEST_H
|
||||
|
||||
int HapVerify001(void);
|
||||
int HapVerifyEnableDebug001(void);
|
||||
int HapVerify002(void);
|
||||
int HapVerifyOsApp001(void);
|
||||
#endif // HAP_VERIFY_TEST_H
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_VERIFY_V2_TEST_H
|
||||
#define HAP_VERIFY_V2_TEST_H
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
int CheckFilePathTest001(void);
|
||||
int GenerateAppIdTest001(void);
|
||||
int VerifyProfileInfoTest001(void);
|
||||
int ParseAndVerifyProfileIfNeedTest001(void);
|
||||
int GetDigestAndAlgorithmTest001(void);
|
||||
#endif // HAP_VERIFY_V2_TEST_H
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef PROVISION_VERIFY_TEST_H
|
||||
#define PROVISION_VERIFY_TEST_H
|
||||
int ProvisionVerify001(void);
|
||||
int ProvisionVerify002(void);
|
||||
int ProvisionVerify003(void);
|
||||
int ProvisionVerify004(void);
|
||||
int ProvisionVerify005(void);
|
||||
int ProvisionVerify006(void);
|
||||
int ProvisionVerify007(void);
|
||||
int ProvisionVerify008(void);
|
||||
#endif // PROVISION_VERIFY_TEST_H
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef RANDOM_ACCESS_FILE_TEST_H
|
||||
#define RANDOM_ACCESS_FILE_TEST_H
|
||||
|
||||
int ReadFileFullyFromOffsetTest001(void);
|
||||
#endif // RANDOM_ACCESS_FILE_TEST_H
|
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAPVERIFY_TEST_CONST_H
|
||||
#define HAPVERIFY_TEST_CONST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
#define protected public
|
||||
#define private public
|
||||
|
||||
constexpr char TEST_HAPBYTEBUFFER_CHAR_DATA = 0xff;
|
||||
constexpr unsigned short TEST_HAPBYTEBUFFER_UINT16_DATA = 0xffff;
|
||||
constexpr unsigned int TEST_HAPBYTEBUFFER_UINT32_DATA = 0xffffffff;
|
||||
constexpr int TEST_HAPBYTEBUFFER_INT32_DATA = 0xffffffff;
|
||||
constexpr long long TEST_HAPBYTEBUFFER_INT64_DATA = 0xffffffffffffffff;
|
||||
constexpr int TEST_HAPBYTEBUFFER_INT32_DATA_2 = 100000;
|
||||
constexpr int TEST_HAPBYTEBUFFER_INVALID_INDEX = -1;
|
||||
|
||||
constexpr int TEST_RANDOMREAD_LENGTH = 150000;
|
||||
constexpr int TEST_HAPBYTEBUFFER_LENGTH = 15;
|
||||
constexpr int TEST_HAPBYTEBUFFER_LENGTH_2 = 8;
|
||||
constexpr int TEST_HAPBYTEBUFFER_POSITION = 10;
|
||||
|
||||
constexpr int TEST_HAPBYTEBUFFER_UINT16_LENGTH = 2;
|
||||
constexpr int TEST_HAPBYTEBUFFER_INT64_LENGTH = 8;
|
||||
|
||||
constexpr int TEST_FILE_BLOCK_LENGTH = 50;
|
||||
constexpr int TEST_FILE_BLOCK_COUNT = 3;
|
||||
|
||||
constexpr int TEST_FILE_CD_OFFSET_POSITION = 6;
|
||||
|
||||
constexpr int TEST_HAP_SIGN_VERSION = 1;
|
||||
|
||||
constexpr int TEST_MAX_COMMENT_SIZE = 4;
|
||||
constexpr int TEST_INVALID_MAX_COMMENT_SIZE = -1;
|
||||
|
||||
constexpr int TEST_ZIP_EOCD_SIZE = 22;
|
||||
constexpr int TEST_ZIP_ECD_OFFSET_FIELD_OFFSET = 16;
|
||||
constexpr int TEST_ZIP_ECD_SIZE_FIELD_OFFSET = 12;
|
||||
|
||||
constexpr int TEST_NULL_NID = 118;
|
||||
constexpr int TEST_SHA256_NID = 672;
|
||||
constexpr int TEST_SHA384_NID = 673;
|
||||
constexpr int TEST_SHA512_NID = 674;
|
||||
|
||||
constexpr int TEST_MINI_HAP_FILE_LENGTH = 2619;
|
||||
|
||||
constexpr int TEST_SIGN_VERSION = 2;
|
||||
constexpr int TEST_CERT_CHAIN_LEN = 3;
|
||||
|
||||
constexpr int TEST_FILE_NUM = 2;
|
||||
constexpr int TEST_PFOFILE_PKCS7_DATA_INDEX = 5110;
|
||||
constexpr int TEST_APP_PKCS7_DATA_INDEX = 7000;
|
||||
|
||||
const std::string TEST_ANS_TIME = "000000000000Z";
|
||||
|
||||
constexpr char miniHapFile[] = {
|
||||
80, 75, 3, 4, 10, 0, 0, 8, 0, 0, 0, 0, 33, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 18, 0,
|
||||
49, 46, 116, 120, 116, 85, 84, 9, 0, 6, 49, 40, 41, 94, 49, 40, 41, 94, -2, -54, 0, 0, 0, 0, 0,
|
||||
0, 32, -117, 9, 0, 0, 48, -126, 9, -121, 6, 9, 42, -122, 72, -122, -9, 13, 1, 7, 2, -96, -126, 9,
|
||||
120, 48, -126, 9, 116, 2, 1, 1, 49, 15, 48, 13, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1, 5, 0, 48,
|
||||
-126, 3, -6, 6, 9, 42, -122, 72, -122, -9, 13, 1, 7, 1, -96, -126, 3, -21, 4, -126, 3, -25, 44, 0,
|
||||
0, 0, 40, 0, 0, 0, 1, 1, 0, 0, 32, 0, 0, 0, -9, 111, -2, 4, -40, -83, -50, -26, 50, -78, -26, 18,
|
||||
101, 6, -30, -100, -26, -96, 17, -84, 15, 112, 74, -114, -67, 67, -81, -49, 19, -28, -110, 48, -77,
|
||||
3, 0, 0, -81, 3, 0, 0, 48, -126, 3, -85, 48, -126, 2, -109, -96, 3, 2, 1, 2, 2, 20, 122, 93, -87,
|
||||
110, 73, 90, -84, 41, -27, -29, -93, 93, 59, 56, -105, -122, -20, -75, 10, -99, 48, 13, 6, 9, 42,
|
||||
-122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49,
|
||||
17, 48, 15, 6, 3, 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85,
|
||||
4, 7, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, 4, 10, 12, 6, 72, 117,
|
||||
97, 119, 101, 105, 49, 15, 48, 13, 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101, 105, 49, 14, 48, 12,
|
||||
6, 3, 85, 4, 3, 12, 5, 67, 104, 105, 110, 97, 48, 30, 23, 13, 50, 48, 48, 49, 49, 48, 48, 55, 51, 54,
|
||||
53, 57, 90, 23, 13, 52, 55, 48, 53, 50, 56, 48, 55, 51, 54, 53, 57, 90, 48, 101, 49, 11, 48, 9, 6, 3,
|
||||
85, 4, 6, 19, 2, 67, 78, 49, 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110,
|
||||
49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85,
|
||||
4, 10, 12, 6, 72, 117, 97, 119, 101, 105, 49, 15, 48, 13, 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101,
|
||||
105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, 104, 105, 110, 97, 48, -126, 1, 34, 48, 13, 6, 9, 42,
|
||||
-122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -17, -107,
|
||||
-66, -22, 68, -42, -13, 116, 108, -23, 84, -30, -19, 127, -45, -40, -60, -67, -53, -33, -114, 26, -11,
|
||||
104, 46, 103, 105, -78, -42, -32, 89, -70, 87, 67, 32, 81, 35, 61, -121, 114, -83, 71, 8, -100, -35, 82,
|
||||
-91, -3, 44, 95, -55, -118, 118, 19, 1, -50, 35, -3, -123, 29, 103, 54, -16, -3, 36, -67, 54, 51, 2, 107,
|
||||
112, -9, -23, 40, -117, -84, -72, -7, 112, -92, -127, 97, 122, -86, -126, 93, -37, -55, 17, 35, 118, -110,
|
||||
-40, 27, -123, 2, 123, 102, 39, 117, -48, -71, 103, -84, -105, -81, 28, -86, 118, -95, 63, 59, 107, 4, -71,
|
||||
-30, 83, 39, 105, -112, -35, -15, 112, -52, -58, -118, -114, 127, -54, -125, 46, 70, -95, -70, -11, 125, 49,
|
||||
116, -54, 34, 93, 34, 113, 119, -33, -26, -21, 13, 69, -69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80,
|
||||
-86, -11, 103, -121, 97, 122, -114, -88, -83, 59, 119, 56, 22, 72, 35, -67, -67, -83, -60, 112, 105, 117,
|
||||
50, -19, 16, -53, 83, 103, -110, -107, 45, 5, 17, -28, -97, -90, 59, 117, -88, 47, -86, -32, 17, -96, 111,
|
||||
88, -103, -60, -55, 20, -80, 44, 64, -48, 104, 94, -118, 49, 72, -68, 42, 2, -9, 87, 17, -127, -43, -82, 85,
|
||||
70, 13, -98, 24, -55, -90, -51, 103, -65, -58, -97, 52, -71, -85, -3, -118, -99, -84, 110, 2, 110, 56, -18,
|
||||
-21, -109, -65, 67, 2, 3, 1, 0, 1, -93, 83, 48, 81, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 49, 59, -102,
|
||||
-88, 25, -106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, 3, 36, -51, 48, 31, 6, 3, 85, 29, 35,
|
||||
4, 24, 48, 22, -128, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122,
|
||||
3, 36, -51, 48, 15, 6, 3, 85, 29, 19, 1, 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, 13, 6, 9, 42, -122, 72, -122,
|
||||
-9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -33, 97, 20, 104, -18, -45, -47, -109, 81, -55, -69, 34, -119,
|
||||
-4, -78, 9, -101, 7, -42, 107, 41, -65, -115, -64, -89, -38, 24, 103, -119, 22, -38, 60, 4, -2, 36, -94,
|
||||
103, 84, 89, 115, -93, -67, -2, -41, 124, 53, 6, 37, 116, -30, 49, -78, 83, -110, 50, 26, 120, -58, -11,
|
||||
91, -119, -121, 87, 99, 74, -71, 23, -113, -63, -14, -68, -44, 17, -109, 24, -94, -26, -60, 32, -8, 77, 29,
|
||||
113, 42, -94, -9, -92, -71, -57, -41, 24, -62, 2, -3, 53, -98, -99, -32, -1, 120, -17, 26, 32, -2, -59, 85,
|
||||
-22, 23, -79, 9, -72, 116, 67, 55, 118, 12, 7, 79, -83, -103, -66, 123, -55, 5, -29, -53, 92, -95, 99, 4, -23,
|
||||
26, -121, -22, 69, 89, 7, -109, -54, -76, -59, 0, 54, -24, -58, -42, 14, -51, -121, -14, 97, 68, -70, -122, -30,
|
||||
-113, 43, -102, -34, 96, 38, -8, -14, 65, 83, -124, -104, 27, 69, -42, -69, -30, -108, -76, -1, -47, -117, -2,
|
||||
108, 9, 61, 79, 59, 67, -18, -126, -117, 36, -14, -102, 23, 55, -27, 97, -47, -24, 16, 102, 60, 88, 47, -59, 63,
|
||||
-57, 46, -77, -112, -88, -93, -60, -120, 101, -3, 117, -102, -113, -10, -61, -69, -122, 6, 96, -78, 28, -111, 1,
|
||||
-88, -60, -123, -39, 28, -28, 40, -28, -59, -97, 77, -45, -9, -113, 120, 84, 58, 105, 24, -35, -113, -97, 115,
|
||||
-107, -3, 121, 56, -60, 75, -60, -96, -126, 3, -81, 48, -126, 3, -85, 48, -126, 2, -109, -96, 3, 2, 1, 2, 2,
|
||||
20, 122, 93, -87, 110, 73, 90, -84, 41, -27, -29, -93, 93, 59, 56, -105, -122, -20, -75, 10, -99, 48, 13, 6,
|
||||
9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, 17,
|
||||
48, 15, 6, 3, 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8,
|
||||
83, 104, 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, 4, 10, 12, 6, 72, 117, 97, 119, 101, 105, 49,
|
||||
15, 48, 13, 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101, 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, 104,
|
||||
105, 110, 97, 48, 30, 23, 13, 50, 48, 48, 49, 49, 48, 48, 55, 51, 54, 53, 57, 90, 23, 13, 52, 55, 48, 53, 50,
|
||||
56, 48, 55, 51, 54, 53, 57, 90, 48, 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, 17, 48, 15, 6, 3,
|
||||
85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8, 83, 104, 101,
|
||||
110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, 4, 10, 12, 6, 72, 117, 97, 119, 101, 105, 49, 15, 48, 13,
|
||||
6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101, 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, 104, 105, 110,
|
||||
97, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1,
|
||||
10, 2, -126, 1, 1, 0, -17, -107, -66, -22, 68, -42, -13, 116, 108, -23, 84, -30, -19, 127, -45, -40, -60, -67,
|
||||
-53, -33, -114, 26, -11, 104, 46, 103, 105, -78, -42, -32, 89, -70, 87, 67, 32, 81, 35, 61, -121, 114, -83, 71,
|
||||
8, -100, -35, 82, -91, -3, 44, 95, -55, -118, 118, 19, 1, -50, 35, -3, -123, 29, 103, 54, -16, -3, 36, -67, 54,
|
||||
51, 2, 107, 112, -9, -23, 40, -117, -84, -72, -7, 112, -92, -127, 97, 122, -86, -126, 93, -37, -55, 17, 35, 118,
|
||||
-110, -40, 27, -123, 2, 123, 102, 39, 117, -48, -71, 103, -84, -105, -81, 28, -86, 118, -95, 63, 59, 107, 4,
|
||||
-71, -30, 83, 39, 105, -112, -35, -15, 112, -52, -58, -118, -114, 127, -54, -125, 46, 70, -95, -70, -11, 125,
|
||||
49, 116, -54, 34, 93, 34, 113, 119, -33, -26, -21, 13, 69, -69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80,
|
||||
-86, -11, 103, -121, 97, 122, -114, -88, -83, 59, 119, 56, 22, 72, 35, -67, -67, -83, -60, 112, 105, 117, 50,
|
||||
-19, 16, -53, 83, 103, -110, -107, 45, 5, 17, -28, -97, -90, 59, 117, -88, 47, -86, -32, 17, -96, 111, 88,
|
||||
-103, -60, -55, 20, -80, 44, 64, -48, 104, 94, -118, 49, 72, -68, 42, 2, -9, 87, 17, -127, -43, -82, 85, 70,
|
||||
13, -98, 24, -55, -90, -51, 103, -65, -58, -97, 52, -71, -85, -3, -118, -99, -84, 110, 2, 110, 56, -18, -21,
|
||||
-109, -65, 67, 2, 3, 1, 0, 1, -93, 83, 48, 81, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 49, 59, -102, -88, 25,
|
||||
-106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, 3, 36, -51, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22,
|
||||
-128, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, 3, 36, -51, 48, 15,
|
||||
6, 3, 85, 29, 19, 1, 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 3,
|
||||
-126, 1, 1, 0, -33, 97, 20, 104, -18, -45, -47, -109, 81, -55, -69, 34, -119, -4, -78, 9, -101, 7, -42, 107, 41,
|
||||
-65, -115, -64, -89, -38, 24, 103, -119, 22, -38, 60, 4, -2, 36, -94, 103, 84, 89, 115, -93, -67, -2, -41, 124,
|
||||
53, 6, 37, 116, -30, 49, -78, 83, -110, 50, 26, 120, -58, -11, 91, -119, -121, 87, 99, 74, -71, 23, -113, -63,
|
||||
-14, -68, -44, 17, -109, 24, -94, -26, -60, 32, -8, 77, 29, 113, 42, -94, -9, -92, -71, -57, -41, 24, -62, 2,
|
||||
-3, 53, -98, -99, -32, -1, 120, -17, 26, 32, -2, -59, 85, -22, 23, -79, 9, -72, 116, 67, 55, 118, 12, 7, 79,
|
||||
-83, -103, -66, 123, -55, 5, -29, -53, 92, -95, 99, 4, -23, 26, -121, -22, 69, 89, 7, -109, -54, -76, -59, 0,
|
||||
54, -24, -58, -42, 14, -51, -121, -14, 97, 68, -70, -122, -30, -113, 43, -102, -34, 96, 38, -8, -14, 65, 83,
|
||||
-124, -104, 27, 69, -42, -69, -30, -108, -76, -1, -47, -117, -2, 108, 9, 61, 79, 59, 67, -18, -126, -117, 36,
|
||||
-14, -102, 23, 55, -27, 97, -47, -24, 16, 102, 60, 88, 47, -59, 63, -57, 46, -77, -112, -88, -93, -60, -120,
|
||||
101, -3, 117, -102, -113, -10, -61, -69, -122, 6, 96, -78, 28, -111, 1, -88, -60, -123, -39, 28, -28, 40, -28,
|
||||
-59, -97, 77, -45, -9, -113, 120, 84, 58, 105, 24, -35, -113, -97, 115, -107, -3, 121, 56, -60, 75, -60, 49,
|
||||
-126, 1, -85, 48, -126, 1, -89, 2, 1, 1, 48, 125, 48, 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49,
|
||||
17, 48, 15, 6, 3, 85, 4, 8, 19, 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, 4, 7, 19,
|
||||
8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, 4, 10, 19, 6, 72, 117, 97, 119, 101, 105,
|
||||
49, 15, 48, 13, 6, 3, 85, 4, 11, 19, 6, 72, 117, 97, 119, 101, 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 19, 5, 67,
|
||||
104, 105, 110, 97, 2, 20, 122, 93, -87, 110, 73, 90, -84, 41, -27, -29, -93, 93, 59, 56, -105, -122, -20, -75,
|
||||
10, -99, 48, 13, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1, 5, 0, 48, 14, 6, 10, 42, -122, 72, -122, -9, 13, 1, 1,
|
||||
-113, 95, 5, 0, 4, -126, 1, 0, 10, -19, -16, -126, -10, -94, 59, 95, 83, 115, -33, 23, 97, -30, -91, -114, 59,
|
||||
93, 97, -15, -12, 60, 39, -53, 28, -25, -6, 32, -48, 120, -97, 64, 125, 23, -9, 53, 104, -122, 18, -5, 122, 126,
|
||||
19, -80, 53, 14, 70, 21, 63, -99, -76, -52, -2, 103, -114, 95, -21, -60, -49, -42, -81, 58, -16, -23, 19, 108,
|
||||
-30, -32, -12, -103, -107, 25, 33, 85, 61, 2, 30, 17, 0, 117, -63, -12, -112, 60, 12, 58, 114, 126, 24, -25,
|
||||
-123, 32, 19, 99, 54, -2, -78, -23, 126, 61, 46, 61, 4, -114, -36, 53, -1, -71, 22, -10, 127, 63, -10, -73,
|
||||
51, -74, -8, 80, -34, 63, 57, -17, 106, 100, -109, -27, -30, 46, 35, -85, -91, -20, -72, -128, 22, -97, 107,
|
||||
101, 21, 63, -36, 50, -69, 99, -10, -88, 52, 19, -115, 67, 53, 53, 30, -107, 122, -123, -118, -56, 80, -50,
|
||||
-58, 30, 110, -109, -14, 50, 18, 2, -46, 102, 64, 6, -71, 25, 71, -36, 95, -121, -7, -11, 90, 18, 20, 96,
|
||||
-6, -61, 59, 90, -1, 64, -111, 73, 82, 50, -61, 111, 41, -29, -102, 100, -100, -73, 42, -88, 21, -64, -122,
|
||||
8, 117, -65, 47, 86, -55, -37, -14, 20, 60, 91, -22, -101, 90, -18, 10, -101, -40, 64, -110, -120, 119, -7,
|
||||
-41, -109, 82, -2, -122, 72, 74, 44, 54, -48, -51, -52, -37, -56, -10, -8, 78, 64, -105, 59, -71, 54, -25,
|
||||
-9, 105, 29, -95, 0, 1, 0, 0, 0, -77, 9, 0, 0, 0, 0, 0, 0, 72, 65, 80, 32, 83, 105, 103, 32, 66, 108, 111,
|
||||
99, 107, 32, 52, 50, 1, 0, 0, 0, 80, 75, 1, 2, 10, 0, 10, 0, 0, 8, 0, 0, 0, 0, 33, 58, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 5, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 46, 116, 120, 116, 85, 84, 1, 0, 6,
|
||||
-2, -54, 0, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 61, 0, 0, 0, -24, 9, 0, 0, 0, 0, -33, -26, -21, 13, 69,
|
||||
-69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80, -86, -11, 103, -121, 97, 122, -114, -88, -83, 59, 119, 56,
|
||||
22, 72, 35, -67, -67, -83, -60, 112, 105, 117, 50, -19, 16, -53, 83, 103, -110, -107, 45, 5, 17, -28, -97, -90,
|
||||
59, 117, -88, 47, -86, -32, 17, -96, 111, 88, -103, -60, -55, 20, -80, 44, 64, -48, 104, 94, -118, 49, 72, -68,
|
||||
42, 2, -9, 87, 17, -127, -43, -82, 85, 70, 13, -98, 24, -55, -90, -51, 103, -65, -58, -97, 52, -71, -85, -3,
|
||||
-118, -99, -84, 110, 2, 110, 56, -18, -21, -109, -65, 67, 2, 3, 1, 0, 1, -93, 83, 48, 81, 48, 29, 6, 3, 85, 29,
|
||||
14, 4, 22, 4, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, 3, 36, -51,
|
||||
48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, -86, -88, -67, -85,
|
||||
-88, -36, 8, -122, 3, 36, -51, 48, 15, 6, 3, 85, 29, 19, 1, 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, 13, 6, 9, 42, -122,
|
||||
72, -122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -33, 97, 20, 104, -18, -45, -47, -109, 81, -55, -69, 34, -119,
|
||||
-4, -78, 9, -101, 7, -42, 107, 41, -65, -115, -64, -89, -38, 24, 103, -119, 22, -38, 60, 4, -2, 36, -94, 103, 84,
|
||||
89, 115, -93, -67, -2, -41, 124, 53, 6, 37, 116, -30, 49, -78, 83, -110, 50, 26, 120, -58, -11, 91, -119, -121,
|
||||
87, 99, 74, -71, 23, -113, -63, -14, -68, -44, 17, -109, 24, -94, -26, -60, 32, -8, 77, 29, 113, 42, -94, -9,
|
||||
-92, -71, -57, -41, 24, -62, 2, -3, 53, -98, -99, -32, -1, 120, -17, 26, 32, -2, -59, 85, -22, 23, -79, 9, -72,
|
||||
116, 67, 55, 118, 12, 7, 79, -83, -103, -66, 123, -55, 5, -29, -53, 92, -95, 99, 4, -23, 26, -121, -22, 69, 89,
|
||||
7, -109, -54, -76, -59, 0, 54, -24, -58, -42, 14, -51, -121, -14, 97, 68, -70, -122, -30, -113, 43, -102, -34,
|
||||
96, 38, -8, -14, 65, 83, -124, -104, 27, 69, -42, -69, -30, -108, -76, -1, -47, -117, -2, 108, 9, 61, 79, 59,
|
||||
67, -18, -126, -117, 36, -14, -102, 23, 55, -27, 97, -47, -24, 16, 102, 60, 88, 47, -59, 63, -57, 46, -77,
|
||||
-112, -88, -93, -60, -120, 101, -3, 117, -102, -113, -10, -61, -69, -122, 6, 96, -78, 28, -111, 1, -88, -60,
|
||||
-123, -39, 28
|
||||
};
|
||||
|
||||
const std::string ROOTCERT = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICGjCCAaGgAwIBAgIIShhpn519jNAwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\n"
|
||||
"Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\n"
|
||||
"AwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjAzMDQzOVoXDTQ5MDMx\n"
|
||||
"NjAzMDQzOVowUzELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\n"
|
||||
"CwwKSHVhd2VpIENCRzEeMBwGA1UEAwwVSHVhd2VpIENCRyBSb290IENBIEcyMHYw\n"
|
||||
"EAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrs\n"
|
||||
"GUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpHMB\n"
|
||||
"wcz4DA0kgHCMm/wDec6kOHx1xvCRo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\n"
|
||||
"AQH/BAUwAwEB/zAdBgNVHQ4EFgQUo45a9Vq8cYwqaiVyfkiS4pLcIAAwCgYIKoZI\n"
|
||||
"zj0EAwMDZwAwZAIwMypeB7P0IbY7c6gpWcClhRznOJFj8uavrNu2PIoz9KIqr3jn\n"
|
||||
"BlBHJs0myI7ntYpEAjBbm8eDMZY5zq5iMZUC6H7UzYSix4Uy1YlsLVV738PtKP9h\n"
|
||||
"FTjgDHctXJlC5L7+ZDY=\n-----END CERTIFICATE-----\n";
|
||||
|
||||
const std::string SOFT_CA_CERT = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDADCCAoegAwIBAgIIJGDixWQS3MkwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\n"
|
||||
"Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\n"
|
||||
"AwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjEyMzIzOVoXDTQwMDMx\n"
|
||||
"NjEyMzIzOVowZDELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\n"
|
||||
"CwwKSHVhd2VpIENCRzEvMC0GA1UEAwwmSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWdu\n"
|
||||
"aW5nIFNlcnZpY2UgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASsEz7cwYkzFh9b\n"
|
||||
"xIwKfXx5qHGjl5WITy0teGnNWqv+jYCceeixHqErvK7YRn2hVPIqhRqKWeANHZUK\n"
|
||||
"G0qxi+NIpmSmQS8/63CLz1QAcxfv2Xl3/V82dF0v9lm16ehMsN+jggEVMIIBETAf\n"
|
||||
"BgNVHSMEGDAWgBSjjlr1WrxxjCpqJXJ+SJLiktwgADAdBgNVHQ4EFgQU+vX3viBW\n"
|
||||
"XV3U2m3xFBU8HQnbsjQwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUd\n"
|
||||
"IAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9j\n"
|
||||
"cGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDov\n"
|
||||
"L2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24u\n"
|
||||
"Y3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBk\n"
|
||||
"AjBrAQQxUlNgqhYkcEm5eksnPxDkPJSY/qNd2BDgbvEydiLwPSvB7Z9lipxz8ikZ\n"
|
||||
"EeUCMGppWcaV//SIG1y5tEwthLwWeEaF613vUILWQLir8+CA3RZGsRBqtE8xSqfz\n"
|
||||
"yafLYQ==\n-----END CERTIFICATE-----\n";
|
||||
|
||||
const std::string UAT_SOFT_SIGN_CA = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDCjCCApGgAwIBAgIIWbEqGvOqT10wCgYIKoZIzj0EAwMwWDELMAkGA1UEBhMC\n"
|
||||
"Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEjMCEGA1UE\n"
|
||||
"AwwaSHVhd2VpIENCRyBSb290IENBIEcyIFRlc3QwHhcNMjAwMzEzMTE1ODI4WhcN\n"
|
||||
"NDAwMzEzMTE1ODI4WjBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMw\n"
|
||||
"EQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJl\n"
|
||||
"IFNpZ25pbmcgU2VydmljZSBDQSBUZXN0MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE\n"
|
||||
"ukPDS3s0TpYa/lANCTc7eX8fdGGjMPUbvso3TtlBvzdm0XDNTdVtZq3XVOfefgpE\n"
|
||||
"OaC/JSoXgiNHkeEQ4XSSm0d7MbeoYEyoEKWa1G2/SOQxbVNqKLexxlGMjMuOLdMb\n"
|
||||
"o4IBFTCCAREwHwYDVR0jBBgwFoAUaV3AWPH1POb9CkDxHWBz3Bx4xsUwHQYDVR0O\n"
|
||||
"BBYEFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMA8GA1UdEwEB/wQFMAMBAf8wRgYDVR0g\n"
|
||||
"BD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly9jcGtpLWNhd2ViLmh1\n"
|
||||
"YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgEGMGYGA1UdHwRfMF0wW6BZ\n"
|
||||
"oFeGVWh0dHA6Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20vY3BraS9zZXJ2bGV0L2Ny\n"
|
||||
"bEZpbGVEb3duLmNybD9jZXJ0eXBlPTEwJi9yb290X2cyX2NybC5jcmwwCgYIKoZI\n"
|
||||
"zj0EAwMDZwAwZAIwF7PjIuOODhpDhzpw2cqV/xbLNJ5CExFJHxcy1D0bHljE5xTt\n"
|
||||
"csIN40Ma6aEi3MJQAjAHQLfAzZvMmreYwKnc2bHXlS68roSRvNTvrUKp3Lcp92nK\n"
|
||||
"MzieiyKHlWKEgrUjnKc=\n-----END CERTIFICATE-----\n";
|
||||
|
||||
const std::string ECC_TEST_KEY = "-----BEGIN EC PARAMETERS-----\n"
|
||||
"BggqhkjOPQMBBw==\n-----END EC PARAMETERS-----\n"
|
||||
"-----BEGIN EC PRIVATE KEY-----\n"
|
||||
"MHcCAQEEIPPNgGEGZA97B5g54d0D8kDBIOYS1LDldMGRf1aifZauoAoGCCqGSM49\n"
|
||||
"AwEHoUQDQgAE4BehGAUU+XDXxtlQ+7Ct4sILmYL7CligKCSWbRw0YsBp4F20626u\n"
|
||||
"8+T9xNlH7pGc5moba0EKy003FH1sVbtEtg==\n-----END EC PRIVATE KEY-----\n";
|
||||
|
||||
const std::string ECC_TEST_CERT = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIBkjCCATgCCQCncuWaDED8pjAKBggqhkjOPQQDAjBQMQswCQYDVQQGEwJDTjEM\n"
|
||||
"MAoGA1UECgwDQ0JHMRwwGgYDVQQLDBNDQkcgSE9TIHNpZ25lZCBUZWFtMRUwEwYD\n"
|
||||
"VQQDDAxIT1MgdW5pdHRlc3QwIBcNMjAwNDI3MDQwNDQ2WhgPMjEyMDA0MDMwNDA0\n"
|
||||
"NDZaMFAxCzAJBgNVBAYTAkNOMQwwCgYDVQQKDANDQkcxHDAaBgNVBAsME0NCRyBI\n"
|
||||
"T1Mgc2lnbmVkIFRlYW0xFTATBgNVBAMMDEhPUyB1bml0dGVzdDBZMBMGByqGSM49\n"
|
||||
"AgEGCCqGSM49AwEHA0IABOAXoRgFFPlw18bZUPuwreLCC5mC+wpYoCgklm0cNGLA\n"
|
||||
"aeBdtOturvPk/cTZR+6RnOZqG2tBCstNNxR9bFW7RLYwCgYIKoZIzj0EAwIDSAAw\n"
|
||||
"RQIhALYbUacS0XrpPzVatHMpHnCmYgsi28hf1UTBNk+iPG/9AiBGh25CpFoDmGqb\n"
|
||||
"fz5ebYSvkSe1KNtVHUTprMBQeWaB0A==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const std::string APP_SIGN_TEST = "-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDHjCCAqWgAwIBAgIISwRVtFpC3o0wCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMC\n"
|
||||
"Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UE\n"
|
||||
"AwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDAe\n"
|
||||
"Fw0yMDA0MjcxMjQyMjJaFw0yMzA0MjcxMjQyMjJaMGUxCzAJBgNVBAYTAkNOMRMw\n"
|
||||
"EQYDVQQKDApIdWF3ZWkgQ0JHMR0wGwYDVQQLDBRIT1MgRGV2ZWxvcG1lbnQgVGVh\n"
|
||||
"bTEiMCAGA1UEAwwZSE9TIEFwcGxpY2F0aW9uIFByb3Zpc2lvbjBZMBMGByqGSM49\n"
|
||||
"AgEGCCqGSM49AwEHA0IABNrFL0TBoPUBcwLCT+jzlDatUBcxv8l4/3xirQkSgPq8\n"
|
||||
"ZTsrVChJE51ZotHcDN8QOtLfEJZC92ev+hAqksltfDKjggE5MIIBNTAfBgNVHSME\n"
|
||||
"GDAWgBR7uEdSp/HMWJ77VezhLXEOB5ovJjAdBgNVHQ4EFgQU80TcTfc+VizmL+/V\n"
|
||||
"0fFAXwsh2vgwRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6\n"
|
||||
"Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgeA\n"
|
||||
"MGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20v\n"
|
||||
"Y3BraS9zZXJ2bGV0L2NybEZpbGVEb3duLmNybD9jZXJ0eXBlPTE0Ji9zb2Z0X3Np\n"
|
||||
"Z25fc3J2X2NybC5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGAYMKwYBBAGPWwKC\n"
|
||||
"eAECBAgwBgIBAQoBADAKBggqhkjOPQQDAwNnADBkAjAqTxz2Z9F1HaPVoBD2e3fL\n"
|
||||
"VXWASZx+YGFMpN0pyCGScDQr4zj+MXuNKewv13M+yaICMHCemT39agd/dHF+sorJ\n"
|
||||
"Gz6qDn/r0hmkeHoCzUwA0Dwq/417Re81BbZvHHv7yPO7jw==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const std::string BASE64_NOT_URL_SAFE_CERT =
|
||||
"MIIDLDCCArOgAwIBAgIIRBvbxEi6hzwwCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwK"
|
||||
"SHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDAeFw0yMDA0MjkxMTUw"
|
||||
"NTlaFw0yMzA0MjkxMTUwNTlaMHMxCzAJBgNVBAYTAkNOMRMwEQYDVQQKDApIdWF3ZWkgQ0JHMR0wGwYDVQQLDBRIT1MgRGV2ZWxvcG1l"
|
||||
"bnQgVGVhbTEwMC4GA1UEAwwnSE9TIEFwcGxpY2F0aW9uIFByb3Zpc2lvbiBQcm9maWxlIERlYnVnMFkwEwYHKoZIzj0CAQYIKoZIzj0D"
|
||||
"AQcDQgAEcS/2lY4sb1EHegznTHYurPL4isgkq/AS4r8TqTnAkP2GI3N/e/+AX9MvdNQrCdNObSp/jXikxnU/Ng/m/pL0UaOCATkwggE1"
|
||||
"MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBSOm2cVJTbTlMJF+CJer6HVFCC1iDBGBgNVHSAEPzA9MDsG"
|
||||
"BFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4AwbAYD"
|
||||
"VR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5"
|
||||
"cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBggrBgEFBQcDAzAYBgwrBgEEAY9bAoJ4AQMECDAGAgEBCgEBMAoG"
|
||||
"CCqGSM49BAMDA2cAMGQCMBs+JL4mtRpANjBvrv4zPQr/dE9Fk+eS/rj38qwkMM2CyDdoo0akI8HQ+fNGJP6JKwIwJqNjupjVsQ60b2tQ"
|
||||
"AQSLisHmegx5s7USRD3dlpcUEGnepWMop1r8D4Ko8jHsKOX7";
|
||||
|
||||
const std::string BASE64_CRL =
|
||||
"MIIBLTCBswIBATAKBggqhkjOPQQDAzBTMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMR4w"
|
||||
"HAYDVQQDDBVIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIXDTIwMDMyNjE2NDkwNVoXDTMwMDMyNTAxMzgzM1qgLzAtMB8GA1UdIwQYMBaAFKOO"
|
||||
"WvVavHGMKmolcn5IkuKS3CAAMAoGA1UdFAQDAgEAMAoGCCqGSM49BAMDA2kAMGYCMQCuQOz7IvwENw/Mf1ytoXT5AHiknrrOaw/dqTuZ"
|
||||
"RR0wcxP5IJqI1I3Bg5WNbUmTomMCMQDIs23wc9iLgvuDOmMQia4srWunydbbslpFNfV3SIIhtyWDIPVch7RTf/s92HqnrVw=";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAPVERIFY_TEST_CONST_H
|
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef TEST_HAP_FILE_DATA_H
|
||||
#define TEST_HAP_FILE_DATA_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const std::string HAP_FILE_ECC_SIGN_BASE64 =
|
||||
"UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAFAAQAMS50eHT+ygAAMzQEAFBLBwh3FVrWBAAAAAIAAAACAAAg2hMAABgAAAAAAAAgmA0AAP"
|
||||
"ITAAAwghPWBgkqhkiG9w0BBwKgghPHMIITwwIBATEPMA0GCWCGSAFlAwQCAQUAMIIGhAYJKoZIhvcNAQcBoIIGdQSCBnF7InZlcnNpb24t"
|
||||
"bmFtZSI6IjEuMC4wIiwidmVyc2lvbi1jb2RlIjoxLCJhcHAtZGlzdHJpYnV0aW9uLXR5cGUiOiJvc19pbnRlZ3JhdGlvbiIsInV1aWQiOi"
|
||||
"I5OEE3Rjc3Mi01ODRCLTRFRDctOTczRC1CMDg4M0YwRjE5RUYiLCJ2YWxpZGl0eSI6eyJub3QtYmVmb3JlIjoxNTg2NDIyNzQzLCJub3Qt"
|
||||
"YWZ0ZXIiOjI1MzU2OTk4NDN9LCJ0eXBlIjoicmVsZWFzZSIsImJ1bmRsZS1pbmZvIjp7ImRldmVsb3Blci1pZCI6Inpob25neGlhbmciLC"
|
||||
"JkaXN0cmlidXRpb24tY2VydGlmaWNhdGUiOiItLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS1cbk1JSUREVENDQXBPZ0F3SUJBZ0lJYmZG"
|
||||
"eTVTaXR3ME13Q2dZSUtvWkl6ajBFQXdNd2FURUxNQWtHQTFVRUJoTUNcblEwNHhEekFOQmdOVkJBb01Ca2gxWVhkbGFURVRNQkVHQTFVRU"
|
||||
"N3d0tTSFZoZDJWcElFTkNSekUwTURJR0ExVUVcbkF3d3JTSFZoZDJWcElFTkNSeUJUYjJaMGQyRnlaU0JUYVdkdWFXNW5JRk5sY25acFky"
|
||||
"VWdRMEVnVkdWemREQWVcbkZ3MHlNREEwTWpnd016SXlNRGRhRncwek1EQTBNamd3TXpJeU1EZGFNRkF4Q3pBSkJnTlZCQVlUQWtOT01ROH"
|
||||
"dcbkRRWURWUVFLREFaSWRXRjNaV2t4RXpBUkJnTlZCQXNNQ2toMVlYZGxhU0JEUWtjeEd6QVpCZ05WQkFNTUVucG9cbmIyNW5lR2xoYm1k"
|
||||
"ZmNtVnNaV0Z6WlRCMk1CQUdCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCRzEzc1J3RjJVeXVcblVTdFpoblJLV3ZKMkxHZGdOTGxEMk54cj"
|
||||
"RCRWtBUnVQVnB2aDBvMGV0UmpxSEFjZ1k3K0c1dmpobytLL01zSHlcbjVPeHJ3clBaenFmT2dsSjlvL2ZNakJNR2I2VUVzWS9ncE5xd1Vi"
|
||||
"WjNEdU5uZmt6VFo2QldMcU9DQVI4d2dnRWJcbk1COEdBMVVkSXdRWU1CYUFGSHU0UjFLbjhjeFludnRWN09FdGNRNEhtaThtTUIwR0ExVW"
|
||||
"REZ1FXQkJTcXAwa3Fcbi9UQ29tKzc2R2YrNzBGcjROYXAyNHpCR0JnTlZIU0FFUHpBOU1Ec0dCRlVkSUFBd016QXhCZ2dyQmdFRkJRY0Nc"
|
||||
"bkFSWWxhSFIwY0RvdkwyTndhMmt0WTJGM1pXSXVhSFZoZDJWcExtTnZiUzlqY0d0cEwyTndjekFPQmdOVkhROEJcbkFmOEVCQU1DQjRBd2"
|
||||
"JBWURWUjBmQkdVd1l6QmhvRitnWFlaYmFIUjBjRG92TDJOd2Eya3RZMkYzWldJdWFIVmhcbmQyVnBMbU52YlM5amNHdHBMM05sY25ac1pY"
|
||||
"UXZZM0pzUm1sc1pVUnZkMjR1WTNKc1AyTmxjblI1Y0dVOU1UUW1cbkwzTnZablJmYzJsbmJsOXpjblpmWTNKc0xtTnliREFUQmdOVkhTVU"
|
||||
"VEREFLQmdnckJnRUZCUWNEQXpBS0JnZ3Fcbmhrak9QUVFEQXdOb0FEQmxBakE1Y2VicEo2alQzL1A5b3N0S2V6UGl3cGRNODUvTnRneWp3"
|
||||
"QU4wQi82SUZIYlZcblNDWllMcStZcXNQYUt2SXh4RkVDTVFESUgxeDZUTVdwZmJNV2M4N0R5OTZ4Q0hLbEtsU0tkalM2dXZML210N2Zcbk"
|
||||
"YzT3o1QXIxZFhuVDRBSi9RYzFsUHNrPVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLVxuIiwiYnVuZGxlLW5hbWUiOiJjb20uaHVhd2Vp"
|
||||
"Lmhpd29ybGQuaGlkZW1vIiwiYXBwLWZlYXR1cmUiOiJob3Nfbm9ybWFsX2FwcCJ9LCJwZXJtaXNzaW9ucyI6eyJyZXN0cmljdGVkLXBlcm"
|
||||
"1pc3Npb25zIjpbImhhcm1vbnlvcy5wZXJtaXNzaW9uLkFOU1dFUl9QSE9ORV9DQUxMIiwiQkJCIl0sInJlc3RyaWN0ZWQtY2FwYWJpbGl0"
|
||||
"aWVzIjpbIkNDQyIsImRkZCJdfSwiaXNzdWVyIjoiSHVhd2VpIEFwcHMgU3RvcmUifaCCBj4wggMKMIICkaADAgECAghZsSoa86pPXTAKBg"
|
||||
"gqhkjOPQQDAzBYMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkg"
|
||||
"Q0JHIFJvb3QgQ0EgRzIgVGVzdDAeFw0yMDAzMTMxMTU4MjhaFw00MDAzMTMxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdW"
|
||||
"F3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3Qw"
|
||||
"djAQBgcqhkjOPQIBBgUrgQQAIgNiAAS6Q8NLezROlhr+UA0JNzt5fx90YaMw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0"
|
||||
"eR4RDhdJKbR3sxt6hgTKgQpZrUbb9I5DFtU2oot7HGUYyMy44t0xujggEVMIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjG"
|
||||
"xTAdBgNVHQ4EFgQUe7hHUqfxzFie+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQ"
|
||||
"cCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0"
|
||||
"cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLm"
|
||||
"NybDAKBggqhkjOPQQDAwNnADBkAjAXs+Mi444OGkOHOnDZypX/Fss0nkITEUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8ya"
|
||||
"t5jAqdzZsdeVLryuhJG81O+tQqnctyn3acozOJ6LIoeVYoSCtSOcpzCCAywwggKxoAMCAQICCC0zffQhq5r9MAoGCCqGSM49BAMDMGkxCz"
|
||||
"AJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUg"
|
||||
"U2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwHhcNMjAwNTA2MDcwMDE5WhcNMjMwNTA2MDcwMDE5WjBxMQswCQYDVQQGEwJDTjETMBEGA1UECg"
|
||||
"wKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0xLjAsBgNVBAMMJUhPUyBBcHBsaWNhdGlvbiBQcm92aXNpb24g"
|
||||
"UHJvZmlsZSBEZXYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARn9+yWcHv7JRXSe4bPNE6jQnMaPwRAwJOXn3hGvMoPJPCQKg+hYIoxU/"
|
||||
"XNOBxnfNbneRDaFToQGJuEAK8ljAWvo4IBOTCCATUwHwYDVR0jBBgwFoAUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFH4PO+Wo"
|
||||
"xfnSw6b2fU0tsRiDSeXuMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2"
|
||||
"Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2Vy"
|
||||
"dmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF9zaWduX3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDC"
|
||||
"sGAQQBj1sCgngBAwQIMAYCAQEKAQEwCgYIKoZIzj0EAwMDaQAwZgIxAOWOtWEhKZU2e11FBrOtaBnshDWzQJBi1RIB0uqicO/dGx7Vj7JA"
|
||||
"RD8ayn/zGtUzewIxAKHSW0bh2OmR2Eg3JnwufW0UXomUkm21Q72Dg6pY33wl6pHsuh1dX8hHFb72ZZPvcKGCBY4wggWKMIIFEgIBATAJBg"
|
||||
"cqhkjOPQQBMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBD"
|
||||
"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"
|
||||
"6RfHW0zQuwMzDSFUEEK6E4bUJMc7BikhRX4RcTq9oIIGHzCCAwowggKRoAMCAQICCFmxKhrzqk9dMAoGCCqGSM49BAMDMFgxCzAJBgNVBA"
|
||||
"YTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxIzAhBgNVBAMMGkh1YXdlaSBDQkcgUm9vdCBDQSBHMiBUZXN0"
|
||||
"MB4XDTIwMDMxMzExNTgyOFoXDTQwMDMxMzExNTgyOFowaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2"
|
||||
"VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDB2MBAGByqGSM49AgEGBSuBBAAi"
|
||||
"A2IABLpDw0t7NE6WGv5QDQk3O3l/H3RhozD1G77KN07ZQb83ZtFwzU3VbWat11Tn3n4KRDmgvyUqF4IjR5HhEOF0kptHezG3qGBMqBClmt"
|
||||
"Rtv0jkMW1Taii3scZRjIzLji3TG6OCARUwggERMB8GA1UdIwQYMBaAFGldwFjx9Tzm/QpA8R1gc9wceMbFMB0GA1UdDgQWBBR7uEdSp/HM"
|
||||
"WJ77VezhLXEOB5ovJjAPBgNVHRMBAf8EBTADAQH/MEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYX"
|
||||
"dlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIBBjBmBgNVHR8EXzBdMFugWaBXhlVodHRwOi8vY3BraS1jYXdlYi5odWF3"
|
||||
"ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xMCYvcm9vdF9nMl9jcmwuY3JsMAoGCCqGSM49BAMDA2cAMG"
|
||||
"QCMBez4yLjjg4aQ4c6cNnKlf8WyzSeQhMRSR8XMtQ9Gx5YxOcU7XLCDeNDGumhItzCUAIwB0C3wM2bzJq3mMCp3Nmx15UuvK6EkbzU761C"
|
||||
"qdy3KfdpyjM4nosih5VihIK1I5ynMIIDDTCCApOgAwIBAgIIbfFy5Sitw0MwCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMCQ04xDzANBgNVBA"
|
||||
"oMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0Eg"
|
||||
"VGVzdDAeFw0yMDA0MjgwMzIyMDdaFw0zMDA0MjgwMzIyMDdaMFAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCk"
|
||||
"h1YXdlaSBDQkcxGzAZBgNVBAMMEnpob25neGlhbmdfcmVsZWFzZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABG13sRwF2UyuUStZhnRKWvJ2"
|
||||
"LGdgNLlD2Nxr4BEkARuPVpvh0o0etRjqHAcgY7+G5vjho+K/MsHy5OxrwrPZzqfOglJ9o/fMjBMGb6UEsY/gpNqwUbZ3DuNnfkzTZ6BWLq"
|
||||
"OCAR8wggEbMB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBSqp0kq/TCom+76Gf+70Fr4Nap24zBGBgNVHSAE"
|
||||
"PzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4"
|
||||
"AwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2Nl"
|
||||
"cnR5cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBggrBgEFBQcDAzAKBggqhkjOPQQDAwNoADBlAjA5cebpJ6jT3/"
|
||||
"P9ostKezPiwpdM85/NtgyjwAN0B/6IFHbVSCZYLq+YqsPaKvIxxFECMQDIH1x6TMWpfbMWc87Dy96xCHKlKlSKdjS6uvL/mt7fF3Oz5Ar1"
|
||||
"dXnT4AJ/Qc1lPsmhggWOMIIFijCCBRICAQEwCQYHKoZIzj0EATBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDA"
|
||||
"pIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0Fw0yMDA0MTcwNzMzMzNa"
|
||||
"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"
|
||||
"AAAA5SEAAAAA";
|
||||
|
||||
const std::string HAP_FILE_RSA_SIGN_BASE64 =
|
||||
"UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAMAAQAcnNhX3Rlc3QuaGFw/soAADM0BABQSwcIdxVa1gQAAAACAAAAAgAAIFIVAAAYAAAAAA"
|
||||
"AAILEMAABqFQAAMIIVTgYJKoZIhvcNAQcCoIIVPzCCFTsCAQExDzANBglghkgBZQMEAgEFADCCB/sGCSqGSIb3DQEHAaCCB+wEggfoeyJ2"
|
||||
"ZXJzaW9uLW5hbWUiOiIxLjAuMCIsInZlcnNpb24tY29kZSI6MSwiYXBwLWRpc3RyaWJ1dGlvbi10eXBlIjoib3NfaW50ZWdyYXRpb24iLC"
|
||||
"J1dWlkIjoiOThBN0Y3NzItNTg0Qi00RUQ3LTk3M0QtQjA4ODNGMEYxOUVGIiwidmFsaWRpdHkiOnsibm90LWJlZm9yZSI6MTU4NjQyMjc0"
|
||||
"Mywibm90LWFmdGVyIjoxNjE3OTU4NzQzfSwidHlwZSI6InJlbGVhc2UiLCJidW5kbGUtaW5mbyI6eyJkZXZlbG9wZXItaWQiOiJ6aG9uZ3"
|
||||
"hpYW5nIiwiZGlzdHJpYnV0aW9uLWNlcnRpZmljYXRlIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlFVXpDQ0E5cWdBd0lC"
|
||||
"QWdJSWRFY05DbEFLNmU4d0NnWUlLb1pJemowRUF3TXdhVEVMTUFrR0ExVUVCaE1DXG5RMDR4RHpBTkJnTlZCQW9NQmtoMVlYZGxhVEVUTU"
|
||||
"JFR0ExVUVDd3dLU0hWaGQyVnBJRU5DUnpFME1ESUdBMVVFXG5Bd3dyU0hWaGQyVnBJRU5DUnlCVGIyWjBkMkZ5WlNCVGFXZHVhVzVuSUZO"
|
||||
"bGNuWnBZMlVnUTBFZ1ZHVnpkREFlXG5GdzB5TURBMU1Ea3dNalU0TlRCYUZ3MHlNVEExTURrd01qVTROVEJhTUU4eFRUQkxCZ05WQkFZTV"
|
||||
"JFTk9JRTg5XG5TSFZoZDJWcElFTkNSeUJQVlQxSVQxTWdSR1YyWld4dmNHMWxiblFnU1VSRklGUmxZVzBnUTA0OWFIZGZhR0Z3XG5hMlY1"
|
||||
"WDNKellWOXBaR1ZmWkdWMk1JSUJvakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBWThBTUlJQmlnS0NBWUVBXG5oM3VJalE1ZUhvL1pmMG5hVV"
|
||||
"J6L2VRZ0hnOHdzSUl5VEFYd3lYdGh2VDZ6TEdtcmpCbjBiOWhEeHcwbGJxU2NGXG4yamZLQzk3b0EyNlg1K2E2NmdGdzhzTnZQa29DaHJI"
|
||||
"T08yRloyMS9vUEVGbGYwK21NY3N4UjNDZUpkTTF1NmxvXG5samxncEF0TFZveFJiSTVqMW9SU3U5Vkw4aUFycHJIeEVnclFSbHV5aERzRm"
|
||||
"RtZHN3ZnROaWl1UDdidVhQeHFYXG5ISWxka0IwK0RFSzlvSHY0L0JRWnhoOFJFQlBuYjNCck45OFc4SnYrYWdIMzhPMlBxd1gyeDZHRFl2"
|
||||
"SSt6ODVLXG5uRFpCNlFPL3JTVjdiWVhuWXFkSDZJa3lGMzNuTzFnbVZ5T3lZQlF0azhLNE1mYkMrM29pWERwVzlxQnByUHJzXG4zek1ubz"
|
||||
"NLa1ZNMEpJdzFXVTFwK05nNk1lTDJja3JYRzYrV3lrM2x5QnNuZ2VDVEp6ejBaZ29JOTRFZWxNL3pxXG5tejZ6cTl5TUFpWTZnTWhTdWpJ"
|
||||
"a1pOendKQ3d1N1BMZXFrKzdyLy8rNGNXMEJJZ3Q5WElCTmdXd1FoOGdNWU9sXG5saHNxZmR4VWlUa1FpYnpZOXNQQ0J4bFBNWnJENW9WSX"
|
||||
"hJZ1IyTUZMRDVyam5CN0ZZUytJYU14bTV1NFBYYytCXG5BZ01CQUFHamdnRTVNSUlCTlRBZkJnTlZIU01FR0RBV2dCUjd1RWRTcC9ITVdK"
|
||||
"NzdWZXpoTFhFT0I1b3ZKakFkXG5CZ05WSFE0RUZnUVVmVFkwVGZhS0VjdWhhM1dPUHJnNE1XMDBaMHd3UmdZRFZSMGdCRDh3UFRBN0JnUl"
|
||||
"ZIU0FBXG5NRE13TVFZSUt3WUJCUVVIQWdFV0pXaDBkSEE2THk5amNHdHBMV05oZDJWaUxtaDFZWGRsYVM1amIyMHZZM0JyXG5hUzlqY0hN"
|
||||
"d0RnWURWUjBQQVFIL0JBUURBZ2VBTUd3R0ExVWRId1JsTUdNd1lhQmZvRjJHVzJoMGRIQTZMeTlqXG5jR3RwTFdOaGQyVmlMbWgxWVhkbG"
|
||||
"FTNWpiMjB2WTNCcmFTOXpaWEoyYkdWMEwyTnliRVpwYkdWRWIzZHVMbU55XG5iRDlqWlhKMGVYQmxQVEUwSmk5emIyWjBYM05wWjI1ZmMz"
|
||||
"SjJYMk55YkM1amNtd3dFd1lEVlIwbEJBd3dDZ1lJXG5Ld1lCQlFVSEF3TXdHQVlNS3dZQkJBR1BXd0tDZUFFREJBZ3dCZ0lCQVFvQkFEQU"
|
||||
"tCZ2dxaGtqT1BRUURBd05uXG5BREJrQWpCRHJGTUNiZzAyTUdoa0p3emhCdFVIbk85Ny9hMlNqVCs4bEpxTkpCTkhMWVh3VER1Kzg5a1Jj"
|
||||
"cG1zXG4rVFlCam5vQ01BL0dHUXJscTgrbldIZFNZMjkzY0hNcG5DZ09oNVJkdk5BRkRwNjlkU0NqSTdqTWc2YWN5Y2hHXG5qVlorTXVIY1"
|
||||
"VRPT1cbi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS1cbiIsImJ1bmRsZS1uYW1lIjoiY29tLmh1YXdlaS5oaXdvcmxkLmhpZGVtbyIsImFw"
|
||||
"cC1mZWF0dXJlIjoiaG9zX25vcm1hbF9hcHAifSwicGVybWlzc2lvbnMiOnsicmVzdHJpY3RlZC1wZXJtaXNzaW9ucyI6WyJhYWEiLCJCQk"
|
||||
"IiXX0sImlzc3VlciI6Ikh1YXdlaSBBcHBzIFN0b3JlIn2gggY+MIIDCjCCApGgAwIBAgIIWbEqGvOqT10wCgYIKoZIzj0EAwMwWDELMAkG"
|
||||
"A1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEjMCEGA1UEAwwaSHVhd2VpIENCRyBSb290IENBIEcyIF"
|
||||
"Rlc3QwHhcNMjAwMzEzMTE1ODI4WhcNNDAwMzEzMTE1ODI4WjBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApI"
|
||||
"dWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0MHYwEAYHKoZIzj0CAQYFK4"
|
||||
"EEACIDYgAEukPDS3s0TpYa/lANCTc7eX8fdGGjMPUbvso3TtlBvzdm0XDNTdVtZq3XVOfefgpEOaC/JSoXgiNHkeEQ4XSSm0d7MbeoYEyo"
|
||||
"EKWa1G2/SOQxbVNqKLexxlGMjMuOLdMbo4IBFTCCAREwHwYDVR0jBBgwFoAUaV3AWPH1POb9CkDxHWBz3Bx4xsUwHQYDVR0OBBYEFHu4R1"
|
||||
"Kn8cxYnvtV7OEtcQ4Hmi8mMA8GA1UdEwEB/wQFMAMBAf8wRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly9jcGtp"
|
||||
"LWNhd2ViLmh1YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgEGMGYGA1UdHwRfMF0wW6BZoFeGVWh0dHA6Ly9jcGtpLWNhd2ViLm"
|
||||
"h1YXdlaS5jb20vY3BraS9zZXJ2bGV0L2NybEZpbGVEb3duLmNybD9jZXJ0eXBlPTEwJi9yb290X2cyX2NybC5jcmwwCgYIKoZIzj0EAwMD"
|
||||
"ZwAwZAIwF7PjIuOODhpDhzpw2cqV/xbLNJ5CExFJHxcy1D0bHljE5xTtcsIN40Ma6aEi3MJQAjAHQLfAzZvMmreYwKnc2bHXlS68roSRvN"
|
||||
"TvrUKp3Lcp92nKMzieiyKHlWKEgrUjnKcwggMsMIICsaADAgECAggtM330Iaua/TAKBggqhkjOPQQDAzBpMQswCQYDVQQGEwJDTjEPMA0G"
|
||||
"A1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZS"
|
||||
"BDQSBUZXN0MB4XDTIwMDUwNjA3MDAxOVoXDTIzMDUwNjA3MDAxOVowcTELMAkGA1UEBhMCQ04xEzARBgNVBAoMCkh1YXdlaSBDQkcxHTAb"
|
||||
"BgNVBAsMFEhPUyBEZXZlbG9wbWVudCBUZWFtMS4wLAYDVQQDDCVIT1MgQXBwbGljYXRpb24gUHJvdmlzaW9uIFByb2ZpbGUgRGV2MFkwEw"
|
||||
"YHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ/fslnB7+yUV0nuGzzROo0JzGj8EQMCTl594RrzKDyTwkCoPoWCKMVP1zTgcZ3zW53kQ2hU6EBib"
|
||||
"hACvJYwFr6OCATkwggE1MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBR+DzvlqMX50sOm9n1NLbEYg0nl7j"
|
||||
"BGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8B"
|
||||
"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"
|
||||
"jOPQQDAwNoADBlAjEAglA0WoJZsnFBqx5hfi/KMCiYW6jlKm8Ll+1y/7yXKdx3h44l7u12ZmEPkALxz4VNAjAosFhWw5fBE8OFStuUG8IS"
|
||||
"/0IlH4kXwiei87Xjr4y0xFeYnm0DM/50tY+/6I90bKowggMKMIICkaADAgECAghZsSoa86pPXTAKBggqhkjOPQQDAzBYMQswCQYDVQQGEw"
|
||||
"JDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIgVGVzdDAe"
|
||||
"Fw0yMDAzMTMxMTU4MjhaFw00MDAzMTMxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaS"
|
||||
"BDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNi"
|
||||
"AAS6Q8NLezROlhr+UA0JNzt5fx90YaMw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0eR4RDhdJKbR3sxt6hgTKgQpZrUbb"
|
||||
"9I5DFtU2oot7HGUYyMy44t0xujggEVMIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjGxTAdBgNVHQ4EFgQUe7hHUqfxzFie"
|
||||
"+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZW"
|
||||
"IuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2Vp"
|
||||
"LmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBkAj"
|
||||
"AXs+Mi444OGkOHOnDZypX/Fss0nkITEUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8yat5jAqdzZsdeVLryuhJG81O+tQqnc"
|
||||
"tyn3acozOJ6LIoeVYoSCtSOcpzCCBFMwggPaoAMCAQICCHRHDQpQCunvMAoGCCqGSM49BAMDMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDA"
|
||||
"ZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRl"
|
||||
"c3QwHhcNMjAwNTA5MDI1ODUwWhcNMjEwNTA5MDI1ODUwWjBPMU0wSwYDVQQGDERDTiBPPUh1YXdlaSBDQkcgT1U9SE9TIERldmVsb3BtZW"
|
||||
"50IElERSBUZWFtIENOPWh3X2hhcGtleV9yc2FfaWRlX2RldjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAId7iI0OXh6P2X9J"
|
||||
"2lEc/3kIB4PMLCCMkwF8Ml7Yb0+syxpq4wZ9G/YQ8cNJW6knBdo3ygve6ANul+fmuuoBcPLDbz5KAoaxzjthWdtf6DxBZX9PpjHLMUdwni"
|
||||
"XTNbupaJY5YKQLS1aMUWyOY9aEUrvVS/IgK6ax8RIK0EZbsoQ7BXZnbMH7TYorj+27lz8alxyJXZAdPgxCvaB7+PwUGcYfERAT529wazff"
|
||||
"FvCb/moB9/Dtj6sF9sehg2LyPs/OSpw2QekDv60le22F52KnR+iJMhd95ztYJlcjsmAULZPCuDH2wvt6Ilw6Vvagaaz67N8zJ6NypFTNCS"
|
||||
"MNVlNafjYOjHi9nJK1xuvlspN5cgbJ4Hgkyc89GYKCPeBHpTP86ps+s6vcjAImOoDIUroyJGTc8CQsLuzy3qpPu6///uHFtASILfVyATYF"
|
||||
"sEIfIDGDpZYbKn3cVIk5EIm82PbDwgcZTzGaw+aFSMSIEdjBSw+a45wexWEviGjMZubuD13PgQIDAQABo4IBOTCCATUwHwYDVR0jBBgwFo"
|
||||
"AUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFH02NE32ihHLoWt1jj64ODFtNGdMMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsG"
|
||||
"AQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGgX6Bdhl"
|
||||
"todHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF9zaWdu"
|
||||
"X3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDCsGAQQBj1sCgngBAwQIMAYCAQEKAQAwCgYIKoZIzj0EAwMDZwAwZAIwQ6"
|
||||
"xTAm4NNjBoZCcM4QbVB5zve/2tko0/vJSajSQTRy2F8Ew7vvPZEXKZrPk2AY56AjAPxhkK5avPp1h3UmNvd3BzKZwoDoeUXbzQBQ6evXUg"
|
||||
"oyO4zIOmnMnIRo1WfjLh3FExggKbMIIClwIBATB1MGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKEwZIdWF3ZWkxEzARBgNVBAsTCkh1YXdlaS"
|
||||
"BDQkcxNDAyBgNVBAMTK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QCCHRHDQpQCunvMA0GCWCGSAFlAwQC"
|
||||
"AgUAoHkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwNzA4MDk0NDA0WjA/BgkqhkiG9w0BCQQxMgQwOL"
|
||||
"EvnL4cEWbEqTNF7esYgRUohGGQqh9+wFbegP6EXq8b6gT0J89i4SeKKCxdMJ3/MA0GCSqGSIb3DQEBCgUABIIBgHDm/h9/MGJdNAOJs4zk"
|
||||
"uP41PmnWSyjxGtoUzhNscXn0iO0Mw1NDMEsBzjXZBAoEvzQ8KxN4gXNFZ/Jlb8IZ4uSd0cKRWig9lSTP52mJwHbVXYG+AlU81nauqzieVw"
|
||||
"Wr4HQwXFONw4zJLyWm3ZWSw398kJ2S8nSamqvPOHWgKUIWNktPywNQk4yF4QY0gZ0AiA1AiGynkObkw88aPsLQ+afgsLCnXGzf42QSz5QM"
|
||||
"/l9DcBndUpL0palOLHGLcl4o+QaYHFa4ywHGc8m9tb/omiIGPs6YnmaNCbEOBB9dgMdExqbOpVw40aRRCc7Vz7WhW7gh0PS/sIlMOj2d8c"
|
||||
"DkWLAaDio8nRz8lmT+PUelubHt8svP2RMw5vI/j4CR9XVbL8qxhbZAYt0700f53ihuuGglh0ABhtpazSyT7bUcC8s/nXQVV5gmzw/aRlAa"
|
||||
"m+cArPFrDBen/P6ezF5PTqvcqenc5X9Lc97HXn0UZEluIQAStfs6J4hq3+YXbXJAVy5WJgIAAAA7IgAAAAAAAEhBUCBTaWcgQmxvY2sgND"
|
||||
"ICAAAAUEsBAhQAFAAICAgAAAAhOncVWtYEAAAAAgAAAAwABAAAAAAAAAAAAAAAAAAAAHJzYV90ZXN0LmhhcP7KAABQSwUGAAAAAAEAAQA+"
|
||||
"AAAAfSIAAAAA";
|
||||
|
||||
const std::string HAP_FILE_INNER =
|
||||
"UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAFAAQAMS50eHT+ygAAMzQ0NAQAUEsHCPfI+dsGAAAABAAAAAIAACBhEwAAGAAAAAAAACBVGQ"
|
||||
"AAeRMAADCCE10GCSqGSIb3DQEHAqCCE04wghNKAgEBMQ8wDQYJYIZIAWUDBAIBBQAwggYHBgkqhkiG9w0BBwGgggX4BIIF9HsidmVyc2lv"
|
||||
"bi1uYW1lIjoiMS4wLjAiLCJ2ZXJzaW9uLWNvZGUiOjEsImFwcC1kaXN0cmlidXRpb24tdHlwZSI6Im9zX2ludGVncmF0aW9uIiwidXVpZC"
|
||||
"I6Ijk5QTdGNzcyLTU4NEItNEVENy05NzNELUIwODgzRjBGMTlFRiIsInZhbGlkaXR5Ijp7Im5vdC1iZWZvcmUiOjE1ODg3NDc2MTUsIm5v"
|
||||
"dC1hZnRlciI6MTY4MzM1NTYxNX0sInR5cGUiOiJyZWxlYXNlIiwiYnVuZGxlLWluZm8iOnsiZGV2ZWxvcGVyLWlkIjoiaHVhd2VpIiwiZG"
|
||||
"lzdHJpYnV0aW9uLWNlcnRpZmljYXRlIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlESkRDQ0FxbWdBd0lCQWdJSVJyaDhw"
|
||||
"cTUwNEZFd0NnWUlLb1pJemowRUF3TXdhVEVMTUFrR0ExVUVCaE1DXG5RMDR4RHpBTkJnTlZCQW9NQmtoMVlYZGxhVEVUTUJFR0ExVUVDd3"
|
||||
"dLU0hWaGQyVnBJRU5DUnpFME1ESUdBMVVFXG5Bd3dyU0hWaGQyVnBJRU5DUnlCVGIyWjBkMkZ5WlNCVGFXZHVhVzVuSUZObGNuWnBZMlVn"
|
||||
"UTBFZ1ZHVnpkREFlXG5GdzB5TURBMU1EWXdOalV4TkRoYUZ3MHlNekExTURZd05qVXhORGhhTUdreEN6QUpCZ05WQkFZVEFrTk9NUk13XG"
|
||||
"5FUVlEVlFRS0RBcElkV0YzWldrZ1EwSkhNUjB3R3dZRFZRUUxEQlJJVDFNZ1JHVjJaV3h2Y0cxbGJuUWdWR1ZoXG5iVEVtTUNRR0ExVUVB"
|
||||
"d3dkU0U5VElFRndjR3hwWTJGMGFXOXVJRkJ5YjNacGMybHZiaUJFWlhZd1dUQVRCZ2NxXG5oa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQV"
|
||||
"MxYjZwS3FPVXo2WC9YMURNRThici9NaHlZdldyVHhVYnFQMlpYXG5UWk9iNk1tOUZoMno2YUtkdE43RVJ6N0hvVGNPbGpHQzBhU1BybHho"
|
||||
"UjdqNk8ySjBvNElCT1RDQ0FUVXdId1lEXG5WUjBqQkJnd0ZvQVVlN2hIVXFmeHpGaWUrMVhzNFMxeERnZWFMeVl3SFFZRFZSME9CQllFRk"
|
||||
"43ejA5RjUvajRkXG5nalRMK1pxajhjZ2U4RUNCTUVZR0ExVWRJQVEvTUQwd093WUVWUjBnQURBek1ERUdDQ3NHQVFVRkJ3SUJGaVZvXG5k"
|
||||
"SFJ3T2k4dlkzQnJhUzFqWVhkbFlpNW9kV0YzWldrdVkyOXRMMk53YTJrdlkzQnpNQTRHQTFVZER3RUIvd1FFXG5Bd0lIZ0RCc0JnTlZIUj"
|
||||
"hFWlRCak1HR2dYNkJkaGx0b2RIUndPaTh2WTNCcmFTMWpZWGRsWWk1b2RXRjNaV2t1XG5ZMjl0TDJOd2Eya3ZjMlZ5ZG14bGRDOWpjbXhH"
|
||||
"YVd4bFJHOTNiaTVqY213L1kyVnlkSGx3WlQweE5DWXZjMjltXG5kRjl6YVdkdVgzTnlkbDlqY213dVkzSnNNQk1HQTFVZEpRUU1NQW9HQ0"
|
||||
"NzR0FRVUZCd01ETUJnR0RDc0dBUVFCXG5qMXNDZ25nQkF3UUlNQVlDQVFFS0FRQXdDZ1lJS29aSXpqMEVBd01EYVFBd1pnSXhBTC9mNXQ5"
|
||||
"VGVxRStWcDVXXG5HOEgwVktxYWNFdGhVVmVzV1VKSTU3ZXRMclFkQ2dUY2haMjBqMC9Sc25oSCtsYWhmd0l4QUlOMWlpY2M3OUVhXG5Fb0"
|
||||
"9URFNZMUVzaFpucSsvaUkwallYMUlJNitnbjVKZmJmem14RG1VcEtIaEsyVjAzZEpKMFE9PVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0t"
|
||||
"LVxuIiwiYnVuZGxlLW5hbWUiOiIuKiIsImFwcC1mZWF0dXJlIjoiaG9zX3N5c3RlbV9hcHAifSwiaXNzdWVyIjoiSHVhd2VpIEFwcHMgU3"
|
||||
"RvcmUifaCCBkMwggMKMIICkaADAgECAghZsSoa86pPXTAKBggqhkjOPQQDAzBYMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMw"
|
||||
"EQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIgVGVzdDAeFw0yMDAzMTMxMTU4MjhaFw00MDAzMT"
|
||||
"MxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBD"
|
||||
"QkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAS6Q8NLezROlhr+UA0JNzt5fx90Ya"
|
||||
"Mw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0eR4RDhdJKbR3sxt6hgTKgQpZrUbb9I5DFtU2oot7HGUYyMy44t0xujggEV"
|
||||
"MIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjGxTAdBgNVHQ4EFgQUe7hHUqfxzFie+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BA"
|
||||
"UwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAO"
|
||||
"BgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRm"
|
||||
"lsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBkAjAXs+Mi444OGkOHOnDZypX/Fss0nkIT"
|
||||
"EUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8yat5jAqdzZsdeVLryuhJG81O+tQqnctyn3acozOJ6LIoeVYoSCtSOcpzCCAz"
|
||||
"EwggK3oAMCAQICCGv0psZNBT6MMAoGCCqGSM49BAMDMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdl"
|
||||
"aSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwHhcNMjAwNTA2MDcwMTEzWhcNMj"
|
||||
"MwNTA2MDcwMTEzWjB3MQswCQYDVQQGEwJDTjETMBEGA1UECgwKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0x"
|
||||
"NDAyBgNVBAMMK0hPUyBBcHBsaWNhdGlvbiBQcm92aXNpb24gUHJvZmlsZSBEZXZfRGVidWcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAA"
|
||||
"QdB9SYqO9atez14k6Jv6xX7TfE+m7gzj8ttU7P9+eGGBYCLRbs0LcNb6Z7krHq+8bUgnr0dffQfbhvJCaRp135o4IBOTCCATUwHwYDVR0j"
|
||||
"BBgwFoAUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFFTh4cdLADjM2EtQnZFreAUtdWZuMEYGA1UdIAQ/MD0wOwYEVR0gADAzMD"
|
||||
"EGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGg"
|
||||
"X6BdhltodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF"
|
||||
"9zaWduX3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDCsGAQQBj1sCgngBAwQIMAYCAQEKAQEwCgYIKoZIzj0EAwMDaAAw"
|
||||
"ZQIwfX/jQDoWeCvU+U285TgTBPgj8wMY9R2aR/UvL5eKwuDiMbEMWra/7OnGeG4tM6m/AjEA6ek/0qGNL+9QoxYs+p4NCcMERSN2fbLLaC"
|
||||
"OH/nqKKqzJfgMuBhsGEDylKsuAl7BuoYIFjjCCBYowggUSAgEBMAkGByqGSM49BAEwaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdl"
|
||||
"aTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdBcNMj"
|
||||
"AwNDE3MDczMzMzWhcNMjAwNDE3MTEzMzMzWjCCBEYwGQIIFDszO+/tkL4XDTIwMDQwOTAyMDU1MlowGQIIFIDfZVEvZV4XDTIwMDQxNzAx"
|
||||
"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"
|
||||
"swCQYDVQQGEwJDTjETMBEGA1UECgwKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0xJjAkBgNVBAMMHUhPUyBB"
|
||||
"cHBsaWNhdGlvbiBQcm92aXNpb24gRGV2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtW+qSqjlM+l/19QzBPG6/zIcmL1q08VG6j9mV0"
|
||||
"2Tm+jJvRYds+minbTexEc+x6E3DpYxgtGkj65cYUe4+jtidKOCATkwggE1MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0G"
|
||||
"A1UdDgQWBBTe89PRef4+HYI0y/mao/HIHvBAgTBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZW"
|
||||
"IuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4AwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2Vp"
|
||||
"LmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBg"
|
||||
"grBgEFBQcDAzAYBgwrBgEEAY9bAoJ4AQMECDAGAgEBCgEAMAoGCCqGSM49BAMDA2kAMGYCMQC/3+bfU3qhPlaeVhvB9FSqmnBLYVFXrFlC"
|
||||
"SOe3rS60HQoE3IWdtI9P0bJ4R/pWoX8CMQCDdYonHO/RGhKDkw0mNRLIWZ6vv4iNI2F9SCOvoJ+SX2385sQ5lKSh4StldN3SSdGhghFVMI"
|
||||
"IRUTCCENcCAQEwCQYHKoZIzj0EATBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYD"
|
||||
"VQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0Fw0yMDA1MTkwNDMyNDJaFw0yMDA1MTkwODMyNDJaMI"
|
||||
"IQCzAZAggRw8ia8W75jBcNMjAwNDIzMDkwNzQ1WjAZAggSPIRWNvcy6BcNMjAwNDIxMDczNTQ3WjAZAggSxqS2QKLsGRcNMjAwNDIyMDIw"
|
||||
"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";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAP_FILE_DATA_H
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HAP_TRUSTED_ROOT_CA_TEST_H
|
||||
#define HAP_TRUSTED_ROOT_CA_TEST_H
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
int CreatTrustedRootCA001(void);
|
||||
int FindMatchedRootTest001(void);
|
||||
int GetTrustedRootCAFromJsonTest001(void);
|
||||
#endif // HAP_TRUSTED_ROOT_CA_TEST_H
|
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_byte_buffer_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "securec.h"
|
||||
|
||||
#include "test_const.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
namespace {
|
||||
class HapByteBufferTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapByteBufferTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapByteBufferTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapByteBufferTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapByteBufferTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HapByteBuffer Constructor and overload function.
|
||||
* @tc.desc: The static function will return an object of HapByteBuffer;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, HapByteBuffer001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Run HapByteBuffer(buffer1).
|
||||
* @tc.expected: step1. The returned object is the same as buffer1.
|
||||
*/
|
||||
HapByteBuffer buffer1;
|
||||
HapByteBuffer buffer2(buffer1);
|
||||
bool judge = (buffer2.GetCapacity() == buffer1.GetCapacity()) &&
|
||||
(buffer2.GetPosition() == buffer1.GetPosition()) &&
|
||||
(buffer2.GetLimit() == buffer1.GetLimit()) && (buffer2.GetBufferPtr() == nullptr);
|
||||
ASSERT_TRUE(judge);
|
||||
/*
|
||||
* @tc.steps: step1. Run overloaded function =.
|
||||
* @tc.expected: step1. The left object is the same as right object.
|
||||
*/
|
||||
HapByteBuffer buffer3(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
buffer3.PutInt32(0, 0);
|
||||
HapByteBuffer buffer4(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
buffer4.PutInt32(0, TEST_HAPBYTEBUFFER_INT32_DATA);
|
||||
buffer3 = buffer4;
|
||||
ASSERT_TRUE(buffer3.IsEqual(buffer4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test a HapByteBuffer object's operation of GetInt and Put
|
||||
* @tc.desc: The static function will return data from HapByteBuffer's buffer
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, GetIntAndPutOperation001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Create an empty buffer and get data from it.
|
||||
* @tc.expected: step1. The return result is false.
|
||||
*/
|
||||
HapByteBuffer emptyBuffer;
|
||||
int dataInt32;
|
||||
ASSERT_FALSE(emptyBuffer.GetInt32(dataInt32));
|
||||
long long dataInt64;
|
||||
ASSERT_FALSE(emptyBuffer.GetInt64(dataInt64));
|
||||
unsigned short dataUInt16;
|
||||
ASSERT_FALSE(emptyBuffer.GetUInt16(0, dataUInt16));
|
||||
/*
|
||||
* @tc.steps: step2. Create a HapByteBuffer with one byte's buffer and get data from second byte.
|
||||
* @tc.expected: step2. The return result is false.
|
||||
*/
|
||||
HapByteBuffer testBuffer(1);
|
||||
char testChar = TEST_HAPBYTEBUFFER_CHAR_DATA;
|
||||
testBuffer.PutData(0, &testChar, sizeof(testChar));
|
||||
unsigned int dataUInt32;
|
||||
ASSERT_FALSE(testBuffer.GetUInt32(1, dataUInt32));
|
||||
ASSERT_FALSE(testBuffer.GetInt32(1, dataInt32));
|
||||
ASSERT_FALSE(testBuffer.GetInt64(1, dataInt64));
|
||||
ASSERT_FALSE(testBuffer.GetUInt16(1, dataUInt16));
|
||||
/*
|
||||
* @tc.steps: step3. Get data from negative position.
|
||||
* @tc.expected: step3. The return result is false.
|
||||
*/
|
||||
ASSERT_FALSE(testBuffer.GetInt64(TEST_HAPBYTEBUFFER_INVALID_INDEX, dataInt64));
|
||||
/*
|
||||
* @tc.steps: step4. Put data to buffer and get data from it.
|
||||
* @tc.expected: step4. The return data is same as which we put.
|
||||
*/
|
||||
HapByteBuffer testBuffer2(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
testBuffer2.PutByte(0, testChar);
|
||||
char testUInt16[TEST_HAPBYTEBUFFER_UINT16_LENGTH];
|
||||
errno_t err;
|
||||
err = memcpy_s(testUInt16, sizeof(testUInt16), &TEST_HAPBYTEBUFFER_UINT16_DATA,
|
||||
sizeof(TEST_HAPBYTEBUFFER_UINT16_DATA));
|
||||
ASSERT_EQ(err, EOK);
|
||||
testBuffer2.PutData(sizeof(char), testUInt16, sizeof(testUInt16));
|
||||
int testInt32 = TEST_HAPBYTEBUFFER_INT32_DATA;
|
||||
testBuffer2.PutInt32(sizeof(char) + sizeof(unsigned short), testInt32);
|
||||
char testInt64[TEST_HAPBYTEBUFFER_INT64_LENGTH];
|
||||
err = memcpy_s(testInt64, sizeof(testInt64), &TEST_HAPBYTEBUFFER_INT64_DATA,
|
||||
sizeof(TEST_HAPBYTEBUFFER_INT64_DATA));
|
||||
ASSERT_EQ(err, EOK);
|
||||
testBuffer2.PutData(TEST_HAPBYTEBUFFER_LENGTH - sizeof(testInt64), testInt64, sizeof(testInt64));
|
||||
ASSERT_TRUE(testBuffer2.GetUInt32(sizeof(char) + sizeof(unsigned short), dataUInt32));
|
||||
ASSERT_EQ(dataUInt32, TEST_HAPBYTEBUFFER_UINT32_DATA);
|
||||
ASSERT_TRUE(testBuffer2.GetInt32(sizeof(char) + sizeof(unsigned short), dataInt32));
|
||||
ASSERT_EQ(dataInt32, TEST_HAPBYTEBUFFER_INT32_DATA);
|
||||
ASSERT_TRUE(testBuffer2.GetInt64(TEST_HAPBYTEBUFFER_LENGTH - sizeof(testInt64), dataInt64));
|
||||
ASSERT_EQ(dataInt64, TEST_HAPBYTEBUFFER_INT64_DATA);
|
||||
ASSERT_TRUE(testBuffer2.GetUInt16(sizeof(char), dataUInt16));
|
||||
ASSERT_EQ(dataUInt16, TEST_HAPBYTEBUFFER_UINT16_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HapByteBuffer function of slice
|
||||
* @tc.desc: The static function will get an object after slice and detect it is right;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, Slice001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Set a fixed length buffer.
|
||||
* @tc.expected: step1. The return is same as value is set.
|
||||
*/
|
||||
HapByteBuffer buffer1(TEST_HAPBYTEBUFFER_LENGTH_2);
|
||||
buffer1.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
ASSERT_TRUE(buffer1.GetCapacity() == TEST_HAPBYTEBUFFER_LENGTH);
|
||||
/*
|
||||
* @tc.steps: step2. Slice buffer.
|
||||
* @tc.expected: step2. The return is the target length after slice.
|
||||
*/
|
||||
buffer1.PutInt32(0, TEST_HAPBYTEBUFFER_INT32_DATA);
|
||||
buffer1.PutInt32(sizeof(int), TEST_HAPBYTEBUFFER_INT32_DATA_2);
|
||||
buffer1.SetPosition(sizeof(int));
|
||||
buffer1.SetLimit(sizeof(int) + sizeof(int));
|
||||
buffer1.Slice();
|
||||
ASSERT_TRUE(buffer1.Remaining() == sizeof(int));
|
||||
/*
|
||||
* @tc.steps: step3. Get int32 from buffer1.
|
||||
* @tc.expected: step3. The return result is equal to TEST_HAPBYTEBUFFER_INT32_DATA_2.
|
||||
*/
|
||||
int testDataInt32;
|
||||
ASSERT_TRUE(buffer1.GetInt32(testDataInt32));
|
||||
ASSERT_EQ(testDataInt32, TEST_HAPBYTEBUFFER_INT32_DATA_2);
|
||||
/*
|
||||
* @tc.steps: step4. Slice continue, reset position and limit, and calculate if buffer has remain.
|
||||
* @tc.expected: step4. The return result is true.
|
||||
*/
|
||||
buffer1.Slice();
|
||||
buffer1.Clear();
|
||||
ASSERT_TRUE(buffer1.HasRemaining());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HapByteBuffer function of CopyPartialBuffer
|
||||
* @tc.desc: The static function will copy data from an object, detect the data is right;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, CopyPartialBuffer001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Copy 8 bytes data from 10st-position in a 15 bytes length buffer.
|
||||
* @tc.expected: step1. The return result is false.
|
||||
*/
|
||||
HapByteBuffer buffer1(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
buffer1.PutInt32(0, TEST_HAPBYTEBUFFER_INT32_DATA);
|
||||
buffer1.PutInt32(sizeof(int), TEST_HAPBYTEBUFFER_INT32_DATA_2);
|
||||
HapByteBuffer buffer2(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
buffer1.SetPosition(TEST_HAPBYTEBUFFER_POSITION);
|
||||
ASSERT_FALSE(buffer2.CopyPartialBuffer(buffer1, TEST_HAPBYTEBUFFER_LENGTH_2));
|
||||
/*
|
||||
* @tc.steps: step2. Copy 8 bytes data from first-position in a 15 bytes length buffer.
|
||||
* @tc.expected: step2. Buffer2 return is targeted value.
|
||||
*/
|
||||
buffer1.Clear();
|
||||
buffer2.CopyPartialBuffer(buffer1, TEST_HAPBYTEBUFFER_LENGTH_2);
|
||||
int target1;
|
||||
ASSERT_TRUE(buffer2.GetInt32(target1));
|
||||
ASSERT_EQ(target1, TEST_HAPBYTEBUFFER_INT32_DATA);
|
||||
int target2;
|
||||
ASSERT_TRUE(buffer2.GetInt32(target2));
|
||||
ASSERT_EQ(target2, TEST_HAPBYTEBUFFER_INT32_DATA_2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HapByteBuffer function of IsEqual001
|
||||
* @tc.desc: The static function will return two object whether is equal.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, IsEqual001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Create a buffer, and compare it with itself.
|
||||
* @tc.expected: step1. The return result is true.
|
||||
*/
|
||||
char testChar[TEST_HAPBYTEBUFFER_LENGTH] = "Hello, world!!";
|
||||
HapByteBuffer buffer1(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
buffer1.PutData(0, testChar, TEST_HAPBYTEBUFFER_LENGTH);
|
||||
ASSERT_TRUE(buffer1.IsEqual(buffer1));
|
||||
/*
|
||||
* @tc.steps: step2. Create another buffer and compare it with buffer1.
|
||||
* @tc.expected: step2. The return result is false.
|
||||
*/
|
||||
HapByteBuffer buffer2;
|
||||
ASSERT_FALSE(buffer1.IsEqual(buffer2));
|
||||
/*
|
||||
* @tc.steps: step3. Set length of buffer2 same as buffer1.
|
||||
* @tc.expected: step3. The return result is false.
|
||||
*/
|
||||
buffer2.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
ASSERT_FALSE(buffer1.IsEqual(buffer2));
|
||||
/*
|
||||
* @tc.steps: step4. Use copy constructor to create an buffer3, and compare it with buffer1.
|
||||
* @tc.expected: step4. The return result is true.
|
||||
*/
|
||||
HapByteBuffer buffer3(buffer1);
|
||||
ASSERT_TRUE(buffer1.IsEqual(buffer3));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HapByteBuffer function of IsEqual002
|
||||
* @tc.desc: The static function will return whether the value in buffer is equal to a string.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (HapByteBufferTest, IsEqual002, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Create a buffer and string, and compare.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
std::string testStr = "Hello, world!!!";
|
||||
HapByteBuffer buffer1;
|
||||
const HapByteBuffer& buffer2 = buffer1;
|
||||
buffer1 = buffer2;
|
||||
ASSERT_FALSE(buffer1.IsEqual(testStr));
|
||||
/*
|
||||
* @tc.steps: step2. Set length of buffer1 same as string.
|
||||
* @tc.expected: step2. The return is false.
|
||||
*/
|
||||
buffer1.SetCapacity(static_cast<int>(testStr.size()));
|
||||
ASSERT_FALSE(buffer1.IsEqual(testStr));
|
||||
/*
|
||||
* @tc.steps: step3. Put string to buffer1 and compare.
|
||||
* @tc.expected: step3. The return is true.
|
||||
*/
|
||||
for (int i = 0; i < static_cast<int>(testStr.size()); i++) {
|
||||
buffer1.PutByte(i, testStr[i]);
|
||||
}
|
||||
ASSERT_TRUE(buffer1.IsEqual(testStr));
|
||||
}
|
||||
}
|
@ -0,0 +1,445 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_cert_verify_openssl_utils_test.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "openssl/asn1.h"
|
||||
#include "openssl/x509.h"
|
||||
|
||||
#include "init/trusted_root_ca.h"
|
||||
#include "interfaces/hap_verify.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
bool Base64StringDecode(const std::string& base64String, HapByteBuffer& output)
|
||||
{
|
||||
std::unique_ptr<char[]> decodeBuffer = std::make_unique<char[]>(base64String.size());
|
||||
if (decodeBuffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char* input = reinterpret_cast<const unsigned char*>(base64String.c_str());
|
||||
int len = EVP_DecodeBlock(reinterpret_cast<unsigned char*>(decodeBuffer.get()), input, base64String.size());
|
||||
if (len <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
output.SetCapacity(len);
|
||||
output.PutData(0, decodeBuffer.get(), len);
|
||||
decodeBuffer.reset(nullptr);
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
|
||||
namespace {
|
||||
class HapCertVerifyOpensslUtilsTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapCertVerifyOpensslUtilsTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtilsTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
void HapCertVerifyOpensslUtilsTest::SetUp()
|
||||
{
|
||||
EnableDebugMode();
|
||||
}
|
||||
|
||||
void HapCertVerifyOpensslUtilsTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetSubjectFromX509 and GetIssuerFromX509 functions.
|
||||
* @tc.desc: Check whether GetSubjectFromX509 and GetIssuerFromX509 can be used to obtain the certificate information.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, GetCertInfo001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input an ECC self signed cert with PEM encoded.
|
||||
* @tc.expected: step1. The return is an X509 object.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(UAT_SOFT_SIGN_CA);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
/*
|
||||
* @tc.steps: step2. Find the CA certificate that signed certX509.
|
||||
* @tc.expected: step2. The return is an X509 object.
|
||||
*/
|
||||
X509* issuerCert = rootCertsObj.FindMatchedRoot(certX509);
|
||||
/*
|
||||
* @tc.steps: step3. Get subject of rootCertsObj and get issuer of certX509.
|
||||
* @tc.expected: step3. The subject is same as issuer.
|
||||
*/
|
||||
std::string subject;
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetSubjectFromX509(issuerCert, subject));
|
||||
std::string issuer;
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetIssuerFromX509(certX509, issuer));
|
||||
ASSERT_TRUE(subject.compare(issuer) == 0);
|
||||
X509_free(certX509);
|
||||
X509_free(issuerCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test CertVerify function
|
||||
* @tc.desc: Check whether the CertVerify function can be used to verify a certificate.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, CertVerify001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input an ECC self signed cert with PEM encoded.
|
||||
* @tc.expected: step1. The return is an X509 object.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
/*
|
||||
* @tc.steps: step2. Use all possible input to test CertVerify.
|
||||
* @tc.expected: step2. The return is verify result.
|
||||
*/
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CertVerify(nullptr, certX509));
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CertVerify(certX509, nullptr));
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::CertVerify(certX509, certX509));
|
||||
X509_free(certX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetX509CertFromBase64String function
|
||||
* @tc.desc: Verify whether the GetX509CertFromBase64String function can get an X509 cert from a Base64S string.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, Base64NotUrlSafeCertTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input string of ECC cert with base64 decode
|
||||
* @tc.expected: step1. The return is an X509 object.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromBase64String(BASE64_NOT_URL_SAFE_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
std::string subject;
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetSubjectFromX509(certX509, subject));
|
||||
X509_free(certX509);
|
||||
certX509 = nullptr;
|
||||
/*
|
||||
* @tc.steps: step2. Use the subject as an error input.
|
||||
* @tc.expected: step2. The return is nullptr.
|
||||
*/
|
||||
certX509 = HapCertVerifyOpensslUtils::GetX509CertFromBase64String(subject);
|
||||
ASSERT_TRUE(certX509 == nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetX509CrlFromDerBuffer function
|
||||
* @tc.desc: Verify whether the GetX509CrlFromDerBuffer function can get an X509 Crl from DerData.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, GetX509CrlFromDerBufferTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input invalid data.
|
||||
* @tc.expected: step1. The return is nullptr.
|
||||
*/
|
||||
HapByteBuffer crlBuffer;
|
||||
X509_CRL* crlX509 = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, 0);
|
||||
ASSERT_TRUE(crlX509 == nullptr);
|
||||
crlBuffer.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
crlX509 = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, 0);
|
||||
ASSERT_TRUE(crlX509 == nullptr);
|
||||
/*
|
||||
* @tc.steps: step2. Input a string of crl encoded by base64.
|
||||
* @tc.expected: step2. Ihe return is a crl object.
|
||||
*/
|
||||
ASSERT_TRUE(Base64StringDecode(BASE64_CRL, crlBuffer));
|
||||
crlX509 = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, crlBuffer.GetCapacity());
|
||||
std::string crlIssuer;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(nullptr, crlIssuer));
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(crlX509, crlIssuer));
|
||||
ASSERT_TRUE(crlX509 != nullptr);
|
||||
X509_CRL_free(crlX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetCertsChain function
|
||||
* @tc.desc: Verify whether the GetCertsChain function can get a trusted cert chain from certs.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, GetCertsChainTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use a certVisitSign included a self signed cert and an empty certsChain as input.
|
||||
* @tc.expected: step1. The return is false due to invalid input.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
CertChain certsChain;
|
||||
CertSign certVisitSign;
|
||||
certVisitSign[certX509] = false;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetCertsChain(certsChain, certVisitSign));
|
||||
/*
|
||||
* @tc.steps: step2. Push a self signed cert to certChain.
|
||||
* @tc.expected: step2. The return is false due to can not verify by root ca.
|
||||
*/
|
||||
certsChain.push_back(certX509);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetCertsChain(certsChain, certVisitSign));
|
||||
certVisitSign[certX509] = true;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetCertsChain(certsChain, certVisitSign));
|
||||
X509_free(certX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetSubjectFromX509 and GetIssuerFromX509 functions.
|
||||
* @tc.desc: The static function will return false due to invalid input;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, GetIssuerAndSubjectTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use nullptr as input to test GetSubjectFromX509.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
std::string subject;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetSubjectFromX509(nullptr, subject));
|
||||
/*
|
||||
* @tc.steps: step2. Use nullptr as input to test GetIssuerFromX509.
|
||||
* @tc.expected: step2. The return is false.
|
||||
*/
|
||||
std::string issuer;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetIssuerFromX509(nullptr, issuer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetSerialNumberFromX509 function.
|
||||
* @tc.desc: Verify whether the GetSerialNumberFromX509 function can get the SerialNumber from an X509 certificate.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, GetSerialNumberFromX509Test001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use nullptr as input to test GetSerialNumberFromX509.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
long long certSerialNumber;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::GetSerialNumberFromX509(nullptr, certSerialNumber));
|
||||
/*
|
||||
* @tc.steps: step2. Use real cert to test GetX509CertFromPemString.
|
||||
* @tc.expected: step2. the return is true.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetSerialNumberFromX509(certX509, certSerialNumber));
|
||||
X509_free(certX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test VerifyCertChainPeriodOfValidity function.
|
||||
* @tc.desc: Verify whether the VerifyCertChainPeriodOfValidity function can verify validity
|
||||
* period of a certificate chain.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, VerifyCertChainPeriodOfValidityTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input an empty certChain.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
CertChain certsChain;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, nullptr));
|
||||
/*
|
||||
* @tc.steps: step2. Input a nullptr signTime and a certChain with two cert.
|
||||
* @tc.expected: step2. The return is false.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromBase64String(BASE64_NOT_URL_SAFE_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
certsChain.push_back(certX509);
|
||||
certsChain.push_back(certX509);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, nullptr));
|
||||
/*
|
||||
* @tc.steps: step3. Input a signTime which out of period of validity.
|
||||
* @tc.expected: step3. The return is false.
|
||||
*/
|
||||
ASN1_OCTET_STRING* asnString = ASN1_OCTET_STRING_new();
|
||||
ASSERT_TRUE(asnString != nullptr);
|
||||
ASSERT_TRUE(ASN1_OCTET_STRING_set(asnString, reinterpret_cast<const unsigned char*>(TEST_ANS_TIME.c_str()),
|
||||
static_cast<int>(TEST_ANS_TIME.size())));
|
||||
ASN1_TYPE* time = ASN1_TYPE_new();
|
||||
ASSERT_TRUE(time != nullptr);
|
||||
ASN1_TYPE_set(time, V_ASN1_UTCTIME, asnString);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, time));
|
||||
/*
|
||||
* @tc.steps: step4. Input a certChain with two nullptr.
|
||||
* @tc.expected: step4. The return iis false.
|
||||
*/
|
||||
certsChain.clear();
|
||||
certsChain.push_back(nullptr);
|
||||
certsChain.push_back(nullptr);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, time));
|
||||
X509_free(certX509);
|
||||
ASN1_TYPE_free(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test VerifyCrl function.
|
||||
* @tc.desc: Verify whether the VerifyCrl function can verify a crl.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, VerifyCrlTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Input an empty certChain.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
CertChain certsChain;
|
||||
Pkcs7Context pkcs7Context;
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCrl(certsChain, nullptr, pkcs7Context));
|
||||
/*
|
||||
* @tc.steps: step2. Input a certChain with two nullptr.
|
||||
* @tc.expected: step2. the return is false.
|
||||
*/
|
||||
STACK_OF(X509_CRL)* crls = sk_X509_CRL_new_null();
|
||||
ASSERT_TRUE(crls != nullptr);
|
||||
certsChain.push_back(nullptr);
|
||||
certsChain.push_back(nullptr);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context));
|
||||
/*
|
||||
* @tc.steps: step3. Input valid certChain and null.
|
||||
* @tc.expected: step3. The return is true due to crl is optional.
|
||||
*/
|
||||
certsChain.clear();
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
certsChain.push_back(certX509);
|
||||
certsChain.push_back(certX509);
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context));
|
||||
/*
|
||||
* @tc.steps: step4. Input error certChain and crls.
|
||||
* @tc.expected: step4. The return is false.
|
||||
*/
|
||||
certsChain.clear();
|
||||
X509* root = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ROOTCERT);
|
||||
ASSERT_TRUE(root != nullptr);
|
||||
certsChain.push_back(root);
|
||||
certsChain.push_back(certX509);
|
||||
HapByteBuffer crlBuffer;
|
||||
ASSERT_TRUE(Base64StringDecode(BASE64_CRL, crlBuffer));
|
||||
X509_CRL* crlX509 = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, crlBuffer.GetCapacity());
|
||||
ASSERT_TRUE(crlX509 != nullptr);
|
||||
sk_X509_CRL_push(crls, crlX509);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context));
|
||||
/*
|
||||
* @tc.steps: step5. Input right certChain and crls.
|
||||
* @tc.expected: step5. The return is true.
|
||||
*/
|
||||
certsChain.clear();
|
||||
certsChain.push_back(root);
|
||||
certsChain.push_back(root);
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context));
|
||||
X509_free(certX509);
|
||||
X509_free(root);
|
||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test CompareX509Cert function
|
||||
* @tc.desc: Verify whether the CompareX509Cert function can compare two certificates.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, CompareX509CertTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use nullptr as input to test CompareX509Cert.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CompareX509Cert(nullptr, ECC_TEST_KEY));
|
||||
/*
|
||||
* @tc.steps: step2. The second cert is not a cert string.
|
||||
* @tc.expected: step2. the return is false.
|
||||
*/
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CompareX509Cert(certX509, ECC_TEST_KEY));
|
||||
/*
|
||||
* @tc.steps: step3. Input two same cert.
|
||||
* @tc.expected: step3. The return is true.
|
||||
*/
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::CompareX509Cert(certX509, ECC_TEST_CERT));
|
||||
X509_free(certX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test WriteX509CrlToStream function.
|
||||
* @tc.desc: Verify whether the WriteX509CrlToStream function can write crl to a file.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, WriteX509CrlToStreamTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use invalid input.
|
||||
* @tc.expected: step1. The file length is zero.
|
||||
*/
|
||||
std::ofstream crlFile;
|
||||
HapCertVerifyOpensslUtils::WriteX509CrlToStream(crlFile, nullptr);
|
||||
std::string filePath = "./test_crl";
|
||||
crlFile.open(filePath, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
|
||||
HapCertVerifyOpensslUtils::WriteX509CrlToStream(crlFile, nullptr);
|
||||
ASSERT_TRUE(crlFile.tellp() == 0);
|
||||
if (crlFile.is_open()) {
|
||||
crlFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test private function
|
||||
* @tc.desc: The static function will return result of invalid input;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCertVerifyOpensslUtilsTest, PrivateFuncInvalidInputTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. Use invalid input.
|
||||
* @tc.expected: step1. The return is false.
|
||||
*/
|
||||
CertSign certVisitSign;
|
||||
HapCertVerifyOpensslUtils::GenerateCertSignFromCertStack(nullptr, certVisitSign);
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::FindCertOfIssuer(nullptr, certVisitSign) == nullptr);
|
||||
std::string str = HapCertVerifyOpensslUtils::GetDnToString(nullptr);
|
||||
ASSERT_FALSE(str.size() > 0);
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetCrlBySignedCertIssuer(nullptr, nullptr) == nullptr);
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::X509NameCompare(nullptr, nullptr));
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CheckSignTimeInValidPeriod(nullptr, nullptr, nullptr));
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CheckAsn1TimeIsValid(nullptr));
|
||||
ASSERT_FALSE(HapCertVerifyOpensslUtils::CheckAsn1TypeIsValid(nullptr));
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_crl_manager_test.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "init/hap_crl_manager.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
#include "hap_cert_verify_openssl_utils_test.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
const std::string HAP_CRL_TEST_BACKUP_FILE_PATH = "/data/system/hap_crl_backup_test";
|
||||
|
||||
enum CopyFileState {
|
||||
NO_SOURCE_FILE = 0,
|
||||
COPY_FAIL,
|
||||
COPY_SUC,
|
||||
};
|
||||
|
||||
CopyFileState CopyFile(const std::string& sourceFilePath, const std::string& destFilePath)
|
||||
{
|
||||
std::ifstream source;
|
||||
std::ofstream dest;
|
||||
source.open(sourceFilePath.c_str(), std::ios::in);
|
||||
if (!source.is_open()) {
|
||||
return NO_SOURCE_FILE;
|
||||
}
|
||||
dest.open(destFilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
if (!dest.is_open()) {
|
||||
source.close();
|
||||
return COPY_FAIL;
|
||||
}
|
||||
dest << source.rdbuf();
|
||||
source.close();
|
||||
dest.close();
|
||||
return COPY_SUC;
|
||||
}
|
||||
|
||||
bool ClearFile(const std::string& filePath)
|
||||
{
|
||||
std::ofstream fileStream;
|
||||
fileStream.open(filePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
if (!fileStream.is_open()) {
|
||||
return false;
|
||||
}
|
||||
fileStream.close();
|
||||
return true;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
|
||||
namespace {
|
||||
class HapCrlManagerTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapCrlManagerTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapCrlManagerTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapCrlManagerTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapCrlManagerTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test Write and Read Crl function
|
||||
* @tc.desc: The static function will return whether file written can be read;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapCrlManagerTest, WriteAndReadCrlsFileTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. backup crl file
|
||||
* @tc.expected: step1. ret will be success if crl file is exist, or ret will be NO_SOURCE_FILE.
|
||||
*/
|
||||
CopyFileState ret = CopyFile(HapCrlManager::HAP_CRL_FILE_PATH, HAP_CRL_TEST_BACKUP_FILE_PATH);
|
||||
ASSERT_TRUE(ret != COPY_FAIL);
|
||||
/*
|
||||
* @tc.steps: step2. update a crl to crl manager and write crls to file
|
||||
* @tc.expected: step2. binary code of crls is written to file.
|
||||
*/
|
||||
HapByteBuffer crlBuffer;
|
||||
ASSERT_TRUE(Base64StringDecode(BASE64_CRL, crlBuffer));
|
||||
X509_CRL* crlX509 = HapCertVerifyOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, crlBuffer.GetCapacity());
|
||||
ASSERT_TRUE(crlX509 != nullptr);
|
||||
std::string crlIssuer;
|
||||
ASSERT_TRUE(HapCertVerifyOpensslUtils::GetIssuerFromX509Crl(crlX509, crlIssuer));
|
||||
HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
|
||||
hapCrlManager.UpdateCrlByIssuer(crlIssuer, nullptr);
|
||||
hapCrlManager.UpdateCrlByIssuer(crlIssuer, crlX509);
|
||||
hapCrlManager.WriteCrlsToFile();
|
||||
X509_CRL_free(crlX509);
|
||||
/*
|
||||
* @tc.steps: step3. read crl file.
|
||||
* @tc.expected: step3. crl file can be read and parse rightly.
|
||||
*/
|
||||
HapByteBuffer crlsBuffer;
|
||||
ASSERT_TRUE(hapCrlManager.ReadCrls(crlsBuffer));
|
||||
ASSERT_TRUE(crlsBuffer.HasRemaining());
|
||||
ASSERT_TRUE(hapCrlManager.ParseCrls(crlsBuffer));
|
||||
/*
|
||||
* @tc.steps: step4. recovery crl file.
|
||||
* @tc.expected: step4. if backup result is NO_SOURCE_FILE, crl file will be clear.
|
||||
*/
|
||||
if (ret == NO_SOURCE_FILE) {
|
||||
ASSERT_TRUE(ClearFile(HapCrlManager::HAP_CRL_FILE_PATH));
|
||||
} else {
|
||||
ASSERT_TRUE(CopyFile(HAP_CRL_TEST_BACKUP_FILE_PATH, HapCrlManager::HAP_CRL_FILE_PATH) == COPY_SUC);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_signing_block_utils_test.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/hap_byte_buffer_data_source.h"
|
||||
#include "common/random_access_file.h"
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace OHOS {
|
||||
namespace Security {
|
||||
namespace Verify {
|
||||
void CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob, HapSubSignBlockHead& profileBlob,
|
||||
HapSubSignBlockHead& propertyBlob)
|
||||
{
|
||||
signBlob.type = HAP_SIGN_BLOB;
|
||||
signBlob.length = TEST_FILE_BLOCK_LENGTH;
|
||||
signBlob.offset = sizeof(HapSubSignBlockHead) * TEST_FILE_BLOCK_COUNT;
|
||||
profileBlob.type = PROFILE_BLOB;
|
||||
profileBlob.length = TEST_FILE_BLOCK_LENGTH;
|
||||
profileBlob.offset = signBlob.offset + signBlob.length;
|
||||
propertyBlob.type = PROPERTY_BLOB;
|
||||
propertyBlob.length = TEST_FILE_BLOCK_LENGTH;
|
||||
propertyBlob.offset = profileBlob.offset + profileBlob.length;
|
||||
}
|
||||
|
||||
long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo)
|
||||
{
|
||||
std::ofstream hapFile(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
if (!hapFile.is_open()) {
|
||||
return 0;
|
||||
}
|
||||
char block[TEST_FILE_BLOCK_LENGTH] = {0};
|
||||
/* input contents of ZIP entries */
|
||||
hapFile.seekp(0, std::ios_base::beg);
|
||||
hapFile.write(block, sizeof(block));
|
||||
/* input sign block */
|
||||
HapSubSignBlockHead signBlob;
|
||||
HapSubSignBlockHead profileBlob;
|
||||
HapSubSignBlockHead propertyBlob;
|
||||
CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob);
|
||||
hapFile.write(reinterpret_cast<char*>(&signBlob), sizeof(signBlob));
|
||||
hapFile.write(reinterpret_cast<char*>(&profileBlob), sizeof(profileBlob));
|
||||
hapFile.write(reinterpret_cast<char*>(&propertyBlob), sizeof(propertyBlob));
|
||||
for (int i = 0; i < TEST_FILE_BLOCK_COUNT; i++) {
|
||||
hapFile.write(block, sizeof(block));
|
||||
}
|
||||
int blockCount = TEST_FILE_BLOCK_COUNT;
|
||||
hapFile.write(reinterpret_cast<char*>(&blockCount), sizeof(blockCount));
|
||||
long long signBlockSize = (sizeof(HapSubSignBlockHead) + sizeof(block)) * TEST_FILE_BLOCK_COUNT +
|
||||
HapSigningBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
|
||||
hapFile.write(reinterpret_cast<char*>(&signBlockSize), sizeof(signBlockSize));
|
||||
long long magic = HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW;
|
||||
hapFile.write(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
magic = HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH;
|
||||
hapFile.write(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
int version = 1;
|
||||
hapFile.write(reinterpret_cast<char*>(&version), sizeof(version));
|
||||
/* input central direction */
|
||||
hapFile.write(block, sizeof(block));
|
||||
/* input end of central direction */
|
||||
int zidEocdSign = HapSigningBlockUtils::ZIP_EOCD_SEGMENT_FLAG;
|
||||
hapFile.write(reinterpret_cast<char*>(&zidEocdSign), sizeof(zidEocdSign));
|
||||
hapFile.write(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
unsigned int centralDirLen = sizeof(block);
|
||||
hapFile.write(reinterpret_cast<char*>(¢ralDirLen), sizeof(centralDirLen));
|
||||
unsigned int centralDirOffset = TEST_FILE_BLOCK_LENGTH + signBlockSize;
|
||||
hapFile.write(reinterpret_cast<char*>(¢ralDirOffset), sizeof(centralDirOffset));
|
||||
short eocdCommentLen = 0;
|
||||
hapFile.write(reinterpret_cast<char*>(&eocdCommentLen), sizeof(eocdCommentLen));
|
||||
hapFile.close();
|
||||
signInfo.hapCentralDirOffset = centralDirOffset;
|
||||
signInfo.hapEocdOffset = centralDirOffset + centralDirLen;
|
||||
signInfo.hapSignatureBlock.SetCapacity(TEST_FILE_BLOCK_LENGTH);
|
||||
signInfo.hapSignatureBlock.PutData(0, block, sizeof(block));
|
||||
long long sumLen = signInfo.hapEocdOffset + sizeof(zidEocdSign) + sizeof(centralDirLen) +
|
||||
sizeof(centralDirOffset) + sizeof(magic) + sizeof(eocdCommentLen);
|
||||
return sumLen;
|
||||
}
|
||||
} // namespace Verify
|
||||
} // namespace Security
|
||||
} // namespace OHOS
|
||||
|
||||
namespace {
|
||||
class HapSigningBlockUtilsTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
|
||||
static const int TEST_ZIP_BLOCKS_NUM_NEED_DIGEST;
|
||||
};
|
||||
|
||||
const int HapSigningBlockUtilsTest::TEST_ZIP_BLOCKS_NUM_NEED_DIGEST = 3;
|
||||
|
||||
void HapSigningBlockUtilsTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapSigningBlockUtilsTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapSigningBlockUtilsTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapSigningBlockUtilsTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test FindHapSignature function
|
||||
* @tc.desc: input one right file and two error file, The static function will return correct result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, FindHapSignatureTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. create a test zip file.
|
||||
*/
|
||||
std::string pathFile = "./test_hapverify.hap";
|
||||
SignatureInfo signInfo;
|
||||
int sumLen = CreatTestZipFile(pathFile, signInfo);
|
||||
/*
|
||||
* @tc.steps: step2. test FindHapSignature function
|
||||
* @tc.expected: step2. the return will be true.
|
||||
*/
|
||||
RandomAccessFile hapTestFile;
|
||||
ASSERT_TRUE(hapTestFile.Init(pathFile));
|
||||
ASSERT_EQ(hapTestFile.GetLength(), sumLen);
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
SignatureInfo hapSignInfo;
|
||||
ASSERT_TRUE(hapSignBlockUtils.FindHapSignature(hapTestFile, hapSignInfo));
|
||||
/*
|
||||
* @tc.steps: step3. make central offset error, and test FindHapSignature function
|
||||
* @tc.expected: step3. can not find central direction, the return will be false.
|
||||
*/
|
||||
std::ofstream hapFile;
|
||||
hapFile.open(pathFile.c_str(), std::ios::binary | std::ios::out);
|
||||
ASSERT_TRUE(hapFile.is_open());
|
||||
hapFile.seekp(sumLen - TEST_FILE_CD_OFFSET_POSITION, std::ios_base::beg);
|
||||
unsigned int errorCentralDirOffset = 20;
|
||||
hapFile.write(reinterpret_cast<char*>(&errorCentralDirOffset), sizeof(errorCentralDirOffset));
|
||||
hapFile.close();
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindHapSignature(hapTestFile, hapSignInfo));
|
||||
/*
|
||||
* @tc.steps: step4. make eocdCommentLen error, and test FindHapSignature function
|
||||
* @tc.expected: step4. can not find eocd, the return will be false.
|
||||
*/
|
||||
std::ofstream hapFile2;
|
||||
hapFile2.open(pathFile.c_str(), std::ios::binary | std::ios::out);
|
||||
ASSERT_TRUE(hapFile2.is_open());
|
||||
short errorEocdCommentLen = 10;
|
||||
hapFile2.write(reinterpret_cast<char*>(&errorEocdCommentLen), sizeof(errorEocdCommentLen));
|
||||
hapFile2.close();
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindHapSignature(hapTestFile, hapSignInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test VerifyHapIntegrity function
|
||||
* @tc.desc: create a file and input error digest, The static function will return false;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, VerifyHapIntegrityTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. create a test zip file without eocd.
|
||||
*/
|
||||
std::string pathFile = "./test_hapverify.hap";
|
||||
SignatureInfo signInfo;
|
||||
CreatTestZipFile(pathFile, signInfo);
|
||||
/*
|
||||
* @tc.steps: step2. create an error digest to test VerifyHapIntegrity function
|
||||
* @tc.expected: step2. the return will be false.
|
||||
*/
|
||||
Pkcs7Context digestInfo;
|
||||
digestInfo.content.SetCapacity(TEST_FILE_BLOCK_LENGTH);
|
||||
RandomAccessFile hapTestFile;
|
||||
hapTestFile.Init(pathFile);
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
ASSERT_FALSE(hapSignBlockUtils.VerifyHapIntegrity(digestInfo, hapTestFile, signInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test FindEocdInHap function
|
||||
* @tc.desc: create a file with invalid length, The function will return false;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, FindEocdInHapTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. create a test file with invalid length.
|
||||
*/
|
||||
std::string pathFile = "./test_hapverify.hap";
|
||||
std::ofstream hapFile;
|
||||
hapFile.open(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile.is_open());
|
||||
unsigned int centralDirLen = TEST_FILE_BLOCK_LENGTH;
|
||||
hapFile.write(reinterpret_cast<char*>(¢ralDirLen), sizeof(centralDirLen));
|
||||
hapFile.close();
|
||||
/*
|
||||
* @tc.steps: step2. run function
|
||||
* @tc.expected: step2. the return will be false.
|
||||
*/
|
||||
RandomAccessFile hapTestFile;
|
||||
hapTestFile.Init(pathFile);
|
||||
std::pair<HapByteBuffer, long long> eocd;
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindEocdInHap(hapTestFile, eocd));
|
||||
int maxCommentSize = TEST_INVALID_MAX_COMMENT_SIZE;
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindEocdInHap(hapTestFile, maxCommentSize, eocd));
|
||||
maxCommentSize = TEST_MAX_COMMENT_SIZE;
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindEocdInHap(hapTestFile, maxCommentSize, eocd));
|
||||
HapByteBuffer testHapBuffer(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
int offset = 0;
|
||||
ASSERT_FALSE(hapSignBlockUtils.FindEocdInSearchBuffer(testHapBuffer, offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetCentralDirectoryOffset function
|
||||
* @tc.desc: create an ecod with invalid central offset and length,
|
||||
* The function will return TEST_NOT_FIND_TARGET_OFFSET;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, GetCentralDirectoryOffsetTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. create a test eocd with invalid central offset and length.
|
||||
*/
|
||||
HapByteBuffer testEocd(TEST_ZIP_EOCD_SIZE);
|
||||
int centralDirLen = TEST_FILE_BLOCK_LENGTH;
|
||||
testEocd.PutInt32(TEST_ZIP_ECD_SIZE_FIELD_OFFSET, centralDirLen);
|
||||
int centralDirOffset = TEST_FILE_BLOCK_LENGTH;
|
||||
testEocd.PutInt32(TEST_ZIP_ECD_OFFSET_FIELD_OFFSET, centralDirOffset);
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
ASSERT_FALSE(hapSignBlockUtils.SetUnsignedInt32(testEocd, 0, TEST_INVALID_MAX_COMMENT_SIZE));
|
||||
HapByteBuffer emptyEocd;
|
||||
/*
|
||||
* @tc.steps: step2. run function with error eocdoffset
|
||||
* @tc.expected: step2. the return will be NOT_FIND_TARGET_OFFSET.
|
||||
*/
|
||||
long long offset;
|
||||
ASSERT_FALSE(hapSignBlockUtils.GetCentralDirectoryOffset(emptyEocd, 0, offset));
|
||||
ASSERT_FALSE(hapSignBlockUtils.GetCentralDirectoryOffset(testEocd, 0, offset));
|
||||
ASSERT_FALSE(hapSignBlockUtils.GetCentralDirectoryOffset(testEocd, TEST_FILE_BLOCK_LENGTH, offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test ClassifyHapSubSigningBlock function
|
||||
* @tc.desc: test function of classify optional block
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, ClassifyHapSubSigningBlock001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. run function with input of property block
|
||||
* @tc.expected: step1. the return signInfo.optionBlocks has property block which inputed.
|
||||
*/
|
||||
SignatureInfo signInfo;
|
||||
HapByteBuffer subBlock;
|
||||
unsigned int type = PROPERTY_BLOB;
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
hapSignBlockUtils.ClassifyHapSubSigningBlock(signInfo, subBlock, type);
|
||||
ASSERT_FALSE(signInfo.optionBlocks.empty());
|
||||
ASSERT_TRUE(signInfo.optionBlocks[0].optionalType == PROPERTY_BLOB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test ComputeDigestsWithOptionalBlock function
|
||||
* @tc.desc: use an error nid and a right nid to compute digest
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, ComputeDigestsWithOptionalBlock001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. run function with an error nid and a right nid
|
||||
* @tc.expected: step1. the return will be false and right respectively.
|
||||
*/
|
||||
OptionalBlock testOptionalBlock;
|
||||
testOptionalBlock.optionalType = PROPERTY_BLOB;
|
||||
testOptionalBlock.optionalBlockValue.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
std::vector<OptionalBlock> optionalBlocks;
|
||||
optionalBlocks.push_back(testOptionalBlock);
|
||||
HapSigningBlockUtils hapSignBlockUtils;
|
||||
HapByteBuffer chunkDigest(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
HapByteBuffer finalDigest;
|
||||
int nid = TEST_NULL_NID;
|
||||
DigestParameter errorParam = hapSignBlockUtils.GetDigestParameter(nid);
|
||||
int ret = hapSignBlockUtils.ComputeDigestsWithOptionalBlock(errorParam, optionalBlocks, chunkDigest, finalDigest);
|
||||
ASSERT_FALSE(ret);
|
||||
nid = TEST_SHA256_NID;
|
||||
DigestParameter digestParam = hapSignBlockUtils.GetDigestParameter(nid);
|
||||
ret = hapSignBlockUtils.ComputeDigestsWithOptionalBlock(digestParam, optionalBlocks, chunkDigest, finalDigest);
|
||||
ASSERT_TRUE(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetSumOfChunkDigestLen function
|
||||
* @tc.desc: Test GetSumOfChunkDigestLen with some error inputs
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapSigningBlockUtilsTest, GetSumOfChunkDigestLenTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input some error input to test GetSumOfChunkDigestLen
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
int chunkCount = 0;
|
||||
int sumOfChunkDigestLen = 0;
|
||||
DataSource* contents[TEST_ZIP_BLOCKS_NUM_NEED_DIGEST] = { nullptr, nullptr, nullptr };
|
||||
bool ret = HapSigningBlockUtils::GetSumOfChunkDigestLen(contents, 0, 0, chunkCount, sumOfChunkDigestLen);
|
||||
ASSERT_FALSE(ret);
|
||||
ret = HapSigningBlockUtils::GetSumOfChunkDigestLen(contents,
|
||||
TEST_ZIP_BLOCKS_NUM_NEED_DIGEST, 0, chunkCount, sumOfChunkDigestLen);
|
||||
ASSERT_FALSE(ret);
|
||||
HapByteBuffer testBuffer(TEST_ZIP_EOCD_SIZE);
|
||||
HapByteBufferDataSource testSource(testBuffer);
|
||||
for (int i = 0; i < TEST_ZIP_BLOCKS_NUM_NEED_DIGEST; i++) {
|
||||
contents[i] = &testSource;
|
||||
}
|
||||
ret = HapSigningBlockUtils::GetSumOfChunkDigestLen(contents,
|
||||
TEST_ZIP_BLOCKS_NUM_NEED_DIGEST, INT_MAX, chunkCount, sumOfChunkDigestLen);
|
||||
ASSERT_FALSE(ret);
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_verify_openssl_utils_test.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "openssl/x509.h"
|
||||
|
||||
#include "util/hap_verify_openssl_utils.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace {
|
||||
class HapVerifyOpensslUtilsTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapVerifyOpensslUtilsTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyOpensslUtilsTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
void HapVerifyOpensslUtilsTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyOpensslUtilsTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test VerifyPkcs7 functions
|
||||
* @tc.desc: use invalid input to verify pkcs7, The function will return false;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyOpensslUtilsTest, VerifyPkcs7_001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. use a null input to run OpensslVerifyPkcs7
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
Pkcs7Context digest;
|
||||
ASSERT_FALSE(HapVerifyOpensslUtils::VerifyPkcs7SignedData(digest));
|
||||
ASSERT_FALSE(HapVerifyOpensslUtils::VerifySignInfo(nullptr, nullptr, 0, digest));
|
||||
ASSERT_FALSE(HapVerifyOpensslUtils::VerifyShaWithRsaPss(nullptr, nullptr, true, nullptr, 0));
|
||||
std::vector<std::string> publicKeyVec;
|
||||
ASSERT_FALSE(HapVerifyOpensslUtils::GetPublickeyFromCertificate(nullptr, publicKeyVec));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetDigestAlgorithmId functions
|
||||
* @tc.desc: use different algorithm IDs to run this function, The function will return nid
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyOpensslUtilsTest, GetDigestAlgorithmId001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. use different algorithm IDs to run OpensslVerifyPkcs7
|
||||
* @tc.expected: step1. the return will be nID.
|
||||
*/
|
||||
int nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(ALGORITHM_SHA512_WITH_RSA_PSS);
|
||||
ASSERT_TRUE(nId == TEST_SHA512_NID);
|
||||
nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(ALGORITHM_SHA384_WITH_RSA_PSS);
|
||||
ASSERT_TRUE(nId == TEST_SHA384_NID);
|
||||
nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(ALGORITHM_SHA256_WITH_RSA_PSS);
|
||||
ASSERT_TRUE(nId == TEST_SHA256_NID);
|
||||
nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(0);
|
||||
ASSERT_TRUE(nId == 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_verify_result_test.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
#include "util/hap_signing_block_utils.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
namespace {
|
||||
class HapVerifyResultTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapVerifyResultTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyResultTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyResultTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyResultTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetPublicKey and GetSignature function
|
||||
* @tc.desc: The static function return publickey and signature will be null;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyResultTest, GetPublicKeyAndSignature001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. set a null buffer to HapVerifyResult as data package of pkcs7,
|
||||
* and do GetPublicKey and GetSignature.
|
||||
* @tc.expected: step1. the return vector of string is null.
|
||||
*/
|
||||
HapByteBuffer testBuffer;
|
||||
HapVerifyResult hapVerifyResult;
|
||||
hapVerifyResult.SetPkcs7SignBlock(testBuffer);
|
||||
std::vector<string> publicKeys = hapVerifyResult.GetPublicKey();
|
||||
ASSERT_TRUE(publicKeys.empty());
|
||||
std::vector<string> signatures = hapVerifyResult.GetSignature();
|
||||
ASSERT_TRUE(signatures.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test SetOptionalBlocks and GetProfile GetProperty function
|
||||
* @tc.desc: The static function will return no profile and have a property;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyResultTest, GetProfileAndProperty001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. set an option with property to HapVerifyResult
|
||||
*/
|
||||
std::vector<OptionalBlock> option;
|
||||
HapVerifyResult hapVerifyResult;
|
||||
OptionalBlock testblock;
|
||||
testblock.optionalType = PROPERTY_BLOB;
|
||||
testblock.optionalBlockValue.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH);
|
||||
option.push_back(testblock);
|
||||
hapVerifyResult.SetOptionalBlocks(option);
|
||||
/*
|
||||
* @tc.steps: step2. GetProfile and detect it right.
|
||||
* @tc.expected: step2. the return code will be NO_THIS_BLOCK_IN_PACKAGE.
|
||||
*/
|
||||
std::string getProfile;
|
||||
GetOptionalBlockResultCode targetResult = NO_THIS_BLOCK_IN_PACKAGE;
|
||||
int ret = hapVerifyResult.GetBlockFromOptionalBlocks(PROFILE_BLOB, getProfile);
|
||||
ASSERT_TRUE(ret == targetResult);
|
||||
/*
|
||||
* @tc.steps: step3. GetProperty.
|
||||
* @tc.expected: step3. the return code will be GET_SUCCESS.
|
||||
*/
|
||||
std::string getProperty;
|
||||
ASSERT_TRUE(hapVerifyResult.GetProperty(getProperty) == GET_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test SetVersion and GetVersion function
|
||||
* @tc.desc: The static function return Version which is set;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyResultTest, SetVersionAndGetVersion001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. set a target version to HapVerifyResult.
|
||||
* @tc.expected: step1. the return version is the value we set.
|
||||
*/
|
||||
int targetVersion = TEST_HAP_SIGN_VERSION;
|
||||
HapVerifyResult hapVerifyResult;
|
||||
hapVerifyResult.SetVersion(targetVersion);
|
||||
int version = hapVerifyResult.GetVersion();
|
||||
ASSERT_TRUE(version == targetVersion);
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_verify_test.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "init/trusted_root_ca.h"
|
||||
#include "interfaces/hap_verify.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
|
||||
#include "hap_cert_verify_openssl_utils_test.h"
|
||||
#include "test_const.h"
|
||||
#include "test_hap_file_data.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
namespace {
|
||||
class HapVerifyTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapVerifyTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HapVerifyTest.HapVerifyEnableDebug001
|
||||
* @tc.desc: The static function will return true;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyTest, HapVerifyEnableDebug001, TestSize.Level1)
|
||||
{
|
||||
ASSERT_TRUE(EnableDebugMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HapVerifyTest.HapVerify001
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyTest, HapVerify001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input a invalid path to function of HapVerify.
|
||||
* @tc.expected: step1. the return will be FILE_PATH_INVALID.
|
||||
*/
|
||||
HapVerifyResult hapVerifyResult;
|
||||
std::string errorFile = "./signed_test.app";
|
||||
int resultCode = HapVerify(errorFile, hapVerifyResult);
|
||||
HapVerifyResultCode targetResult = FILE_PATH_INVALID;
|
||||
ASSERT_TRUE(resultCode == targetResult);
|
||||
std::ofstream appFile;
|
||||
appFile.open(errorFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(appFile.is_open());
|
||||
appFile.close();
|
||||
resultCode = HapVerify(errorFile, hapVerifyResult);
|
||||
ASSERT_TRUE(resultCode == targetResult);
|
||||
/*
|
||||
* @tc.steps: step2. create a hapfile and run HapVerify.
|
||||
* @tc.expected: step2. the return will be SIGNATURE_NOT_FOUND.
|
||||
*/
|
||||
std::string rightFile = "./signed.hap";
|
||||
std::ofstream hapFile;
|
||||
hapFile.open(rightFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile.is_open());
|
||||
hapFile.seekp(0, std::ios_base::beg);
|
||||
hapFile.write(miniHapFile, TEST_MINI_HAP_FILE_LENGTH);
|
||||
hapFile.close();
|
||||
resultCode = HapVerify(rightFile, hapVerifyResult);
|
||||
ASSERT_TRUE(resultCode == SIGNATURE_NOT_FOUND);
|
||||
/*
|
||||
* @tc.steps: step3. create an error hapfile and run HapVerify.
|
||||
* @tc.expected: step3. the return will be SIGNATURE_NOT_FOUND.
|
||||
*/
|
||||
std::string rightFile1 = "./signed1.hap";
|
||||
std::ofstream hapFile1;
|
||||
hapFile1.open(rightFile1.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile1.is_open());
|
||||
hapFile1.seekp(0, std::ios_base::beg);
|
||||
hapFile1.write(miniHapFile, sizeof(miniHapFile));
|
||||
hapFile1.seekp(TEST_MINI_HAP_FILE_LENGTH - sizeof(short), std::ios_base::beg);
|
||||
hapFile1.close();
|
||||
resultCode = HapVerify(rightFile1, hapVerifyResult);
|
||||
ASSERT_TRUE(resultCode == SIGNATURE_NOT_FOUND);
|
||||
/*
|
||||
* @tc.steps: step4. use an empty file to run HapVerify.
|
||||
* @tc.expected: step4. the return will be SIGNATURE_NOT_FOUND.
|
||||
*/
|
||||
std::string invalidFile = "./signed2.hap";
|
||||
std::ofstream hapFile2;
|
||||
hapFile2.open(invalidFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile2.is_open());
|
||||
hapFile2.close();
|
||||
resultCode = HapVerify(invalidFile, hapVerifyResult);
|
||||
ASSERT_TRUE(resultCode == SIGNATURE_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HapVerifyTest.HapVerifyOsApp001
|
||||
* @tc.desc: The static function will return verify result of signed file;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyTest, HapVerifyOsApp001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input a signed file to verify.
|
||||
* @tc.expected: step1. the return will be VERIFY_SUCCESS.
|
||||
*/
|
||||
HapByteBuffer hapInnerApp;
|
||||
std::string filePath = "./signed_inner.hap";
|
||||
ASSERT_TRUE(Base64StringDecode(HAP_FILE_INNER, hapInnerApp));
|
||||
std::ofstream hapFile;
|
||||
hapFile.open(filePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile.is_open());
|
||||
hapFile.seekp(0, std::ios_base::beg);
|
||||
hapFile.write(hapInnerApp.GetBufferPtr(), hapInnerApp.GetCapacity());
|
||||
hapFile.close();
|
||||
HapVerifyResult hapVerifyResult;
|
||||
int ret = HapVerify(filePath, hapVerifyResult);
|
||||
ASSERT_EQ(ret, VERIFY_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: HapVerifyTest.HapVerify002
|
||||
* @tc.desc: The static function will return verify result of signed file;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyTest, HapVerify002, TestSize.Level1)
|
||||
{
|
||||
std::string fileContent[TEST_FILE_NUM] = {HAP_FILE_ECC_SIGN_BASE64, HAP_FILE_RSA_SIGN_BASE64};
|
||||
std::string filePath[TEST_FILE_NUM] = {"./signed_ecc.hap", "./signed_rsa.hap"};
|
||||
std::string errorfilePath[TEST_FILE_NUM] = {"./signed_ecc_error.hap", "./signed_rsa_error.hap"};
|
||||
for (int i = 0; i < TEST_FILE_NUM; i++) {
|
||||
/*
|
||||
* @tc.steps: step1. input a signed file to verify.
|
||||
* @tc.expected: step1. the return will be VERIFY_SUCCESS.
|
||||
*/
|
||||
HapByteBuffer hapFileEccSign;
|
||||
ASSERT_TRUE(Base64StringDecode(fileContent[i], hapFileEccSign));
|
||||
std::ofstream hapFile;
|
||||
hapFile.open(filePath[i].c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(hapFile.is_open());
|
||||
hapFile.seekp(0, std::ios_base::beg);
|
||||
hapFile.write(hapFileEccSign.GetBufferPtr(), hapFileEccSign.GetCapacity());
|
||||
hapFile.close();
|
||||
HapVerifyResult hapVerifyResult;
|
||||
ASSERT_TRUE(HapVerify(filePath[i], hapVerifyResult) == VERIFY_SUCCESS);
|
||||
/*
|
||||
* @tc.steps: step2. check verify result.
|
||||
* @tc.expected: step2. cert version is 1, certChains Len is 3.
|
||||
*/
|
||||
ProvisionInfo profile = hapVerifyResult.GetProvisionInfo();
|
||||
ASSERT_TRUE(profile.type == ProvisionType::RELEASE);
|
||||
ASSERT_TRUE(hapVerifyResult.GetVersion() == TEST_SIGN_VERSION);
|
||||
std::vector<std::string> publicKeys = hapVerifyResult.GetPublicKey();
|
||||
ASSERT_TRUE(static_cast<int>(publicKeys.size()) == TEST_CERT_CHAIN_LEN);
|
||||
std::vector<std::string> signatures = hapVerifyResult.GetSignature();
|
||||
ASSERT_TRUE(static_cast<int>(signatures.size()) == TEST_CERT_CHAIN_LEN);
|
||||
/*
|
||||
* @tc.steps: step3. change comment data.
|
||||
* @tc.expected: step3. the return will be VERIFY_INTEGRITY_FAIL.
|
||||
*/
|
||||
HapByteBuffer errorCommentFile = hapFileEccSign;
|
||||
char tmp = TEST_HAPBYTEBUFFER_CHAR_DATA;
|
||||
errorCommentFile.PutByte(0, tmp);
|
||||
std::ofstream errorFile;
|
||||
errorFile.open(errorfilePath[i].c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(errorFile.is_open());
|
||||
errorFile.seekp(0, std::ios_base::beg);
|
||||
errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity());
|
||||
errorFile.close();
|
||||
HapVerifyResult verifyRet;
|
||||
ASSERT_TRUE(HapVerify(errorfilePath[i], verifyRet) == VERIFY_INTEGRITY_FAIL);
|
||||
/*
|
||||
* @tc.steps: step4. change profile pkcs7 data.
|
||||
* @tc.expected: step4. the return will be APP_SOURCE_NOT_TRUSTED.
|
||||
*/
|
||||
errorCommentFile.PutByte(TEST_PFOFILE_PKCS7_DATA_INDEX, tmp);
|
||||
errorFile.open(errorfilePath[i].c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(errorFile.is_open());
|
||||
errorFile.seekp(0, std::ios_base::beg);
|
||||
errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity());
|
||||
errorFile.close();
|
||||
ASSERT_TRUE(HapVerify(errorfilePath[i], verifyRet) == APP_SOURCE_NOT_TRUSTED);
|
||||
/*
|
||||
* @tc.steps: step5. change app pkcs7 data.
|
||||
* @tc.expected: step5. the return will be VERIFY_APP_PKCS7_FAIL.
|
||||
*/
|
||||
errorCommentFile.PutByte(TEST_APP_PKCS7_DATA_INDEX, tmp);
|
||||
errorFile.open(errorfilePath[i].c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
ASSERT_TRUE(errorFile.is_open());
|
||||
errorFile.seekp(0, std::ios_base::beg);
|
||||
errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity());
|
||||
errorFile.close();
|
||||
ASSERT_TRUE(HapVerify(errorfilePath[i], verifyRet) == VERIFY_APP_PKCS7_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hap_verify_v2_test.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "init/trusted_source_manager.h"
|
||||
#include "provision/provision_info.h"
|
||||
#include "verify/hap_verify_v2.h"
|
||||
|
||||
#include "test_hap_file_data.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace {
|
||||
class HapVerifyV2Test : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void HapVerifyV2Test::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyV2Test::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyV2Test::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void HapVerifyV2Test::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test CheckFilePath function
|
||||
* @tc.desc: The static function test whether input is a valid filepath;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyV2Test, CheckFilePathTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input an too long filepath.
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
HapVerifyV2 v2;
|
||||
std::string filePath = HAP_FILE_ECC_SIGN_BASE64;
|
||||
std::string standardFilePath;
|
||||
ASSERT_FALSE(v2.CheckFilePath(filePath, standardFilePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GenerateAppId function
|
||||
* @tc.desc: The static function will return whether generate appid successfully;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyV2Test, GenerateAppIdTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input a null ProvisionInfo.
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
HapVerifyV2 v2;
|
||||
ProvisionInfo provisionInfo;
|
||||
ASSERT_FALSE(v2.GenerateAppId(provisionInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test VerifyProfileInfo function
|
||||
* @tc.desc: The static function will return result of verify profile info;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyV2Test, VerifyProfileInfoTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. profile match with debug and profile type is release.
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
HapVerifyV2 v2;
|
||||
Pkcs7Context pkcs7Context;
|
||||
Pkcs7Context profileContext;
|
||||
ProvisionInfo provisionInfo;
|
||||
profileContext.matchResult.matchState = MATCH_WITH_PROFILE_DEBUG;
|
||||
provisionInfo.type = ProvisionType::RELEASE;
|
||||
ASSERT_FALSE(v2.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo));
|
||||
/*
|
||||
* @tc.steps: step2. profile debug cert is null.
|
||||
* @tc.expected: step2. the return will be false.
|
||||
*/
|
||||
provisionInfo.type = ProvisionType::DEBUG;
|
||||
CertChain test;
|
||||
pkcs7Context.certChains.push_back(test);
|
||||
X509* certX509 = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(certX509 != nullptr);
|
||||
pkcs7Context.certChains[0].push_back(certX509);
|
||||
ASSERT_FALSE(v2.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo));
|
||||
/*
|
||||
* @tc.steps: step3. app distributed type is NONE_TYPE.
|
||||
* @tc.expected: step3. the return will be false.
|
||||
*/
|
||||
profileContext.matchResult.matchState = MATCH_WITH_PROFILE;
|
||||
provisionInfo.type = ProvisionType::RELEASE;
|
||||
provisionInfo.distributionType = AppDistType::NONE_TYPE;
|
||||
ASSERT_FALSE(v2.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo));
|
||||
/*
|
||||
* @tc.steps: step4. profile distributed cert is null.
|
||||
* @tc.expected: step4. the return will be false.
|
||||
*/
|
||||
provisionInfo.distributionType = AppDistType::ENTERPRISE;
|
||||
ASSERT_FALSE(v2.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo));
|
||||
X509_free(certX509);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test ParseAndVerifyProfileIfNeed function
|
||||
* @tc.desc: The static function will return result of ParseAndVerifyProfileIfNeed;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyV2Test, ParseAndVerifyProfileIfNeedTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input a null profile.
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
HapVerifyV2 v2;
|
||||
std::string profile;
|
||||
ProvisionInfo provisionInfo;
|
||||
ASSERT_FALSE(v2.ParseAndVerifyProfileIfNeed(profile, provisionInfo, false));
|
||||
/*
|
||||
* @tc.steps: step1. input no need parse and verify profile.
|
||||
* @tc.expected: step1. the return will be true.
|
||||
*/
|
||||
ASSERT_TRUE(v2.ParseAndVerifyProfileIfNeed(profile, provisionInfo, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetDigestAndAlgorithm function
|
||||
* @tc.desc: The static function will return result of GetDigestAndAlgorithm;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HapVerifyV2Test, GetDigestAndAlgorithmTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input an error pkcs7 content.
|
||||
* @tc.expected: step1. the return will be false.
|
||||
*/
|
||||
HapVerifyV2 v2;
|
||||
Pkcs7Context digest;
|
||||
digest.content.SetCapacity(TEST_FILE_BLOCK_LENGTH);
|
||||
ASSERT_FALSE(v2.GetDigestAndAlgorithm(digest));
|
||||
}
|
||||
}
|
@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "provision_verify_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "provision/provision_verify.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace {
|
||||
const std::string INVALID_PROVISION_1 = R"(
|
||||
{
|
||||
"version-name": "1.0.0",
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
const std::string INVALID_PROVISION_2 = R"(
|
||||
{
|
||||
"version-code": 2,
|
||||
"version-name": "1.1.0",
|
||||
"uuid": "uuid_1_1",
|
||||
"type": "release",
|
||||
"app-distribution-type": "os_integration",
|
||||
"validity": {
|
||||
"not-before": 1262275201,
|
||||
"not-after": 2524579301
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_1_1",
|
||||
"development-certificate": "ABCD",
|
||||
"distribution-certificate": "1234",
|
||||
"bundle-name": "com.test1_1",
|
||||
"app-feature": "hos_normal_app"
|
||||
}
|
||||
}})"; // brackets mismatching
|
||||
/* validity: 2010 - 2030 */
|
||||
const std::string VALID_PROVISION = R"(
|
||||
{
|
||||
"version-code": 2,
|
||||
"version-name": "2.0.0",
|
||||
"uuid": "uuid_2",
|
||||
"type": "release",
|
||||
"app-distribution-type": "os_integration",
|
||||
"validity": {
|
||||
"not-before": 1262275200,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_2",
|
||||
"development-certificate": "ABCDEFG",
|
||||
"distribution-certificate": "123456789",
|
||||
"bundle-name": "com.test2",
|
||||
"app-feature": "hos_normal_app"
|
||||
}
|
||||
})";
|
||||
const std::string VALID_PROVISION_PERMISSION = R"(
|
||||
{
|
||||
"version-code": 3,
|
||||
"version-name": "3.0.0",
|
||||
"uuid": "uuid_3",
|
||||
"type": "release",
|
||||
"app-distribution-type": "app_gallery",
|
||||
"validity": {
|
||||
"not-before": 1262275300,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_3",
|
||||
"development-certificate": "ABCDEFGH",
|
||||
"distribution-certificate": "1234567890",
|
||||
"bundle-name": "com.test3",
|
||||
"app-feature": "hos_normal_app"
|
||||
},
|
||||
"permissions" : {
|
||||
"restricted-permissions" : ["ohos.permission.GET_PHONE_STATE",
|
||||
"ohos.permission.GET_APP_ACCOUNTS"],
|
||||
"restricted-capabilities" : ["ohos.permission.test"]
|
||||
},
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
const std::string UNAUTHORIZED_DEVICE_EMPTY_DEVICE_LIST_PROVISION = R"(
|
||||
{
|
||||
"version-code": 6,
|
||||
"version-name": "6.0.0",
|
||||
"uuid": "uuid_6",
|
||||
"type": "debug",
|
||||
"validity": {
|
||||
"not-before": 1262275600,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_6",
|
||||
"development-certificate": "ABCDEFGHIJ",
|
||||
"distribution-certificate": "1234567890123",
|
||||
"bundle-name": "com.test6",
|
||||
"app-feature": "hos_normal_app"
|
||||
},
|
||||
"debug-info": {
|
||||
"device-id-type": "udid"
|
||||
},
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
const std::string UNSUPPORTED_DEVICE_TYPE_PROVISION = R"(
|
||||
{
|
||||
"version-code": 7,
|
||||
"version-name": "7.0.0",
|
||||
"uuid": "uuid_7",
|
||||
"type": "debug",
|
||||
"validity": {
|
||||
"not-before": 1262275600,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_7",
|
||||
"development-certificate": "ABCDEFGHIJM",
|
||||
"distribution-certificate": "12345678901231",
|
||||
"bundle-name": "com.test7",
|
||||
"app-feature": "hos_normal_app"
|
||||
},
|
||||
"debug-info": {
|
||||
"device-id-type": "unknownType",
|
||||
"device-ids" : ["1234ABCD"]
|
||||
},
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
const std::string DEVICE_UNAUTH_PROVISION = R"(
|
||||
{
|
||||
"version-code": 8,
|
||||
"version-name": "8.0.0",
|
||||
"uuid": "uuid_8",
|
||||
"type": "debug",
|
||||
"validity": {
|
||||
"not-before": 1262275700,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "developer_id_8",
|
||||
"development-certificate": "ABCDEFGHIJK",
|
||||
"distribution-certificate": "12345678901234",
|
||||
"bundle-name": "com.test8",
|
||||
"app-feature": "hos_normal_app"
|
||||
},
|
||||
"debug-info": {
|
||||
"device-id-type": "udid",
|
||||
"device-ids" : ["1234ABCD"]
|
||||
},
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
const int MAXIMUM_NUM_DEVICES = 100;
|
||||
|
||||
class ProvisionVerifyTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void ProvisionVerifyTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ProvisionVerifyTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ProvisionVerifyTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void ProvisionVerifyTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify001 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input a invalid HarmonyAppProvision
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step1. return code will be PROVISION_INVALID.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(INVALID_PROVISION_1, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_INVALID);
|
||||
ret = ParseAndVerify(INVALID_PROVISION_2, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify002 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify002, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step2. input a valid HarmonyAppProvision (without permission info)
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step2. return code will be PROVISION_OK.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(VALID_PROVISION, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_OK);
|
||||
ASSERT_EQ(info.versionCode, 2); // version code is 2
|
||||
ASSERT_EQ(info.versionName, "2.0.0");
|
||||
ASSERT_EQ(info.uuid, "uuid_2");
|
||||
ASSERT_EQ(info.type, ProvisionType::RELEASE);
|
||||
ASSERT_TRUE(info.permissions.restrictedPermissions.empty());
|
||||
ASSERT_TRUE(info.permissions.restrictedCapabilities.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify003 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify003, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step3. input a valid HarmonyAppProvision (with permission info)
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step3. return code will be PROVISION_OK.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(VALID_PROVISION_PERMISSION, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_OK);
|
||||
ASSERT_EQ(info.versionCode, 3); // version code is 3
|
||||
ASSERT_EQ(info.versionName, "3.0.0");
|
||||
ASSERT_EQ(info.uuid, "uuid_3");
|
||||
ASSERT_EQ(info.type, ProvisionType::RELEASE);
|
||||
ASSERT_EQ(info.distributionType, AppDistType::APP_GALLERY);
|
||||
ASSERT_TRUE(info.permissions.restrictedPermissions.size() == 2); // 2 restricted permissions
|
||||
ASSERT_EQ(info.permissions.restrictedPermissions[0], "ohos.permission.GET_PHONE_STATE");
|
||||
ASSERT_TRUE(info.permissions.restrictedCapabilities.size() == 1); // 1 restricted capabilities
|
||||
ASSERT_EQ(info.permissions.restrictedCapabilities[0], "ohos.permission.test");
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify004 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify004, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step4. input a HarmonyAppProvision with empty device-id list
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step4. return code will be PROVISION_DEVICE_UNAUTHORIZED.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(UNAUTHORIZED_DEVICE_EMPTY_DEVICE_LIST_PROVISION, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_DEVICE_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify005 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify005, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step5. input a HarmonyAppProvision with a list of device IDs (Exceed maximum number)
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step5. return code will be PROVISION_NUM_DEVICE_EXCEEDED.
|
||||
*/
|
||||
std::string prefixNumDeviceExceededProvision = R"(
|
||||
{
|
||||
"version-code": 1,
|
||||
"version-name": "1.0.0",
|
||||
"uuid": "test_uuid",
|
||||
"type": "debug",
|
||||
"validity": {
|
||||
"not-before": 1262275200,
|
||||
"not-after": 2524579300
|
||||
},
|
||||
"bundle-info": {
|
||||
"developer-id": "test_developer_id",
|
||||
"development-certificate": "ABCDEFG",
|
||||
"distribution-certificate": "123456789",
|
||||
"bundle-name": "com.hello",
|
||||
"app-feature": "hos_normal_app"
|
||||
},
|
||||
"debug-info": {
|
||||
"device-id-type": "udid",
|
||||
"device-ids" : [)";
|
||||
std::string postfixNumDeviceExceededProvision = R"(]
|
||||
},
|
||||
"issuer": "App Gallery"
|
||||
})";
|
||||
for (int i = 0; i < MAXIMUM_NUM_DEVICES; i++) {
|
||||
prefixNumDeviceExceededProvision += R"("1234ABCD",)";
|
||||
}
|
||||
prefixNumDeviceExceededProvision += R"("1234ABCD")";
|
||||
prefixNumDeviceExceededProvision += postfixNumDeviceExceededProvision;
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(prefixNumDeviceExceededProvision, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_NUM_DEVICE_EXCEEDED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify006 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify006, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step6. input a HarmonyAppProvision with unsupported device type
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step6. return code will be PROVISION_UNSUPPORTED_DEVICE_TYPE.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(UNSUPPORTED_DEVICE_TYPE_PROVISION, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_UNSUPPORTED_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test HarmonyAppProvision ProvisionVerify007 function
|
||||
* @tc.desc: The static function will return verify result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ProvisionVerifyTest, ProvisionVerify007, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step7. input a HarmonyAppProvision with an unauthorized device id
|
||||
* and run ParseAndVerify function.
|
||||
* @tc.expected: step7. return code will be PROVISION_DEVICE_UNAUTHORIZED.
|
||||
*/
|
||||
ProvisionInfo info;
|
||||
int ret = ParseAndVerify(DEVICE_UNAUTH_PROVISION, info);
|
||||
ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_DEVICE_UNAUTHORIZED);
|
||||
}
|
||||
} // namespace
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "random_access_file_test.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/hap_byte_buffer.h"
|
||||
#include "common/random_access_file.h"
|
||||
#include "interfaces/hap_verify_result.h"
|
||||
|
||||
#include "hap_signing_block_utils_test.h"
|
||||
#include "test_const.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace {
|
||||
class RandomAccessFileTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void RandomAccessFileTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void RandomAccessFileTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void RandomAccessFileTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void RandomAccessFileTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test ReadFileFullyFromOffset function
|
||||
* @tc.desc: The static function will return each reading result;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RandomAccessFileTest, ReadFileFullyFromOffsetTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. use null buffer to ReadFileFullyFromOffset .
|
||||
* @tc.expected: step1. the return will be DEST_BUFFER_IS_NULL.
|
||||
*/
|
||||
std::string filePath = "./test_hapverify.zip";
|
||||
SignatureInfo si0;
|
||||
int sumLen = CreatTestZipFile(filePath, si0);
|
||||
RandomAccessFile hapTestFile1;
|
||||
bool initRet = hapTestFile1.Init(filePath);
|
||||
ASSERT_TRUE(initRet);
|
||||
ASSERT_TRUE(hapTestFile1.GetLength() == sumLen);
|
||||
ReadFileErrorCode targetCode = DEST_BUFFER_IS_NULL;
|
||||
long long ret = hapTestFile1.ReadFileFullyFromOffset(nullptr, 0, 0);
|
||||
ASSERT_TRUE(ret == targetCode);
|
||||
HapByteBuffer nullBuffer;
|
||||
ret = hapTestFile1.ReadFileFullyFromOffset(nullBuffer, 0);
|
||||
ASSERT_TRUE(ret == targetCode);
|
||||
/*
|
||||
* @tc.steps: step2. use a buffer to read a null file.
|
||||
* @tc.expected: step2. the return will be FILE_IS_CLOSE.
|
||||
*/
|
||||
filePath = "./test_hapverify1.zip";
|
||||
RandomAccessFile nullTestFile;
|
||||
initRet = nullTestFile.Init(filePath);
|
||||
ASSERT_FALSE(initRet);
|
||||
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(TEST_RANDOMREAD_LENGTH);
|
||||
ASSERT_TRUE(buffer != nullptr);
|
||||
ret = nullTestFile.ReadFileFullyFromOffset(buffer.get(), 0, TEST_RANDOMREAD_LENGTH);
|
||||
ASSERT_EQ(ret, FILE_IS_CLOSE);
|
||||
/*
|
||||
* @tc.steps: step3. use a large buffer to read a mini file.
|
||||
* @tc.expected: step3. the return will be READ_DATA_NOT_ENOUGH.
|
||||
*/
|
||||
std::string testFile = "./test_hapverify.txt";
|
||||
SignatureInfo si;
|
||||
sumLen = CreatTestZipFile(testFile, si);
|
||||
RandomAccessFile hapTestFile2;
|
||||
initRet = hapTestFile2.Init(testFile);
|
||||
ASSERT_TRUE(initRet);
|
||||
ASSERT_TRUE(hapTestFile2.GetLength() == sumLen);
|
||||
ret = hapTestFile2.ReadFileFullyFromOffset(buffer.get(), 0, TEST_RANDOMREAD_LENGTH);
|
||||
ASSERT_EQ(ret, READ_OFFSET_OUT_OF_RANGE);
|
||||
HapByteBuffer hapBuffer(TEST_RANDOMREAD_LENGTH);
|
||||
ret = hapTestFile2.ReadFileFullyFromOffset(hapBuffer, 0);
|
||||
ASSERT_EQ(ret, READ_OFFSET_OUT_OF_RANGE);
|
||||
/*
|
||||
* @tc.steps: step4. use a negative offset to read a file.
|
||||
* @tc.expected: step4. the return will be READ_OFFSET_OUT_OF_RANGE.
|
||||
*/
|
||||
ret = hapTestFile2.ReadFileFullyFromOffset(hapBuffer, -1);
|
||||
ASSERT_TRUE(ret == READ_OFFSET_OUT_OF_RANGE);
|
||||
ret = hapTestFile2.ReadFileFullyFromOffset(buffer.get(), -1, TEST_RANDOMREAD_LENGTH);
|
||||
ASSERT_TRUE(ret == READ_OFFSET_OUT_OF_RANGE);
|
||||
buffer.reset(nullptr);
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "trusted_root_ca_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "init/trusted_root_ca.h"
|
||||
#include "util/hap_cert_verify_openssl_utils.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Security::Verify;
|
||||
|
||||
namespace {
|
||||
class TrustedRootCaTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void);
|
||||
|
||||
static void TearDownTestCase(void);
|
||||
|
||||
void SetUp();
|
||||
|
||||
void TearDown();
|
||||
};
|
||||
|
||||
void TrustedRootCaTest::SetUpTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TrustedRootCaTest::TearDownTestCase(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TrustedRootCaTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void TrustedRootCaTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test trusted root init and debug mode
|
||||
* @tc.desc: The static function will return true;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (TrustedRootCaTest, CreatTrustedRootCA001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. run init and recovery.
|
||||
* @tc.expected: step1. the return will true.
|
||||
*/
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
ASSERT_TRUE(rootCertsObj.Init());
|
||||
rootCertsObj.Recovery();
|
||||
ASSERT_TRUE(rootCertsObj.Init());
|
||||
/*
|
||||
* @tc.steps: step2. run EableDebug and DisableDebug.
|
||||
* @tc.expected: step2. the return will true.
|
||||
*/
|
||||
ASSERT_TRUE(rootCertsObj.EnableDebug());
|
||||
rootCertsObj.DisableDebug();
|
||||
ASSERT_TRUE(rootCertsObj.EnableDebug());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test FindMatchedRoot function
|
||||
* @tc.desc: The static function will return object of matched cert;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (TrustedRootCaTest, FindMatchedRootTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. input nullptr.
|
||||
* @tc.expected: step1. the return will be nullptr.
|
||||
*/
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
X509* cert = nullptr;
|
||||
ASSERT_TRUE(rootCertsObj.FindMatchedRoot(cert) == nullptr);
|
||||
/*
|
||||
* @tc.steps: step2. input a self sign cert.
|
||||
* @tc.expected: step2. the return will be nullptr, because no trusted root is matched.
|
||||
*/
|
||||
cert = HapCertVerifyOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT);
|
||||
ASSERT_TRUE(cert != nullptr);
|
||||
ASSERT_TRUE(rootCertsObj.FindMatchedRoot(cert) == nullptr);
|
||||
X509_free(cert);
|
||||
/*
|
||||
* @tc.steps: step2. input a slft ca sign cert.
|
||||
* @tc.expected: step2. the return will be ptr of trusted root.
|
||||
*/
|
||||
cert = HapCertVerifyOpensslUtils::GetX509CertFromPemString(SOFT_CA_CERT);
|
||||
ASSERT_TRUE(cert != nullptr);
|
||||
X509* matchCert = rootCertsObj.FindMatchedRoot(cert);
|
||||
ASSERT_TRUE(matchCert != nullptr);
|
||||
X509_free(cert);
|
||||
X509_free(matchCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Test GetTrustedRootCAFromJson function.
|
||||
* @tc.desc: The static function will return false;
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F (TrustedRootCaTest, GetTrustedRootCAFromJsonTest001, TestSize.Level1)
|
||||
{
|
||||
/*
|
||||
* @tc.steps: step1. use an error filePath as input.
|
||||
* @tc.expected: step1. the return will false.
|
||||
*/
|
||||
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
|
||||
StringCertMap rootCertMap;
|
||||
std::string filePath = "./trusted_root_ca.json";
|
||||
ASSERT_FALSE(rootCertsObj.GetTrustedRootCAFromJson(rootCertMap, filePath));
|
||||
}
|
||||
}
|
0
interfaces/innerkits/appverify_lite/BUILD.gn
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/BUILD.gn
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_centraldirectory.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_centraldirectory.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_common.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_common.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_file.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_file.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_provision.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_provision.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_verify.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_verify.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_verify_hap.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/app_verify_hap.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/mbedtls_pkcs7.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/include/mbedtls_pkcs7.h
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/products/ipcamera/app_verify_base.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/products/ipcamera/app_verify_base.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/src/app_verify.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/src/app_verify.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/src/mbedtls_pkcs7.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/src/mbedtls_pkcs7.c
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/business_packet.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/business_packet.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/modified_packet.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/modified_packet.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/udid_right_test.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/udid_right_test.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/udid_wrong_test.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/udid_wrong_test.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/unsigned_packet.cpp
Normal file → Executable file
0
interfaces/innerkits/appverify_lite/unittest/packets/unsigned_packet.cpp
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user