summaryrefslogtreecommitdiffstats
path: root/tools/obbtool
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2010-10-13 15:00:07 -0700
committerKenny Root <kroot@google.com>2010-10-13 18:25:33 -0700
commit3b1abba6bbc895d63da3e82e9b158c01bd12eddd (patch)
tree1296e8c25a2927c94783eda83100c061fc9fe379 /tools/obbtool
parentdfc07279fc6205c38f5f39cb5ba4f0aef6b593a4 (diff)
downloadframeworks_base-3b1abba6bbc895d63da3e82e9b158c01bd12eddd.zip
frameworks_base-3b1abba6bbc895d63da3e82e9b158c01bd12eddd.tar.gz
frameworks_base-3b1abba6bbc895d63da3e82e9b158c01bd12eddd.tar.bz2
OBB: use PBKDF2 for key generation.
Switch to using PBKDF2 for the key generation for OBBs. Any previously generated OBBs will stop being read correctly. A small pbkdf2gen program is available to allow generation of appropriate keys with the salts. Bug: 3059950 Change-Id: If4305c989fd692fd1150eb270dbf751e09c37295
Diffstat (limited to 'tools/obbtool')
-rw-r--r--tools/obbtool/Android.mk16
-rw-r--r--tools/obbtool/Main.cpp91
-rwxr-xr-xtools/obbtool/mkobb.sh18
-rw-r--r--tools/obbtool/pbkdf2gen.cpp78
4 files changed, 192 insertions, 11 deletions
diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk
index b02c1cb..9300bb7 100644
--- a/tools/obbtool/Android.mk
+++ b/tools/obbtool/Android.mk
@@ -13,6 +13,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
Main.cpp
+LOCAL_CFLAGS := -Wall -Werror
+
#LOCAL_C_INCLUDES +=
LOCAL_STATIC_LIBRARIES := \
@@ -27,4 +29,18 @@ LOCAL_MODULE := obbtool
include $(BUILD_HOST_EXECUTABLE)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := pbkdf2gen
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Wall -Werror
+
+LOCAL_SRC_FILES := pbkdf2gen.cpp
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+include $(BUILD_HOST_EXECUTABLE)
+
endif # TARGET_BUILD_APPS
diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp
index 49e077f..932dbec 100644
--- a/tools/obbtool/Main.cpp
+++ b/tools/obbtool/Main.cpp
@@ -20,6 +20,7 @@
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
using namespace android;
@@ -29,7 +30,9 @@ static const char* gProgVersion = "1.0";
static int wantUsage = 0;
static int wantVersion = 0;
-#define ADD_OPTS "n:v:o"
+#define SALT_LEN 8
+
+#define ADD_OPTS "n:v:os:"
static const struct option longopts[] = {
{"help", no_argument, &wantUsage, 1},
{"version", no_argument, &wantVersion, 1},
@@ -38,14 +41,27 @@ static const struct option longopts[] = {
{"name", required_argument, NULL, 'n'},
{"version", required_argument, NULL, 'v'},
{"overlay", optional_argument, NULL, 'o'},
+ {"salt", required_argument, NULL, 's'},
{NULL, 0, NULL, '\0'}
};
-struct package_info_t {
+class PackageInfo {
+public:
+ PackageInfo()
+ : packageName(NULL)
+ , packageVersion(-1)
+ , overlay(false)
+ , salted(false)
+ {
+ memset(&salt, 0, sizeof(salt));
+ }
+
char* packageName;
int packageVersion;
bool overlay;
+ bool salted;
+ unsigned char salt[SALT_LEN];
};
/*
@@ -59,6 +75,13 @@ void usage(void)
" %s a[dd] [ OPTIONS ] FILENAME\n"
" Adds an OBB signature to the file.\n\n", gProgName);
fprintf(stderr,
+ " Options:\n"
+ " -n <package name> sets the OBB package name (required)\n"
+ " -v <OBB version> sets the OBB version (required)\n"
+ " -o sets the OBB overlay flag\n"
+ " -s <8 byte hex salt> sets the crypto key salt (if encrypted)\n"
+ "\n");
+ fprintf(stderr,
" %s r[emove] FILENAME\n"
" Removes the OBB signature from the file.\n\n", gProgName);
fprintf(stderr,
@@ -66,7 +89,7 @@ void usage(void)
" Prints the OBB signature information of a file.\n\n", gProgName);
}
-void doAdd(const char* filename, struct package_info_t* info) {
+void doAdd(const char* filename, struct PackageInfo* info) {
ObbFile *obb = new ObbFile();
if (obb->readFrom(filename)) {
fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename);
@@ -76,6 +99,9 @@ void doAdd(const char* filename, struct package_info_t* info) {
obb->setPackageName(String8(info->packageName));
obb->setVersion(info->packageVersion);
obb->setOverlay(info->overlay);
+ if (info->salted) {
+ obb->setSalt(info->salt, SALT_LEN);
+ }
if (!obb->writeTo(filename)) {
fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
@@ -113,6 +139,40 @@ void doInfo(const char* filename) {
printf(" Version: %d\n", obb->getVersion());
printf(" Flags: 0x%08x\n", obb->getFlags());
printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false");
+ printf(" Salt: ");
+
+ size_t saltLen;
+ const unsigned char* salt = obb->getSalt(&saltLen);
+ if (salt != NULL) {
+ for (int i = 0; i < SALT_LEN; i++) {
+ printf("%02x", salt[i]);
+ }
+ printf("\n");
+ } else {
+ printf("<empty>\n");
+ }
+}
+
+bool fromHex(char h, unsigned char *b) {
+ if (h >= '0' && h <= '9') {
+ *b = h - '0';
+ return true;
+ } else if (h >= 'a' && h <= 'f') {
+ *b = h - 'a' + 10;
+ return true;
+ } else if (h >= 'A' && h <= 'F') {
+ *b = h - 'A' + 10;
+ return true;
+ }
+ return false;
+}
+
+bool hexToByte(char h1, char h2, unsigned char* b) {
+ unsigned char first, second;
+ if (!fromHex(h1, &first)) return false;
+ if (!fromHex(h2, &second)) return false;
+ *b = (first << 4) | second;
+ return true;
}
/*
@@ -120,11 +180,9 @@ void doInfo(const char* filename) {
*/
int main(int argc, char* const argv[])
{
- const char *prog = argv[0];
- struct options *options;
int opt;
int option_index = 0;
- struct package_info_t package_info;
+ struct PackageInfo package_info;
int result = 1; // pessimistically assume an error.
@@ -145,7 +203,7 @@ int main(int argc, char* const argv[])
package_info.packageName = optarg;
break;
case 'v': {
- char *end;
+ char* end;
package_info.packageVersion = strtol(optarg, &end, 10);
if (*optarg == '\0' || *end != '\0') {
fprintf(stderr, "ERROR: invalid version; should be integer!\n\n");
@@ -157,6 +215,25 @@ int main(int argc, char* const argv[])
case 'o':
package_info.overlay = true;
break;
+ case 's':
+ if (strlen(optarg) != SALT_LEN * 2) {
+ fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n");
+ wantUsage = 1;
+ goto bail;
+ }
+
+ package_info.salted = true;
+
+ unsigned char b;
+ for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) {
+ if (!hexToByte(optarg[j], optarg[j+1], &b)) {
+ fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n");
+ wantUsage = 1;
+ goto bail;
+ }
+ package_info.salt[i] = b;
+ }
+ break;
case '?':
wantUsage = 1;
goto bail;
diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh
index ba5256f..725250d 100755
--- a/tools/obbtool/mkobb.sh
+++ b/tools/obbtool/mkobb.sh
@@ -35,6 +35,7 @@ find_binaries() {
UMOUNTBIN=`which umount`
DDBIN=`which dd`
RSYNCBIN=`which rsync`
+ PBKDF2GEN=`which pbkdf2gen`
}
check_prereqs() {
@@ -76,6 +77,11 @@ check_prereqs() {
echo "ERROR: ${LOSETUPBIN} is not executable!"
exit 1
fi
+
+ if [ "${PBKDF2GEN}x" = "x" ]; then \
+ echo "ERROR: Could not find pbkdf2gen in your path!"
+ exit 1
+ fi
}
cleanup() {
@@ -142,7 +148,6 @@ onexit() {
usage() {
echo "mkobb.sh -- Create OBB files for use on Android"
echo ""
- echo " -c Use an encrypted OBB; must specify key"
echo " -d <directory> Use <directory> as input for OBB files"
echo " -k <key> Use <key> to encrypt OBB file"
echo " -K Prompt for key to encrypt OBB file"
@@ -156,7 +161,7 @@ check_prereqs
use_crypto=0
-args=`getopt -o cd:hk:Ko:v -- "$@"`
+args=`getopt -o d:hk:Ko:v -- "$@"`
eval set -- "$args"
while true; do \
@@ -223,9 +228,9 @@ loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next
${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
if [ ${use_crypto} -eq 1 ]; then \
- hashed_key=`echo -n "${key}" | md5sum | awk '{ print $1 }'`
+ eval `${PBKDF2GEN} ${key}`
unique_dm_name=`basename ${tempfile}`
- echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${hashed_key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
+ echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
old_loop_dev=${loop_dev}
loop_dev=/dev/mapper/${unique_dm_name}
fi
@@ -253,6 +258,11 @@ echo ""
echo "Successfully created \`${filename}'"
+if [ ${use_crypto} -eq 1 ]; then \
+ echo "salt for use with obbtool is:"
+ echo "${salt}"
+fi
+
#
# Undo all the temporaries
#
diff --git a/tools/obbtool/pbkdf2gen.cpp b/tools/obbtool/pbkdf2gen.cpp
new file mode 100644
index 0000000..98d67c0
--- /dev/null
+++ b/tools/obbtool/pbkdf2gen.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <openssl/evp.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/**
+ * Simple program to generate a key based on PBKDF2 with preset inputs.
+ *
+ * Will print out the salt and key in hex.
+ */
+
+#define SALT_LEN 8
+#define ROUNDS 1024
+#define KEY_BITS 128
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <password>\n", argv[0]);
+ exit(1);
+ }
+
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Could not open /dev/urandom: %s\n", strerror(errno));
+ close(fd);
+ exit(1);
+ }
+
+ unsigned char salt[SALT_LEN];
+
+ if (read(fd, &salt, SALT_LEN) != SALT_LEN) {
+ fprintf(stderr, "Could not read salt from /dev/urandom: %s\n", strerror(errno));
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+
+ unsigned char rawKey[KEY_BITS];
+
+ if (PKCS5_PBKDF2_HMAC_SHA1(argv[1], strlen(argv[1]), salt, SALT_LEN,
+ ROUNDS, KEY_BITS, rawKey) != 1) {
+ fprintf(stderr, "Could not generate PBKDF2 output: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ printf("salt=");
+ for (int i = 0; i < SALT_LEN; i++) {
+ printf("%02x", salt[i]);
+ }
+ printf("\n");
+
+ printf("key=");
+ for (int i = 0; i < (KEY_BITS / 8); i++) {
+ printf("%02x", rawKey[i]);
+ }
+ printf("\n");
+}