Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add support for large zips.

  • Loading branch information...
commit b967d4130dd195c67d895315ca61c9421dd8d412 1 parent 9121f70
@kmdm authored
View
2  Makefile.am
@@ -2,6 +2,6 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -D_FORTIFY_SOURCE=0 $(LIBMCRYPT_CFLAGS)
AM_LDFLAGS = $(EXTRA_LDFLAGS) $(LIBMCRYPT_LDFLAGS)
bin_PROGRAMS = ruuveal
-ruuveal_SOURCES = main.c htcaes.c htckey.c htczip.c htc/devices.c
+ruuveal_SOURCES = main.c htcaes.c htckey.c htclargezip.c htczip.c htc/devices.c
ruuveal_LDADD = $(LIBMCRYPT_LIBS)
EXTRA_DIST = *.h htc/*.h htc/*.c
View
33 htcaes.c
@@ -66,12 +66,13 @@ static int encrypt_chunk(MCRYPT td, char *buf, int size, char *key, char *iv)
memcpy(iv, &buf[size - HTC_AES_KEYSIZE], HTC_AES_KEYSIZE);
}
-static int htc_aes_crypt(FILE *in, FILE *out, char *key, char *iv,
- unsigned char chunks_in, htc_aes_progress_t callback,
- htc_aes_crypt_t crypt_func)
+static int htc_aes_crypt(FILE *in, unsigned int maxlen,
+ FILE *out, char *key, char *iv,
+ unsigned char chunks_in, htc_aes_progress_t callback,
+ htc_aes_crypt_t crypt_func)
{
char buf[HTC_AES_READBUF], orig_iv[HTC_AES_KEYSIZE];
- unsigned int pos, size, chunks, bytes, chunksdone = 0;
+ unsigned int pos, size, chunks, bytes, bytesdone = 0, chunksdone = 0;
unsigned int count = HTC_AES_READBUF_ROUNDS + 1;
unsigned int chunk_size = (((int)chunks_in)<<HTC_AES_CHUNK_SIZE);
MCRYPT td;
@@ -82,6 +83,10 @@ static int htc_aes_crypt(FILE *in, FILE *out, char *key, char *iv,
size = ftell(in) - pos;
fseek(in, pos, SEEK_SET);
+ if(maxlen > 0 && maxlen < size) {
+ size = maxlen;
+ }
+
chunks = get_num_chunks(size, chunk_size);
td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, NULL, MCRYPT_CBC, NULL);
@@ -93,8 +98,12 @@ static int htc_aes_crypt(FILE *in, FILE *out, char *key, char *iv,
memcpy(orig_iv, iv, HTC_AES_KEYSIZE);
- while((bytes = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
- if(callback) callback(ftell(in), size);
+ while(bytesdone < size &&
+ (bytes = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
+ bytesdone += bytes;
+ if(bytesdone > size) bytes -= (bytesdone - size);
+
+ if(callback) callback(bytesdone, size);
if(chunksdone < chunks) {
if((ftell(in) - bytes - pos) % chunk_size == 0) {
count = 0;
@@ -102,30 +111,30 @@ static int htc_aes_crypt(FILE *in, FILE *out, char *key, char *iv,
}
if(count < HTC_AES_READBUF_ROUNDS) {
- crypt_func(td, buf, sizeof(buf), key, iv);
+ crypt_func(td, buf, bytes, key, iv);
count++;
} else if(count == HTC_AES_READBUF_ROUNDS) {
chunksdone++;
count++;
}
}
- fwrite(buf, sizeof(char), sizeof(buf), out);
+ fwrite(buf, sizeof(char), bytes, out);
}
mcrypt_module_close(td);
return 1;
}
-int htc_aes_decrypt(FILE *in, FILE *out, char *key, char *iv,
- unsigned char chunks, htc_aes_progress_t callback)
+int htc_aes_decrypt(FILE *in, unsigned int maxlen, FILE *out, char *key,
+ char *iv, unsigned char chunks, htc_aes_progress_t callback)
{
- return htc_aes_crypt(in, out, key, iv, chunks, callback, decrypt_chunk);
+ return htc_aes_crypt(in,maxlen,out,key,iv,chunks,callback,decrypt_chunk);
}
int htc_aes_encrypt(FILE *in, FILE *out, char *key, char *iv,
unsigned char chunks, htc_aes_progress_t callback)
{
- return htc_aes_crypt(in, out, key, iv, chunks, callback, encrypt_chunk);
+ return htc_aes_crypt(in, -1, out, key, iv, chunks, callback, encrypt_chunk);
}
View
2  htcaes.h
@@ -3,7 +3,7 @@
#include <mcrypt.h>
typedef void (*htc_aes_progress_t) (unsigned int, unsigned int);
typedef int (*htc_aes_crypt_t) (MCRYPT, char *, int, char *, char *);
-int htc_aes_decrypt(FILE *, FILE *, char *, char *, unsigned char,
+int htc_aes_decrypt(FILE *, unsigned int, FILE *, char *, char *, unsigned char,
htc_aes_progress_t);
int htc_aes_encrypt(FILE *, FILE *, char *, char *, unsigned char,
htc_aes_progress_t);
View
45 htclargezip.c
@@ -0,0 +1,45 @@
+/* ruuveal - Decrypt HTC encrypted RUUs (rom.zip files).
+ *
+ * Copyright (C) 2013 Kenny Millington
+ *
+ * This file is part of ruuveal.
+ *
+ * ruuveal is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ruuveal is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ruuveal. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "htclargezip.h"
+
+int htc_largezip_read_header(FILE *in, htc_largezip_header_t *header)
+{
+ int pos = ftell(in);
+
+ if(fread(header, 1, sizeof(*header), in) != sizeof(*header)) {
+ printf("%d\n", sizeof(*header));
+ perror("failed to read htc largezip header");
+ fseek(in, pos, SEEK_SET);
+ return 0;
+ }
+
+ if(strncmp(header->magic, HTC_LARGEZIP_HEADER_MAGIC,
+ strlen(HTC_LARGEZIP_HEADER_MAGIC))) {
+ fseek(in, pos, SEEK_SET);
+ fprintf(stderr, "not a largezip - header mismatch!\n");
+ return 0;
+ }
+
+ return 1;
+}
View
13 htclargezip.h
@@ -0,0 +1,13 @@
+#ifndef HTC_LARGEZIP_H
+#define HTC_LARGEZIP_HEADER_MAGIC "LaR@eZip"
+typedef struct {
+ char magic[8];
+ unsigned int starts[8];
+ unsigned int lengths[8];
+ unsigned int count;
+ unsigned int unknown;
+ char padding[0x100 - (8 + ((8 + 8 + 1 + 1)*4))];
+} htc_largezip_header_t;
+
+int htc_largezip_read_header(FILE *, htc_largezip_header_t *);
+#endif
View
6 htczip.c
@@ -55,13 +55,17 @@ int htc_zip_init_header(htc_zip_header_t *header)
int htc_zip_read_header(FILE *in, htc_zip_header_t *header)
{
+ int pos = ftell(in);
+
if(fread(header, 1, sizeof(*header), in) != sizeof(*header)) {
perror("failed to read htc zip header");
+ fseek(in, pos, SEEK_SET);
return 0;
}
-
+
if(strncmp(header->magic, HTC_ZIP_HEADER_MAGIC,
strlen(HTC_ZIP_HEADER_MAGIC))) {
+ fseek(in, pos, SEEK_SET);
return 0;
}
View
94 main.c
@@ -25,6 +25,7 @@
#include "htcaes.h"
#include "htckey.h"
+#include "htclargezip.h"
#include "htczip.h"
#include "htc/devices.h"
@@ -180,42 +181,21 @@ static int parse_opts(int argc, char * const *argv)
return 1;
}
-int main(int argc, char * const *argv)
+static int process_zip(FILE *in, int length, const char *filename)
{
+ int rc = 0;
char key[HTC_AES_KEYSIZE] = {0};
char iv[HTC_AES_KEYSIZE] = {0};
char *keydata = NULL;
int rc = 0;
- FILE *fh;
-
+ FILE *out;
htc_zip_header_t header;
- // FIXME: Better way to set these defaults.
- opts.keymap_index = HTC_ZIP_HEADER_DEFAULT_KEYMAP;
- opts.chunks = HTC_ZIP_HEADER_DEFAULT_CHUNKS;
- strncpy(opts.mainver, HTC_ZIP_HEADER_DEFAULT_MAINVER, sizeof(opts.mainver));
-
- FILE *in = NULL, *out = NULL;
-
- printf("ruuveal\n");
- printf("-------\n\n");
-
- if(!parse_opts(argc, argv)) {
- usage(argv);
- FAIL(-1);
- }
-
- /* Open the source file. */
- if((in = fopen(opts.source, "rb")) == NULL) {
- perror("failed to open source zip");
- FAIL(-2)
- }
-
/* Read the header. */
if(!opts.encrypt) {
if(!htc_zip_read_header(in, &header)) {
- fseek(in, 0x100, SEEK_SET);
+ fseek(in, 0x100, SEEK_CUR);
if(!htc_zip_read_header(in, &header)) {
fprintf(stderr, "invalid htc aes encrypted zip file!\n");
FAIL(-4);
@@ -273,7 +253,7 @@ int main(int argc, char * const *argv)
DEBUG(dump("iv", iv, sizeof(iv));)
/* Open the output file. */
- if((out = fopen(opts.dest, "wb")) == NULL) {
+ if((out = fopen(filename, "wb")) == NULL) {
perror("failed to open output zip destination");
FAIL(-6)
}
@@ -286,19 +266,73 @@ int main(int argc, char * const *argv)
FAIL(-7)
}
- printf("Encrypted RUU (zip) written to: %s\n", opts.dest);
+ printf("Encrypted RUU (zip) written to: %s\n", filename);
} else {
- if(!htc_aes_decrypt(in, out, key, iv, header.chunks, progress_update)) {
+ if(!htc_aes_decrypt(in, length, out, key, iv, header.chunks,
+ progress_update)) {
fprintf(stderr, "failed to decrypt zip file!\n");
FAIL(-7)
}
- printf("Decrypted RUU (zip) written to: %s\n", opts.dest);
+ printf("Decrypted RUU (zip) written to: %s\n", filename);
}
+
end:
- if(in) fclose(in);
if(out) fclose(out);
return rc;
}
+
+int main(int argc, char * const *argv)
+{
+ int i, rc = 0;
+ char *name = 0;
+ htc_largezip_header_t hdr;
+
+ // FIXME: Better way to set these defaults.
+ opts.keymap_index = HTC_ZIP_HEADER_DEFAULT_KEYMAP;
+ opts.chunks = HTC_ZIP_HEADER_DEFAULT_CHUNKS;
+ strncpy(opts.mainver, HTC_ZIP_HEADER_DEFAULT_MAINVER, sizeof(opts.mainver));
+
+ FILE *in = NULL;
+
+ printf("ruuveal\n");
+ printf("-------\n\n");
+
+ if(!parse_opts(argc, argv)) {
+ usage(argv);
+ FAIL(-1);
+ }
+
+ /* Open the source file. */
+ if((in = fopen(opts.source, "rb")) == NULL) {
+ perror("failed to open source zip");
+ FAIL(-2)
+ }
+
+ /* Check for a "Large Zip" */
+ if(!opts.encrypt && htc_largezip_read_header(in, &hdr)) {
+ printf("Large zip format detected containing %d zipfile(s)\n",
+ hdr.count);
+
+ if((name = calloc(strlen(opts.dest) + 3, sizeof(char))) == NULL) {
+ FAIL(-8)
+ };
+
+ for(i=0; i<hdr.count;i++) {
+ sprintf(name, "%02d_", i + 1);
+ strcat(name, opts.dest);
+ fseek(in, sizeof(hdr) + hdr.starts[i], SEEK_SET);
+ rc = process_zip(in, hdr.lengths[i], name);
+ if(rc != 0) goto end;
+ }
+ } else {
+ rc = process_zip(in, -1, opts.dest);
+ }
+
+end:
+ if(in) fclose(in);
+ if(name) free(name);
+ return rc;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.