154aa6d63Sopenharmony_ci/* 254aa6d63Sopenharmony_ci * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 354aa6d63Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 454aa6d63Sopenharmony_ci * you may not use this file except in compliance with the License. 554aa6d63Sopenharmony_ci * You may obtain a copy of the License at 654aa6d63Sopenharmony_ci * 754aa6d63Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 854aa6d63Sopenharmony_ci * 954aa6d63Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1054aa6d63Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1154aa6d63Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1254aa6d63Sopenharmony_ci * See the License for the specific language governing permissions and 1354aa6d63Sopenharmony_ci * limitations under the License. 1454aa6d63Sopenharmony_ci */ 1554aa6d63Sopenharmony_ci 1654aa6d63Sopenharmony_ci#include <cinttypes> 1754aa6d63Sopenharmony_ci 1854aa6d63Sopenharmony_ci#include "securec.h" 1954aa6d63Sopenharmony_ci#include "signature_info.h" 2054aa6d63Sopenharmony_ci#include "signature_tools_log.h" 2154aa6d63Sopenharmony_ci#include "digest_common.h" 2254aa6d63Sopenharmony_ci//#include "verify_hap_openssl_utils.h" 2354aa6d63Sopenharmony_ci#include "random_access_file.h" 2454aa6d63Sopenharmony_ci 2554aa6d63Sopenharmony_cinamespace OHOS { 2654aa6d63Sopenharmony_cinamespace SignatureTools { 2754aa6d63Sopenharmony_ciint32_t RandomAccessFile::memoryPageSize = sysconf(_SC_PAGESIZE); 2854aa6d63Sopenharmony_ci 2954aa6d63Sopenharmony_ciRandomAccessFile::RandomAccessFile() 3054aa6d63Sopenharmony_ci : fd(-1), fileLength(0) 3154aa6d63Sopenharmony_ci{ 3254aa6d63Sopenharmony_ci} 3354aa6d63Sopenharmony_ci 3454aa6d63Sopenharmony_ciRandomAccessFile::~RandomAccessFile() 3554aa6d63Sopenharmony_ci{ 3654aa6d63Sopenharmony_ci if (fd != -1) { 3754aa6d63Sopenharmony_ci close(fd); 3854aa6d63Sopenharmony_ci } 3954aa6d63Sopenharmony_ci} 4054aa6d63Sopenharmony_ci 4154aa6d63Sopenharmony_cibool RandomAccessFile::Init(const std::string& filePath) 4254aa6d63Sopenharmony_ci{ 4354aa6d63Sopenharmony_ci fd = open(filePath.c_str(), O_RDWR); 4454aa6d63Sopenharmony_ci if (fd == -1) { 4554aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + filePath + " failed"); 4654aa6d63Sopenharmony_ci return false; 4754aa6d63Sopenharmony_ci } 4854aa6d63Sopenharmony_ci 4954aa6d63Sopenharmony_ci if (memoryPageSize <= 0) { 5054aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 5154aa6d63Sopenharmony_ci "getting pagesize failed. memoryPageSize: " + std::to_string(memoryPageSize)); 5254aa6d63Sopenharmony_ci return false; 5354aa6d63Sopenharmony_ci } 5454aa6d63Sopenharmony_ci 5554aa6d63Sopenharmony_ci struct stat file_stat; 5654aa6d63Sopenharmony_ci if (fstat(fd, &file_stat) == -1) { 5754aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 5854aa6d63Sopenharmony_ci filePath + "get status failed"); 5954aa6d63Sopenharmony_ci return false; 6054aa6d63Sopenharmony_ci } 6154aa6d63Sopenharmony_ci fileLength = file_stat.st_size; 6254aa6d63Sopenharmony_ci 6354aa6d63Sopenharmony_ci return true; 6454aa6d63Sopenharmony_ci} 6554aa6d63Sopenharmony_ci 6654aa6d63Sopenharmony_ciint64_t RandomAccessFile::GetLength() const 6754aa6d63Sopenharmony_ci{ 6854aa6d63Sopenharmony_ci return fileLength; 6954aa6d63Sopenharmony_ci} 7054aa6d63Sopenharmony_ci 7154aa6d63Sopenharmony_cibool RandomAccessFile::CheckLittleEndian() 7254aa6d63Sopenharmony_ci{ 7354aa6d63Sopenharmony_ci union LittleEndian { 7454aa6d63Sopenharmony_ci int32_t number; 7554aa6d63Sopenharmony_ci char ch; 7654aa6d63Sopenharmony_ci } t; 7754aa6d63Sopenharmony_ci t.number = 1; 7854aa6d63Sopenharmony_ci return (t.ch == 1); 7954aa6d63Sopenharmony_ci} 8054aa6d63Sopenharmony_ci 8154aa6d63Sopenharmony_ciint32_t RandomAccessFile::DoMMap(int32_t bufCapacity, int64_t offset, MmapInfo& mmapInfo) 8254aa6d63Sopenharmony_ci{ 8354aa6d63Sopenharmony_ci if (!CheckLittleEndian()) { 8454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("CheckLittleEndian: failed"); 8554aa6d63Sopenharmony_ci return MMAP_FAILED; 8654aa6d63Sopenharmony_ci } 8754aa6d63Sopenharmony_ci 8854aa6d63Sopenharmony_ci // Starting address for memory mapping 8954aa6d63Sopenharmony_ci mmapInfo.mapAddr = reinterpret_cast<char*>(MAP_FAILED); 9054aa6d63Sopenharmony_ci if (fd == -1) { 9154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("random access file's fd is -1, the file is closed"); 9254aa6d63Sopenharmony_ci return FILE_IS_CLOSE; 9354aa6d63Sopenharmony_ci } 9454aa6d63Sopenharmony_ci if (offset < 0 || offset > fileLength - bufCapacity) { 9554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("offset is less than 0 OR read offset is out of range. offset: %" PRId64 9654aa6d63Sopenharmony_ci ", range: %" PRId64, offset, fileLength - bufCapacity); 9754aa6d63Sopenharmony_ci return READ_OFFSET_OUT_OF_RANGE; 9854aa6d63Sopenharmony_ci } 9954aa6d63Sopenharmony_ci // Memory mapped file offset, 0 OR an integer multiple of 4K 10054aa6d63Sopenharmony_ci mmapInfo.mmapPosition = (offset / memoryPageSize) * memoryPageSize; 10154aa6d63Sopenharmony_ci // How many more bytes can be read from the current mapped memory page to find 10254aa6d63Sopenharmony_ci mmapInfo.readMoreLen = static_cast<int>(offset - mmapInfo.mmapPosition); 10354aa6d63Sopenharmony_ci mmapInfo.mmapSize = bufCapacity + mmapInfo.readMoreLen; 10454aa6d63Sopenharmony_ci mmapInfo.mapAddr = reinterpret_cast<char*>(mmap(nullptr, mmapInfo.mmapSize, PROT_READ | PROT_WRITE, 10554aa6d63Sopenharmony_ci MAP_SHARED | MAP_POPULATE, fd, mmapInfo.mmapPosition)); 10654aa6d63Sopenharmony_ci if (mmapInfo.mapAddr == MAP_FAILED) { 10754aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("mmap failed"); 10854aa6d63Sopenharmony_ci return MMAP_FAILED; 10954aa6d63Sopenharmony_ci } 11054aa6d63Sopenharmony_ci return 0; 11154aa6d63Sopenharmony_ci} 11254aa6d63Sopenharmony_ci 11354aa6d63Sopenharmony_ciint32_t RandomAccessFile::ReadFileFullyFromOffset(char buf[], int64_t offset, int64_t bufCapacity) 11454aa6d63Sopenharmony_ci{ 11554aa6d63Sopenharmony_ci if (buf == nullptr) { 11654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The dest buffer is null"); 11754aa6d63Sopenharmony_ci return DEST_BUFFER_IS_NULL; 11854aa6d63Sopenharmony_ci } 11954aa6d63Sopenharmony_ci 12054aa6d63Sopenharmony_ci MmapInfo mmapInfo; 12154aa6d63Sopenharmony_ci int32_t ret = DoMMap(bufCapacity, offset, mmapInfo); 12254aa6d63Sopenharmony_ci if (ret < 0) { 12354aa6d63Sopenharmony_ci return ret; 12454aa6d63Sopenharmony_ci } 12554aa6d63Sopenharmony_ci 12654aa6d63Sopenharmony_ci if (memcpy_s(buf, bufCapacity, mmapInfo.mapAddr + mmapInfo.readMoreLen, 12754aa6d63Sopenharmony_ci mmapInfo.mmapSize - mmapInfo.readMoreLen) != EOK) { 12854aa6d63Sopenharmony_ci munmap(mmapInfo.mapAddr, mmapInfo.mmapSize); 12954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("memcpy_s error, errno: %d", IO_ERROR); 13054aa6d63Sopenharmony_ci return MMAP_COPY_FAILED; 13154aa6d63Sopenharmony_ci } 13254aa6d63Sopenharmony_ci munmap(mmapInfo.mapAddr, mmapInfo.mmapSize); 13354aa6d63Sopenharmony_ci return bufCapacity; 13454aa6d63Sopenharmony_ci} 13554aa6d63Sopenharmony_ci 13654aa6d63Sopenharmony_ciint32_t RandomAccessFile::ReadFileFullyFromOffset(ByteBuffer& buffer, int64_t offset) 13754aa6d63Sopenharmony_ci{ 13854aa6d63Sopenharmony_ci if (!buffer.HasRemaining()) { 13954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The dest buffer has not remaining"); 14054aa6d63Sopenharmony_ci return DEST_BUFFER_IS_NULL; 14154aa6d63Sopenharmony_ci } 14254aa6d63Sopenharmony_ci 14354aa6d63Sopenharmony_ci MmapInfo mmapInfo; 14454aa6d63Sopenharmony_ci int32_t bufCapacity = buffer.GetCapacity(); 14554aa6d63Sopenharmony_ci int64_t ret = DoMMap(bufCapacity, offset, mmapInfo); 14654aa6d63Sopenharmony_ci if (ret < 0) { 14754aa6d63Sopenharmony_ci return ret; 14854aa6d63Sopenharmony_ci } 14954aa6d63Sopenharmony_ci 15054aa6d63Sopenharmony_ci buffer.PutData(0, mmapInfo.mapAddr + mmapInfo.readMoreLen, bufCapacity); 15154aa6d63Sopenharmony_ci munmap(mmapInfo.mapAddr, mmapInfo.mmapSize); 15254aa6d63Sopenharmony_ci return bufCapacity; 15354aa6d63Sopenharmony_ci} 15454aa6d63Sopenharmony_ci 15554aa6d63Sopenharmony_ciint32_t RandomAccessFile::WriteToFile(ByteBuffer& buffer, int64_t position, int64_t length) 15654aa6d63Sopenharmony_ci{ 15754aa6d63Sopenharmony_ci // write file, file length may change 15854aa6d63Sopenharmony_ci int64_t remainLength = fileLength - position; 15954aa6d63Sopenharmony_ci fileLength = (length <= remainLength) ? fileLength : (fileLength + (length - remainLength)); 16054aa6d63Sopenharmony_ci // update file length 16154aa6d63Sopenharmony_ci if (ftruncate(fd, fileLength) == -1) { 16254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("RandomAccessFile ftruncate error: %s", strerror(errno)); 16354aa6d63Sopenharmony_ci return IO_ERROR; 16454aa6d63Sopenharmony_ci } 16554aa6d63Sopenharmony_ci 16654aa6d63Sopenharmony_ci int32_t bufCapacity = buffer.GetCapacity(); 16754aa6d63Sopenharmony_ci if (bufCapacity == 0) { 16854aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The dest buffer capacity is 0"); 16954aa6d63Sopenharmony_ci return DEST_BUFFER_IS_NULL; 17054aa6d63Sopenharmony_ci } 17154aa6d63Sopenharmony_ci 17254aa6d63Sopenharmony_ci MmapInfo mmapInfo; 17354aa6d63Sopenharmony_ci 17454aa6d63Sopenharmony_ci int32_t ret = DoMMap(bufCapacity, position, mmapInfo); 17554aa6d63Sopenharmony_ci if (ret < 0) { 17654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("DoMMap failed: %d", ret); 17754aa6d63Sopenharmony_ci return ret; 17854aa6d63Sopenharmony_ci } 17954aa6d63Sopenharmony_ci 18054aa6d63Sopenharmony_ci if (memcpy_s(mmapInfo.mapAddr + mmapInfo.readMoreLen, 18154aa6d63Sopenharmony_ci mmapInfo.mmapSize - mmapInfo.readMoreLen, 18254aa6d63Sopenharmony_ci buffer.GetBufferPtr(), bufCapacity) != RET_OK) { 18354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("memcpy_s error, errno: %d", IO_ERROR); 18454aa6d63Sopenharmony_ci return MMAP_COPY_FAILED; 18554aa6d63Sopenharmony_ci } 18654aa6d63Sopenharmony_ci munmap(mmapInfo.mapAddr, mmapInfo.mmapSize); 18754aa6d63Sopenharmony_ci return bufCapacity; 18854aa6d63Sopenharmony_ci} 18954aa6d63Sopenharmony_ci 19054aa6d63Sopenharmony_cibool RandomAccessFile::ReadFileFromOffsetAndDigestUpdate(const DigestParameter& digestParam, 19154aa6d63Sopenharmony_ci int32_t chunkSize, int64_t offset) 19254aa6d63Sopenharmony_ci{ 19354aa6d63Sopenharmony_ci MmapInfo mmapInfo; 19454aa6d63Sopenharmony_ci int32_t ret = DoMMap(chunkSize, offset, mmapInfo); 19554aa6d63Sopenharmony_ci if (ret < 0) { 19654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("DoMMap failed: %d", ret); 19754aa6d63Sopenharmony_ci return false; 19854aa6d63Sopenharmony_ci } 19954aa6d63Sopenharmony_ci unsigned char* content = reinterpret_cast<unsigned char*>(mmapInfo.mapAddr + mmapInfo.readMoreLen); 20054aa6d63Sopenharmony_ci bool res = DigestCommon::DigestUpdate(digestParam, content, chunkSize); 20154aa6d63Sopenharmony_ci munmap(mmapInfo.mapAddr, mmapInfo.mmapSize); 20254aa6d63Sopenharmony_ci return res; 20354aa6d63Sopenharmony_ci} 20454aa6d63Sopenharmony_ci} 20554aa6d63Sopenharmony_ci}