blob: 4023c813dd0e414f97bd09f5454b2bca28802c67 [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;
bigbiff bigbiff718ab392019-03-28 19:46:56 -040073 if (Filename.find(".zip") == std::string::npos) {
74 gui_msg(Msg(msg::kError, "no_digest_found=No digest file found for '{1}'. Please unselect Enable Digest verification to restore.")(Filename));
Ethan Yonkerc53d5202019-04-02 15:56:25 -050075 } else {
76 return true;
bigbiff bigbiff718ab392019-03-28 19:46:56 -040077 }
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040078 return false;
79 }
80
81
82 if (TWFunc::read_file(digestfile, digest_str) != 0) {
83 gui_msg("digest_error=Digest Error!");
84 delete digest;
85 return false;
86 }
87
88 if (!stream_file_to_digest(file_name, digest)) {
89 delete digest;
90 return false;
91 }
92 string digest_check = digest->return_digest_string();
93 if (digest_check == digest_str) {
94 if (use_sha2)
95 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
96 else
97 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
bigbiff bigbiff718ab392019-03-28 19:46:56 -040098 gui_msg(Msg("digest_matched=Digest matched for '{1}'.")(Filename));
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040099 delete digest;
100 return true;
101 }
102
103 gui_msg(Msg(msg::kError, "digest_fail_match=Digest failed to match on '{1}'.")(Filename));
104 delete digest;
105 return false;
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400106}
107
108bool twrpDigestDriver::Check_Digest(string Full_Filename) {
109 char split_filename[512];
110 int index = 0;
111
112 sync();
113 if (!TWFunc::Path_Exists(Full_Filename)) {
114 // This is a split archive, we presume
115 memset(split_filename, 0, sizeof(split_filename));
116 while (index < 1000) {
117 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
118 if (!TWFunc::Path_Exists(split_filename))
119 break;
120 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400121 if (!Check_File_Digest(split_filename))
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400122 return false;
123 index++;
124 }
125 return true;
126 }
bigbiff bigbiff718ab392019-03-28 19:46:56 -0400127 return Check_File_Digest(Full_Filename); // Single file archive
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400128}
129
130bool twrpDigestDriver::Write_Digest(string Full_Filename) {
131 twrpDigest *digest;
132 string digest_filename, digest_str;
133 int use_sha2;
134
135#ifdef TW_NO_SHA2_LIBRARY
136 use_sha2 = 0;
137#else
138 DataManager::GetValue(TW_USE_SHA2, use_sha2);
139#endif
140
141 if (use_sha2) {
142#ifndef TW_NO_SHA2_LIBRARY
143 digest = new twrpSHA256();
144 digest_filename = Full_Filename + ".sha2";
145 if (!stream_file_to_digest(Full_Filename, digest)) {
146 delete digest;
147 return false;
148 }
149 digest_str = digest->return_digest_string();
150 if (digest_str.empty()) {
151 delete digest;
152 return false;
153 }
154 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
155#endif
156 }
157 else {
158 digest = new twrpMD5();
159 digest_filename = Full_Filename + ".md5";
160 if (!stream_file_to_digest(Full_Filename, digest)) {
161 delete digest;
162 return false;
163 }
164 digest_str = digest->return_digest_string();
165 if (digest_str.empty()) {
166 delete digest;
167 return false;
168 }
169 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
170 }
171
172 digest_str = digest_str + " " + TWFunc::Get_Filename(Full_Filename) + "\n";
173 LOGINFO("digest_filename: %s\n", digest_filename.c_str());
174
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600175 if (TWFunc::write_to_file(digest_filename, digest_str) == 0) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400176 tw_set_default_metadata(digest_filename.c_str());
177 gui_msg("digest_created= * Digest Created.");
178 }
179 else {
180 gui_err("digest_error= * Digest Error!");
181 delete digest;
182 return false;
183 }
184 delete digest;
185 return true;
186}
187
188bool twrpDigestDriver::Make_Digest(string Full_Filename) {
189 string command, result;
190
191 TWFunc::GUI_Operation_Text(TW_GENERATE_DIGEST_TEXT, gui_parse_text("{@generating_digest1}"));
192 gui_msg("generating_digest2= * Generating digest...");
193 if (TWFunc::Path_Exists(Full_Filename)) {
194 if (!Write_Digest(Full_Filename))
195 return false;
196 } else {
197 char filename[512];
198 int index = 0;
199 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
200 while (index < 1000) {
201 string digest_src(filename);
202 if (TWFunc::Path_Exists(filename)) {
203 if (!Write_Digest(filename))
204 return false;
205 }
206 else
207 break;
208 index++;
209 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
210 }
211 if (index == 0) {
212 LOGERR("Backup file: '%s' not found!\n", filename);
213 return false;
214 }
215 gui_msg("digest_created= * Digest Created.");
216 }
217 return true;
218}
219
220bool twrpDigestDriver::stream_file_to_digest(string filename, twrpDigest* digest) {
221 char buf[4096];
222 int bytes;
223
224 int fd = open(filename.c_str(), O_RDONLY);
225 if (fd < 0) {
226 return false;
227 }
228 while ((bytes = read(fd, &buf, sizeof(buf))) != 0) {
229 digest->update((unsigned char*)buf, bytes);
230 }
231 close(fd);
232 return true;
233}