介绍
应用签名系统主要负责鸿蒙hap应用包的签名完整性校验,以及应用来源识别等功能。
- 子系统间接口: 应用完整性校验模块给其他模块提供的接口;
- 完整性校验: 通过验签,保障应用包完整性,防篡改;
- 应用来源识别: 通过匹配签名证书链与可信源列表,识别应用来源。
目录
/base/security/appverify ├── interfaces/innerkits/appverify # 应用完整性校验模块代码 │ ├── config # 应用签名根证书和可信源列表配置文件存放目录 │ ├── include # 头文件存放目录 │ ├── src # 源代码存放目录 │ ├── test # 模块自动化测试用例存放目录 ├── test/resource # 测试资源存放目录
接口
目前签名系统对外只提供了一个校验的接口,这个接口会负责完整性已经来源的校验。
接口名 | 说明 |
int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult) | 校验应用完整性,识别应用来源 |
代码分析
HapVerify
HapVerify函数是签名校验的入口函数,目前实现在
interfaces/innerkits/appverify/src/hap_verify.cpp
这个函数里面首先是做了一个初始化的操作,然后就是对应的完整性验证逻辑了。
int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)
{
if (!g_isInit && !HapVerifyInit()) {
return VERIFY_SOURCE_INIT_FAIL;
}
HapVerifyV2 hapVerifyV2;
return hapVerifyV2.Verify(filePath, hapVerifyResult);
}
HapVerifyInit
这个函数主要就是签名需要用到的信息的初始化。
签名系统内部在签名校验前需要做的:
ca管理,可信资源管理,CRL管理,设备类型管理,ticket管理
/**
* @brief 初始化
*
* @return true
* @return false
*/
bool HapVerifyInit()
{
//初始化ca管理实例,主要是从json文件中获取ca,方便后续验证ca比较ca
TrustedRootCa& rootCertsObj = TrustedRootCa::GetInstance();
//初始化可信资源管理实例,主要是可信app的管理,主要是匹配app的证书。
TrustedSourceManager& trustedAppSourceManager = TrustedSourceManager::GetInstance();
//初始化CRL管理实例,证书吊销列表的相关管理
HapCrlManager& hapCrlManager = HapCrlManager::GetInstance();
//设备信息的管理,主要用于判断是否是debug模式
DeviceTypeManager& deviceTypeManager = DeviceTypeManager::GetInstance();
TrustedTicketManager& trustedTicketSourceManager = TrustedTicketManager::GetInstance();
g_mtx.lock();
g_isInit = rootCertsObj.Init() && trustedAppSourceManager.Init();
if (!g_isInit) {
rootCertsObj.Recovery();
trustedAppSourceManager.Recovery();
}
trustedTicketSourceManager.Init();
hapCrlManager.Init();
deviceTypeManager.GetDeviceTypeInfo();
g_mtx.unlock();
return g_isInit;
}
verify
目前使用的是v2版本的校验,猜测和android对应的v2签名一致。
int HapVerifyV2::Verify(const std::string& filePath, HapVerifyResult& hapVerifyV1Result)
{
HAPVERIFY_LOG_DEBUG(LABEL, "Start Verify");
std::string standardFilePath;
//检查文件路径信息
if (!CheckFilePath(filePath, standardFilePath)) {
return FILE_PATH_INVALID;
}
//检查文件是否可以正常open,并且不是空文件
RandomAccessFile hapFile;
if (!hapFile.Init(standardFilePath)) {
HAPVERIFY_LOG_ERROR(LABEL, "open standard file failed");
return OPEN_FILE_ERROR;
}
int resultCode = Verify(hapFile, hapVerifyV1Result);
return resultCode;
}
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;
}
签名结构
SignatureInfo
这部分主要是在zip文件头部添加的签名的信息。
struct SignatureInfo {
HapByteBuffer hapSignatureBlock;
long long hapSigningBlockOffset;
long long hapCentralDirOffset;
long long hapEocdOffset;
HapByteBuffer hapEocd;
std::vector<OptionalBlock> optionBlocks;
int version;
};
Pkcs7Context
签名算法相关的结构信息,这部分是在SignatureInfo.hapSignatureBlock中存储的信息
struct Pkcs7Context {
bool needWriteCrl;
int digestAlgorithm;
MatchingResult matchResult;
std::string certIssuer;
PKCS7* p7;
Pkcs7CertChains certChains;
HapByteBuffer content;
};