1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hs_hashstream.h"
17
18 #include <iomanip>
19 #include <sstream>
20
21 #include "filemgmt_libhilog.h"
22
23 namespace OHOS {
24 namespace FileManagement {
25 namespace ModuleFileIO {
26 using namespace std;
27
GetHashAlgorithm(const string & alg)28 static HASH_ALGORITHM_TYPE GetHashAlgorithm(const string &alg)
29 {
30 return (algorithmMaps.find(alg) != algorithmMaps.end()) ? algorithmMaps.at(alg) : HASH_ALGORITHM_TYPE_UNSUPPORTED;
31 }
32
HashFinal(const unique_ptr<unsigned char[]> & hashBuf,size_t hashLen)33 static string HashFinal(const unique_ptr<unsigned char[]> &hashBuf, size_t hashLen)
34 {
35 stringstream ss;
36 for (size_t i = 0; i < hashLen; ++i) {
37 const int hexPerByte = 2;
38 ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex
39 << static_cast<uint32_t>(hashBuf[i]);
40 }
41
42 return ss.str();
43 }
44
GetHsEntity()45 tuple<bool, HsHashStreamEntity *> HsHashStream::GetHsEntity()
46 {
47 if (!entity) {
48 return { false, nullptr };
49 }
50
51 return { true, entity.get() };
52 }
53
Update(ArrayBuffer & buffer)54 FsResult<void> HsHashStream::Update(ArrayBuffer &buffer)
55 {
56 auto [succ, hsEntity] = GetHsEntity();
57 if (!succ) {
58 HILOGE("Failed to get entity of HashStream");
59 return FsResult<void>::Error(EIO);
60 }
61
62 switch (hsEntity->algType) {
63 case HASH_ALGORITHM_TYPE_MD5:
64 MD5_Update(&hsEntity->md5Ctx, buffer.buf, buffer.length);
65 break;
66 case HASH_ALGORITHM_TYPE_SHA1:
67 SHA1_Update(&hsEntity->shaCtx, buffer.buf, buffer.length);
68 break;
69 case HASH_ALGORITHM_TYPE_SHA256:
70 SHA256_Update(&hsEntity->sha256Ctx, buffer.buf, buffer.length);
71 break;
72 default:
73 break;
74 }
75
76 return FsResult<void>::Success();
77 }
78
Digest()79 FsResult<string> HsHashStream::Digest()
80 {
81 auto [succ, hsEntity] = GetHsEntity();
82 if (!succ) {
83 HILOGE("Failed to get entity of HashStream");
84 return FsResult<string>::Error(EIO);
85 }
86
87 string digestStr;
88 switch (hsEntity->algType) {
89 case HASH_ALGORITHM_TYPE_MD5: {
90 auto res = make_unique<unsigned char[]>(MD5_DIGEST_LENGTH);
91 MD5_Final(res.get(), &hsEntity->md5Ctx);
92 digestStr = HashFinal(res, MD5_DIGEST_LENGTH);
93 break;
94 }
95 case HASH_ALGORITHM_TYPE_SHA1: {
96 auto res = make_unique<unsigned char[]>(SHA_DIGEST_LENGTH);
97 SHA1_Final(res.get(), &hsEntity->shaCtx);
98 digestStr = HashFinal(res, SHA_DIGEST_LENGTH);
99 break;
100 }
101 case HASH_ALGORITHM_TYPE_SHA256: {
102 auto res = make_unique<unsigned char[]>(SHA256_DIGEST_LENGTH);
103 SHA256_Final(res.get(), &hsEntity->sha256Ctx);
104 digestStr = HashFinal(res, SHA256_DIGEST_LENGTH);
105 break;
106 }
107 default:
108 break;
109 }
110 return FsResult<string>::Success(digestStr);
111 }
112
Constructor(string alg)113 FsResult<HsHashStream *> HsHashStream::Constructor(string alg)
114 {
115 HASH_ALGORITHM_TYPE algType = GetHashAlgorithm(alg);
116 if (algType == HASH_ALGORITHM_TYPE_UNSUPPORTED) {
117 HILOGE("algType is not found.");
118 return FsResult<HsHashStream *>::Error(EINVAL);
119 }
120
121 HsHashStreamEntity *rawPtr = new (std::nothrow) HsHashStreamEntity();
122 if (rawPtr == nullptr) {
123 HILOGE("Failed to request heap memory.");
124 return FsResult<HsHashStream *>::Error(ENOMEM);
125 }
126 std::unique_ptr<HsHashStreamEntity> hsEntity(rawPtr);
127 hsEntity->algType = algType;
128
129 switch (algType) {
130 case HASH_ALGORITHM_TYPE_MD5: {
131 MD5_CTX ctx;
132 MD5_Init(&ctx);
133 hsEntity->md5Ctx = ctx;
134 break;
135 }
136 case HASH_ALGORITHM_TYPE_SHA1: {
137 SHA_CTX ctx;
138 SHA1_Init(&ctx);
139 hsEntity->shaCtx = ctx;
140 break;
141 }
142 case HASH_ALGORITHM_TYPE_SHA256: {
143 SHA256_CTX ctx;
144 SHA256_Init(&ctx);
145 hsEntity->sha256Ctx = ctx;
146 break;
147 }
148 default:
149 break;
150 }
151
152 HsHashStream *hsStreamPtr = new HsHashStream(move(hsEntity));
153 if (hsStreamPtr == nullptr) {
154 HILOGE("Failed to create HsHashStream object on heap.");
155 return FsResult<HsHashStream *>::Error(ENOMEM);
156 }
157
158 return FsResult<HsHashStream *>::Success(move(hsStreamPtr));
159 }
160
161 } // namespace ModuleFileIO
162 } // namespace FileManagement
163 } // namespace OHOS