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