blob: 0f8eb63f4e5f311a7d32aad45a7eed85260478bd [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;
epicX9d80efa2021-03-12 18:14:23 +053073 gui_msg(Msg(msg::kError, "no_digest_found=No digest file found for '{1}'. Please unselect Enable Digest verification to restore.")(Filename));
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040074 return false;
75 }
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();
89 if (digest_check == digest_str) {
90 if (use_sha2)
91 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
92 else
93 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
bigbiff bigbiff718ab392019-03-28 19:46:56 -040094 gui_msg(Msg("digest_matched=Digest matched for '{1}'.")(Filename));
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040095 delete digest;
96 return true;
97 }
98
99 gui_msg(Msg(msg::kError, "digest_fail_match=Digest failed to match on '{1}'.")(Filename));
100 delete digest;
101 return false;
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400102}
103
104bool twrpDigestDriver::Check_Digest(string Full_Filename) {
105 char split_filename[512];
106 int index = 0;
107
108 sync();
109 if (!TWFunc::Path_Exists(Full_Filename)) {
110 // This is a split archive, we presume
111 memset(split_filename, 0, sizeof(split_filename));
112 while (index < 1000) {
113 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
114 if (!TWFunc::Path_Exists(split_filename))
115 break;
116 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400117 if (!Check_File_Digest(split_filename))
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400118 return false;
119 index++;
120 }
121 return true;
122 }
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400123 return Check_File_Digest(Full_Filename); // Single file archive
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400124}
125
126bool twrpDigestDriver::Write_Digest(string Full_Filename) {
127 twrpDigest *digest;
128 string digest_filename, digest_str;
129 int use_sha2;
130
131#ifdef TW_NO_SHA2_LIBRARY
132 use_sha2 = 0;
133#else
134 DataManager::GetValue(TW_USE_SHA2, use_sha2);
135#endif
136
137 if (use_sha2) {
138#ifndef TW_NO_SHA2_LIBRARY
139 digest = new twrpSHA256();
140 digest_filename = Full_Filename + ".sha2";
141 if (!stream_file_to_digest(Full_Filename, digest)) {
142 delete digest;
143 return false;
144 }
145 digest_str = digest->return_digest_string();
146 if (digest_str.empty()) {
147 delete digest;
148 return false;
149 }
150 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
151#endif
152 }
153 else {
154 digest = new twrpMD5();
155 digest_filename = Full_Filename + ".md5";
156 if (!stream_file_to_digest(Full_Filename, digest)) {
157 delete digest;
158 return false;
159 }
160 digest_str = digest->return_digest_string();
161 if (digest_str.empty()) {
162 delete digest;
163 return false;
164 }
165 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
166 }
167
168 digest_str = digest_str + " " + TWFunc::Get_Filename(Full_Filename) + "\n";
169 LOGINFO("digest_filename: %s\n", digest_filename.c_str());
170
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600171 if (TWFunc::write_to_file(digest_filename, digest_str) == 0) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400172 tw_set_default_metadata(digest_filename.c_str());
173 gui_msg("digest_created= * Digest Created.");
174 }
175 else {
176 gui_err("digest_error= * Digest Error!");
177 delete digest;
178 return false;
179 }
180 delete digest;
181 return true;
182}
183
184bool twrpDigestDriver::Make_Digest(string Full_Filename) {
185 string command, result;
186
187 TWFunc::GUI_Operation_Text(TW_GENERATE_DIGEST_TEXT, gui_parse_text("{@generating_digest1}"));
188 gui_msg("generating_digest2= * Generating digest...");
189 if (TWFunc::Path_Exists(Full_Filename)) {
190 if (!Write_Digest(Full_Filename))
191 return false;
192 } else {
193 char filename[512];
194 int index = 0;
195 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
196 while (index < 1000) {
197 string digest_src(filename);
198 if (TWFunc::Path_Exists(filename)) {
199 if (!Write_Digest(filename))
200 return false;
201 }
202 else
203 break;
204 index++;
205 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
206 }
207 if (index == 0) {
208 LOGERR("Backup file: '%s' not found!\n", filename);
209 return false;
210 }
211 gui_msg("digest_created= * Digest Created.");
212 }
213 return true;
214}
215
216bool twrpDigestDriver::stream_file_to_digest(string filename, twrpDigest* digest) {
217 char buf[4096];
218 int bytes;
219
220 int fd = open(filename.c_str(), O_RDONLY);
221 if (fd < 0) {
222 return false;
223 }
224 while ((bytes = read(fd, &buf, sizeof(buf))) != 0) {
225 digest->update((unsigned char*)buf, bytes);
226 }
227 close(fd);
228 return true;
229}