blob: 71ec9840b88455a41f773fb73b3300947121dd94 [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
36bool twrpDigestDriver::Check_Restore_File_Digest(const string& Filename) {
37 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 {
50 digest = new twrpMD5();
51 digestfile = Filename + ".md5";
52
53 }
54#else
55 digest = new twrpMD5();
56 digestfile = Filename + ".md5";
57
58#endif
59
60 if (!TWFunc::Path_Exists(digestfile)) {
61 gui_msg(Msg(msg::kError, "no_digest_found=No digest file found for '{1}'. Please unselect Enable Digest verification to restore.")(Filename));
62 delete digest;
63 return false;
64 }
65
66
67 if (TWFunc::read_file(digestfile, digest_str) != 0) {
68 gui_msg("digest_error=Digest Error!");
69 delete digest;
70 return false;
71 }
72
73 if (!stream_file_to_digest(file_name, digest)) {
74 delete digest;
75 return false;
76 }
77 string digest_check = digest->return_digest_string();
78 if (digest_check == digest_str) {
79 if (use_sha2)
80 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
81 else
82 LOGINFO("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Filename).c_str());
83 delete digest;
84 return true;
85 }
86
87 gui_msg(Msg(msg::kError, "digest_fail_match=Digest failed to match on '{1}'.")(Filename));
88 delete digest;
89 return false;
90
91}
92
93bool twrpDigestDriver::Check_Digest(string Full_Filename) {
94 char split_filename[512];
95 int index = 0;
96
97 sync();
98 if (!TWFunc::Path_Exists(Full_Filename)) {
99 // This is a split archive, we presume
100 memset(split_filename, 0, sizeof(split_filename));
101 while (index < 1000) {
102 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
103 if (!TWFunc::Path_Exists(split_filename))
104 break;
105 LOGINFO("split_filename: %s\n", split_filename);
106 if (!Check_Restore_File_Digest(split_filename))
107 return false;
108 index++;
109 }
110 return true;
111 }
112 return Check_Restore_File_Digest(Full_Filename); // Single file archive
113}
114
115bool twrpDigestDriver::Write_Digest(string Full_Filename) {
116 twrpDigest *digest;
117 string digest_filename, digest_str;
118 int use_sha2;
119
120#ifdef TW_NO_SHA2_LIBRARY
121 use_sha2 = 0;
122#else
123 DataManager::GetValue(TW_USE_SHA2, use_sha2);
124#endif
125
126 if (use_sha2) {
127#ifndef TW_NO_SHA2_LIBRARY
128 digest = new twrpSHA256();
129 digest_filename = Full_Filename + ".sha2";
130 if (!stream_file_to_digest(Full_Filename, digest)) {
131 delete digest;
132 return false;
133 }
134 digest_str = digest->return_digest_string();
135 if (digest_str.empty()) {
136 delete digest;
137 return false;
138 }
139 LOGINFO("SHA2 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
140#endif
141 }
142 else {
143 digest = new twrpMD5();
144 digest_filename = Full_Filename + ".md5";
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("MD5 Digest: %s %s\n", digest_str.c_str(), TWFunc::Get_Filename(Full_Filename).c_str());
155 }
156
157 digest_str = digest_str + " " + TWFunc::Get_Filename(Full_Filename) + "\n";
158 LOGINFO("digest_filename: %s\n", digest_filename.c_str());
159
160 if (TWFunc::write_file(digest_filename, digest_str) == 0) {
161 tw_set_default_metadata(digest_filename.c_str());
162 gui_msg("digest_created= * Digest Created.");
163 }
164 else {
165 gui_err("digest_error= * Digest Error!");
166 delete digest;
167 return false;
168 }
169 delete digest;
170 return true;
171}
172
173bool twrpDigestDriver::Make_Digest(string Full_Filename) {
174 string command, result;
175
176 TWFunc::GUI_Operation_Text(TW_GENERATE_DIGEST_TEXT, gui_parse_text("{@generating_digest1}"));
177 gui_msg("generating_digest2= * Generating digest...");
178 if (TWFunc::Path_Exists(Full_Filename)) {
179 if (!Write_Digest(Full_Filename))
180 return false;
181 } else {
182 char filename[512];
183 int index = 0;
184 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
185 while (index < 1000) {
186 string digest_src(filename);
187 if (TWFunc::Path_Exists(filename)) {
188 if (!Write_Digest(filename))
189 return false;
190 }
191 else
192 break;
193 index++;
194 sprintf(filename, "%s%03i", Full_Filename.c_str(), index);
195 }
196 if (index == 0) {
197 LOGERR("Backup file: '%s' not found!\n", filename);
198 return false;
199 }
200 gui_msg("digest_created= * Digest Created.");
201 }
202 return true;
203}
204
205bool twrpDigestDriver::stream_file_to_digest(string filename, twrpDigest* digest) {
206 char buf[4096];
207 int bytes;
208
209 int fd = open(filename.c_str(), O_RDONLY);
210 if (fd < 0) {
211 return false;
212 }
213 while ((bytes = read(fd, &buf, sizeof(buf))) != 0) {
214 digest->update((unsigned char*)buf, bytes);
215 }
216 close(fd);
217 return true;
218}