summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/zen_crypt/main.cpp
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2008-07-11 16:51:25 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2008-07-11 16:51:25 +0000
commitca5bb76d2b8f65aa97e50b633f828c1deb241526 (patch)
tree453a1b2de3a0dc0d0b2f7080d10d033bf8fbcdf1 /utils/zenutils/source/zen_crypt/main.cpp
parent141774be48940d56e3ad4dbf451d245b61d4f8b2 (diff)
downloadrockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.tar.gz
rockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.zip
Delete the svn:executable property and set svn:eol-style to native for all those text files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18012 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/source/zen_crypt/main.cpp')
-rw-r--r--[-rwxr-xr-x]utils/zenutils/source/zen_crypt/main.cpp1374
1 files changed, 687 insertions, 687 deletions
diff --git a/utils/zenutils/source/zen_crypt/main.cpp b/utils/zenutils/source/zen_crypt/main.cpp
index 8301cbbea5..9944ba97f8 100755..100644
--- a/utils/zenutils/source/zen_crypt/main.cpp
+++ b/utils/zenutils/source/zen_crypt/main.cpp
@@ -1,687 +1,687 @@
1/* zenutils - Utilities for working with creative firmwares. 1/* zenutils - Utilities for working with creative firmwares.
2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> 2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or 6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version. 7 * (at your option) any later version.
8 * 8 *
9 * This program is distributed in the hope that it will be useful, 9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */ 17 */
18 18
19#include <iostream> 19#include <iostream>
20#include <getpot/getpot.hpp> 20#include <getpot/getpot.hpp>
21#include <cenc.h> 21#include <cenc.h>
22#include <crypt.h> 22#include <crypt.h>
23#include <file.h> 23#include <file.h>
24#include <firmware.h> 24#include <firmware.h>
25#include <utils.h> 25#include <utils.h>
26 26
27 27
28namespace { 28namespace {
29enum command_t 29enum command_t
30{ 30{
31 cmd_none = 0, 31 cmd_none = 0,
32 cmd_sign, 32 cmd_sign,
33 cmd_verify, 33 cmd_verify,
34 cmd_encrypt, 34 cmd_encrypt,
35 cmd_decrypt 35 cmd_decrypt
36}; 36};
37 37
38enum mode_t 38enum mode_t
39{ 39{
40 mode_none = 0, 40 mode_none = 0,
41 mode_cenc, 41 mode_cenc,
42 mode_fresc, 42 mode_fresc,
43 mode_tl 43 mode_tl
44}; 44};
45 45
46struct player_info_t 46struct player_info_t
47{ 47{
48 const char* name; 48 const char* name;
49 const char* null_key; // HMAC-SHA1 key 49 const char* null_key; // HMAC-SHA1 key
50 const char* fresc_key; // BlowFish key 50 const char* fresc_key; // BlowFish key
51 const char* tl_key; // BlowFish key 51 const char* tl_key; // BlowFish key
52 bool big_endian; 52 bool big_endian;
53}; 53};
54}; //namespace 54}; //namespace
55 55
56 56
57static const char VERSION[] = "0.1"; 57static const char VERSION[] = "0.1";
58 58
59static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN."; 59static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
60static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP."; 60static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
61 61
62static const char fresc_key[] = "Copyright (C) CTL. -" 62static const char fresc_key[] = "Copyright (C) CTL. -"
63 " zN0MAD iz v~p0wderful!"; 63 " zN0MAD iz v~p0wderful!";
64 64
65static const char tl_zvm_key[] = "1sN0TM3D az u~may th1nk*" 65static const char tl_zvm_key[] = "1sN0TM3D az u~may th1nk*"
66 "Creative Zen Vision:M"; 66 "Creative Zen Vision:M";
67static const char tl_zvw_key[] = "1sN0TM3D az u~may th1nk*" 67static const char tl_zvw_key[] = "1sN0TM3D az u~may th1nk*"
68 "Creative ZEN Vision W"; 68 "Creative ZEN Vision W";
69static const char tl_zm_key[] = "1sN0TM3D az u~may th1nk*" 69static const char tl_zm_key[] = "1sN0TM3D az u~may th1nk*"
70 "Creative Zen Micro"; 70 "Creative Zen Micro";
71static const char tl_zmp_key[] = "1sN0TM3D az u~may th1nk*" 71static const char tl_zmp_key[] = "1sN0TM3D az u~may th1nk*"
72 "Creative Zen MicroPhoto"; 72 "Creative Zen MicroPhoto";
73static const char tl_zs_key[] = "1sN0TM3D az u~may th1nk*" 73static const char tl_zs_key[] = "1sN0TM3D az u~may th1nk*"
74 "Creative Zen Sleek"; 74 "Creative Zen Sleek";
75static const char tl_zsp_key[] = "1sN0TM3D az u~may th1nk*" 75static const char tl_zsp_key[] = "1sN0TM3D az u~may th1nk*"
76 "Creative Zen Sleek Photo"; 76 "Creative Zen Sleek Photo";
77static const char tl_zt_key[] = "1sN0TM3D az u~may th1nk*" 77static const char tl_zt_key[] = "1sN0TM3D az u~may th1nk*"
78 "Creative Zen Touch"; 78 "Creative Zen Touch";
79static const char tl_zx_key[] = "1sN0TM3D az u~may th1nk*" 79static const char tl_zx_key[] = "1sN0TM3D az u~may th1nk*"
80 "NOMAD Jukebox Zen Xtra"; 80 "NOMAD Jukebox Zen Xtra";
81 81
82player_info_t players[] = { 82player_info_t players[] = {
83 {"Vision:M", null_key_v2, fresc_key, tl_zvm_key, false}, 83 {"Vision:M", null_key_v2, fresc_key, tl_zvm_key, false},
84 {"Vision W", null_key_v2, fresc_key, tl_zvw_key, false}, 84 {"Vision W", null_key_v2, fresc_key, tl_zvw_key, false},
85 {"Micro", null_key_v1, fresc_key, tl_zm_key, true}, 85 {"Micro", null_key_v1, fresc_key, tl_zm_key, true},
86 {"MicroPhoto", null_key_v1, fresc_key, tl_zmp_key, true}, 86 {"MicroPhoto", null_key_v1, fresc_key, tl_zmp_key, true},
87 {"Sleek", null_key_v1, fresc_key, tl_zs_key, true}, 87 {"Sleek", null_key_v1, fresc_key, tl_zs_key, true},
88 {"SleekPhoto", null_key_v1, fresc_key, tl_zsp_key, true}, 88 {"SleekPhoto", null_key_v1, fresc_key, tl_zsp_key, true},
89 {"Touch", null_key_v1, fresc_key, tl_zt_key, true}, 89 {"Touch", null_key_v1, fresc_key, tl_zt_key, true},
90 {"Xtra", null_key_v1, fresc_key, tl_zx_key, true}, 90 {"Xtra", null_key_v1, fresc_key, tl_zx_key, true},
91 {NULL, NULL, NULL, NULL, false} 91 {NULL, NULL, NULL, NULL, false}
92}; 92};
93 93
94 94
95player_info_t* find_player_info(std::string player) 95player_info_t* find_player_info(std::string player)
96{ 96{
97 for (int i = 0; players[i].name != NULL; i++) 97 for (int i = 0; players[i].name != NULL; i++)
98 { 98 {
99 if (!stricmp(players[i].name, player.c_str())) 99 if (!stricmp(players[i].name, player.c_str()))
100 { 100 {
101 return &players[i]; 101 return &players[i];
102 } 102 }
103 } 103 }
104 return NULL; 104 return NULL;
105} 105}
106 106
107void print_version() 107void print_version()
108{ 108{
109 std::cout 109 std::cout
110 << "zen_crypt - A utility for encrypting, decrypting or signing" 110 << "zen_crypt - A utility for encrypting, decrypting or signing"
111 " Creative firmwares." << std::endl 111 " Creative firmwares." << std::endl
112 << "Version " << VERSION << std::endl 112 << "Version " << VERSION << std::endl
113 << "Copyright (c) 2007 Rasmus Ry" << std::endl; 113 << "Copyright (c) 2007 Rasmus Ry" << std::endl;
114} 114}
115 115
116void print_help() 116void print_help()
117{ 117{
118 print_version(); 118 print_version();
119 std::cout << std::endl 119 std::cout << std::endl
120 << "Usage: zen_crypt [command] [options]" << std::endl 120 << "Usage: zen_crypt [command] [options]" << std::endl
121 << std::endl 121 << std::endl
122 << " Commands:" << std::endl 122 << " Commands:" << std::endl
123 << " -h,--help" << std::endl 123 << " -h,--help" << std::endl
124 << " prints this message." << std::endl 124 << " prints this message." << std::endl
125 << " -s,--sign" << std::endl 125 << " -s,--sign" << std::endl
126 << " signs a given input file." << std::endl 126 << " signs a given input file." << std::endl
127 << " -v,--verify" << std::endl 127 << " -v,--verify" << std::endl
128 << " verifies a signed input file." << std::endl 128 << " verifies a signed input file." << std::endl
129 << " -e,--encrypt" << std::endl 129 << " -e,--encrypt" << std::endl
130 << " encrypts a given input file." << std::endl 130 << " encrypts a given input file." << std::endl
131 << " -d,--decrypt" << std::endl 131 << " -d,--decrypt" << std::endl
132 << " decrypts a given input file." << std::endl 132 << " decrypts a given input file." << std::endl
133 << std::endl 133 << std::endl
134 << " Options:" << std::endl 134 << " Options:" << std::endl
135 << " -V,--verbose" << std::endl 135 << " -V,--verbose" << std::endl
136 << " prints verbose messages." << std::endl 136 << " prints verbose messages." << std::endl
137 << " -b,--big-endian" << std::endl 137 << " -b,--big-endian" << std::endl
138 << " specifies that the input is big-endian, default is" 138 << " specifies that the input is big-endian, default is"
139 " little-endian." << std::endl 139 " little-endian." << std::endl
140 << " -i,--input [file]" << std::endl 140 << " -i,--input [file]" << std::endl
141 << " specifies the input file." << std::endl 141 << " specifies the input file." << std::endl
142 << " -o,--output [file]" << std::endl 142 << " -o,--output [file]" << std::endl
143 << " specifies the output file." << std::endl 143 << " specifies the output file." << std::endl
144 << " -m,--mode [CENC|FRESC|TL]" << std::endl 144 << " -m,--mode [CENC|FRESC|TL]" << std::endl
145 << " specifies which algorithm to use." << std::endl 145 << " specifies which algorithm to use." << std::endl
146 << " -k,--key [player|key]" << std::endl 146 << " -k,--key [player|key]" << std::endl
147 << " specifies which key to use." << std::endl 147 << " specifies which key to use." << std::endl
148 << std::endl 148 << std::endl
149 ; 149 ;
150 std::cout << " Players:" << std::endl; 150 std::cout << " Players:" << std::endl;
151 for (int i = 0; players[i].name != NULL; i++) 151 for (int i = 0; players[i].name != NULL; i++)
152 { 152 {
153 std::cout << " " << players[i].name; 153 std::cout << " " << players[i].name;
154 if (!i) 154 if (!i)
155 std::cout << " (default)"; 155 std::cout << " (default)";
156 std::cout << std::endl; 156 std::cout << std::endl;
157 } 157 }
158} 158}
159 159
160size_t find_null_signature(shared::bytes& data) 160size_t find_null_signature(shared::bytes& data)
161{ 161{
162 size_t index = data.size(); 162 size_t index = data.size();
163 if (index < (20 + 8 + 7)) 163 if (index < (20 + 8 + 7))
164 return 0; 164 return 0;
165 index -= 20 + 8; 165 index -= 20 + 8;
166 for (int i = 0; i < 7; i++) 166 for (int i = 0; i < 7; i++)
167 { 167 {
168 if (*(dword*)&data[index-i] == 'NULL' || 168 if (*(dword*)&data[index-i] == 'NULL' ||
169 *(dword*)&data[index-i] == 'LLUN') 169 *(dword*)&data[index-i] == 'LLUN')
170 { 170 {
171 return index-i; 171 return index-i;
172 } 172 }
173 } 173 }
174 return 0; 174 return 0;
175} 175}
176 176
177 177
178bool sign(shared::bytes& data, player_info_t* pi, const std::string& file, 178bool sign(shared::bytes& data, player_info_t* pi, const std::string& file,
179 bool verbose) 179 bool verbose)
180{ 180{
181 if (verbose) 181 if (verbose)
182 std::cout << "[*] Checking for the presence of an existing" 182 std::cout << "[*] Checking for the presence of an existing"
183 " NULL signature..." << std::endl; 183 " NULL signature..." << std::endl;
184 size_t index = find_null_signature(data); 184 size_t index = find_null_signature(data);
185 if (index) 185 if (index)
186 { 186 {
187 if (verbose) 187 if (verbose)
188 std::cout << "[*] Found NULL signature at: " 188 std::cout << "[*] Found NULL signature at: "
189 << std::hex << index << std::endl; 189 << std::hex << index << std::endl;
190 190
191 if (verbose) 191 if (verbose)
192 std::cout << "[*] Computing digest..." << std::endl; 192 std::cout << "[*] Computing digest..." << std::endl;
193 193
194 shared::bytes digest(20); 194 shared::bytes digest(20);
195 if (!zen::hmac_sha1_calc((const byte*)pi->null_key, 195 if (!zen::hmac_sha1_calc((const byte*)pi->null_key,
196 strlen(pi->null_key)+1, &data[0], index, 196 strlen(pi->null_key)+1, &data[0], index,
197 &digest[0], NULL)) 197 &digest[0], NULL))
198 { 198 {
199 std::cerr << "Failed to compute digest." << std::endl; 199 std::cerr << "Failed to compute digest." << std::endl;
200 return false; 200 return false;
201 } 201 }
202 202
203 if (verbose) 203 if (verbose)
204 std::cout << "[*] Writing file data..." << std::endl; 204 std::cout << "[*] Writing file data..." << std::endl;
205 205
206 if (!shared::write_file(file, data, true)) 206 if (!shared::write_file(file, data, true))
207 { 207 {
208 std::cerr << "Failed to write file data." << std::endl; 208 std::cerr << "Failed to write file data." << std::endl;
209 return false; 209 return false;
210 } 210 }
211 211
212 if (verbose) 212 if (verbose)
213 std::cout << "[*] Writing digest data..." << std::endl; 213 std::cout << "[*] Writing digest data..." << std::endl;
214 214
215 if (!shared::write_file(file, digest, false, index+8)) 215 if (!shared::write_file(file, digest, false, index+8))
216 { 216 {
217 std::cerr << "Failed to write digest data." << std::endl; 217 std::cerr << "Failed to write digest data." << std::endl;
218 return false; 218 return false;
219 } 219 }
220 } 220 }
221 else 221 else
222 { 222 {
223 if (verbose) 223 if (verbose)
224 std::cout << "[*] Computing digest..." << std::endl; 224 std::cout << "[*] Computing digest..." << std::endl;
225 225
226 shared::bytes signature(20+8); 226 shared::bytes signature(20+8);
227 if (!zen::hmac_sha1_calc((const byte*)pi->null_key, 227 if (!zen::hmac_sha1_calc((const byte*)pi->null_key,
228 strlen(pi->null_key)+1, &data[0], data.size(), 228 strlen(pi->null_key)+1, &data[0], data.size(),
229 &signature[8], NULL)) 229 &signature[8], NULL))
230 { 230 {
231 std::cerr << "Failed to compute digest." << std::endl; 231 std::cerr << "Failed to compute digest." << std::endl;
232 return false; 232 return false;
233 } 233 }
234 234
235 235
236 zen::firmware_header_t header = {'NULL', 20}; 236 zen::firmware_header_t header = {'NULL', 20};
237 if (pi->big_endian) 237 if (pi->big_endian)
238 { 238 {
239 header.tag = shared::swap(header.tag); 239 header.tag = shared::swap(header.tag);
240 header.size = shared::swap(header.size); 240 header.size = shared::swap(header.size);
241 } 241 }
242 memcpy(&signature[0], &header, sizeof(zen::firmware_header_t)); 242 memcpy(&signature[0], &header, sizeof(zen::firmware_header_t));
243 243
244 if (verbose) 244 if (verbose)
245 std::cout << "[*] Writing file data..." << std::endl; 245 std::cout << "[*] Writing file data..." << std::endl;
246 246
247 if (!shared::write_file(file, data, true)) 247 if (!shared::write_file(file, data, true))
248 { 248 {
249 std::cerr << "Failed to write file data." << std::endl; 249 std::cerr << "Failed to write file data." << std::endl;
250 return false; 250 return false;
251 } 251 }
252 252
253 if (verbose) 253 if (verbose)
254 std::cout << "[*] Writing signature data..." << std::endl; 254 std::cout << "[*] Writing signature data..." << std::endl;
255 255
256 if (!shared::write_file(file, signature, false, data.size())) 256 if (!shared::write_file(file, signature, false, data.size()))
257 { 257 {
258 std::cerr << "Failed to write signature data." << std::endl; 258 std::cerr << "Failed to write signature data." << std::endl;
259 return false; 259 return false;
260 } 260 }
261 261
262 if (verbose) 262 if (verbose)
263 std::cout << "[*] Ensuring that the file length is" 263 std::cout << "[*] Ensuring that the file length is"
264 " 32-bit aligned..." << std::endl; 264 " 32-bit aligned..." << std::endl;
265 265
266 int length = data.size() + signature.size(); 266 int length = data.size() + signature.size();
267 int align = length % 4; 267 int align = length % 4;
268 if (align) 268 if (align)
269 { 269 {
270 shared::bytes padding(4 - align, 0); 270 shared::bytes padding(4 - align, 0);
271 if (!shared::write_file(file, padding, false, length)) 271 if (!shared::write_file(file, padding, false, length))
272 { 272 {
273 std::cerr << "Failed to write padding data." << std::endl; 273 std::cerr << "Failed to write padding data." << std::endl;
274 return false; 274 return false;
275 } 275 }
276 } 276 }
277 } 277 }
278 278
279 return true; 279 return true;
280} 280}
281 281
282bool verify(shared::bytes& data, player_info_t* pi, bool verbose) 282bool verify(shared::bytes& data, player_info_t* pi, bool verbose)
283{ 283{
284 if (verbose) 284 if (verbose)
285 std::cout << "[*] Checking for the presence of an existing" 285 std::cout << "[*] Checking for the presence of an existing"
286 " NULL signature..." << std::endl; 286 " NULL signature..." << std::endl;
287 size_t index = find_null_signature(data); 287 size_t index = find_null_signature(data);
288 if (!index) 288 if (!index)
289 { 289 {
290 std::cerr << "No NULL signature present in the input file." 290 std::cerr << "No NULL signature present in the input file."
291 << std::endl; 291 << std::endl;
292 return false; 292 return false;
293 } 293 }
294 if (verbose) 294 if (verbose)
295 std::cout << "[*] Found NULL signature at: " 295 std::cout << "[*] Found NULL signature at: "
296 << std::hex << index << std::endl; 296 << std::hex << index << std::endl;
297 297
298 if (verbose) 298 if (verbose)
299 std::cout << "[*] Computing digest..." << std::endl; 299 std::cout << "[*] Computing digest..." << std::endl;
300 300
301 byte digest[20]; 301 byte digest[20];
302 if (!zen::hmac_sha1_calc((const byte*)pi->null_key, strlen(pi->null_key)+1, 302 if (!zen::hmac_sha1_calc((const byte*)pi->null_key, strlen(pi->null_key)+1,
303 &data[0], index, digest, NULL)) 303 &data[0], index, digest, NULL))
304 { 304 {
305 std::cerr << "Failed to compute digest." << std::endl; 305 std::cerr << "Failed to compute digest." << std::endl;
306 return false; 306 return false;
307 } 307 }
308 308
309 if (verbose) 309 if (verbose)
310 std::cout << "[*] Verifying NULL signature digest..." << std::endl; 310 std::cout << "[*] Verifying NULL signature digest..." << std::endl;
311 311
312 if (memcmp(&digest[0], &data[index+8], 20)) 312 if (memcmp(&digest[0], &data[index+8], 20))
313 { 313 {
314 std::cerr << "The NULL signature contains an incorrect digest." 314 std::cerr << "The NULL signature contains an incorrect digest."
315 << std::endl; 315 << std::endl;
316 return false; 316 return false;
317 } 317 }
318 318
319 return true; 319 return true;
320} 320}
321 321
322bool encrypt(shared::bytes& data, int mode, player_info_t* pi, 322bool encrypt(shared::bytes& data, int mode, player_info_t* pi,
323 const std::string& file, bool verbose) 323 const std::string& file, bool verbose)
324{ 324{
325 if (mode == mode_cenc) 325 if (mode == mode_cenc)
326 { 326 {
327 if (verbose) 327 if (verbose)
328 std::cout << "[*] Encoding input file..." << std::endl; 328 std::cout << "[*] Encoding input file..." << std::endl;
329 329
330 shared::bytes outbuf(data.size() * 2); 330 shared::bytes outbuf(data.size() * 2);
331 int len = zen::cenc_encode(&data[0], data.size(), &outbuf[0], outbuf.size()); 331 int len = zen::cenc_encode(&data[0], data.size(), &outbuf[0], outbuf.size());
332 if (!len) 332 if (!len)
333 { 333 {
334 std::cerr << "Failed to encode the input file." << std::endl; 334 std::cerr << "Failed to encode the input file." << std::endl;
335 return false; 335 return false;
336 } 336 }
337 337
338 if (verbose) 338 if (verbose)
339 std::cout << "[*] Writing decoded length to file..." << std::endl; 339 std::cout << "[*] Writing decoded length to file..." << std::endl;
340 340
341 shared::bytes length(sizeof(dword)); 341 shared::bytes length(sizeof(dword));
342 *(dword*)&length[0] = pi->big_endian ? shared::swap(data.size()) : data.size(); 342 *(dword*)&length[0] = pi->big_endian ? shared::swap(data.size()) : data.size();
343 if (!shared::write_file(file, length, true)) 343 if (!shared::write_file(file, length, true))
344 { 344 {
345 std::cerr << "Failed to write the file data." << std::endl; 345 std::cerr << "Failed to write the file data." << std::endl;
346 return false; 346 return false;
347 } 347 }
348 348
349 if (verbose) 349 if (verbose)
350 std::cout << "[*] Writing file data..." << std::endl; 350 std::cout << "[*] Writing file data..." << std::endl;
351 351
352 if (!shared::write_file(file, outbuf, sizeof(dword), len)) 352 if (!shared::write_file(file, outbuf, sizeof(dword), len))
353 { 353 {
354 std::cerr << "Failed to write the file data." << std::endl; 354 std::cerr << "Failed to write the file data." << std::endl;
355 return false; 355 return false;
356 } 356 }
357 } 357 }
358 else if (mode == mode_fresc) 358 else if (mode == mode_fresc)
359 { 359 {
360 std::cerr << "FRESC mode is not supported." << std::endl; 360 std::cerr << "FRESC mode is not supported." << std::endl;
361 return false; 361 return false;
362 } 362 }
363 else if (mode == mode_tl) 363 else if (mode == mode_tl)
364 { 364 {
365 if (verbose) 365 if (verbose)
366 std::cout << "[*] Encoding input file..." << std::endl; 366 std::cout << "[*] Encoding input file..." << std::endl;
367 367
368 shared::bytes outbuf(data.size() * 2); 368 shared::bytes outbuf(data.size() * 2);
369 *(dword*)&outbuf[0] = pi->big_endian ? shared::swap(data.size()) : data.size(); 369 *(dword*)&outbuf[0] = pi->big_endian ? shared::swap(data.size()) : data.size();
370 int len = zen::cenc_encode(&data[0], data.size(), 370 int len = zen::cenc_encode(&data[0], data.size(),
371 &outbuf[sizeof(dword)], 371 &outbuf[sizeof(dword)],
372 outbuf.size()-sizeof(dword)); 372 outbuf.size()-sizeof(dword));
373 if (!len) 373 if (!len)
374 { 374 {
375 std::cerr << "Failed to encode the input file." << std::endl; 375 std::cerr << "Failed to encode the input file." << std::endl;
376 return false; 376 return false;
377 } 377 }
378 len += sizeof(dword); 378 len += sizeof(dword);
379 379
380 int align = len % 8; 380 int align = len % 8;
381 align = align ? (8 - align) : 0; 381 align = align ? (8 - align) : 0;
382 len += align; 382 len += align;
383 383
384 if (verbose) 384 if (verbose)
385 std::cout << "[*] Encrypting encoded data..." << std::endl; 385 std::cout << "[*] Encrypting encoded data..." << std::endl;
386 386
387 dword iv[2] = {0, shared::swap(len)}; 387 dword iv[2] = {0, shared::swap(len)};
388 if (!zen::bf_cbc_encrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1, 388 if (!zen::bf_cbc_encrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1,
389 &outbuf[0], len, (const byte*)iv)) 389 &outbuf[0], len, (const byte*)iv))
390 { 390 {
391 std::cerr << "Failed to decrypt the input file." << std::endl; 391 std::cerr << "Failed to decrypt the input file." << std::endl;
392 return false; 392 return false;
393 } 393 }
394 394
395 if (verbose) 395 if (verbose)
396 std::cout << "[*] Writing file data..." << std::endl; 396 std::cout << "[*] Writing file data..." << std::endl;
397 397
398 if (!shared::write_file(file, outbuf, true, 0, len)) 398 if (!shared::write_file(file, outbuf, true, 0, len))
399 { 399 {
400 std::cerr << "Failed to save the output file." << std::endl; 400 std::cerr << "Failed to save the output file." << std::endl;
401 return false; 401 return false;
402 } 402 }
403 } 403 }
404 else 404 else
405 { 405 {
406 std::cerr << "Invalid mode specified." << std::endl; 406 std::cerr << "Invalid mode specified." << std::endl;
407 return false; 407 return false;
408 } 408 }
409 409
410 return true; 410 return true;
411} 411}
412 412
413bool decrypt(shared::bytes& data, int mode, player_info_t* pi, 413bool decrypt(shared::bytes& data, int mode, player_info_t* pi,
414 const std::string& file, bool verbose) 414 const std::string& file, bool verbose)
415{ 415{
416 if (mode == mode_cenc) 416 if (mode == mode_cenc)
417 { 417 {
418 dword length = *(dword*)&data[0]; 418 dword length = *(dword*)&data[0];
419 length = pi->big_endian ? shared::swap(length) : length; 419 length = pi->big_endian ? shared::swap(length) : length;
420 420
421 if (verbose) 421 if (verbose)
422 std::cout << "[*] Decoding input file..." << std::endl; 422 std::cout << "[*] Decoding input file..." << std::endl;
423 423
424 shared::bytes outbuf(length); 424 shared::bytes outbuf(length);
425 if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword), 425 if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword),
426 &outbuf[0], length)) 426 &outbuf[0], length))
427 { 427 {
428 std::cerr << "Failed to decode the input file." << std::endl; 428 std::cerr << "Failed to decode the input file." << std::endl;
429 return false; 429 return false;
430 } 430 }
431 431
432 if (verbose) 432 if (verbose)
433 std::cout << "[*] Writing file data..." << std::endl; 433 std::cout << "[*] Writing file data..." << std::endl;
434 434
435 if (!shared::write_file(file, outbuf, true)) 435 if (!shared::write_file(file, outbuf, true))
436 { 436 {
437 std::cerr << "Failed to write the file data." << std::endl; 437 std::cerr << "Failed to write the file data." << std::endl;
438 return false; 438 return false;
439 } 439 }
440 } 440 }
441 else if (mode == mode_fresc) 441 else if (mode == mode_fresc)
442 { 442 {
443 if (verbose) 443 if (verbose)
444 std::cout << "[*] Decrypting input file..." << std::endl; 444 std::cout << "[*] Decrypting input file..." << std::endl;
445 445
446 dword iv[2] = {shared::swap(data.size()), 0}; 446 dword iv[2] = {shared::swap(data.size()), 0};
447 if (!zen::bf_cbc_decrypt((const byte*)pi->fresc_key, 447 if (!zen::bf_cbc_decrypt((const byte*)pi->fresc_key,
448 strlen(pi->fresc_key)+1, &data[0], 448 strlen(pi->fresc_key)+1, &data[0],
449 data.size(), (const byte*)iv)) 449 data.size(), (const byte*)iv))
450 { 450 {
451 std::cerr << "Failed to decrypt the input file." << std::endl; 451 std::cerr << "Failed to decrypt the input file." << std::endl;
452 return false; 452 return false;
453 } 453 }
454 454
455 if (verbose) 455 if (verbose)
456 std::cout << "[*] Writing file data..." << std::endl; 456 std::cout << "[*] Writing file data..." << std::endl;
457 457
458 if (!shared::write_file(file, data, true)) 458 if (!shared::write_file(file, data, true))
459 { 459 {
460 std::cerr << "Failed to save the output file." << std::endl; 460 std::cerr << "Failed to save the output file." << std::endl;
461 return false; 461 return false;
462 } 462 }
463 } 463 }
464 else if (mode == mode_tl) 464 else if (mode == mode_tl)
465 { 465 {
466 if (verbose) 466 if (verbose)
467 std::cout << "[*] Decrypting input file..." << std::endl; 467 std::cout << "[*] Decrypting input file..." << std::endl;
468 468
469 dword iv[2] = {0, shared::swap(data.size())}; 469 dword iv[2] = {0, shared::swap(data.size())};
470 if (!zen::bf_cbc_decrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1, 470 if (!zen::bf_cbc_decrypt((const byte*)pi->tl_key, strlen(pi->tl_key)+1,
471 &data[0], data.size(), (const byte*)iv)) 471 &data[0], data.size(), (const byte*)iv))
472 { 472 {
473 std::cerr << "Failed to decrypt the input file." << std::endl; 473 std::cerr << "Failed to decrypt the input file." << std::endl;
474 return false; 474 return false;
475 } 475 }
476 476
477 dword length = *(dword*)&data[0]; 477 dword length = *(dword*)&data[0];
478 length = pi->big_endian ? shared::swap(length) : length; 478 length = pi->big_endian ? shared::swap(length) : length;
479 if (length > (data.size() * 3)) 479 if (length > (data.size() * 3))
480 { 480 {
481 std::cerr << "Decrypted length is unexpectedly large: " 481 std::cerr << "Decrypted length is unexpectedly large: "
482 << std::hex << length 482 << std::hex << length
483 << " Check the endian and key settings." << std::endl; 483 << " Check the endian and key settings." << std::endl;
484 return false; 484 return false;
485 } 485 }
486 486
487 if (verbose) 487 if (verbose)
488 std::cout << "[*] Decoding decrypted data..." << std::endl; 488 std::cout << "[*] Decoding decrypted data..." << std::endl;
489 489
490 shared::bytes outbuf(length); 490 shared::bytes outbuf(length);
491 if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword), 491 if (!zen::cenc_decode(&data[sizeof(dword)], data.size()-sizeof(dword),
492 &outbuf[0], length)) 492 &outbuf[0], length))
493 { 493 {
494 std::cerr << "Failed to decode the input file." << std::endl; 494 std::cerr << "Failed to decode the input file." << std::endl;
495 return false; 495 return false;
496 } 496 }
497 497
498 if (verbose) 498 if (verbose)
499 std::cout << "[*] Writing file data..." << std::endl; 499 std::cout << "[*] Writing file data..." << std::endl;
500 500
501 if (!shared::write_file(file, outbuf, true)) 501 if (!shared::write_file(file, outbuf, true))
502 { 502 {
503 std::cerr << "Failed to save the output file." << std::endl; 503 std::cerr << "Failed to save the output file." << std::endl;
504 return false; 504 return false;
505 } 505 }
506 } 506 }
507 else 507 else
508 { 508 {
509 std::cerr << "Invalid mode specified." << std::endl; 509 std::cerr << "Invalid mode specified." << std::endl;
510 return false; 510 return false;
511 } 511 }
512 512
513 return true; 513 return true;
514} 514}
515 515
516int process_arguments(int argc, char*argv[]) 516int process_arguments(int argc, char*argv[])
517{ 517{
518 //-------------------------------------------------------------------- 518 //--------------------------------------------------------------------
519 // Parse input variables. 519 // Parse input variables.
520 //-------------------------------------------------------------------- 520 //--------------------------------------------------------------------
521 521
522 GetPot cl(argc, argv); 522 GetPot cl(argc, argv);
523 if (cl.size() == 1 || cl.search(2, "-h", "--help")) 523 if (cl.size() == 1 || cl.search(2, "-h", "--help"))
524 { 524 {
525 print_help(); 525 print_help();
526 return 1; 526 return 1;
527 } 527 }
528 528
529 int command = cmd_none; 529 int command = cmd_none;
530 if (cl.search(2, "-s", "--sign")) 530 if (cl.search(2, "-s", "--sign"))
531 command = cmd_sign; 531 command = cmd_sign;
532 else if (cl.search(2, "-v", "--verify")) 532 else if (cl.search(2, "-v", "--verify"))
533 command = cmd_verify; 533 command = cmd_verify;
534 else if (cl.search(2, "-e", "--encrypt")) 534 else if (cl.search(2, "-e", "--encrypt"))
535 command = cmd_encrypt; 535 command = cmd_encrypt;
536 else if (cl.search(2, "-d", "--decrypt")) 536 else if (cl.search(2, "-d", "--decrypt"))
537 command = cmd_decrypt; 537 command = cmd_decrypt;
538 538
539 if (command == cmd_none) 539 if (command == cmd_none)
540 { 540 {
541 std::cerr << "No command specified." << std::endl; 541 std::cerr << "No command specified." << std::endl;
542 return 2; 542 return 2;
543 } 543 }
544 544
545 int mode = mode_none; 545 int mode = mode_none;
546 if (command == cmd_encrypt || command == cmd_decrypt) 546 if (command == cmd_encrypt || command == cmd_decrypt)
547 { 547 {
548 if (!cl.search(2, "-m", "--mode")) 548 if (!cl.search(2, "-m", "--mode"))
549 { 549 {
550 std::cerr << "The specified command requires that" 550 std::cerr << "The specified command requires that"
551 " a mode is specified." 551 " a mode is specified."
552 << std::endl; 552 << std::endl;
553 return 3; 553 return 3;
554 } 554 }
555 std::string name = cl.next(""); 555 std::string name = cl.next("");
556 if (!name.empty()) 556 if (!name.empty())
557 { 557 {
558 if (!stricmp(name.c_str(), "CENC")) 558 if (!stricmp(name.c_str(), "CENC"))
559 mode = mode_cenc; 559 mode = mode_cenc;
560 else if (!stricmp(name.c_str(), "FRESC")) 560 else if (!stricmp(name.c_str(), "FRESC"))
561 mode = mode_fresc; 561 mode = mode_fresc;
562 else if (!stricmp(name.c_str(), "TL")) 562 else if (!stricmp(name.c_str(), "TL"))
563 mode = mode_tl; 563 mode = mode_tl;
564 } 564 }
565 if (mode == mode_none) 565 if (mode == mode_none)
566 { 566 {
567 std::cerr << "Invalid mode specified." << std::endl; 567 std::cerr << "Invalid mode specified." << std::endl;
568 return 4; 568 return 4;
569 } 569 }
570 } 570 }
571 571
572 bool verbose = false; 572 bool verbose = false;
573 if (cl.search(2, "-V", "--verbose")) 573 if (cl.search(2, "-V", "--verbose"))
574 verbose = true; 574 verbose = true;
575 575
576 bool big_endian = false; 576 bool big_endian = false;
577 if (cl.search(2, "-b", "--big-endian")) 577 if (cl.search(2, "-b", "--big-endian"))
578 big_endian = true; 578 big_endian = true;
579 579
580 std::string infile; 580 std::string infile;
581 if (cl.search(2, "-i", "--input")) 581 if (cl.search(2, "-i", "--input"))
582 infile = cl.next(""); 582 infile = cl.next("");
583 if (infile.empty()) 583 if (infile.empty())
584 { 584 {
585 std::cerr << "An input file must be specified." << std::endl; 585 std::cerr << "An input file must be specified." << std::endl;
586 return 5; 586 return 5;
587 } 587 }
588 588
589 std::string outfile = infile; 589 std::string outfile = infile;
590 if (cl.search(2, "-o", "--output")) 590 if (cl.search(2, "-o", "--output"))
591 outfile = cl.next(outfile.c_str()); 591 outfile = cl.next(outfile.c_str());
592 592
593 player_info_t* pi = &players[0]; 593 player_info_t* pi = &players[0];
594 std::string key; 594 std::string key;
595 if (cl.search(2, "-k", "--key")) 595 if (cl.search(2, "-k", "--key"))
596 key = cl.next(""); 596 key = cl.next("");
597 if (!key.empty()) 597 if (!key.empty())
598 { 598 {
599 player_info_t* pitmp = find_player_info(key); 599 player_info_t* pitmp = find_player_info(key);
600 if (pitmp != NULL) 600 if (pitmp != NULL)
601 pi = pitmp; 601 pi = pitmp;
602 else 602 else
603 { 603 {
604 static player_info_t player = { 604 static player_info_t player = {
605 NULL, key.c_str(), key.c_str(), key.c_str(), false 605 NULL, key.c_str(), key.c_str(), key.c_str(), false
606 }; 606 };
607 pi = &player; 607 pi = &player;
608 } 608 }
609 } 609 }
610 if (big_endian) 610 if (big_endian)
611 pi->big_endian = big_endian; 611 pi->big_endian = big_endian;
612 612
613 613
614 //-------------------------------------------------------------------- 614 //--------------------------------------------------------------------
615 // Read the input file. 615 // Read the input file.
616 //-------------------------------------------------------------------- 616 //--------------------------------------------------------------------
617 617
618 if (verbose) 618 if (verbose)
619 std::cout << "[*] Reading input file..." << std::endl; 619 std::cout << "[*] Reading input file..." << std::endl;
620 620
621 shared::bytes buffer; 621 shared::bytes buffer;
622 if (!shared::read_file(infile, buffer)) 622 if (!shared::read_file(infile, buffer))
623 { 623 {
624 std::cerr << "Failed to read the input file." << std::endl; 624 std::cerr << "Failed to read the input file." << std::endl;
625 return 6; 625 return 6;
626 } 626 }
627 627
628 628
629 //-------------------------------------------------------------------- 629 //--------------------------------------------------------------------
630 // Process the input file. 630 // Process the input file.
631 //-------------------------------------------------------------------- 631 //--------------------------------------------------------------------
632 632
633 switch (command) 633 switch (command)
634 { 634 {
635 case cmd_sign: 635 case cmd_sign:
636 if (verbose) 636 if (verbose)
637 std::cout << "[*] Signing input file..." << std::endl; 637 std::cout << "[*] Signing input file..." << std::endl;
638 if (!sign(buffer, pi, outfile, verbose)) 638 if (!sign(buffer, pi, outfile, verbose))
639 return 7; 639 return 7;
640 std::cout << "Successfully signed the input file." << std::endl; 640 std::cout << "Successfully signed the input file." << std::endl;
641 break; 641 break;
642 case cmd_verify: 642 case cmd_verify:
643 if (verbose) 643 if (verbose)
644 std::cout << "[*] Verifying signature on input file..." 644 std::cout << "[*] Verifying signature on input file..."
645 << std::endl; 645 << std::endl;
646 if (!verify(buffer, pi, verbose)) 646 if (!verify(buffer, pi, verbose))
647 return 8; 647 return 8;
648 std::cout << "Successfully verified the input file signature." 648 std::cout << "Successfully verified the input file signature."
649 << std::endl; 649 << std::endl;
650 break; 650 break;
651 case cmd_encrypt: 651 case cmd_encrypt:
652 if (verbose) 652 if (verbose)
653 std::cout << "[*] Encrypting input file..." << std::endl; 653 std::cout << "[*] Encrypting input file..." << std::endl;
654 if (!encrypt(buffer, mode, pi, outfile, verbose)) 654 if (!encrypt(buffer, mode, pi, outfile, verbose))
655 return 9; 655 return 9;
656 std::cout << "Successfully encrypted the input file." << std::endl; 656 std::cout << "Successfully encrypted the input file." << std::endl;
657 break; 657 break;
658 case cmd_decrypt: 658 case cmd_decrypt:
659 if (verbose) 659 if (verbose)
660 std::cout << "[*] Decrypting input file..." << std::endl; 660 std::cout << "[*] Decrypting input file..." << std::endl;
661 if (!decrypt(buffer, mode, pi, outfile, verbose)) 661 if (!decrypt(buffer, mode, pi, outfile, verbose))
662 return 10; 662 return 10;
663 std::cout << "Successfully decrypted the input file." << std::endl; 663 std::cout << "Successfully decrypted the input file." << std::endl;
664 break; 664 break;
665 }; 665 };
666 666
667 return 0; 667 return 0;
668} 668}
669 669
670int main(int argc, char* argv[]) 670int main(int argc, char* argv[])
671{ 671{
672 try 672 try
673 { 673 {
674 return process_arguments(argc, argv); 674 return process_arguments(argc, argv);
675 } 675 }
676 catch (const std::exception& xcpt) 676 catch (const std::exception& xcpt)
677 { 677 {
678 std::cerr << "Exception caught: " << xcpt.what() << std::endl; 678 std::cerr << "Exception caught: " << xcpt.what() << std::endl;
679 return -1; 679 return -1;
680 } 680 }
681 catch (...) 681 catch (...)
682 { 682 {
683 std::cerr << "Unknown exception caught." << std::endl; 683 std::cerr << "Unknown exception caught." << std::endl;
684 return -2; 684 return -2;
685 } 685 }
686 return -3; 686 return -3;
687} 687}