blob: 82fa3c2b469646c72073c5584dbd5489ac858a04 [file] [log] [blame]
bigbiff bigbiff56cf5642016-08-19 17:43:45 -04001/*
2 Copyright 2013 to 2017 TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20#include <fcntl.h>
21#include <string>
22#include <unistd.h>
23#include "data.hpp"
24#include "partitions.hpp"
25#include "set_metadata.h"
26#include "twrpDigestDriver.hpp"
27#include "twrp-functions.hpp"
28#include "twcommon.h"
29#include "variables.h"
30#include "gui/gui.hpp"
31#include "twrpDigest/twrpDigest.hpp"
32#include "twrpDigest/twrpMD5.hpp"
33#include "twrpDigest/twrpSHA.hpp"
34
35
bigbiff bigbiff718ab392019-03-28 19:46:56 -040036bool twrpDigestDriver::Check_File_Digest(const string& Filename) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040037 twrpDigest *digest;
38 string digestfile = Filename, file_name = Filename;
39 string digest_str;
40 bool use_sha2 = false;
41
42#ifndef TW_NO_SHA2_LIBRARY
43
44 digestfile += ".sha2";
45 if (TWFunc::Path_Exists(digestfile)) {
46 digest = new twrpSHA256();
47 use_sha2 = true;
48 }
49 else {
bigbiff bigbiff718ab392019-03-28 19:46:56 -040050 digestfile = Filename + ".sha256";
51 if (TWFunc::Path_Exists(digestfile)) {
52 digest = new twrpSHA256();
53 use_sha2 = true;
54 } else {
55 digest = new twrpMD5();
56 digestfile = Filename + ".md5";
57 if (!TWFunc::Path_Exists(digestfile)) {
58 digestfile = Filename + ".md5sum";
59 }
60 }
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040061 }
62#else
63 digest = new twrpMD5();
64 digestfile = Filename + ".md5";
bigbiff bigbiff718ab392019-03-28 19:46:56 -040065 if (!TWFunc::Path_Exists(digestfile)) {
66 digestfile = Filename + ".md5sum";
67 }
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040068
69#endif
70
71 if (!TWFunc::Path_Exists(digestfile)) {
Ethan Yonkerc53d5202019-04-02 15:56:25 -050072 delete digest;
epicX9597b842021-03-20 21:58:17 +053073 gui_msg(Msg(msg::kWarning, "no_digest=Skipping Digest check: no Digest file found"));
74 return true;
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040075 }
76
77
78 if (TWFunc::read_file(digestfile, digest_str) != 0) {
79 gui_msg("digest_error=Digest Error!");
80 delete digest;
81 return false;
82 }
83
84 if (!stream_file_to_digest(file_name, digest)) {
85 delete digest;
86 return false;
87 }
88 string digest_check = digest->return_digest_string();
bigbiff61627612021-10-06 17:03:02 -040089 digest_check = digest_check + " " + TWFunc::Get_Filename(file_name);
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040090 if (digest_check == digest_str) {
91 if (use_sha2)
92 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
93 else
94 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
bigbiff bigbiff718ab392019-03-28 19:46:56 -040095 gui_msg(Msg("digest_matched=Digest matched for '{1}'.")(Filename));
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040096 delete digest;
97 return true;
98 }
99
100 gui_msg(Msg(msg::kError, "digest_fail_match=Digest failed to match on '{1}'.")(Filename));
101 delete digest;
102 return false;
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400103}
104
105bool twrpDigestDriver::Check_Digest(string Full_Filename) {
106 char split_filename[512];
107 int index = 0;
108
109 sync();
110 if (!TWFunc::Path_Exists(Full_Filename)) {
111 // This is a split archive, we presume
112 memset(split_filename, 0, sizeof(split_filename));
113 while (index < 1000) {
114 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
115 if (!TWFunc::Path_Exists(split_filename))
116 break;
117 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400118 if (!Check_File_Digest(split_filename))
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400119 return false;
120 index++;
121 }
122 return true;
123 }
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400124 return Check_File_Digest(Full_Filename); // Single file archive
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400125}
126
127bool twrpDigestDriver::Write_Digest(string Full_Filename) {
128 twrpDigest *digest;
129 string digest_filename, digest_str;
130 int use_sha2;
131
132#ifdef TW_NO_SHA2_LIBRARY
133 use_sha2 = 0;
134#else
135 DataManager::GetValue(TW_USE_SHA2, use_sha2);
136#endif
137
138 if (use_sha2) {
139#ifndef TW_NO_SHA2_LIBRARY
140 digest = new twrpSHA256();
141 digest_filename = Full_Filename + ".sha2";
142 if (!stream_file_to_digest(Full_Filename, digest)) {
143 delete digest;
144 return false;
145 }
146 digest_str = digest->return_digest_string();
147 if (digest_str.empty()) {
148 delete digest;
149 return false;
150 }
151 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
152#endif
153 }
154 else {
155 digest = new twrpMD5();
156 digest_filename = Full_Filename + ".md5";
157 if (!stream_file_to_digest(Full_Filename, digest)) {
158 delete digest;
159 return false;
160 }
161 digest_str = digest->return_digest_string();
162 if (digest_str.empty()) {
163 delete digest;
164 return false;
165 }
166 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
167 }
168
169 digest_str = digest_str + " " + TWFunc::Get_Filename(Full_Filename) + "\n";
170 LOGINFO("digest_filename: %s\n", digest_filename.c_str());
171
bigbiff22851b92021-09-01 16:46:57 -0400172 if (TWFunc::write_to_file(digest_filename, digest_str)) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400173 tw_set_default_metadata(digest_filename.c_str());
174 gui_msg("digest_created= * Digest Created.");
175 }
176 else {
177 gui_err("digest_error= * Digest Error!");
178 delete digest;
179 return false;
180 }
181 delete digest;
182 return true;
183}
184
185bool twrpDigestDriver::Make_Digest(string Full_Filename) {
186 string command, result;
187
188 TWFunc::GUI_Operation_Text(TW_GENERATE_DIGEST_TEXT, gui_parse_text("{@generating_digest1}"));
189 gui_msg("generating_digest2= * Generating digest...");
190 if (TWFunc::Path_Exists(Full_Filename)) {
191 if (!Write_Digest(Full_Filename))
192 return false;
193 } else {
194 char filename[512];
195 int index = 0;
196 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
197 while (index < 1000) {
198 string digest_src(filename);
199 if (TWFunc::Path_Exists(filename)) {
200 if (!Write_Digest(filename))
201 return false;
202 }
203 else
204 break;
205 index++;
206 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
207 }
208 if (index == 0) {
209 LOGERR("Backup file: '%s' not found!\n", filename);
210 return false;
211 }
212 gui_msg("digest_created= * Digest Created.");
213 }
214 return true;
215}
216
217bool twrpDigestDriver::stream_file_to_digest(string filename, twrpDigest* digest) {
218 char buf[4096];
219 int bytes;
220
221 int fd = open(filename.c_str(), O_RDONLY);
222 if (fd < 0) {
223 return false;
224 }
225 while ((bytes = read(fd, &buf, sizeof(buf))) != 0) {
226 digest->update((unsigned char*)buf, bytes);
227 }
228 close(fd);
229 return true;
230}