1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "calc_fingerprint.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <securec.h> 18020a203aSopenharmony_ci 19020a203aSopenharmony_ci#include "common_defines.h" 20020a203aSopenharmony_ci#include "file_util.h" 21020a203aSopenharmony_ci 22020a203aSopenharmony_ciusing namespace std; 23020a203aSopenharmony_cinamespace OHOS { 24020a203aSopenharmony_cinamespace HiviewDFX { 25020a203aSopenharmony_ciDEFINE_LOG_TAG("CalcFingerprint"); 26020a203aSopenharmony_ciint CalcFingerprint::ConvertToString(const unsigned char hash[SHA256_DIGEST_LENGTH], char *outstr, size_t len) 27020a203aSopenharmony_ci{ 28020a203aSopenharmony_ci uint32_t i; 29020a203aSopenharmony_ci char *outHash = outstr; 30020a203aSopenharmony_ci 31020a203aSopenharmony_ci if (hash == nullptr || outHash == nullptr) { 32020a203aSopenharmony_ci return EINVAL; 33020a203aSopenharmony_ci } 34020a203aSopenharmony_ci constexpr int charsEachHex = 2; 35020a203aSopenharmony_ci if (len < (SHA256_DIGEST_LENGTH * charsEachHex + 1)) { // 1: add '\0' 36020a203aSopenharmony_ci return ENOMEM; 37020a203aSopenharmony_ci } 38020a203aSopenharmony_ci for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { 39020a203aSopenharmony_ci int err = snprintf_s(outHash, charsEachHex + 1, charsEachHex, "%02x", hash[i]); 40020a203aSopenharmony_ci if (err < 0) { 41020a203aSopenharmony_ci return err; 42020a203aSopenharmony_ci } 43020a203aSopenharmony_ci outHash += charsEachHex; 44020a203aSopenharmony_ci } 45020a203aSopenharmony_ci *outHash = '\0'; 46020a203aSopenharmony_ci return 0; 47020a203aSopenharmony_ci} 48020a203aSopenharmony_ci 49020a203aSopenharmony_ci/* 50020a203aSopenharmony_ci * API name : calc_file_sha1 51020a203aSopenharmony_ci * Description : calculate a file sha1 hash for given file 52020a203aSopenharmony_ci * Input parameters 53020a203aSopenharmony_ci * filePath : path of the file to be calculated 54020a203aSopenharmony_ci * hash : buffer to store output sha1 string 55020a203aSopenharmony_ci * Return 56020a203aSopenharmony_ci * 0 : successful 57020a203aSopenharmony_ci * x : fail 58020a203aSopenharmony_ci */ 59020a203aSopenharmony_ciint CalcFingerprint::CalcFileSha(const string& filePath, char *hash, size_t len) 60020a203aSopenharmony_ci{ 61020a203aSopenharmony_ci if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) { 62020a203aSopenharmony_ci HIVIEW_LOGE("invalid param."); 63020a203aSopenharmony_ci return EINVAL; 64020a203aSopenharmony_ci } 65020a203aSopenharmony_ci unsigned char value[SHA256_DIGEST_LENGTH] = {0}; 66020a203aSopenharmony_ci int ret = CalcFileShaOriginal(filePath, value, len); 67020a203aSopenharmony_ci if (ret != 0) { 68020a203aSopenharmony_ci HIVIEW_LOGE("CalcFileShaOriginal failed."); 69020a203aSopenharmony_ci return ret; 70020a203aSopenharmony_ci } 71020a203aSopenharmony_ci return ConvertToString(value, hash, len); 72020a203aSopenharmony_ci} 73020a203aSopenharmony_ci 74020a203aSopenharmony_ciint CalcFingerprint::CalcFileShaOriginal(const string& filePath, unsigned char *hash, size_t len) 75020a203aSopenharmony_ci{ 76020a203aSopenharmony_ci if (filePath.empty() || hash == nullptr || !FileUtil::IsLegalPath(filePath)) { 77020a203aSopenharmony_ci HIVIEW_LOGE("file is invalid."); 78020a203aSopenharmony_ci return EINVAL; 79020a203aSopenharmony_ci } 80020a203aSopenharmony_ci 81020a203aSopenharmony_ci if (len < SHA256_DIGEST_LENGTH) { 82020a203aSopenharmony_ci HIVIEW_LOGE("hash buf len error."); 83020a203aSopenharmony_ci return ENOMEM; 84020a203aSopenharmony_ci } 85020a203aSopenharmony_ci 86020a203aSopenharmony_ci FILE *fp = nullptr; 87020a203aSopenharmony_ci fp = fopen(filePath.c_str(), "rb"); 88020a203aSopenharmony_ci if (fp == nullptr) { 89020a203aSopenharmony_ci HIVIEW_LOGE("open file failed."); 90020a203aSopenharmony_ci return errno; // if file not exist, errno will be ENOENT 91020a203aSopenharmony_ci } 92020a203aSopenharmony_ci 93020a203aSopenharmony_ci size_t n; 94020a203aSopenharmony_ci char buffer[HASH_BUFFER_SIZE] = {0}; 95020a203aSopenharmony_ci SHA256_CTX ctx; 96020a203aSopenharmony_ci SHA256_Init(&ctx); 97020a203aSopenharmony_ci while ((n = fread(buffer, 1, sizeof(buffer), fp))) { 98020a203aSopenharmony_ci SHA256_Update(&ctx, (unsigned char *)buffer, n); 99020a203aSopenharmony_ci } 100020a203aSopenharmony_ci if (fclose(fp)) { 101020a203aSopenharmony_ci HIVIEW_LOGE("fclose is failed"); 102020a203aSopenharmony_ci } 103020a203aSopenharmony_ci fp = nullptr; 104020a203aSopenharmony_ci SHA256_Final(hash, &ctx); 105020a203aSopenharmony_ci return 0; 106020a203aSopenharmony_ci} 107020a203aSopenharmony_ci 108020a203aSopenharmony_ci/* 109020a203aSopenharmony_ci * API name : calc_buffer_sha1 110020a203aSopenharmony_ci * Description : calculate a buffer sha1 hash for given buffer 111020a203aSopenharmony_ci * Input parameters 112020a203aSopenharmony_ci * buffer : buffer to store the content which needed to be calculated 113020a203aSopenharmony_ci * hash_str : buffer to store output sha1 string 114020a203aSopenharmony_ci * Return 115020a203aSopenharmony_ci * 0 : successful 116020a203aSopenharmony_ci * x : fail 117020a203aSopenharmony_ci */ 118020a203aSopenharmony_ciint CalcFingerprint::CalcBufferSha(const string& buffer, size_t bufSize, char *hash, size_t len) 119020a203aSopenharmony_ci{ 120020a203aSopenharmony_ci if (buffer.empty()) { 121020a203aSopenharmony_ci return EINVAL; 122020a203aSopenharmony_ci } 123020a203aSopenharmony_ci return CalcBufferSha((unsigned char *)buffer.c_str(), bufSize, hash, len); 124020a203aSopenharmony_ci} 125020a203aSopenharmony_ci 126020a203aSopenharmony_ci/* 127020a203aSopenharmony_ci * API name : calc_buffer_sha1 128020a203aSopenharmony_ci * Description : calculate a buffer sha1 hash for given buffer 129020a203aSopenharmony_ci * Input parameters 130020a203aSopenharmony_ci * source : buffer to store the content which needed to be calculated 131020a203aSopenharmony_ci * sourceLen : input buffer len 132020a203aSopenharmony_ci * hash : buffer to store output sha1 string 133020a203aSopenharmony_ci * hashLen : output buff len 134020a203aSopenharmony_ci * Return 135020a203aSopenharmony_ci * 0 : successful 136020a203aSopenharmony_ci * x : fail 137020a203aSopenharmony_ci */ 138020a203aSopenharmony_ciint CalcFingerprint::CalcBufferSha(unsigned char* source, size_t sourceLen, char *hash, size_t hashLen) 139020a203aSopenharmony_ci{ 140020a203aSopenharmony_ci if (source == nullptr || hash == nullptr || sourceLen == 0) { 141020a203aSopenharmony_ci return EINVAL; 142020a203aSopenharmony_ci } 143020a203aSopenharmony_ci unsigned char value[SHA256_DIGEST_LENGTH] = {0}; 144020a203aSopenharmony_ci SHA256(source, sourceLen, value); 145020a203aSopenharmony_ci return ConvertToString(value, hash, hashLen); 146020a203aSopenharmony_ci} 147020a203aSopenharmony_ci} 148020a203aSopenharmony_ci} 149